summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch
blob: deb40a9387b835e73bed294a244f73fcdd8f03ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
From 8c6e79df48988760178787af39ecd01954569e81 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Mon, 15 Feb 2021 17:08:09 -0700
Subject: [PATCH] image: Adjust the workings of fit_check_format()

At present this function does not accept a size for the FIT. This means
that it must be read from the FIT itself, introducing potential security
risk. Update the function to include a size parameter, which can be
invalid, in which case fit_check_format() calculates it.

For now no callers pass the size, but this can be updated later.

Also adjust the return value to an error code so that all the different
types of problems can be distinguished by the user.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: Bruce Monroe <bruce.monroe@intel.com>
Reported-by: Arie Haenel <arie.haenel@intel.com>
Reported-by: Julien Lenoir <julien.lenoir@intel.com>
---
 board/aspeed/ast-g5/fw-update.c |  2 +-
 cmd/bootm.c                     |  6 ++---
 cmd/disk.c                      |  2 +-
 cmd/fdc.c                       |  2 +-
 cmd/fpga.c                      |  2 +-
 cmd/nand.c                      |  2 +-
 cmd/source.c                    |  2 +-
 cmd/ximg.c                      |  2 +-
 common/image-fdt.c              |  2 +-
 common/image-fit.c              | 44 ++++++++++++++++-----------------
 common/update.c                 |  2 +-
 drivers/misc/fsl_debug_server.c |  2 +-
 drivers/net/fsl-mc/mc.c         |  2 +-
 include/image.h                 | 21 +++++++++++++++-
 tools/fit_image.c               |  2 +-
 tools/mkimage.h                 |  2 ++
 16 files changed, 59 insertions(+), 38 deletions(-)

diff --git a/board/aspeed/ast-g5/fw-update.c b/board/aspeed/ast-g5/fw-update.c
index 99239938b5ee..50b46a2eff5a 100644
--- a/board/aspeed/ast-g5/fw-update.c
+++ b/board/aspeed/ast-g5/fw-update.c
@@ -328,7 +328,7 @@ static int verify_image(void)
 	switch (genimg_get_format(hdr)) {
 	case IMAGE_FORMAT_FIT:
 		printf("   FIT image found\n");
-		if (!fit_check_format(hdr)) {
+		if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
 			printf("Bad FIT image format!\n");
 			return -1;
 		}
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 8da750ec5101..442ae0ba600e 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -288,7 +288,7 @@ static int image_info(ulong addr)
 	case IMAGE_FORMAT_FIT:
 		puts("   FIT image found\n");
 
-		if (!fit_check_format(hdr)) {
+		if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
 			puts("Bad FIT image format!\n");
 			return 1;
 		}
@@ -361,7 +361,7 @@ static int do_imls_nor(void)
 #endif
 #if defined(CONFIG_FIT)
 			case IMAGE_FORMAT_FIT:
-				if (!fit_check_format(hdr))
+				if (fit_check_format(hdr, IMAGE_SIZE_INVAL))
 					goto next_sector;
 
 				printf("FIT Image at %08lX:\n", (ulong)hdr);
@@ -441,7 +441,7 @@ static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
 		return ret;
 	}
 
-	if (!fit_check_format(imgdata)) {
+	if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) {
 		free(imgdata);
 		return 0;
 	}
diff --git a/cmd/disk.c b/cmd/disk.c
index 92de3af8a5c0..3038aacf2215 100644
--- a/cmd/disk.c
+++ b/cmd/disk.c
@@ -113,7 +113,7 @@ int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
 	/* This cannot be done earlier,
 	 * we need complete FIT image in RAM first */
 	if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
