blob: 946196c3785bfb4a3561df6afd1ff22862f5ef5c [file] [log] [blame]
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001From 3f04db891a353f4b127ed57279279f851c6b4917 Mon Sep 17 00:00:00 2001
2From: Simon Glass <sjg@chromium.org>
3Date: Mon, 15 Feb 2021 17:08:12 -0700
4Subject: [PATCH] image: Check for unit addresses in FITs
5
6Using unit addresses in a FIT is a security risk. Add a check for this
7and disallow it.
8
9CVE-2021-27138
10
11Signed-off-by: Simon Glass <sjg@chromium.org>
12Reported-by: Bruce Monroe <bruce.monroe@intel.com>
13Reported-by: Arie Haenel <arie.haenel@intel.com>
14Reported-by: Julien Lenoir <julien.lenoir@intel.com>
15
16CVE: CVE-2021-27138
17Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/3f04db891a353f4b127ed57279279f851c6b4917]
18Signed-off-by: Scott Murray <scott.murray@konsulko.com>
19
20---
21 common/image-fit.c | 56 +++++++++++++++++++++++++++++++++++++++++----
22 test/py/tests/test_vboot.py | 9 ++++----
23 2 files changed, 57 insertions(+), 8 deletions(-)
24
25diff --git a/common/image-fit.c b/common/image-fit.c
26index bcf395f6a1..28b3d2b191 100644
27--- a/common/image-fit.c
28+++ b/common/image-fit.c
29@@ -1568,6 +1568,34 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
30 return (comp == image_comp);
31 }
32
33+/**
34+ * fdt_check_no_at() - Check for nodes whose names contain '@'
35+ *
36+ * This checks the parent node and all subnodes recursively
37+ *
38+ * @fit: FIT to check
39+ * @parent: Parent node to check
40+ * @return 0 if OK, -EADDRNOTAVAIL is a node has a name containing '@'
41+ */
42+static int fdt_check_no_at(const void *fit, int parent)
43+{
44+ const char *name;
45+ int node;
46+ int ret;
47+
48+ name = fdt_get_name(fit, parent, NULL);
49+ if (!name || strchr(name, '@'))
50+ return -EADDRNOTAVAIL;
51+
52+ fdt_for_each_subnode(node, fit, parent) {
53+ ret = fdt_check_no_at(fit, node);
54+ if (ret)
55+ return ret;
56+ }
57+
58+ return 0;
59+}
60+
61 int fit_check_format(const void *fit, ulong size)
62 {
63 int ret;
64@@ -1589,10 +1617,27 @@ int fit_check_format(const void *fit, ulong size)
65 if (size == IMAGE_SIZE_INVAL)
66 size = fdt_totalsize(fit);
67 ret = fdt_check_full(fit, size);
68+ if (ret)
69+ ret = -EINVAL;
70+
71+ /*
72+ * U-Boot stopped using unit addressed in 2017. Since libfdt
73+ * can match nodes ignoring any unit address, signature
74+ * verification can see the wrong node if one is inserted with
75+ * the same name as a valid node but with a unit address
76+ * attached. Protect against this by disallowing unit addresses.
77+ */
78+ if (!ret && CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
79+ ret = fdt_check_no_at(fit, 0);
80
81+ if (ret) {
82+ log_debug("FIT check error %d\n", ret);
83+ return ret;
84+ }
85+ }
86 if (ret) {
87 log_debug("FIT check error %d\n", ret);
88- return -EINVAL;
89+ return ret;
90 }
91 }
92
93@@ -1955,10 +2000,13 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
94 printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
95
96 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
97- if (fit_check_format(fit, IMAGE_SIZE_INVAL)) {
98- printf("Bad FIT %s image format!\n", prop_name);
99+ ret = fit_check_format(fit, IMAGE_SIZE_INVAL);
100+ if (ret) {
101+ printf("Bad FIT %s image format! (err=%d)\n", prop_name, ret);
102+ if (CONFIG_IS_ENABLED(FIT_SIGNATURE) && ret == -EADDRNOTAVAIL)
103+ printf("Signature checking prevents use of unit addresses (@) in nodes\n");
104 bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
105- return -ENOEXEC;
106+ return ret;
107 }
108 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
109 if (fit_uname) {