of_new_node() builds each node's full_name by concatenating the parent's full path, so unflattening a chain of N nested nodes costs O(N^2) time and memory. A crafted FIT/DTB with hundreds of thousands of nested nodes (e.g. the BRLY-2026-042 U-Boot PoC, 500k deep) therefore drives barebox into multi-gigabyte allocations and minutes of CPU before failing, a denial of service, even though the iterative walk here never overflows the stack.
Reject blobs nested deeper than FDT_MAX_DEPTH (64, as Linux's own drivers/of/fdt.c uses) by tracking depth across FDT_BEGIN_NODE/FDT_END_NODE. Real device trees are only a handful of levels deep, so the limit is generous for legitimate input while cutting the pathological case off early. Assisted-by: Claude:fable-5 Signed-off-by: Ahmad Fatoum <[email protected]> --- drivers/of/fdt.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 1648f4c2d945..b5b64cd06b8d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -173,6 +173,12 @@ static int fdt_parse_header(const struct fdt_header *fdt, size_t fdt_size, return 0; } +/* + * Maximum node nesting depth we are willing to unflatten. + * Matches the limit Linux uses in its own drivers/of/fdt.c. + */ +#define FDT_MAX_DEPTH 64 + /** * of_unflatten_dtb - unflatten a dtb binary blob * @infdt - the fdt blob to unflatten @@ -196,6 +202,7 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size, struct fdt_header f; int ret; int maxlen; + unsigned int depth = 0; const struct fdt_header *fdt = infdt; ret = fdt_parse_header(infdt, size, &f); @@ -247,6 +254,12 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size, goto err; } + if (++depth > FDT_MAX_DEPTH) { + pr_err("unflatten: node nesting too deep\n"); + ret = -EINVAL; + goto err; + } + if (!node) { /* The root node must have an empty name */ if (*pathp) { @@ -272,6 +285,7 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size, goto err; } + depth--; node = node->parent; dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE, 0); -- 2.47.3
