diff options
Diffstat (limited to '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')
-rw-r--r-- | 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 | 198 |
1 files changed, 198 insertions, 0 deletions
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 + |