From 7a12dd077e5207d72fadaabf7d4520bd3af84082 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 23:00:53 +0200 Subject: of: move from strlcpy with unused retval to strscpy Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220818210054.7157-1-wsa+renesas@sang-engineering.com --- drivers/of/base.c | 2 +- drivers/of/fdt.c | 6 +++--- drivers/of/unittest.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index 7fa960bd3df1..99cee6b02297 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1228,7 +1228,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) if (!compatible || strlen(compatible) > cplen) return -ENODEV; p = strchr(compatible, ','); - strlcpy(modalias, p ? p + 1 : compatible, len); + strscpy(modalias, p ? p + 1 : compatible, len); return 0; } EXPORT_SYMBOL_GPL(of_modalias_node); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 7bc92923104c..1617a31ecd22 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1178,7 +1178,7 @@ int __init early_init_dt_scan_chosen(char *cmdline) /* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) - strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); /* * CONFIG_CMDLINE is meant to be a default in case nothing else @@ -1190,11 +1190,11 @@ int __init early_init_dt_scan_chosen(char *cmdline) strlcat(cmdline, " ", COMMAND_LINE_SIZE); strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #elif defined(CONFIG_CMDLINE_FORCE) - strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); + strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #else /* No arguments from boot loader, use kernel's cmdl*/ if (!((char *)cmdline)[0]) - strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); + strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #endif #endif /* CONFIG_CMDLINE */ diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index eafa8ffefbd0..6fa14b77086a 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -2465,7 +2465,7 @@ static int unittest_i2c_bus_probe(struct platform_device *pdev) adap = &std->adap; i2c_set_adapdata(adap, std); adap->nr = -1; - strlcpy(adap->name, pdev->name, sizeof(adap->name)); + strscpy(adap->name, pdev->name, sizeof(adap->name)); adap->class = I2C_CLASS_DEPRECATED; adap->algo = &unittest_i2c_algo; adap->dev.parent = dev; -- cgit v1.2.3 From 59f9072f6e48e21d7c40fb0ca75d99f5f68abc04 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Tue, 23 Aug 2022 15:01:52 -0500 Subject: of: unittest: taint the kernel when of unittest runs Make OF unittest trigger the new TAINT_TEST taint when OF unittest runs. Due to OF unittest not being intended to run on production systems, and potentially causing problems (or security issues like leaking kernel addresses), the kernel's state should not be considered safe for production use after OF unittest runs. Signed-off-by: Frank Rowand Link: https://lore.kernel.org/r/20220823200152.3465751-1-frowand.list@gmail.com Signed-off-by: Rob Herring --- drivers/of/unittest.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 6fa14b77086a..2b39470e82d4 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -3467,6 +3467,9 @@ static int __init of_unittest(void) pr_info("start of unittest - you will see error messages\n"); + /* Taint the kernel so we know we've run tests. */ + add_taint(TAINT_TEST, LOCKDEP_STILL_OK); + /* adding data for unittest */ if (IS_ENABLED(CONFIG_UML)) -- cgit v1.2.3 From 27244cbda82787c9283ce79f5e7bea8ecaa58dff Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Wed, 7 Sep 2022 14:16:29 +0200 Subject: of: irq: Report individual failures in of_irq_init() New pr_err(), a copy of preceeding pr_debug(), faciliates debugging. This change was inspired by a long lasting debugging of the octeon_irq_init_ciu() which fails completely silently and leaves the interrupt controller half-way configured which in turn had very non-obvious effects. Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20220907121629.54330-1-alexander.sverdlin@nokia.com Signed-off-by: Rob Herring --- drivers/of/irq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index d22f605fa7ee..2bac44f09554 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -592,6 +592,9 @@ void __init of_irq_init(const struct of_device_id *matches) ret = desc->irq_init_cb(desc->dev, desc->interrupt_parent); if (ret) { + pr_err("%s: Failed to init %pOF (%p), parent %p\n", + __func__, desc->dev, desc->dev, + desc->interrupt_parent); of_node_clear_flag(desc->dev, OF_POPULATED); kfree(desc); continue; -- cgit v1.2.3 From d5e3050c0feb8bf7b9a75482fafcc31b90257926 Mon Sep 17 00:00:00 2001 From: Marek Bykowski Date: Fri, 9 Sep 2022 02:33:57 +0000 Subject: of/fdt: Don't calculate initrd size from DT if start > end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the properties 'linux,initrd-start' and 'linux,initrd-end' of the chosen node populated from the bootloader, eg. U-Boot, are so that start > end, then the phys_initrd_size calculated from end - start is negative that subsequently gets converted to a high positive value for being unsigned long long. Then, the memory region with the (invalid) size is added to the bootmem and attempted being paged in paging_init() that results in the kernel fault. For example, on the FVP ARM64 system I'm running, the U-Boot populates the 'linux,initrd-start' with 8800_0000 and 'linux,initrd-end' with 0. The phys_initrd_size calculated is then ffff_ffff_7800_0000 (= 0 - 8800_0000 = -8800_0000 + ULLONG_MAX + 1). paging_init() then attempts to map the address 8800_0000 + ffff_ffff_7800_0000 and oops'es as below. It should be stressed, it is generally a fault of the bootloader's with the kernel relying on it, however we should not allow the bootloader's misconfiguration to lead to the kernel oops. Not only the kernel should be bullet proof against it but also finding the root cause of the paging fault spanning over the bootloader, DT, and kernel may happen is not so easy. Unable to handle kernel paging request at virtual address fffffffefe43c000 Mem abort info: ESR = 0x96000007 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000007 CM = 0, WnR = 0 swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080e3d000 [fffffffefe43c000] pgd=0000000080de9003, pud=0000000080de9003 Unable to handle kernel paging request at virtual address ffffff8000de9f90 Mem abort info: ESR = 0x96000005 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000005 CM = 0, WnR = 0 swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080e3d000 [ffffff8000de9f90] pgd=0000000000000000, pud=0000000000000000 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 5.4.51-yocto-standard #1 Hardware name: FVP Base (DT) pstate: 60000085 (nZCv daIf -PAN -UAO) pc : show_pte+0x12c/0x1b4 lr : show_pte+0x100/0x1b4 sp : ffffffc010ce3b30 x29: ffffffc010ce3b30 x28: ffffffc010ceed80 x27: fffffffefe43c000 x26: fffffffefe43a028 x25: 0000000080bf0000 x24: 0000000000000025 x23: ffffffc010b8d000 x22: ffffffc010e3d000 x23: ffffffc010b8d000 x22: ffffffc010e3d000 x21: 0000000080de9000 x20: ffffff7f80000f90 x19: fffffffefe43c000 x18: 0000000000000030 x17: 0000000000001400 x16: 0000000000001c00 x15: ffffffc010cef1b8 x14: ffffffffffffffff x13: ffffffc010df1f40 x12: ffffffc010df1b70 x11: ffffffc010ce3b30 x10: ffffffc010ce3b30 x9 : 00000000ffffffc8 x8 : 0000000000000000 x7 : 000000000000000f x6 : ffffffc010df16e8 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 00000000ffffffff x2 : 0000000000000000 x1 : 0000008080000000 x0 : ffffffc010af1d68 Call trace: show_pte+0x12c/0x1b4 die_kernel_fault+0x54/0x78 __do_kernel_fault+0x11c/0x128 do_translation_fault+0x58/0xac do_mem_abort+0x50/0xb0 el1_da+0x1c/0x90 __create_pgd_mapping+0x348/0x598 paging_init+0x3f0/0x70d0 setup_arch+0x2c0/0x5d4 start_kernel+0x94/0x49c Code: 92748eb5 900052a0 9135a000 cb010294 (f8756a96)  Signed-off-by: Marek Bykowski Link: https://lore.kernel.org/r/20220909023358.76881-1-marek.bykowski@gmail.com Signed-off-by: Rob Herring --- drivers/of/fdt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 1617a31ecd22..d1cbb4ad05c8 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -936,6 +936,8 @@ static void __init early_init_dt_check_for_initrd(unsigned long node) if (!prop) return; end = of_read_number(prop, len/4); + if (start > end) + return; __early_init_dt_declare_initrd(start, end); phys_initrd_start = start; -- cgit v1.2.3 From 17005609548f1f0204cbfc988b325533470e585c Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Tue, 27 Sep 2022 13:37:39 +0000 Subject: of: fdt: Remove unused struct fdt_scan_status After commit bba04d965d06("of/fdt: remove unused of_scan_flat_dt_by_path"), no one use struct fdt_scan_status, so remove it. Signed-off-by: Yuan Can Reviewed-by: Frank Rowand Link: https://lore.kernel.org/r/20220927133739.98493-1-yuancan@huawei.com Signed-off-by: Rob Herring --- drivers/of/fdt.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index d1cbb4ad05c8..53b250fcd2a9 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -828,15 +828,6 @@ uint32_t __init of_get_flat_dt_phandle(unsigned long node) return fdt_get_phandle(initial_boot_params, node); } -struct fdt_scan_status { - const char *name; - int namelen; - int depth; - int found; - int (*iterator)(unsigned long node, const char *uname, int depth, void *data); - void *data; -}; - const char * __init of_flat_dt_get_machine_name(void) { const char *name; -- cgit v1.2.3 From f1ad5338a4d57fe1fe6475003acb8c70bf9d1bdf Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 29 Sep 2022 13:48:38 +0100 Subject: of: Fix "dma-ranges" handling for bus controllers Commit 951d48855d86 ("of: Make of_dma_get_range() work on bus nodes") relaxed the handling of "dma-ranges" for any leaf node on the assumption that it would still represent a usage error for the property to be present on a non-bus leaf node. However there turns out to be a fiddly case where a bus also represents a DMA-capable device in its own right, such as a PCIe root complex with an integrated DMA engine on its platform side. In such cases, "dma-ranges" translation is entirely valid for devices discovered behind the bus, but should not be erroneously applied to the bus controller device itself which operates in its parent's address space. Fix this by restoring the previous behaviour for the specific case where a device is configured via its own OF node, since it is logical to assume that a device should never represent its own parent bus. Reported-by: Serge Semin Signed-off-by: Robin Murphy Link: https://lore.kernel.org/r/112e8f3d3e7c054ecf5e12b5ac0aa5596ec00681.1664455433.git.robin.murphy@arm.com Signed-off-by: Rob Herring --- drivers/of/address.c | 4 +++- drivers/of/device.c | 9 ++++++++- drivers/of/of_private.h | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/of/address.c b/drivers/of/address.c index 96f0a12e507c..c34ac33b7338 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -579,7 +579,8 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) } EXPORT_SYMBOL(of_translate_address); -static struct device_node *__of_get_dma_parent(const struct device_node *np) +#ifdef CONFIG_HAS_DMA +struct device_node *__of_get_dma_parent(const struct device_node *np) { struct of_phandle_args args; int ret, index; @@ -596,6 +597,7 @@ static struct device_node *__of_get_dma_parent(const struct device_node *np) return of_node_get(args.np); } +#endif static struct device_node *of_get_next_dma_parent(struct device_node *np) { diff --git a/drivers/of/device.c b/drivers/of/device.c index 75b6cbffa755..8cefe5a7d04e 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -116,12 +116,19 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, { const struct iommu_ops *iommu; const struct bus_dma_region *map = NULL; + struct device_node *bus_np; u64 dma_start = 0; u64 mask, end, size = 0; bool coherent; int ret; - ret = of_dma_get_range(np, &map); + if (np == dev->of_node) + bus_np = __of_get_dma_parent(np); + else + bus_np = of_node_get(np); + + ret = of_dma_get_range(bus_np, &map); + of_node_put(bus_np); if (ret < 0) { /* * For legacy reasons, we have to assume some devices need diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 9324483397f6..fb6792d381a6 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -155,12 +155,17 @@ struct bus_dma_region; #if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA) int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map); +struct device_node *__of_get_dma_parent(const struct device_node *np); #else static inline int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) { return -ENODEV; } +static inline struct device_node *__of_get_dma_parent(const struct device_node *np) +{ + return of_get_parent(np); +} #endif void fdt_init_reserved_mem(void); -- cgit v1.2.3 From 88269151be679b9accb2f1e73487eaeb9eae9e39 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 29 Sep 2022 17:32:49 -0700 Subject: of: base: make of_device_compatible_match() accept const device node of_device_is_compatible() accepts const device node pointer, there is no reason why of_device_compatible_match() can't do the same. Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/YzY5MaU5N4A2st5R@google.com Signed-off-by: Rob Herring --- drivers/of/base.c | 2 +- include/linux/of.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index 99cee6b02297..5e7c11ca1007 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -561,7 +561,7 @@ EXPORT_SYMBOL(of_device_is_compatible); * a NULL terminated array of strings. Returns the best match * score or 0. */ -int of_device_compatible_match(struct device_node *device, +int of_device_compatible_match(const struct device_node *device, const char *const *compat) { unsigned int tmp, score = 0; diff --git a/include/linux/of.h b/include/linux/of.h index 766d002bddb9..6b79ef9a6541 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -342,7 +342,7 @@ extern int of_property_read_string_helper(const struct device_node *np, const char **out_strs, size_t sz, int index); extern int of_device_is_compatible(const struct device_node *device, const char *); -extern int of_device_compatible_match(struct device_node *device, +extern int of_device_compatible_match(const struct device_node *device, const char *const *compat); extern bool of_device_is_available(const struct device_node *device); extern bool of_device_is_big_endian(const struct device_node *device); @@ -562,7 +562,7 @@ static inline int of_device_is_compatible(const struct device_node *device, return 0; } -static inline int of_device_compatible_match(struct device_node *device, +static inline int of_device_compatible_match(const struct device_node *device, const char *const *compat) { return 0; -- cgit v1.2.3 From 7a7f58575483a74db4cc2c1e37f21ddda057083d Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Fri, 30 Sep 2022 16:49:36 +0200 Subject: of: base: Shift refcount decrement in of_find_last_cache_level() Currently, of_find_next_cache_node() and of_property_read_u32() are called on objects after their refcount have been decremented. Re-order the calls to decrement the refcount after the function calls. Signed-off-by: Pierre Gondois Link: https://lore.kernel.org/r/20220930144936.2882481-1-pierre.gondois@arm.com Signed-off-by: Rob Herring --- drivers/of/base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index 5e7c11ca1007..209953c4f6c6 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2088,12 +2088,13 @@ int of_find_last_cache_level(unsigned int cpu) struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu); while (np) { + of_node_put(prev); prev = np; - of_node_put(np); np = of_find_next_cache_node(np); } of_property_read_u32(prev, "cache-level", &cache_level); + of_node_put(prev); return cache_level; } -- cgit v1.2.3