| From 16bb7abc4a6b9defffa294e4dc28383e62a1dbcf Mon Sep 17 00:00:00 2001 |
| From: Bitan Biswas <bbiswas@nvidia.com> |
| Date: Thu, 9 Jan 2020 10:40:17 +0000 |
| Subject: nvmem: core: fix memory abort in cleanup path |
| |
| From: Bitan Biswas <bbiswas@nvidia.com> |
| |
| commit 16bb7abc4a6b9defffa294e4dc28383e62a1dbcf upstream. |
| |
| nvmem_cell_info_to_nvmem_cell implementation has static |
| allocation of name. nvmem_add_cells_from_of() call may |
| return error and kfree name results in memory abort. Use |
| kstrdup_const() and kfree_const calls for name alloc and free. |
| |
| Unable to handle kernel paging request at virtual address ffffffffffe44888 |
| Mem abort info: |
| ESR = 0x96000006 |
| EC = 0x25: DABT (current EL), IL = 32 bits |
| SET = 0, FnV = 0 |
| EA = 0, S1PTW = 0 |
| Data abort info: |
| ISV = 0, ISS = 0x00000006 |
| CM = 0, WnR = 0 |
| swapper pgtable: 64k pages, 48-bit VAs, pgdp=00000000815d0000 |
| [ffffffffffe44888] pgd=0000000081d30803, pud=0000000081d30803, |
| pmd=0000000000000000 |
| Internal error: Oops: 96000006 [#1] PREEMPT SMP |
| Modules linked in: |
| CPU: 2 PID: 43 Comm: kworker/2:1 Tainted |
| Hardware name: quill (DT) |
| Workqueue: events deferred_probe_work_func |
| pstate: a0000005 (NzCv daif -PAN -UAO) |
| pc : kfree+0x38/0x278 |
| lr : nvmem_cell_drop+0x68/0x80 |
| sp : ffff80001284f9d0 |
| x29: ffff80001284f9d0 x28: ffff0001f677e830 |
| x27: ffff800011b0b000 x26: ffff0001c36e1008 |
| x25: ffff8000112ad000 x24: ffff8000112c9000 |
| x23: ffffffffffffffea x22: ffff800010adc7f0 |
| x21: ffffffffffe44880 x20: ffff800011b0b068 |
| x19: ffff80001122d380 x18: ffffffffffffffff |
| x17: 00000000d5cb4756 x16: 0000000070b193b8 |
| x15: ffff8000119538c8 x14: 0720072007200720 |
| x13: 07200720076e0772 x12: 07750762072d0765 |
| x11: 0773077507660765 x10: 072f073007300730 |
| x9 : 0730073207380733 x8 : 0000000000000151 |
| x7 : 07660765072f0720 x6 : ffff0001c00e0f00 |
| x5 : 0000000000000000 x4 : ffff0001c0b43800 |
| x3 : ffff800011b0b068 x2 : 0000000000000000 |
| x1 : 0000000000000000 x0 : ffffffdfffe00000 |
| Call trace: |
| kfree+0x38/0x278 |
| nvmem_cell_drop+0x68/0x80 |
| nvmem_device_remove_all_cells+0x2c/0x50 |
| nvmem_register.part.9+0x520/0x628 |
| devm_nvmem_register+0x48/0xa0 |
| tegra_fuse_probe+0x140/0x1f0 |
| platform_drv_probe+0x50/0xa0 |
| really_probe+0x108/0x348 |
| driver_probe_device+0x58/0x100 |
| __device_attach_driver+0x90/0xb0 |
| bus_for_each_drv+0x64/0xc8 |
| __device_attach+0xd8/0x138 |
| device_initial_probe+0x10/0x18 |
| bus_probe_device+0x90/0x98 |
| deferred_probe_work_func+0x74/0xb0 |
| process_one_work+0x1e0/0x358 |
| worker_thread+0x208/0x488 |
| kthread+0x118/0x120 |
| ret_from_fork+0x10/0x18 |
| Code: d350feb5 f2dffbe0 aa1e03f6 8b151815 (f94006a0) |
| ---[ end trace 49b1303c6b83198e ]--- |
| |
| Fixes: badcdff107cbf ("nvmem: Convert to using %pOFn instead of device_node.name") |
| Signed-off-by: Bitan Biswas <bbiswas@nvidia.com> |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| Link: https://lore.kernel.org/r/20200109104017.6249-5-srinivas.kandagatla@linaro.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/nvmem/core.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/nvmem/core.c |
| +++ b/drivers/nvmem/core.c |
| @@ -83,7 +83,7 @@ static void nvmem_cell_drop(struct nvmem |
| list_del(&cell->node); |
| mutex_unlock(&nvmem_mutex); |
| of_node_put(cell->np); |
| - kfree(cell->name); |
| + kfree_const(cell->name); |
| kfree(cell); |
| } |
| |
| @@ -110,7 +110,9 @@ static int nvmem_cell_info_to_nvmem_cell |
| cell->nvmem = nvmem; |
| cell->offset = info->offset; |
| cell->bytes = info->bytes; |
| - cell->name = info->name; |
| + cell->name = kstrdup_const(info->name, GFP_KERNEL); |
| + if (!cell->name) |
| + return -ENOMEM; |
| |
| cell->bit_offset = info->bit_offset; |
| cell->nbits = info->nbits; |
| @@ -300,7 +302,7 @@ static int nvmem_add_cells_from_of(struc |
| dev_err(dev, "cell %s unaligned to nvmem stride %d\n", |
| cell->name, nvmem->stride); |
| /* Cells already added will be freed later. */ |
| - kfree(cell->name); |
| + kfree_const(cell->name); |
| kfree(cell); |
| return -EINVAL; |
| } |