summaryrefslogtreecommitdiff
path: root/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
diff options
context:
space:
mode:
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.patch198
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
+