]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
image: Adjust the workings of fit_check_format()
authorSimon Glass <sjg@chromium.org>
Tue, 16 Feb 2021 00:08:09 +0000 (17:08 -0700)
committerTom Rini <trini@konsulko.com>
Tue, 16 Feb 2021 03:31:52 +0000 (22:31 -0500)
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>
19 files changed:
arch/arm/cpu/armv8/sec_firmware.c
cmd/bootefi.c
cmd/bootm.c
cmd/disk.c
cmd/fpga.c
cmd/nand.c
cmd/source.c
cmd/ximg.c
common/image-fdt.c
common/image-fit.c
common/splash_source.c
common/update.c
drivers/fpga/socfpga_arria10.c
drivers/net/fsl-mc/mc.c
drivers/net/pfe_eth/pfe_firmware.c
include/image.h
tools/fit_common.c
tools/fit_image.c
tools/mkimage.h

index c6c4fcc7e0730f4463d26c099d4f1919888b47b5..267894fbcb36f10d5c3692ac8ba5076c8bac870b 100644 (file)
@@ -317,7 +317,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;
        }
index 1583a96be14e71bb8a3a748b2c18f776c0aa48b4..271b385edea684f7b16236f2e941ab76ed009ab3 100644 (file)
@@ -73,7 +73,7 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
        /* Remember only PE-COFF and FIT images */
        if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
 #ifdef CONFIG_FIT
-               if (!fit_check_format(buffer))
+               if (fit_check_format(buffer, IMAGE_SIZE_INVAL))
                        return;
                /*
                 * FIT images of type EFI_OS are started via command bootm.
index 7732b97f635da2335ce2fc5e917b95ef19382879..81c6b939781ac0ac0956e0f9564dc6be622f66e7 100644 (file)
@@ -292,7 +292,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");
                        unmap_sysmem(hdr);
                        return 1;
@@ -369,7 +369,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);
@@ -449,7 +449,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;
        }
index 0bc3808dfe2e05ae768c0d4db3e0e7a1d8c5060b..2726115e8558f09e1b842eb4c9410ac5d194e9ad 100644 (file)
@@ -114,7 +114,7 @@ int common_diskboot(struct cmd_tbl *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;
index 8ae1c936fbb5bc7b1161cecbc36e4edc13869c32..51410a8e424cf3a9689e4adb3b2d920eadd3a665 100644 (file)
@@ -330,7 +330,7 @@ static int do_fpga_loadmk(struct cmd_tbl *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;
                }
index 92d039af8f52c6bf9ceb61bffbc58d713e52c1e8..97e117a979a0da97b43d3076bfba20746cf43a77 100644 (file)
@@ -917,7 +917,7 @@ static int nand_load_image(struct cmd_tbl *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;
index b6c709a3d25865f3340f8febd6656d918c3020f8..71f71528ad2a218a8cf53613522692ed584e4a28 100644 (file)
@@ -107,7 +107,7 @@ int image_source_script(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;
                }
index 159ba516489896d81fbde48aeeaf4d96edc43e97..ef738ebfa2f34424ac57e65f4d9ff8e41afe31e1 100644 (file)
@@ -136,7 +136,7 @@ do_imgextract(struct cmd_tbl *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;
                }
index 0157cce32d58d7825beb1a7f55c47c582e3dfd02..61ce6e5779fe3e702b5073a824f2330b881a20e7 100644 (file)
@@ -400,7 +400,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,
index c3dc814115ff86d8d99f0b0c3a4c55c9cfeceff7..f6c0428a96b45ee30ca8179bc8708fcf655095c7 100644 (file)
@@ -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>
@@ -1566,49 +1568,41 @@ 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;
 }
 
-
 /**
  * fit_conf_find_compat
  * @fit: pointer to the FIT format image header
@@ -1945,7 +1939,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;
index 2737fc6e7ffabd250920a118099c751dde52fef4..d7f179e3ea496ebacef74db94c5bf2f50a0bcfb4 100644 (file)
@@ -337,10 +337,10 @@ 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;
+               return res;
        }
 
        /* Get the splash image node */
index a5879cb52c4112702c914ca83c7892abb85931cc..f0848954e5dfb0ae3083ca4238e9bc54644ca035 100644 (file)
@@ -286,7 +286,7 @@ int update_tftp(ulong addr, char *interface, char *devstring)
 got_update_file:
        fit = map_sysmem(addr, 0);
 
-       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;
@@ -363,7 +363,7 @@ int fit_update(const void *fit)
        if (!fit)
                return -EINVAL;
 
-       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 -EINVAL;
        }
index 4bea7fd900d8abe61c1e8e9e8e9bec38aaff3652..b992e6f08053dd455cb95aa48d1f4e4d3df186a5 100644 (file)
@@ -566,10 +566,10 @@ static int first_loading_rbf_to_buffer(struct udevice *dev,
        if (ret < 0)
                return ret;
 
-       ret = fit_check_format(buffer_p);
-       if (!ret) {
+       ret = fit_check_format(buffer_p, IMAGE_SIZE_INVAL);
+       if (ret) {
                debug("FPGA: No valid FIT image was found.\n");
-               return -EBADF;
+               return ret;
        }
 
        confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH);
index c9cf6a987e11e549dc11484455e2825f0384cd40..972db4cf3a0d94a888a17929e9f5409c49801448 100644 (file)
@@ -142,7 +142,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;
        }
index 41999e176d411a08d3d369e039b7254eff845e38..eee70a2e73a2091720ac1655152f7e82fc1002d5 100644 (file)
@@ -160,7 +160,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;
index 856bc3e1b2915a42b8b23c2e6579fb4f396730cc..d5a940313a64ffc6aba8a5b709316c8471ce745a 100644 (file)
@@ -134,6 +134,9 @@ extern ulong image_load_addr;               /* Default Load Address */
 extern ulong image_save_addr;          /* Default Save Address */
 extern ulong image_save_size;          /* Default Save Size */
 
+/* An invalid size, meaning that the image size is not known */
+#define IMAGE_SIZE_INVAL       (-1UL)
+
 enum ih_category {
        IH_ARCH,
        IH_COMP,
@@ -1142,7 +1145,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);
 
index cdf987d3c1389004ccf98135cd1d88aa54e174ff..52b63296f8918c59f181b1d49d2371fc2b46a88b 100644 (file)
@@ -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;
index 06faeda7c26f090142ae590fd523ff5c62948456..d440d143c6781b5ae2744f9a01b3470e0aac193a 100644 (file)
@@ -883,7 +883,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;
        }
index 5b096a545b79e96dee9475eac5cd54eb53576dd7..0d3148444c3f878d20e98fab851cccd54cea41d9 100644 (file)
@@ -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;