From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Mon, 24 Aug 2026 14:01:33 +0200 Received: from mx1.white.stw.pengutronix.de ([2a0a:edc0:0:b01:1d::107]) by lore.white.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wyTMq-006gp6-19 for lore@lore.pengutronix.de; Mon, 24 Aug 2026 14:01:33 +0200 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by mx1.white.stw.pengutronix.de (Postfix) with ESMTPS id EB9FD200062 for ; Mon, 24 Aug 2026 14:01:32 +0200 (CEST) Authentication-Results: mx1.white.stw.pengutronix.de; dkim=pass header.d=lists.infradead.org header.s=bombadil.20210309 header.b=Mqr9rh3D; dmarc=none; spf=pass (mx1.white.stw.pengutronix.de: domain of "barebox-bounces+lore=pengutronix.de@lists.infradead.org" designates 2607:7c80:54:3::133 as permitted sender) smtp.mailfrom="barebox-bounces+lore=pengutronix.de@lists.infradead.org" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Zar07Ml9BFhGv+fGsAWDQS3TtI4XJthDcoKVzTWT1mM=; b=Mqr9rh3DZnF/hWy6fMLUYgmCxl WG4kQ+vbyXUax0ymxWJtZlRZaiNxXc0Sdcp/MspR8dZ/sHS7L/8OofUJ/cHiMRdd6/Zw2XQvNWN4d OguXg84tEJNayGCl90kI4q0qk2CBvjhQFrv4paAUzCPNrJ5PYe9iUQIrgx5e7R2jfPXjlcxqEwJUz wwg10cME2RmrBnBgWRG8i1nLy0LEZGw/hSG0eadZE6hICh4uVuJTLrp5rABbcdKyqRe+3F3wEUd+u jYWe+SFHsPgafin6fMyszqb3WKtFZG/oIUsp6cbrFYa0nLSJiw0ZtrCF7EGoq2wgmO1p5xBHMMRGX M2N0G3sg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wyTLq-0000000GZ3t-3Huv; Mon, 24 Aug 2026 12:00:30 +0000 Received: from mx1.white.stw.pengutronix.de ([2a0a:edc0:0:b01:1d::107]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wyTLl-0000000GZ1D-0wLu for barebox@lists.infradead.org; Mon, 24 Aug 2026 12:00:28 +0000 Received: from drehscheibe.grey.stw.pengutronix.de (drehscheibe.grey.stw.pengutronix.de [IPv6:2a0a:edc0:0:c01:1d::a2]) (Authenticated sender: relay-from-drehscheibe.grey.stw.pengutronix.de) by mx1.white.stw.pengutronix.de (Postfix) with ESMTPSA id 94D44201CD0; Mon, 24 Aug 2026 14:00:23 +0200 (CEST) Received: from dude05.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::54]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wyTLj-00368b-1S; Mon, 24 Aug 2026 14:00:23 +0200 Received: from [::1] (helo=dude05.red.stw.pengutronix.de) by dude05.red.stw.pengutronix.de with esmtp (Exim 4.98.2) (envelope-from ) id 1wyTLj-0000000DyeC-1NXs; Mon, 24 Aug 2026 14:00:23 +0200 From: Ahmad Fatoum To: barebox@lists.infradead.org Cc: Ahmad Fatoum Subject: [PATCH master 4/4] of: fdt: bound node nesting depth in __of_unflatten_dtb Date: Mon, 24 Aug 2026 13:59:58 +0200 Message-ID: <20260824120022.3299742-4-a.fatoum@pengutronix.de> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260824120022.3299742-1-a.fatoum@pengutronix.de> References: <20260824120022.3299742-1-a.fatoum@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260824_050026_233336_DC1303BC X-CRM114-Status: GOOD ( 12.02 ) X-Spam-Score: -1.9 (-) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: 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 [...] Content analysis details: (-1.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 DMARC_MISSING Missing DMARC policy X-BeenThere: barebox@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "barebox" X-Rspamd-Action: no action X-Rspamd-Server: mx1 X-Stat-Signature: 8s6jdr6kn9q3ro91i7o1yfennnft5i5i X-Spamd-Result: default: False [-6.21 / 15.00]; BAYES_HAM(-3.00)[99.99%]; DWL_DNSWL_MED(-2.00)[infradead.org:dkim]; KNOWN_LIST_ID(-1.00)[barebox.lists.infradead.org]; MID_CONTAINS_FROM(1.00)[]; RCVD_DKIM_ARC_DNSWL_MED(-0.50)[]; R_MISSING_CHARSET(0.50)[]; RCVD_IN_DNSWL_MED(-0.40)[2a0a:edc0:0:1101:1d::54:received,2607:7c80:54:3::133:from]; R_SPF_ALLOW(-0.20)[+mx:c]; R_DKIM_ALLOW(-0.20)[lists.infradead.org:s=bombadil.20210309]; MAILLIST(-0.20)[mailman]; MIME_GOOD(-0.10)[text/plain]; RCVD_IN_DNSWL_LOW(-0.10)[2a0a:edc0:0:c01:1d::a2:received]; HAS_LIST_UNSUB(-0.01)[]; RCPT_COUNT_TWO(0.00)[2]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; TO_DN_SOME(0.00)[]; FROM_HAS_DN(0.00)[]; DMARC_NA(0.00)[pengutronix.de]; RECEIVED_HELO_LOCALHOST(0.00)[]; RCVD_TLS_LAST(0.00)[]; FROM_NEQ_ENVFROM(0.00)[a.fatoum@pengutronix.de,barebox-bounces@lists.infradead.org]; RCVD_VIA_SMTP_AUTH(0.00)[]; NEURAL_HAM(-0.00)[-1.000]; TAGGED_FROM(0.00)[lore=pengutronix.de]; ASN(0.00)[asn:7247, ipnet:2607:7c80:54::/48, country:US]; RCVD_COUNT_FIVE(0.00)[5]; DKIM_TRACE(0.00)[lists.infradead.org:+]; FORGED_SENDER_MAILLIST(0.00)[] X-Rspamd-Queue-Id: EB9FD200062 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 --- 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