From: Simon Glass Date: Tue, 16 Feb 2021 00:08:11 +0000 (-0700) Subject: [PATCH] libfdt: Check for multiple/invalid root nodes X-Git-Tag: archive/raspbian/2021.01+dfsg-5+rpi1+deb11u2^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4cb4b9fea3e1824643542a4ffea9e29524dd7fb7;p=u-boot.git [PATCH] libfdt: Check for multiple/invalid root nodes It is possible to construct a devicetree blob with multiple root nodes. Update fdt_check_full() to check for this, along with a root node with an invalid name. CVE-2021-27097 Signed-off-by: Simon Glass Reported-by: Bruce Monroe Reported-by: Arie Haenel Reported-by: Julien Lenoir The test part has not been patched. It would require these patches as well: https://github.com/u-boot/u-boot/commit/fafafacb470b345f2f41b86e4633ef91a7c5ed23 https://github.com/u-boot/u-boot/commit/d5f3aadacbc63df3b690d6fd9f0aa3f575b43356 Reviewed-By: Daniel Leidert Origin: https://github.com/u-boot/u-boot/commit/124c255731c76a2b09587378b2bcce561bcd3f2d Bug: https://github.com/advisories/GHSA-3w66-96j7-fmcp Bug-Debian: https://bugs.debian.org/983270 Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-27097 Bug-Freexian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2021-27097 Gbp-Pq: Name CVE-2021-27097-4.patch --- diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index d984bab03..efe7efe92 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -867,6 +867,7 @@ int fdt_check_full(const void *fdt, size_t bufsize) unsigned depth = 0; const void *prop; const char *propname; + bool expect_end = false; if (bufsize < FDT_V1_SIZE) return -FDT_ERR_TRUNCATED; @@ -887,6 +888,10 @@ int fdt_check_full(const void *fdt, size_t bufsize) if (nextoffset < 0) return nextoffset; + /* If we see two root nodes, something is wrong */ + if (expect_end && tag != FDT_END) + return -FDT_ERR_BADLAYOUT; + switch (tag) { case FDT_NOP: break; @@ -900,12 +905,24 @@ int fdt_check_full(const void *fdt, size_t bufsize) depth++; if (depth > INT_MAX) return -FDT_ERR_BADSTRUCTURE; + + /* The root node must have an empty name */ + if (depth == 1) { + const char *name; + int len; + + name = fdt_get_name(fdt, offset, &len); + if (*name || len) + return -FDT_ERR_BADLAYOUT; + } break; case FDT_END_NODE: if (depth == 0) return -FDT_ERR_BADSTRUCTURE; depth--; + if (depth == 0) + expect_end = true; break; case FDT_PROP: