diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2021-09-10 01:41:26 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2021-09-10 19:47:19 +0300 |
commit | d9a15a908f3fc807f0c5cd3473d28b6a16435127 (patch) | |
tree | 4eb8ac79d9d8eb25ccbabafab87f465c4e21eb11 /meta-openbmc-mods/meta-ast2500 | |
parent | e0d055002bb720caca90e84acc4c13aa29135cae (diff) | |
download | openbmc-d9a15a908f3fc807f0c5cd3473d28b6a16435127.tar.xz |
Update to internal 1.01-42
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-ast2500')
8 files changed, 955 insertions, 2 deletions
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch index 79d7ec60d..838dfde9e 100644 --- a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch +++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch @@ -133,7 +133,7 @@ index 99239938b5..89fe5fd4fd 100644 - 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/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 + diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0002-image-Add-an-option-to-do-a-full-check-of-the-FIT.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0002-image-Add-an-option-to-do-a-full-check-of-the-FIT.patch new file mode 100644 index 000000000..d82767ee9 --- /dev/null +++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27097/0002-image-Add-an-option-to-do-a-full-check-of-the-FIT.patch @@ -0,0 +1,198 @@ +From df6bfa8d2d429addea3dfd9d1bfb3933b4adb7e7 Mon Sep 17 00:00:00 2001 +From: Simon Glass <sjg@chromium.org> +Date: Mon, 15 Feb 2021 17:08:10 -0700 +Subject: [PATCH] image: Add an option to do a full check of the FIT + +Some strange modifications of the FIT can introduce security risks. Add an +option to check it thoroughly, using libfdt's fdt_check_full() function. + +Enable this by default if signature verification is enabled. + +CVE-2021-27097 + +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> +--- + Kconfig | 19 +++++++++++++ + common/image-fit.c | 19 +++++++++++++ + include/libfdt.h | 1 + + lib/libfdt/fdt_ro.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 104 insertions(+) + +diff --git a/Kconfig b/Kconfig +index d6439d01ca60..1c1267fee079 100644 +--- a/Kconfig ++++ b/Kconfig +@@ -222,11 +222,21 @@ config FIT_VERBOSE + bool "Display verbose messages on FIT boot" + depends on FIT + ++config FIT_FULL_CHECK ++ bool "Do a full check of the FIT before using it" ++ default y ++ help ++ Enable this do a full check of the FIT to make sure it is valid. This ++ helps to protect against carefully crafted FITs which take advantage ++ of bugs or omissions in the code. This includes a bad structure, ++ multiple root nodes and the like. ++ + config FIT_SIGNATURE + bool "Enable signature verification of FIT uImages" + depends on FIT + depends on DM + select RSA ++ select FIT_FULL_CHECK + help + This option enables signature verification of FIT uImages, + using a hash signed and verified using RSA. If +@@ -240,11 +250,20 @@ config FIT_SIGNATURE + format support in this case, enable it using + CONFIG_IMAGE_FORMAT_LEGACY. + ++config SPL_FIT_FULL_CHECK ++ bool "Do a full check of the FIT before using it" ++ help ++ Enable this do a full check of the FIT to make sure it is valid. This ++ helps to protect against carefully crafted FITs which take advantage ++ of bugs or omissions in the code. This includes a bad structure, ++ multiple root nodes and the like. ++ + config SPL_FIT_SIGNATURE + bool "Enable signature verification of FIT firmware within SPL" + depends on SPL_FIT + depends on SPL_DM + select SPL_RSA ++ select SPL_FIT_FULL_CHECK + + config FIT_BEST_MATCH + bool "Select the best match for the kernel device tree" +diff --git a/common/image-fit.c b/common/image-fit.c +index 34bbc8645205..78db32e89f6f 100644 +--- a/common/image-fit.c ++++ b/common/image-fit.c +@@ -24,11 +24,14 @@ DECLARE_GLOBAL_DATA_PTR; + #endif /* !USE_HOSTCC*/ + + #include <bootstage.h> ++#include <linux/kconfig.h> + #include <u-boot/crc.h> + #include <u-boot/md5.h> + #include <u-boot/sha1.h> + #include <u-boot/sha256.h> + ++#define log_debug(fmt, args...) debug(fmt, ##args) ++ + /*****************************************************************************/ + /* New uImage format routines */ + /*****************************************************************************/ +@@ -1239,6 +1242,22 @@ int fit_check_format(const void *fit, ulong size) + } + } + ++ if (CONFIG_IS_ENABLED(FIT_FULL_CHECK)) { ++ /* ++ * If we are not given the size, make do wtih calculating it. ++ * This is not as secure, so we should consider a flag to ++ * control this. ++ */ ++ if (size == IMAGE_SIZE_INVAL) ++ size = fdt_totalsize(fit); ++ ret = fdt_check_full(fit, size); ++ ++ if (ret) { ++ log_debug("FIT check error %d\n", ret); ++ return -EINVAL; ++ } ++ } ++ + /* mandatory subimages parent '/images' node */ + if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) { + log_debug("Wrong FIT format: no images parent node\n"); +diff --git a/include/libfdt.h b/include/libfdt.h +index 74b1d149c2dd..6a4b2f871205 100644 +--- a/include/libfdt.h ++++ b/include/libfdt.h +@@ -1980,4 +1980,5 @@ int fdt_next_region(const void *fdt, + int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count, + int max_regions, struct fdt_region_state *info); + ++int fdt_check_full(const void *fdt, size_t bufsize); + #endif /* _LIBFDT_H */ +diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c +index 12214c2dc2b5..5ae4b84d6e54 100644 +--- a/lib/libfdt/fdt_ro.c ++++ b/lib/libfdt/fdt_ro.c +@@ -625,3 +625,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + + return offset; /* error from fdt_next_node() */ + } ++ ++#define INT_MAX ((int)(~0U>>1)) ++ ++int fdt_check_full(const void *fdt, size_t bufsize) ++{ ++ int err; ++ int num_memrsv; ++ int offset, nextoffset = 0; ++ uint32_t tag; ++ unsigned depth = 0; ++ const void *prop; ++ const char *propname; ++ ++ if (bufsize < FDT_V1_SIZE) ++ return -FDT_ERR_TRUNCATED; ++ err = fdt_check_header(fdt); ++ if (err != 0) ++ return err; ++ if (bufsize < fdt_totalsize(fdt)) ++ return -FDT_ERR_TRUNCATED; ++ ++ num_memrsv = fdt_num_mem_rsv(fdt); ++ if (num_memrsv < 0) ++ return num_memrsv; ++ ++ while (1) { ++ offset = nextoffset; ++ tag = fdt_next_tag(fdt, offset, &nextoffset); ++ ++ if (nextoffset < 0) ++ return nextoffset; ++ ++ switch (tag) { ++ case FDT_NOP: ++ break; ++ ++ case FDT_END: ++ if (depth != 0) ++ return -FDT_ERR_BADSTRUCTURE; ++ return 0; ++ ++ case FDT_BEGIN_NODE: ++ depth++; ++ if (depth > INT_MAX) ++ return -FDT_ERR_BADSTRUCTURE; ++ break; ++ ++ case FDT_END_NODE: ++ if (depth == 0) ++ return -FDT_ERR_BADSTRUCTURE; ++ depth--; ++ break; ++ ++ case FDT_PROP: ++ prop = fdt_getprop_by_offset(fdt, offset, &propname, ++ &err); ++ if (!prop) ++ return err; ++ break; ++ ++ default: ++ return -FDT_ERR_INTERNAL; ++ } ++ } ++} +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27138/0001-image-Check-for-unit-addresses-in-FITs.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27138/0001-image-Check-for-unit-addresses-in-FITs.patch new file mode 100644 index 000000000..33dbf15be --- /dev/null +++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/CVE-2021-27138/0001-image-Check-for-unit-addresses-in-FITs.patch @@ -0,0 +1,106 @@ +From dbfcf0735d5f4d27445176f72e6174edf064c118 Mon Sep 17 00:00:00 2001 +From: Simon Glass <sjg@chromium.org> +Date: Mon, 15 Feb 2021 17:08:12 -0700 +Subject: [PATCH] image: Check for unit addresses in FITs + +Using unit addresses in a FIT is a security risk. Add a check for this +and disallow it. + +CVE-2021-27138 + +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> +--- + common/image-fit.c | 56 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 52 insertions(+), 4 deletions(-) + +diff --git a/common/image-fit.c b/common/image-fit.c +index 78db32e89f6f..6c495ffa4349 100644 +--- a/common/image-fit.c ++++ b/common/image-fit.c +@@ -1217,6 +1217,34 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) + return (comp == image_comp); + } + ++/** ++ * fdt_check_no_at() - Check for nodes whose names contain '@' ++ * ++ * This checks the parent node and all subnodes recursively ++ * ++ * @fit: FIT to check ++ * @parent: Parent node to check ++ * @return 0 if OK, -EADDRNOTAVAIL is a node has a name containing '@' ++ */ ++static int fdt_check_no_at(const void *fit, int parent) ++{ ++ const char *name; ++ int node; ++ int ret; ++ ++ name = fdt_get_name(fit, parent, NULL); ++ if (!name || strchr(name, '@')) ++ return -EADDRNOTAVAIL; ++ ++ fdt_for_each_subnode(node, fit, parent) { ++ ret = fdt_check_no_at(fit, node); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + int fit_check_format(const void *fit, ulong size) + { + int ret; +@@ -1251,10 +1279,27 @@ int fit_check_format(const void *fit, ulong size) + if (size == IMAGE_SIZE_INVAL) + size = fdt_totalsize(fit); + ret = fdt_check_full(fit, size); ++ if (ret) ++ ret = -EINVAL; ++ ++ /* ++ * U-Boot stopped using unit addressed in 2017. Since libfdt ++ * can match nodes ignoring any unit address, signature ++ * verification can see the wrong node if one is inserted with ++ * the same name as a valid node but with a unit address ++ * attached. Protect against this by disallowing unit addresses. ++ */ ++ if (!ret && CONFIG_IS_ENABLED(FIT_SIGNATURE)) { ++ ret = fdt_check_no_at(fit, 0); + ++ if (ret) { ++ log_debug("FIT check error %d\n", ret); ++ return ret; ++ } ++ } + if (ret) { + log_debug("FIT check error %d\n", ret); +- return -EINVAL; ++ return ret; + } + } + +@@ -1604,10 +1649,13 @@ 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, IMAGE_SIZE_INVAL)) { +- printf("Bad FIT %s image format!\n", prop_name); ++ ret = fit_check_format(fit, IMAGE_SIZE_INVAL); ++ if (ret) { ++ printf("Bad FIT %s image format! (err=%d)\n", prop_name, ret); ++ if (CONFIG_IS_ENABLED(FIT_SIGNATURE) && ret == -EADDRNOTAVAIL) ++ printf("Signature checking prevents use of unit addresses (@) in nodes\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); +- return -ENOEXEC; ++ return ret; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); + if (fit_uname) { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend index f5dd88f7a..53e91136e 100644 --- a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend +++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend @@ -1,6 +1,5 @@ COMPATIBLE_MACHINE = "intel-ast2500" FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files:" -FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files/CVE-2020-10648:" # the meta-phosphor layer adds this patch, which conflicts # with the intel layout for environment @@ -53,6 +52,7 @@ SRC_URI_append_intel-ast2500 = " \ file://0054-U-Boot-4-4-lib-uuid-Improve-randomness-of-uuid-values-on-RANDOM_UUID-y.patch \ " # CVE-2020-10648 vulnerability fix +FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files/CVE-2020-10648:" SRC_URI_append_intel-ast2500 = " \ file://0001-image-Correct-comment-for-fit_conf_get_node.patch \ file://0002-image-Be-a-little-more-verbose-when-checking-signatu.patch \ @@ -62,6 +62,20 @@ SRC_URI_append_intel-ast2500 = " \ file://0009-fit_check_sign-Allow-selecting-the-configuration-to-.patch \ file://0012-image-Use-constants-for-required-and-key-name-hint.patch \ " + +# CVE-2021-27097 vulnerability fix +FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files/CVE-2021-27097:" +SRC_URI_append_intel-ast2500 = " \ + file://0001-image-Adjust-the-workings-of-fit_check_format.patch \ + file://0002-image-Add-an-option-to-do-a-full-check-of-the-FIT.patch \ + " + +# CVE-2021-27138 vulnerability fix +FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files/CVE-2021-27138:" +SRC_URI_append_intel-ast2500 = " \ + file://0001-image-Check-for-unit-addresses-in-FITs.patch \ + " + PFR_SRC_URI = " \ file://0022-u-boot-env-change-for-PFR-image.patch \ file://0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch \ diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0019-ADCSensor-check-threshold-10-seconds-after-power-on.patch b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0019-ADCSensor-check-threshold-10-seconds-after-power-on.patch new file mode 100644 index 000000000..c4e093083 --- /dev/null +++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0019-ADCSensor-check-threshold-10-seconds-after-power-on.patch @@ -0,0 +1,62 @@ +From 13a5a77c408efd1e84b48de8a48ab5990d26fca9 Mon Sep 17 00:00:00 2001 +From: Zhikui Ren <zhikui.ren@intel.com> +Date: Tue, 9 Mar 2021 20:25:29 -0800 +Subject: [PATCH] ADCSensor: check threshold 10 seconds after power on + +For ADC Sensors, only check for threshold if the host power state file +has been written for more than 10 seconds. + +This is a workaround to ensure that the sensor value that is used to +compare against the threshold level is read after voltages settled and +full ADC sampling cycle has been passed. + +The false SEL logs cannot be reliably reproduced, so it is not +possible to confirm that the issue is fixed with this change. + +Tested: +Use debug print to verify check threshold is skipped during first 10 +seconds after power state transition. +SEL log is created when event is triggered after 10 seconds. + +Signed-off-by: Zhikui Ren <zhikui.ren@intel.com> +--- + src/ADCSensor.cpp | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/src/ADCSensor.cpp b/src/ADCSensor.cpp +index 4de2b1f..2017c0c 100644 +--- a/src/ADCSensor.cpp ++++ b/src/ADCSensor.cpp +@@ -246,6 +246,7 @@ void ADCSensor::handleResponse(const boost::system::error_code& err) + + const static std::filesystem::path tmpHostStateFileDir = "/tmp"; + const static constexpr std::string_view hostStateFile = "host-state"; ++constexpr auto powerSettleTime = std::chrono::seconds{10}; + + static bool isPowerCurrentlyOn() + { +@@ -256,6 +257,21 @@ static bool isPowerCurrentlyOn() + return false; + } + ++ // File time is used as host power state change time. ++ // Make sure we are in the current state longer than settling time. ++ // This is only needed for power on to ensure VRs are sampled in ++ // the steady state. ++ // But it is ok to apply check for power off also, ++ // so always check the timestamp to keep the logic simple. ++ std::filesystem::file_time_type hostStateUpdateTime = ++ std::filesystem::last_write_time( ++ std::filesystem::path(tmpHostStateFileDir / hostStateFile)); ++ if ((std::filesystem::file_time_type::clock::now() - hostStateUpdateTime) <= ++ powerSettleTime) ++ { ++ return false; ++ } ++ + std::string state; + std::getline(hostStateStream, state); + return state == "xyz.openbmc_project.State.Host.HostState.Running"; +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0020-ExitAirTemp-fix-use-weak_ptr-to-in-async-handler.patch b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0020-ExitAirTemp-fix-use-weak_ptr-to-in-async-handler.patch new file mode 100644 index 000000000..c0f8c5c92 --- /dev/null +++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0020-ExitAirTemp-fix-use-weak_ptr-to-in-async-handler.patch @@ -0,0 +1,209 @@ +From efb007d288530ce6ec8a319488422fbccb521edd Mon Sep 17 00:00:00 2001 +From: Zhikui Ren <zhikui.ren@intel.com> +Date: Tue, 9 Mar 2021 20:45:35 -0800 +Subject: ExitAirTemp fix: use weak_ptr to in async handler + +Replace shared_ptr with weak_ptr in async handler's capture. +CFMSensor and ExitAirTempSensor are properly deleted before +new instances are created. + +Tested: +Run dc cycle test and no more memory leak or dbus connection timeout. + +Signed-off-by Zhikui Ren <zhikui.ren@intel.com> +--- + src/ExitAirTempSensor.cpp | 102 +++++++++++++++++++++++++++++--------- + 1 file changed, 79 insertions(+), 23 deletions(-) + +diff --git a/src/ExitAirTempSensor.cpp b/src/ExitAirTempSensor.cpp +index 4661aeb..1ee9301 100644 +--- a/src/ExitAirTempSensor.cpp ++++ b/src/ExitAirTempSensor.cpp +@@ -208,10 +208,16 @@ CFMSensor::CFMSensor(std::shared_ptr<sdbusplus::asio::connection>& conn, + void CFMSensor::setupMatches() + { + +- std::shared_ptr<CFMSensor> self = shared_from_this(); ++ std::weak_ptr<CFMSensor> weakRef = weak_from_this(); + setupSensorMatch( + matches, *dbusConnection, "fan_tach", +- [self](const double& value, sdbusplus::message::message& message) { ++ [weakRef](const double& value, sdbusplus::message::message& message) { ++ std::shared_ptr<CFMSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + self->tachReadings[message.get_path()] = value; + if (self->tachRanges.find(message.get_path()) == + self->tachRanges.end()) +@@ -226,8 +232,15 @@ void CFMSensor::setupMatches() + }); + + dbusConnection->async_method_call( +- [self](const boost::system::error_code ec, +- const std::variant<double> cfmVariant) { ++ [weakRef](const boost::system::error_code ec, ++ const std::variant<double> cfmVariant) { ++ std::shared_ptr<CFMSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } ++ + uint64_t maxRpm = 100; + if (!ec) + { +@@ -252,7 +265,13 @@ void CFMSensor::setupMatches() + "freedesktop.DBus.Properties',path='" + + std::string(cfmSettingPath) + "',arg0='" + + std::string(cfmSettingIface) + "'", +- [self](sdbusplus::message::message& message) { ++ [weakRef](sdbusplus::message::message& message) { ++ std::shared_ptr<CFMSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + boost::container::flat_map<std::string, std::variant<double>> + values; + std::string objectName; +@@ -298,18 +317,24 @@ void CFMSensor::createMaxCFMIface(void) + void CFMSensor::addTachRanges(const std::string& serviceName, + const std::string& path) + { +- std::shared_ptr<CFMSensor> self = shared_from_this(); ++ std::weak_ptr<CFMSensor> weakRef = weak_from_this(); + dbusConnection->async_method_call( +- [self, path](const boost::system::error_code ec, +- const boost::container::flat_map<std::string, +- BasicVariantType>& data) { ++ [weakRef, ++ path](const boost::system::error_code ec, ++ const boost::container::flat_map<std::string, BasicVariantType>& ++ data) { + if (ec) + { + std::cerr << "Error getting properties from " << path << "\n"; + std::cerr << ec.message() << "\n"; + return; + } +- ++ std::shared_ptr<CFMSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + double max = loadVariant<double>(data, "MaxValue"); + double min = loadVariant<double>(data, "MinValue"); + self->tachRanges[path] = std::make_pair(min, max); +@@ -544,13 +569,19 @@ void ExitAirTempSensor::setupMatches(void) + constexpr const std::array<const char*, 2> matchTypes = { + "power", inletTemperatureSensor}; + +- std::shared_ptr<ExitAirTempSensor> self = shared_from_this(); ++ std::weak_ptr<ExitAirTempSensor> weakRef = weak_from_this(); + for (const std::string& type : matchTypes) + { + setupSensorMatch( + matches, *dbusConnection, type, +- [self, type](const double& value, +- sdbusplus::message::message& message) { ++ [weakRef, type](const double& value, ++ sdbusplus::message::message& message) { ++ std::shared_ptr<ExitAirTempSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + if (type == "power") + { + std::string path = message.get_path(); +@@ -579,8 +610,14 @@ void ExitAirTempSensor::setupMatches(void) + }); + } + dbusConnection->async_method_call( +- [self](boost::system::error_code ec, +- const std::variant<double>& value) { ++ [weakRef](boost::system::error_code ec, ++ const std::variant<double>& value) { ++ std::shared_ptr<ExitAirTempSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + if (ec) + { + // sensor not ready yet +@@ -593,7 +630,13 @@ void ExitAirTempSensor::setupMatches(void) + std::string("/xyz/openbmc_project/sensors/") + inletTemperatureSensor, + properties::interface, properties::get, sensorValueInterface, "Value"); + dbusConnection->async_method_call( +- [self](boost::system::error_code ec, const GetSubTreeType& subtree) { ++ [weakRef](boost::system::error_code ec, const GetSubTreeType& subtree) { ++ std::shared_ptr<ExitAirTempSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + if (ec) + { + std::cerr << "Error contacting mapper\n"; +@@ -614,8 +657,15 @@ void ExitAirTempSensor::setupMatches(void) + { + const std::string& path = item.first; + self->dbusConnection->async_method_call( +- [self, path](boost::system::error_code ec, +- const std::variant<double>& value) { ++ [weakRef, path](boost::system::error_code ec, ++ const std::variant<double>& value) { ++ std::shared_ptr<ExitAirTempSensor> self = ++ weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + if (ec) + { + std::cerr << "Error getting value from " << path +@@ -644,18 +694,24 @@ void ExitAirTempSensor::setupMatches(void) + void ExitAirTempSensor::addPowerRanges(const std::string& serviceName, + const std::string& path) + { +- std::shared_ptr<ExitAirTempSensor> self = shared_from_this(); ++ std::weak_ptr<ExitAirTempSensor> weakRef = weak_from_this(); + dbusConnection->async_method_call( +- [self, path](const boost::system::error_code ec, +- const boost::container::flat_map<std::string, +- BasicVariantType>& data) { ++ [weakRef, ++ path](const boost::system::error_code ec, ++ const boost::container::flat_map<std::string, BasicVariantType>& ++ data) { + if (ec) + { + std::cerr << "Error getting properties from " << path << "\n"; + std::cerr << ec.message() << "\n"; + return; + } +- ++ std::shared_ptr<ExitAirTempSensor> self = weakRef.lock(); ++ if (!self) ++ { ++ // we have been deleted ++ return; ++ } + double max = loadVariant<double>(data, "MaxValue"); + double min = loadVariant<double>(data, "MinValue"); + self->powerRanges[path] = std::make_pair(min, max); +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend index 8e2126d9d..c75d5bb97 100644 --- a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend +++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend @@ -18,4 +18,6 @@ SRC_URI += "file://0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch \ file://0016-Fix-threshold-assertion-events-for-cpu-adc-sensors.patch \ file://0017-Add-more-boundary-checking-in-Texitair-calculation.patch \ file://0018-ADCSensor-use-tmp-power-state-file-for-threshold.patch \ + file://0019-ADCSensor-check-threshold-10-seconds-after-power-on.patch \ + file://0020-ExitAirTemp-fix-use-weak_ptr-to-in-async-handler.patch \ " |