From cbf9c4b9617b6767886a913705ca14b7600c77db Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Tue, 31 May 2022 09:44:46 +0530 Subject: of: check previous kernel's ima-kexec-buffer against memory bounds Presently ima_get_kexec_buffer() doesn't check if the previous kernel's ima-kexec-buffer lies outside the addressable memory range. This can result in a kernel panic if the new kernel is booted with 'mem=X' arg and the ima-kexec-buffer was allocated beyond that range by the previous kernel. The panic is usually of the form below: $ sudo kexec --initrd initrd vmlinux --append='mem=16G' BUG: Unable to handle kernel data access on read at 0xc000c01fff7f0000 Faulting instruction address: 0xc000000000837974 Oops: Kernel access of bad area, sig: 11 [#1] NIP [c000000000837974] ima_restore_measurement_list+0x94/0x6c0 LR [c00000000083b55c] ima_load_kexec_buffer+0xac/0x160 Call Trace: [c00000000371fa80] [c00000000083b55c] ima_load_kexec_buffer+0xac/0x160 [c00000000371fb00] [c0000000020512c4] ima_init+0x80/0x108 [c00000000371fb70] [c0000000020514dc] init_ima+0x4c/0x120 [c00000000371fbf0] [c000000000012240] do_one_initcall+0x60/0x2c0 [c00000000371fcc0] [c000000002004ad0] kernel_init_freeable+0x344/0x3ec [c00000000371fda0] [c0000000000128a4] kernel_init+0x34/0x1b0 [c00000000371fe10] [c00000000000ce64] ret_from_kernel_thread+0x5c/0x64 Instruction dump: f92100b8 f92100c0 90e10090 910100a0 4182050c 282a0017 3bc00000 40810330 7c0802a6 fb610198 7c9b2378 f80101d0 2c090001 40820614 e9240010 ---[ end trace 0000000000000000 ]--- Fix this issue by checking returned PFN range of previous kernel's ima-kexec-buffer with page_is_ram() to ensure correct memory bounds. Fixes: 467d27824920 ("powerpc: ima: get the kexec buffer passed by the previous kernel") Cc: Frank Rowand Cc: Prakhar Srivastava Cc: Lakshmi Ramasubramanian Cc: Thiago Jung Bauermann Cc: Rob Herring Cc: Ritesh Harjani Cc: Robin Murphy Signed-off-by: Vaibhav Jain Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220531041446.3334259-1-vaibhav@linux.ibm.com --- drivers/of/kexec.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c index 8d374cc552be..91b04b04eec4 100644 --- a/drivers/of/kexec.c +++ b/drivers/of/kexec.c @@ -126,6 +126,7 @@ int ima_get_kexec_buffer(void **addr, size_t *size) { int ret, len; unsigned long tmp_addr; + unsigned long start_pfn, end_pfn; size_t tmp_size; const void *prop; @@ -140,6 +141,22 @@ int ima_get_kexec_buffer(void **addr, size_t *size) if (ret) return ret; + /* Do some sanity on the returned size for the ima-kexec buffer */ + if (!tmp_size) + return -ENOENT; + + /* + * Calculate the PFNs for the buffer and ensure + * they are with in addressable memory. + */ + start_pfn = PHYS_PFN(tmp_addr); + end_pfn = PHYS_PFN(tmp_addr + tmp_size - 1); + if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn)) { + pr_warn("IMA buffer at 0x%lx, size = 0x%zx beyond memory\n", + tmp_addr, tmp_size); + return -EINVAL; + } + *addr = __va(tmp_addr); *size = tmp_size; -- cgit v1.2.3 From 3a5230a87c3b719bd536190b76b029c4cf2452cc Mon Sep 17 00:00:00 2001 From: Deming Wang Date: Thu, 23 Jun 2022 21:12:47 -0400 Subject: of: Drop duplicate 'the' in of_find_last_cache_level kerneldoc Delete duplicate words of "the". Signed-off-by: Deming Wang Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220624011247.1735-1-wangdeming@inspur.com --- drivers/of/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index d4f98c8469ed..88f86ee54b9a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2077,7 +2077,7 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) * * @cpu: cpu number(logical index) for which the last cache level is needed * - * Return: The the level at which the last cache is present. It is exactly + * Return: The level at which the last cache is present. It is exactly * same as the total number of cache levels for the given logical cpu. */ int of_find_last_cache_level(unsigned int cpu) -- cgit v1.2.3 From 6991cd744f068349a934fd31254c77f48fa530ec Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 28 Jun 2022 13:35:40 +0200 Subject: of: reserved-memory: Print allocation/reservation failures as error If the allocation/reservation of reserved-memory fails, it is normally an error, so print it as an error so that it doesn't get hidden from the console due to the loglevel. Also make the allocation failure include the size just like the reservation failure. Signed-off-by: Vincent Whitchurch Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220628113540.2790835-1-vincent.whitchurch@axis.com --- drivers/of/fdt.c | 4 ++-- drivers/of/of_reserved_mem.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a8f5b6532165..4610729d2297 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -532,8 +532,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, kmemleak_alloc_phys(base, size, 0, 0); } else - pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", - uname, &base, (unsigned long)(size / SZ_1M)); + pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); len -= t_len; if (first) { diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 75caa6f5d36f..65f3b02a0e4e 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -156,7 +156,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, } if (base == 0) { - pr_info("failed to allocate memory for node '%s'\n", uname); + pr_err("failed to allocate memory for node '%s': size %lu MiB\n", + uname, (unsigned long)(size / SZ_1M)); return -ENOMEM; } -- cgit v1.2.3 From 652081b3c64e03ae3229dd33923d295f9f3115db Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 9 Jul 2022 00:45:38 +0300 Subject: of: unittest: Switch to use fwnode instead of of_node The OF node in the GPIO library is deprecated and soon will be removed. GPIO library now accepts fwnode as a firmware node, so switch the module to use it instead. Signed-off-by: Andy Shevchenko Reviewed-by: Bartosz Golaszewski Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220708214539.7254-1-andriy.shevchenko@linux.intel.com --- drivers/of/unittest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 7f6bba18c515..5a842dfc27e8 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1602,7 +1602,7 @@ static int unittest_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, devptr); - devptr->chip.of_node = pdev->dev.of_node; + devptr->chip.fwnode = dev_fwnode(&pdev->dev); devptr->chip.label = "of-unittest-gpio"; devptr->chip.base = -1; /* dynamic allocation */ devptr->chip.ngpio = 5; @@ -1611,7 +1611,7 @@ static int unittest_gpio_probe(struct platform_device *pdev) ret = gpiochip_add_data(&devptr->chip, NULL); unittest(!ret, - "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret); + "gpiochip_add_data() for node @%pfw failed, ret = %d\n", devptr->chip.fwnode, ret); if (!ret) unittest_gpio_probe_pass_count++; -- cgit v1.2.3 From 9465a98458fe2a05015bc90d7587fb891cd0c0cc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 9 Jul 2022 00:45:39 +0300 Subject: of: unittest: make unittest_gpio_remove() consistent with unittest_gpio_probe() On the ->remove() stage the callback uses physical device node instead of one from GPIO chip and the variable name which is different to one used in unittest_gpio_probe(). Make these consistent with unittest_gpio_probe(). Signed-off-by: Andy Shevchenko Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220708214539.7254-2-andriy.shevchenko@linux.intel.com --- drivers/of/unittest.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 5a842dfc27e8..eafa8ffefbd0 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1620,20 +1620,19 @@ static int unittest_gpio_probe(struct platform_device *pdev) static int unittest_gpio_remove(struct platform_device *pdev) { - struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev); + struct unittest_gpio_dev *devptr = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - struct device_node *np = pdev->dev.of_node; - dev_dbg(dev, "%s for node @%pOF\n", __func__, np); + dev_dbg(dev, "%s for node @%pfw\n", __func__, devptr->chip.fwnode); - if (!gdev) + if (!devptr) return -EINVAL; - if (gdev->chip.base != -1) - gpiochip_remove(&gdev->chip); + if (devptr->chip.base != -1) + gpiochip_remove(&devptr->chip); platform_set_drvdata(pdev, NULL); - kfree(gdev); + kfree(devptr); return 0; } -- cgit v1.2.3 From d17e37c41b7ed38459957a5d2968ba61516fd5c2 Mon Sep 17 00:00:00 2001 From: Liang He Date: Sat, 2 Jul 2022 09:44:49 +0800 Subject: of: device: Fix missing of_node_put() in of_dma_set_restricted_buffer We should use of_node_put() for the reference 'node' returned by of_parse_phandle() which will increase the refcount. Fixes: fec9b625095f ("of: Add plumbing for restricted DMA pool") Co-authored-by: Miaoqian Lin Signed-off-by: Liang He Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220702014449.263772-1-windhl@126.com --- drivers/of/device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/device.c b/drivers/of/device.c index 874f031442dc..75b6cbffa755 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -81,8 +81,11 @@ of_dma_set_restricted_buffer(struct device *dev, struct device_node *np) * restricted-dma-pool region is allowed. */ if (of_device_is_compatible(node, "restricted-dma-pool") && - of_device_is_available(node)) + of_device_is_available(node)) { + of_node_put(node); break; + } + of_node_put(node); } /* -- cgit v1.2.3 From e385b0ba6a137f34953e746d70d543660c2de1a0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jul 2022 16:03:14 +0200 Subject: of: overlay: Move devicetree_corrupt() check up There is no point in doing several preparatory steps in of_overlay_fdt_apply(), only to see of_overlay_apply() return early because of a corrupt device tree. Move the check for a corrupt device tree from of_overlay_apply() to of_overlay_fdt_apply(), to check for this as early as possible. Signed-off-by: Geert Uytterhoeven Reviewed-by: Frank Rowand Tested-by: Frank Rowand Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/c91ce7112eb5167ea46a43d8a980e76b920010ba.1657893306.git.geert+renesas@glider.be --- drivers/of/overlay.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 4044ddcb02c6..84a8d402009c 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -903,12 +903,6 @@ static int of_overlay_apply(struct overlay_changeset *ovcs) { int ret = 0, ret_revert, ret_tmp; - if (devicetree_corrupt()) { - pr_err("devicetree state suspect, refuse to apply overlay\n"); - ret = -EBUSY; - goto out; - } - ret = of_resolve_phandles(ovcs->overlay_root); if (ret) goto out; @@ -983,6 +977,11 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, *ret_ovcs_id = 0; + if (devicetree_corrupt()) { + pr_err("devicetree state suspect, refuse to apply overlay\n"); + return -EBUSY; + } + if (overlay_fdt_size < sizeof(struct fdt_header) || fdt_check_header(overlay_fdt)) { pr_err("Invalid overlay_fdt header\n"); -- cgit v1.2.3 From e76f4a6107ebe4af5405bb1b94d0e717a40fd306 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jul 2022 16:03:15 +0200 Subject: of: overlay: Simplify of_overlay_fdt_apply() tail It does not hurt to fill in the changeset id while the mutex is still held. After doing so, the function tails for the success and failure cases become identical, so they can be unified. Signed-off-by: Geert Uytterhoeven Reviewed-by: Frank Rowand Tested-by: Frank Rowand Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/6a3357a8f7f29704350e3ffae768ee8a462b54d3.1657893306.git.geert+renesas@glider.be --- drivers/of/overlay.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 84a8d402009c..bd8ff4df723d 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -1043,20 +1043,15 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, * goto err_free_ovcs. Instead, the caller of of_overlay_fdt_apply() * can call of_overlay_remove(); */ - - mutex_unlock(&of_mutex); - of_overlay_mutex_unlock(); - *ret_ovcs_id = ovcs->id; - - return ret; + goto out_unlock; err_free_ovcs: free_overlay_changeset(ovcs); +out_unlock: mutex_unlock(&of_mutex); of_overlay_mutex_unlock(); - return ret; } EXPORT_SYMBOL_GPL(of_overlay_fdt_apply); -- cgit v1.2.3 From f8a855ed8d07f6f11c6b0d6a692f0220c64f8c21 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 22 Jul 2022 18:53:31 -0700 Subject: of/fdt: Clean up early_init_dt_reserve_memory_arch() As of commit 18250b43f7b6 ("of: fdt: Remove early_init_dt_reserve_memory_arch() override capability") this is no longer an arch hook, so rename it to remove the confusing _arch suffix. Also remove some unnecessary indirection from all but one of the callers by calling memblock_reserve() directly instead. Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/I3362bdd92ae6e47e8f5bac01aa228d32f9d01aad Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220723015331.1607029-1-pcc@google.com --- drivers/of/fdt.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 4610729d2297..872b7b54e197 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -477,8 +477,8 @@ void *initial_boot_params __ro_after_init; static u32 of_fdt_crc32; -static int __init early_init_dt_reserve_memory_arch(phys_addr_t base, - phys_addr_t size, bool nomap) +static int __init early_init_dt_reserve_memory(phys_addr_t base, + phys_addr_t size, bool nomap) { if (nomap) { /* @@ -525,7 +525,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, size = dt_mem_next_cell(dt_root_size_cells, &prop); if (size && - early_init_dt_reserve_memory_arch(base, size, nomap) == 0) { + early_init_dt_reserve_memory(base, size, nomap) == 0) { pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", uname, &base, (unsigned long)(size / SZ_1M)); if (!nomap) @@ -644,7 +644,7 @@ void __init early_init_fdt_scan_reserved_mem(void) fdt_get_mem_rsv(initial_boot_params, n, &base, &size); if (!size) break; - early_init_dt_reserve_memory_arch(base, size, false); + memblock_reserve(base, size); } fdt_scan_reserved_mem(); @@ -661,9 +661,8 @@ void __init early_init_fdt_reserve_self(void) return; /* Reserve the dtb region */ - early_init_dt_reserve_memory_arch(__pa(initial_boot_params), - fdt_totalsize(initial_boot_params), - false); + memblock_reserve(__pa(initial_boot_params), + fdt_totalsize(initial_boot_params)); } /** -- cgit v1.2.3 From 7913145afa51bbed9eaf8e5b4ee55fa9884a71e5 Mon Sep 17 00:00:00 2001 From: Xu Qiang Date: Mon, 1 Aug 2022 12:05:06 +0000 Subject: of/fdt: declared return type does not match actual return type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit 649cab56de8e (“of: properly check for error returned by fdt_get_name()”) changed the return value type from bool to int, but forgot to change the return value simultaneously. populate_node was only called in unflatten_dt_nodes, and returns with values greater than or equal to 0 were discarded without further processing. Considering that return 0 usually indicates success, return 0 instead of return true. Fixes: 649cab56de8e (“of: properly check for error returned by fdt_get_name()”) Signed-off-by: Xu Qiang Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220801120506.11461-2-xuqiang36@huawei.com --- drivers/of/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 872b7b54e197..e02a30c92719 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -246,7 +246,7 @@ static int populate_node(const void *blob, } *pnp = np; - return true; + return 0; } static void reverse_nodes(struct device_node *parent) -- cgit v1.2.3