From 3b717f57dca508f546303dd34067b7b906ba459e Mon Sep 17 00:00:00 2001 From: Dmytro Prokopchuk1 Date: Fri, 26 Jun 2026 07:57:33 +0000 Subject: [PATCH] bootfdt: Fix infinite loop in device_tree_for_each_node() When a node's depth exceeds DEVICE_TREE_MAX_DEPTH inside the device_tree_for_each_node() loop, the code prints a warning and executes 'continue;' statement, which jumps to condition check, bypassing the iterator update step: node = fdt_next_node(fdt, node, &depth). The node and depth are not updated, the loop repeatedly evaluates the same too-deep node, causing a hang. Fix this by wrapping the node processing logic in an 'else' block. This ensures the loop update step is executed on every iteration, safely skipping deeply nested nodes and doing the traversal. Fixes: 40f2ea3df2e2 ("xen/arm: pass node to device_tree_for_each_node") Signed-off-by: Dmytro Prokopchuk Reviewed-by: Michal Orzel Release-Acked-by: Oleskii Kurochko --- xen/common/device-tree/bootfdt.c | 35 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/xen/common/device-tree/bootfdt.c b/xen/common/device-tree/bootfdt.c index 7c790b9a4d..8e9b45d1a7 100644 --- a/xen/common/device-tree/bootfdt.c +++ b/xen/common/device-tree/bootfdt.c @@ -90,23 +90,28 @@ int __init device_tree_for_each_node(const void *fdt, int node, { printk("Warning: device tree node `%s' is nested too deep\n", name); - continue; } - - as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT; - ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT; - - address_cells[depth] = device_tree_get_u32(fdt, node, - "#address-cells", as); - size_cells[depth] = device_tree_get_u32(fdt, node, - "#size-cells", ss); - - /* skip the first node */ - if ( node != first_node ) + else { - ret = func(fdt, node, name, depth, as, ss, data); - if ( ret != 0 ) - return ret; + as = depth > 0 ? + address_cells[depth - 1] : + DT_ROOT_NODE_ADDR_CELLS_DEFAULT; + ss = depth > 0 ? + size_cells[depth - 1] : + DT_ROOT_NODE_SIZE_CELLS_DEFAULT; + + address_cells[depth] = device_tree_get_u32(fdt, node, + "#address-cells", as); + size_cells[depth] = device_tree_get_u32(fdt, node, + "#size-cells", ss); + + /* skip the first node */ + if ( node != first_node ) + { + ret = func(fdt, node, name, depth, as, ss, data); + if ( ret != 0 ) + return ret; + } } node = fdt_next_node(fdt, node, &depth);