| Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame^] | 1 | From 124c255731c76a2b09587378b2bcce561bcd3f2d Mon Sep 17 00:00:00 2001 | 
|  | 2 | From: Simon Glass <sjg@chromium.org> | 
|  | 3 | Date: Mon, 15 Feb 2021 17:08:11 -0700 | 
|  | 4 | Subject: [PATCH] libfdt: Check for multiple/invalid root nodes | 
|  | 5 |  | 
|  | 6 | It is possible to construct a devicetree blob with multiple root nodes. | 
|  | 7 | Update fdt_check_full() to check for this, along with a root node with an | 
|  | 8 | invalid name. | 
|  | 9 |  | 
|  | 10 | CVE-2021-27097 | 
|  | 11 |  | 
|  | 12 | Signed-off-by: Simon Glass <sjg@chromium.org> | 
|  | 13 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | 
|  | 14 | Reported-by: Arie Haenel <arie.haenel@intel.com> | 
|  | 15 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | 
|  | 16 |  | 
|  | 17 | CVE: CVE-2021-27097 | 
|  | 18 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/124c255731c76a2b09587378b2bcce561bcd3f2d] | 
|  | 19 | Signed-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 |  | 
|  | 26 | diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c | 
|  | 27 | index 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: |