diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2021-05-24 22:54:37 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2021-05-24 23:12:35 +0300 |
commit | 2a64b8ae9b952b18b4aef38cb7c41ce6dba16c50 (patch) | |
tree | 704eb802dc7b987411a0e44d128bdd8978745d8c /meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097 | |
parent | 0e0df451ae365f09d5c0c766b253f23de26901f2 (diff) | |
download | openbmc-2a64b8ae9b952b18b4aef38cb7c41ce6dba16c50.tar.xz |
Update to internal 0.52
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097')
2 files changed, 609 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch new file mode 100644 index 000000000..97814024f --- /dev/null +++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/CVE-2021-27097/0001-image-Adjust-the-workings-of-fit_check_format.patch @@ -0,0 +1,397 @@ +From d676a491fb465f11271c47185f1eb3e479c5c738 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> +--- + arch/arm/cpu/armv8/sec_firmware.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 | 45 +++++++++++++----------------- + common/splash_source.c | 4 +-- + common/update.c | 2 +- + drivers/net/fsl-mc/mc.c | 2 +- + drivers/net/pfe_eth/pfe_firmware.c | 2 +- + include/image.h | 21 +++++++++++++- + tools/fit_common.c | 3 +- + tools/fit_image.c | 2 +- + tools/mkimage.h | 2 ++ + 18 files changed, 61 insertions(+), 44 deletions(-) + +diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c +index 8dc0ac92668f..3c5249541222 100644 +--- a/arch/arm/cpu/armv8/sec_firmware.c ++++ b/arch/arm/cpu/armv8/sec_firmware.c +@@ -310,7 +310,7 @@ __weak bool sec_firmware_is_valid(const void *sec_firmware_img) + return false; + } + +- if (!fit_check_format(sec_firmware_img)) { ++ if (fit_check_format(sec_firmware_img, IMAGE_SIZE_INVAL)) { + printf("SEC Firmware: Bad firmware image (bad FIT header)\n"); + return false; + } +diff --git a/cmd/bootm.c b/cmd/bootm.c +index c3a063474ac6..1d6ec0d4cacc 100644 +--- a/cmd/bootm.c ++++ b/cmd/bootm.c +@@ -282,7 +282,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; + } +@@ -355,7 +355,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); +@@ -435,7 +435,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 dcc36a6c2cb7..294fc111023a 100644 +--- a/cmd/disk.c ++++ b/cmd/disk.c +@@ -110,7 +110,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 906845d4049b..37e557a1e7d7 100644 +--- a/cmd/fdc.c ++++ b/cmd/fdc.c +@@ -730,7 +730,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 88a8e3f3186b..9093026ff6ce 100644 +--- a/cmd/fpga.c ++++ b/cmd/fpga.c +@@ -325,7 +325,7 @@ static int do_fpga_loadmk(cmd_tbl_t *cmdtp, int flag, int argc, + return CMD_RET_FAILURE; + } + +- if (!fit_check_format(fit_hdr)) { ++ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { + puts("Bad FIT image format\n"); + return CMD_RET_FAILURE; + } +diff --git a/cmd/nand.c b/cmd/nand.c +index a22945d144b3..536a11be9605 100644 +--- a/cmd/nand.c ++++ b/cmd/nand.c +@@ -911,7 +911,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 6d98a1cfd32b..897b97057d85 100644 +--- a/cmd/source.c ++++ b/cmd/source.c +@@ -106,7 +106,7 @@ source (ulong addr, const char *fit_uname) + #if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + 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 8572a67a0063..51af741c827b 100644 +--- a/cmd/ximg.c ++++ b/cmd/ximg.c +@@ -131,7 +131,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 52ada56fc17b..3aa6c427362c 100644 +--- a/common/image-fdt.c ++++ b/common/image-fdt.c +@@ -394,7 +394,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 = boot_get_fdt_fit(images, +diff --git a/common/image-fit.c b/common/image-fit.c +index 6894384b47b9..124d8895cffd 100644 +--- a/common/image-fit.c ++++ b/common/image-fit.c +@@ -8,6 +8,8 @@ + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + ++#define LOG_CATEGORY LOGC_BOOT ++ + #ifdef USE_HOSTCC + #include "mkimage.h" + #include <time.h> +@@ -1460,46 +1462,39 @@ 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; ++ + /* A FIT image must be a valid FDT */ +- if (fdt_check_header(fit)) { +- debug("Wrong FIT format: not a flattened device tree\n"); +- return 0; ++ 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; + } + + +@@ -1813,7 +1808,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/splash_source.c b/common/splash_source.c +index 62763b9ebd56..d43dd0b2cd98 100644 +--- a/common/splash_source.c ++++ b/common/splash_source.c +@@ -329,8 +329,8 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) + if (res < 0) + return res; + +- res = fit_check_format(fit_header); +- if (!res) { ++ res = fit_check_format(fit_header, IMAGE_SIZE_INVAL); ++ if (res) { + debug("Could not find valid FIT image\n"); + return -EINVAL; + } +diff --git a/common/update.c b/common/update.c +index f237ea53bb2a..42950edbbf22 100644 +--- a/common/update.c ++++ b/common/update.c +@@ -280,7 +280,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/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c +index cc59b21f9f48..c4f35e7325b2 100644 +--- a/drivers/net/fsl-mc/mc.c ++++ b/drivers/net/fsl-mc/mc.c +@@ -130,7 +130,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/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c +index adb2d06010ce..7b930ecc2a02 100644 +--- a/drivers/net/pfe_eth/pfe_firmware.c ++++ b/drivers/net/pfe_eth/pfe_firmware.c +@@ -150,7 +150,7 @@ static int pfe_fit_check(void) + return ret; + } + +- if (!fit_check_format(pfe_fit_addr)) { ++ if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) { + printf("PFE Firmware: Bad firmware image (bad FIT header)\n"); + ret = -1; + return ret; +diff --git a/include/image.h b/include/image.h +index ea4c05ca2586..b73f739c1585 100644 +--- a/include/image.h ++++ b/include/image.h +@@ -453,6 +453,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(). +@@ -1062,7 +1065,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_common.c b/tools/fit_common.c +index 9506390214ce..5e85ca221ac9 100644 +--- a/tools/fit_common.c ++++ b/tools/fit_common.c +@@ -26,7 +26,8 @@ + int fit_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) + { +- if (fdt_check_header(ptr) != EXIT_SUCCESS || !fit_check_format(ptr)) ++ if (fdt_check_header(ptr) != EXIT_SUCCESS || ++ fit_check_format(ptr, IMAGE_SIZE_INVAL)) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +diff --git a/tools/fit_image.c b/tools/fit_image.c +index 3b867e06564e..21fc11c084c9 100644 +--- a/tools/fit_image.c ++++ b/tools/fit_image.c +@@ -764,7 +764,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 0254af59fbed..d32625f0a234 100644 +--- a/tools/mkimage.h ++++ b/tools/mkimage.h +@@ -29,6 +29,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-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 + |