-		if (!fit_check_format(fit_hdr)) {
+		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 			bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
 			puts("** Bad FIT image format\n");
 			return 1;
diff --git a/cmd/fdc.c b/cmd/fdc.c
index d2281abbda90..7395e61fcdae 100644
--- a/cmd/fdc.c
+++ b/cmd/fdc.c
@@ -731,7 +731,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #if defined(CONFIG_FIT)
 	/* This cannot be done earlier, we need complete FIT image in RAM first */
 	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
-		if (!fit_check_format (fit_hdr)) {
+		if (fit_check_format (fit_hdr, IMAGE_SIZE_INVAL)) {
 			puts ("** Bad FIT image format\n");
 			return 1;
 		}
diff --git a/cmd/fpga.c b/cmd/fpga.c
index 8956eb1b654a..ecb26d77c1cc 100644
--- a/cmd/fpga.c
+++ b/cmd/fpga.c
@@ -248,7 +248,7 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 					return 1;
 				}
 
-				if (!fit_check_format(fit_hdr)) {
+				if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 					puts("Bad FIT image format\n");
 					return 1;
 				}
diff --git a/cmd/nand.c b/cmd/nand.c
index ffdeea41a5a7..2b1c931bd937 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -902,7 +902,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
 #if defined(CONFIG_FIT)
 	/* This cannot be done earlier, we need complete FIT image in RAM first */
 	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
-		if (!fit_check_format (fit_hdr)) {
+		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 			bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
 			puts ("** Bad FIT image format\n");
 			return 1;
diff --git a/cmd/source.c b/cmd/source.c
index db7ab7e5f409..300db33b73cd 100644
--- a/cmd/source.c
+++ b/cmd/source.c
@@ -97,7 +97,7 @@ source (ulong addr, const char *fit_uname)
 		}
 
 		fit_hdr = buf;
-		if (!fit_check_format (fit_hdr)) {
+		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 			puts ("Bad FIT image format\n");
 			return 1;
 		}
diff --git a/cmd/ximg.c b/cmd/ximg.c
index d033c15b629c..0e26e747f25d 100644
--- a/cmd/ximg.c
+++ b/cmd/ximg.c
@@ -132,7 +132,7 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 			"at %08lx ...\n", uname, addr);
 
 		fit_hdr = (const void *)addr;
-		if (!fit_check_format(fit_hdr)) {
+		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 			puts("Bad FIT image format\n");
 			return 1;
 		}
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 6cac7dbb7f8b..9b372577dafc 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -353,7 +353,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
 			 */
 #if CONFIG_IS_ENABLED(FIT)
 			/* check FDT blob vs FIT blob */
-			if (fit_check_format(buf)) {
+			if (!fit_check_format(buf, IMAGE_SIZE_INVAL)) {
 				ulong load, len;
 
 				fdt_noffset = fit_image_load(images,
diff --git a/common/image-fit.c b/common/image-fit.c
index 322fde728b50..34bbc8645205 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -9,6 +9,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#define LOG_CATEGORY LOGC_BOOT
+
 #ifdef USE_HOSTCC
 #include "mkimage.h"
 #include <image.h>
@@ -1212,40 +1214,38 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
 	return (comp == image_comp);
 }
 
-/**
- * fit_check_format - sanity check FIT image format
- * @fit: pointer to the FIT format image header
- *
- * fit_check_format() runs a basic sanity FIT image verification.
- * Routine checks for mandatory properties, nodes, etc.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-int fit_check_format(const void *fit)
+int fit_check_format(const void *fit, ulong size)
 {
+	int ret;
+
+	ret = fdt_check_header(fit);
+	if (ret) {
+		log_debug("Wrong FIT format: not a flattened device tree (err=%d)\n",
+			  ret);
+		return -ENOEXEC;
+	}
+
 	/* mandatory / node 'description' property */
-	if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
-		debug("Wrong FIT format: no description\n");
-		return 0;
+	if (!fdt_getprop(fit, 0, FIT_DESC_PROP, NULL)) {
+		log_debug("Wrong FIT format: no description\n");
+		return -ENOMSG;
 	}
 
 	if (IMAGE_ENABLE_TIMESTAMP) {
 		/* mandatory / node 'timestamp' property */
-		if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
-			debug("Wrong FIT format: no timestamp\n");
-			return 0;
+		if (!fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL)) {
+			log_debug("Wrong FIT format: no timestamp\n");
+			return -ENODATA;
 		}
 	}
 
 	/* mandatory subimages parent '/images' node */
 	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
-		debug("Wrong FIT format: no images parent node\n");
-		return 0;
+		log_debug("Wrong FIT format: no images parent node\n");
+		return -ENOENT;
 	}
 
-	return 1;
+	return 0;
 }
 
 
