blob: 060cac1cf66aac72fec5170948e374b670160fb6 [file] [log] [blame]
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001From 124c255731c76a2b09587378b2bcce561bcd3f2d Mon Sep 17 00:00:00 2001
2From: Simon Glass <sjg@chromium.org>
3Date: Mon, 15 Feb 2021 17:08:11 -0700
4Subject: [PATCH] libfdt: Check for multiple/invalid root nodes
5
6It is possible to construct a devicetree blob with multiple root nodes.
7Update fdt_check_full() to check for this, along with a root node with an
8invalid name.
9
10CVE-2021-27097
11
12Signed-off-by: Simon Glass <sjg@chromium.org>
13Reported-by: Bruce Monroe <bruce.monroe@intel.com>
14Reported-by: Arie Haenel <arie.haenel@intel.com>
15Reported-by: Julien Lenoir <julien.lenoir@intel.com>
16
17CVE: CVE-2021-27097
18Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/124c255731c76a2b09587378b2bcce561bcd3f2d]
19Signed-off-by: Scott Murray <scott.murray@konsulko.com>
20
21---
22 scripts/dtc/libfdt/fdt_ro.c | 17 +++++++++++++++++
23 test/py/tests/test_vboot.py | 3 ++-
24 2 files changed, 19 insertions(+), 1 deletion(-)
25
26diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
27index d984bab036..efe7efe921 100644
28--- a/scripts/dtc/libfdt/fdt_ro.c
29+++ b/scripts/dtc/libfdt/fdt_ro.c
30@@ -867,6 +867,7 @@ int fdt_check_full(const void *fdt, size_t bufsize)
31 unsigned depth = 0;
32 const void *prop;
33 const char *propname;
34+ bool expect_end = false;
35
36 if (bufsize < FDT_V1_SIZE)
37 return -FDT_ERR_TRUNCATED;
38@@ -887,6 +888,10 @@ int fdt_check_full(const void *fdt, size_t bufsize)
39 if (nextoffset < 0)
40 return nextoffset;
41
42+ /* If we see two root nodes, something is wrong */
43+ if (expect_end && tag != FDT_END)
44+ return -FDT_ERR_BADLAYOUT;
45+
46 switch (tag) {
47 case FDT_NOP:
48 break;
49@@ -900,12 +905,24 @@ int fdt_check_full(const void *fdt, size_t bufsize)
50 depth++;
51 if (depth > INT_MAX)
52 return -FDT_ERR_BADSTRUCTURE;
53+
54+ /* The root node must have an empty name */
55+ if (depth == 1) {
56+ const char *name;
57+ int len;
58+
59+ name = fdt_get_name(fdt, offset, &len);
60+ if (*name || len)
61+ return -FDT_ERR_BADLAYOUT;
62+ }
63 break;
64
65 case FDT_END_NODE:
66 if (depth == 0)
67 return -FDT_ERR_BADSTRUCTURE;
68 depth--;
69+ if (depth == 0)
70+ expect_end = true;
71 break;
72
73 case FDT_PROP: