diff options
Diffstat (limited to 'meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch')
-rw-r--r-- | meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch new file mode 100644 index 000000000..deb40a938 --- /dev/null +++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch @@ -0,0 +1,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 + |