@@ -1585,7 +1585,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 	printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
-	if (!fit_check_format(fit)) {
+	if (fit_check_format(fit, IMAGE_SIZE_INVAL)) {
 		printf("Bad FIT %s image format!\n", prop_name);
 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
 		return -ENOEXEC;
diff --git a/common/update.c b/common/update.c
index 1da80b70f2db..521772c3645b 100644
--- a/common/update.c
+++ b/common/update.c
@@ -279,7 +279,7 @@ int update_tftp(ulong addr, char *interface, char *devstring)
 got_update_file:
 	fit = (void *)addr;
 
-	if (!fit_check_format((void *)fit)) {
+	if (fit_check_format((void *)fit, IMAGE_SIZE_INVAL)) {
 		printf("Bad FIT format of the update file, aborting "
 							"auto-update\n");
 		return 1;
diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c
index 98d9fbe534c3..25713316a1f5 100644
--- a/drivers/misc/fsl_debug_server.c
+++ b/drivers/misc/fsl_debug_server.c
@@ -63,7 +63,7 @@ int debug_server_parse_firmware_fit_image(const void **raw_image_addr,
 		goto out_error;
 	}
 
-	if (!fit_check_format(fit_hdr)) {
+	if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 		printf("Debug Server FW: Bad FIT image format\n");
 		goto out_error;
 	}
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 1811b0fe1a3f..243563eac400 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -124,7 +124,7 @@ int parse_mc_firmware_fit_image(u64 mc_fw_addr,
 		return -EINVAL;
 	}
 
-	if (!fit_check_format(fit_hdr)) {
+	if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 		printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n");
 		return -EINVAL;
 	}
diff --git a/include/image.h b/include/image.h
index 2c6ef4de259d..130dc03bfb3c 100644
--- a/include/image.h
+++ b/include/image.h
@@ -384,6 +384,9 @@ extern bootm_headers_t images;
 #define uimage_to_cpu(x)		be32_to_cpu(x)
 #define cpu_to_uimage(x)		cpu_to_be32(x)
 
+/* An invalid size, meaning that the image size is not known */
+#define IMAGE_SIZE_INVAL	(-1UL)
+
 /*
  * Translation table for entries of a specific type; used by
  * get_table_entry_id() and get_table_entry_name().
@@ -907,7 +910,23 @@ int fit_image_check_os(const void *fit, int noffset, uint8_t os);
 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch);
 int fit_image_check_type(const void *fit, int noffset, uint8_t type);
 int fit_image_check_comp(const void *fit, int noffset, uint8_t comp);
-int fit_check_format(const void *fit);
+
+/**
+ * fit_check_format() - Check that the FIT is valid
+ *
+ * This performs various checks on the FIT to make sure it is suitable for
+ * use, looking for mandatory properties, nodes, etc.
+ *
+ * If FIT_FULL_CHECK is enabled, it also runs it through libfdt to make
+ * sure that there are no strange tags or broken nodes in the FIT.
+ *
+ * @fit: pointer to the FIT format image header
+ * @return 0 if OK, -ENOEXEC if not an FDT file, -EINVAL if the full FDT check
+ *	failed (e.g. due to bad structure), -ENOMSG if the description is
+ *	missing, -ENODATA if the timestamp is missing, -ENOENT if the /images
+ *	path is missing
+ */
+int fit_check_format(const void *fit, ulong size);
 
 int fit_conf_find_compat(const void *fit, const void *fdt);
 
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 58aa8e27db3e..6960cc74d23f 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -721,7 +721,7 @@ static int fit_extract_contents(void *ptr, struct image_tool_params *params)
 	/* Indent string is defined in header image.h */
 	p = IMAGE_INDENT_STRING;
 
-	if (!fit_check_format(fit)) {
+	if (fit_check_format(fit, IMAGE_SIZE_INVAL)) {
 		printf("Bad FIT image format\n");
 		return -1;
 	}
diff --git a/tools/mkimage.h b/tools/mkimage.h
index 3f369b748ed1..3c6c680218a2 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -30,6 +30,8 @@
 #define debug(fmt,args...)
 #endif /* MKIMAGE_DEBUG */
 
+#define log_debug(fmt, args...)	debug(fmt, ##args)
+
 static inline void *map_sysmem(ulong paddr, unsigned long len)
 {
 	return (void *)(uintptr_t)paddr;
-- 
2.17.1