Messages in this thread Patch in this message | | | From | Vadym Kochan <> | Subject | [PATCH] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell() | Date | Wed, 23 Sep 2020 02:50:05 +0300 |
| |
Fix missing kfree_const(cell->name) when call to nvmem_cell_info_to_nvmem_cell() in several places:
* after nvmem_cell_info_to_nvmem_cell() failed during nvmem_add_cells()
* during nvmem_device_cell_{read,write}. This is fixed by simply re-using info->name instead of duplicating it (happens in case of dynamic module):
cell->name = info->name
because cell->name is useless in these cases except for error message printing in case of un-aligned access is indicated. For this new __nvmem_cell_info_to_nvmem_cell() helper was introduced.
Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.") Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu> --- drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 6cd3edb2eaf6..d1f5a639dfca 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell) blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell); } -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, - const struct nvmem_cell_info *info, - struct nvmem_cell *cell) +static int +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, + const struct nvmem_cell_info *info, + struct nvmem_cell *cell) { cell->nvmem = nvmem; cell->offset = info->offset; cell->bytes = info->bytes; - cell->name = kstrdup_const(info->name, GFP_KERNEL); - if (!cell->name) - return -ENOMEM; + cell->name = info->name; cell->bit_offset = info->bit_offset; cell->nbits = info->nbits; @@ -382,13 +381,30 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, if (!IS_ALIGNED(cell->offset, nvmem->stride)) { dev_err(&nvmem->dev, "cell %s unaligned to nvmem stride %d\n", - cell->name, nvmem->stride); + cell->name ?: "<unknown>", nvmem->stride); return -EINVAL; } return 0; } +static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, + const struct nvmem_cell_info *info, + struct nvmem_cell *cell) +{ + int err; + + err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell); + if (err) + return err; + + cell->name = kstrdup_const(info->name, GFP_KERNEL); + if (!cell->name) + return -ENOMEM; + + return 0; +} + /** * nvmem_add_cells() - Add cell information to an nvmem device * @@ -418,6 +434,7 @@ static int nvmem_add_cells(struct nvmem_device *nvmem, rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]); if (rval) { + kfree_const(cells[i]->name); kfree(cells[i]); goto err; } @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem, if (!nvmem) return -EINVAL; - rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); + rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); if (rc) return rc; @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem, if (!nvmem) return -EINVAL; - rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); + rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); if (rc) return rc; -- 2.17.1
| |