summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2600/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-ast2600/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-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097/0002-image-Add-an-option-to-do-a-full-check-of-the-FIT.patch212
1 files changed, 212 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-ast2600/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-ast2600/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..51d858470
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/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,212 @@
+From cf469ab0783da6783f89a8e31c213f19fdf38dba 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 | 20 ++++++++++++-
+ include/linux/libfdt.h | 2 ++
+ lib/libfdt/fdt_ro.c | 65 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 105 insertions(+), 1 deletion(-)
+
+diff --git a/Kconfig b/Kconfig
+index b62bcdbccf1e..0165ca33c5d1 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -318,11 +318,21 @@ config FIT_ENABLE_SHA512_SUPPORT
+ SHA512 checksum is a 512-bit (64-byte) hash value used to check that
+ the image contents have not been corrupted.
+
++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 DM
+ select HASH
+ select RSA
++ select FIT_FULL_CHECK
+ help
+ This option enables signature verification of FIT uImages,
+ using a hash signed and verified using RSA. If
+@@ -398,6 +408,14 @@ config SPL_FIT_PRINT
+ help
+ Support printing the content of the fitImage in a verbose manner in SPL.
+
++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_DM
+@@ -405,6 +423,7 @@ config SPL_FIT_SIGNATURE
+ select SPL_CRYPTO_SUPPORT
+ select SPL_HASH_SUPPORT
+ select SPL_RSA
++ select SPL_FIT_FULL_CHECK
+
+ config SPL_LOAD_FIT
+ bool "Enable SPL loading U-Boot as a FIT"
+diff --git a/common/image-fit.c b/common/image-fit.c
+index 124d8895cffd..b1926d8b53f8 100644
+--- a/common/image-fit.c
++++ b/common/image-fit.c
+@@ -15,7 +15,6 @@
+ #include <time.h>
+ #else
+ #include <linux/compiler.h>
+-#include <linux/kconfig.h>
+ #include <common.h>
+ #include <errno.h>
+ #include <mapmem.h>
+@@ -26,12 +25,15 @@ DECLARE_GLOBAL_DATA_PTR;
+
+ #include <image.h>
+ #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>
+ #include <u-boot/sha512.h>
+
++#define log_debug(fmt, args...) debug(fmt, ##args)
++
+ /*****************************************************************************/
+ /* New uImage format routines */
+ /*****************************************************************************/
+@@ -1487,6 +1489,22 @@ int fit_check_format(const void *fit, ulong size)
+ return -ENODATA;
+ }
+ }
++
++ 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) {
+diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h
+index eeb2344971f3..29c997ada398 100644
+--- a/include/linux/libfdt.h
++++ b/include/linux/libfdt.h
+@@ -305,6 +305,8 @@ 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 /* SWIG */
+
+ extern struct fdt_header *working_fdt; /* Pointer to the working fdt */
+diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
+index b6ca4e0b0c30..dfbeb2c21a85 100644
+--- a/lib/libfdt/fdt_ro.c
++++ b/lib/libfdt/fdt_ro.c
+@@ -680,3 +680,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
+