From db3dbdfea1b8f38774419c5c2c14e4b81c48708d Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Sun, 14 Jun 2026 22:38:06 +0900 Subject: [PATCH 1/2] of: reserved_mem: prevent OOB when too many dynamic regions are defined On boot, fdt_scan_reserved_mem() saves each dynamically-placed /reserved-memory subnode into a local array of size MAX_RESERVED_REGIONS. If the device tree defines more than MAX_RESERVED_REGIONS dynamically-placed regions, fdt_scan_reserved_mem() writes past the end of the local array. Add a bounds check that logs an error and skips the excess regions, restoring the original behavior. Fixes: 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed") Signed-off-by: Sang-Heon Jeon Link: https://patch.msgid.link/20260614133807.2165124-2-ekffu200098@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/of/of_reserved_mem.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 82222bd45ac6..42e3e2d8a2b8 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -359,6 +359,7 @@ int __init fdt_scan_reserved_mem(void) err = __reserved_mem_reserve_reg(child, uname); if (!err) count++; + /* * Save the nodes for the dynamically-placed regions * into an array which will be used for allocation right @@ -366,10 +367,17 @@ int __init fdt_scan_reserved_mem(void) * or marked as no-map. This is done to avoid dynamically * allocating from one of the statically-placed regions. */ - if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) { - dynamic_nodes[dynamic_nodes_cnt] = child; - dynamic_nodes_cnt++; + if (err != -ENOENT || !of_get_flat_dt_prop(child, "size", NULL)) + continue; + + if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) { + pr_err("too many defined dynamic regions, skip '%s'\n", + uname); + continue; } + + dynamic_nodes[dynamic_nodes_cnt] = child; + dynamic_nodes_cnt++; } for (int i = 0; i < dynamic_nodes_cnt; i++) { const char *uname; From bba13ad17b1a11b3f1ed9b3a5d556191d7755a59 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Mon, 27 Jul 2026 10:36:59 +0200 Subject: [PATCH 2/2] of/address: Fix NULL bus dereference in of_pci_range_parser_one() The bus matching rework made of_match_bus() return NULL for nodes with ranges/dma-ranges but no local #address-cells. parser_init() stored that NULL bus, and the range iterator later dereferenced it. Reject such nodes in parser_init(), leaving an explicit empty iterator for callers that ignore the init return, and make of_dma_get_max_cpu_address() honour the init failure so a rejected node cannot clamp the DMA limit. Fixes: 64ee3cf096ac ("of/address: Rework bus matching to avoid warnings") Cc: stable@vger.kernel.org Signed-off-by: Carlo Caione Link: https://patch.msgid.link/20260727-of-range-parser-null-bus-v3-1-be01b708a4ce@baylibre.com Signed-off-by: Rob Herring (Arm) --- drivers/of/address.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index cf4aab11e9b1..499d37ceae21 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -753,6 +753,7 @@ EXPORT_SYMBOL(of_property_read_reg); static int parser_init(struct of_pci_range_parser *parser, struct device_node *node, const char *name) { + const __be32 *range; int rlen; parser->node = node; @@ -761,12 +762,20 @@ static int parser_init(struct of_pci_range_parser *parser, parser->ns = of_bus_n_size_cells(node); parser->dma = !strcmp(name, "dma-ranges"); parser->bus = of_match_bus(node); + parser->range = NULL; + parser->end = NULL; - parser->range = of_get_property(node, name, &rlen); - if (parser->range == NULL) + range = of_get_property(node, name, &rlen); + if (!range) return -ENOENT; - parser->end = parser->range + rlen / sizeof(__be32); + if (!parser->bus || + !OF_CHECK_COUNTS(parser->na, parser->ns) || + !OF_CHECK_ADDR_COUNT(parser->pna)) + return -EINVAL; + + parser->range = range; + parser->end = range + rlen / sizeof(__be32); return 0; } @@ -792,7 +801,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, int na = parser->na; int ns = parser->ns; int np = parser->pna + na + ns; - int busflag_na = parser->bus->flag_cells; + int busflag_na; if (!range) return NULL; @@ -800,6 +809,8 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, if (!parser->range || parser->range + np > parser->end) return NULL; + busflag_na = parser->bus->flag_cells; + range->flags = parser->bus->get_flags(parser->range); range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); @@ -976,8 +987,7 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np) np = of_root; ranges = of_get_property(np, "dma-ranges", &len); - if (ranges && len) { - of_dma_range_parser_init(&parser, np); + if (ranges && len && !of_dma_range_parser_init(&parser, np)) { for_each_of_range(&parser, &range) if (range.cpu_addr + range.size > cpu_end) cpu_end = range.cpu_addr + range.size - 1;