diff options
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/0001-add-valid-fdt-check.patch | 36 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27097-1.patch | 71 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27097-2.patch | 419 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27097-3.patch | 105 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27097-4.patch | 73 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27138-1.patch | 245 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/files/CVE-2021-27138-2.patch | 109 | ||||
| -rw-r--r-- | meta/recipes-bsp/u-boot/u-boot-common.inc | 7 |
8 files changed, 1065 insertions, 0 deletions
diff --git a/meta/recipes-bsp/u-boot/files/0001-add-valid-fdt-check.patch b/meta/recipes-bsp/u-boot/files/0001-add-valid-fdt-check.patch new file mode 100644 index 0000000000..d4ac9e2ed9 --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/0001-add-valid-fdt-check.patch | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | From ea1a9ec5f430359720d9a0621ed1acfbba6a142a Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Heinrich Schuchardt <xypron.glpk@gmx.de> | ||
| 3 | Date: Wed, 13 Jan 2021 02:09:12 +0100 | ||
| 4 | Subject: [PATCH] image-fit: fit_check_format check for valid FDT | ||
| 5 | |||
| 6 | fit_check_format() must check that the buffer contains a flattened device | ||
| 7 | tree before calling any device tree library functions. | ||
| 8 | |||
| 9 | Failure to do may cause segmentation faults. | ||
| 10 | |||
| 11 | Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> | ||
| 12 | |||
| 13 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/ea1a9ec5f430359720d9a0621ed1acfbba6a142a] | ||
| 14 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 15 | |||
| 16 | --- | ||
| 17 | common/image-fit.c | 6 ++++++ | ||
| 18 | 1 file changed, 6 insertions(+) | ||
| 19 | |||
| 20 | diff --git a/common/image-fit.c b/common/image-fit.c | ||
| 21 | index 6a8787ca0a..21c44bdf69 100644 | ||
| 22 | --- a/common/image-fit.c | ||
| 23 | +++ b/common/image-fit.c | ||
| 24 | @@ -1553,6 +1553,12 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) | ||
| 25 | */ | ||
| 26 | int fit_check_format(const void *fit) | ||
| 27 | { | ||
| 28 | + /* A FIT image must be a valid FDT */ | ||
| 29 | + if (fdt_check_header(fit)) { | ||
| 30 | + debug("Wrong FIT format: not a flattened device tree\n"); | ||
| 31 | + return 0; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | /* mandatory / node 'description' property */ | ||
| 35 | if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) { | ||
| 36 | debug("Wrong FIT format: no description\n"); | ||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27097-1.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-1.patch new file mode 100644 index 0000000000..98ec2c709d --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-1.patch | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | From 8a7d4cf9820ea16fabd25a6379351b4dc291204b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:05 -0700 | ||
| 4 | Subject: [PATCH] fdt_region: Check for a single root node of the correct name | ||
| 5 | |||
| 6 | At present fdt_find_regions() assumes that the FIT is a valid devicetree. | ||
| 7 | If the FIT has two root nodes this is currently not detected in this | ||
| 8 | function, nor does libfdt's fdt_check_full() notice. Also it is possible | ||
| 9 | for the root node to have a name even though it should not. | ||
| 10 | |||
| 11 | Add checks for these and return -FDT_ERR_BADSTRUCTURE if a problem is | ||
| 12 | detected. | ||
| 13 | |||
| 14 | CVE-2021-27097 | ||
| 15 | |||
| 16 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 17 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 18 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 19 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 20 | |||
| 21 | CVE: CVE-2021-27097 | ||
| 22 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/8a7d4cf9820ea16fabd25a6379351b4dc291204b] | ||
| 23 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 24 | |||
| 25 | --- | ||
| 26 | common/fdt_region.c | 11 +++++++++++ | ||
| 27 | 1 file changed, 11 insertions(+) | ||
| 28 | |||
| 29 | diff --git a/common/fdt_region.c b/common/fdt_region.c | ||
| 30 | index ff12c518e9..e4ef0ca770 100644 | ||
| 31 | --- a/common/fdt_region.c | ||
| 32 | +++ b/common/fdt_region.c | ||
| 33 | @@ -43,6 +43,7 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, | ||
| 34 | int depth = -1; | ||
| 35 | int want = 0; | ||
| 36 | int base = fdt_off_dt_struct(fdt); | ||
| 37 | + bool expect_end = false; | ||
| 38 | |||
| 39 | end = path; | ||
| 40 | *end = '\0'; | ||
| 41 | @@ -59,6 +60,10 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, | ||
| 42 | tag = fdt_next_tag(fdt, offset, &nextoffset); | ||
| 43 | stop_at = nextoffset; | ||
| 44 | |||
| 45 | + /* If we see two root nodes, something is wrong */ | ||
| 46 | + if (expect_end && tag != FDT_END) | ||
| 47 | + return -FDT_ERR_BADLAYOUT; | ||
| 48 | + | ||
| 49 | switch (tag) { | ||
| 50 | case FDT_PROP: | ||
| 51 | include = want >= 2; | ||
| 52 | @@ -81,6 +86,10 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, | ||
| 53 | if (depth == FDT_MAX_DEPTH) | ||
| 54 | return -FDT_ERR_BADSTRUCTURE; | ||
| 55 | name = fdt_get_name(fdt, offset, &len); | ||
| 56 | + | ||
| 57 | + /* The root node must have an empty name */ | ||
| 58 | + if (!depth && *name) | ||
| 59 | + return -FDT_ERR_BADLAYOUT; | ||
| 60 | if (end - path + 2 + len >= path_len) | ||
| 61 | return -FDT_ERR_NOSPACE; | ||
| 62 | if (end != path + 1) | ||
| 63 | @@ -108,6 +117,8 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, | ||
| 64 | while (end > path && *--end != '/') | ||
| 65 | ; | ||
| 66 | *end = '\0'; | ||
| 67 | + if (depth == -1) | ||
| 68 | + expect_end = true; | ||
| 69 | break; | ||
| 70 | |||
| 71 | case FDT_END: | ||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27097-2.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-2.patch new file mode 100644 index 0000000000..b13c44e787 --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-2.patch | |||
| @@ -0,0 +1,419 @@ | |||
| 1 | From c5819701a3de61e2ba2ef7ad0b616565b32305e5 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:09 -0700 | ||
| 4 | Subject: [PATCH] image: Adjust the workings of fit_check_format() | ||
| 5 | |||
| 6 | At present this function does not accept a size for the FIT. This means | ||
| 7 | that it must be read from the FIT itself, introducing potential security | ||
| 8 | risk. Update the function to include a size parameter, which can be | ||
| 9 | invalid, in which case fit_check_format() calculates it. | ||
| 10 | |||
| 11 | For now no callers pass the size, but this can be updated later. | ||
| 12 | |||
| 13 | Also adjust the return value to an error code so that all the different | ||
| 14 | types of problems can be distinguished by the user. | ||
| 15 | |||
| 16 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 17 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 18 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 19 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 20 | |||
| 21 | CVE: CVE-2021-27097 CVE-2021-27138 | ||
| 22 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/c5819701a3de61e2ba2ef7ad0b616565b32305e5] | ||
| 23 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 24 | |||
| 25 | --- | ||
| 26 | arch/arm/cpu/armv8/sec_firmware.c | 2 +- | ||
| 27 | cmd/bootm.c | 6 ++--- | ||
| 28 | cmd/disk.c | 2 +- | ||
| 29 | cmd/fpga.c | 2 +- | ||
| 30 | cmd/nand.c | 2 +- | ||
| 31 | cmd/source.c | 2 +- | ||
| 32 | cmd/ximg.c | 2 +- | ||
| 33 | common/image-fdt.c | 2 +- | ||
| 34 | common/image-fit.c | 46 +++++++++++++++++--------------------- | ||
| 35 | common/splash_source.c | 6 ++--- | ||
| 36 | common/update.c | 4 ++-- | ||
| 37 | drivers/fpga/socfpga_arria10.c | 6 ++--- | ||
| 38 | drivers/net/fsl-mc/mc.c | 2 +- | ||
| 39 | drivers/net/pfe_eth/pfe_firmware.c | 2 +- | ||
| 40 | include/image.h | 21 ++++++++++++++++- | ||
| 41 | tools/fit_common.c | 3 ++- | ||
| 42 | tools/fit_image.c | 2 +- | ||
| 43 | tools/mkimage.h | 2 ++ | ||
| 44 | 18 files changed, 65 insertions(+), 49 deletions(-) | ||
| 45 | |||
| 46 | diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c | ||
| 47 | index bfc0fac3ef..0561f5efd1 100644 | ||
| 48 | --- a/arch/arm/cpu/armv8/sec_firmware.c | ||
| 49 | +++ b/arch/arm/cpu/armv8/sec_firmware.c | ||
| 50 | @@ -316,7 +316,7 @@ __weak bool sec_firmware_is_valid(const void *sec_firmware_img) | ||
| 51 | return false; | ||
| 52 | } | ||
| 53 | |||
| 54 | - if (!fit_check_format(sec_firmware_img)) { | ||
| 55 | + if (fit_check_format(sec_firmware_img, IMAGE_SIZE_INVAL)) { | ||
| 56 | printf("SEC Firmware: Bad firmware image (bad FIT header)\n"); | ||
| 57 | return false; | ||
| 58 | } | ||
| 59 | diff --git a/cmd/bootm.c b/cmd/bootm.c | ||
| 60 | index e6b0e04413..a0f823f968 100644 | ||
| 61 | --- a/cmd/bootm.c | ||
| 62 | +++ b/cmd/bootm.c | ||
| 63 | @@ -291,7 +291,7 @@ static int image_info(ulong addr) | ||
| 64 | case IMAGE_FORMAT_FIT: | ||
| 65 | puts(" FIT image found\n"); | ||
| 66 | |||
| 67 | - if (!fit_check_format(hdr)) { | ||
| 68 | + if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) { | ||
| 69 | puts("Bad FIT image format!\n"); | ||
| 70 | unmap_sysmem(hdr); | ||
| 71 | return 1; | ||
| 72 | @@ -368,7 +368,7 @@ static int do_imls_nor(void) | ||
| 73 | #endif | ||
| 74 | #if defined(CONFIG_FIT) | ||
| 75 | case IMAGE_FORMAT_FIT: | ||
| 76 | - if (!fit_check_format(hdr)) | ||
| 77 | + if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) | ||
| 78 | goto next_sector; | ||
| 79 | |||
| 80 | printf("FIT Image at %08lX:\n", (ulong)hdr); | ||
| 81 | @@ -448,7 +448,7 @@ static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off, | ||
| 82 | return ret; | ||
| 83 | } | ||
| 84 | |||
| 85 | - if (!fit_check_format(imgdata)) { | ||
| 86 | + if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) { | ||
| 87 | free(imgdata); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | diff --git a/cmd/disk.c b/cmd/disk.c | ||
| 91 | index 8060e753eb..3195db9127 100644 | ||
| 92 | --- a/cmd/disk.c | ||
| 93 | +++ b/cmd/disk.c | ||
| 94 | @@ -114,7 +114,7 @@ int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc, | ||
| 95 | /* This cannot be done earlier, | ||
| 96 | * we need complete FIT image in RAM first */ | ||
| 97 | if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { | ||
| 98 | - if (!fit_check_format(fit_hdr)) { | ||
| 99 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 100 | bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); | ||
| 101 | puts("** Bad FIT image format\n"); | ||
| 102 | return 1; | ||
| 103 | diff --git a/cmd/fpga.c b/cmd/fpga.c | ||
| 104 | index 8ae1c936fb..51410a8e42 100644 | ||
| 105 | --- a/cmd/fpga.c | ||
| 106 | +++ b/cmd/fpga.c | ||
| 107 | @@ -330,7 +330,7 @@ static int do_fpga_loadmk(struct cmd_tbl *cmdtp, int flag, int argc, | ||
| 108 | return CMD_RET_FAILURE; | ||
| 109 | } | ||
| 110 | |||
| 111 | - if (!fit_check_format(fit_hdr)) { | ||
| 112 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 113 | puts("Bad FIT image format\n"); | ||
| 114 | return CMD_RET_FAILURE; | ||
| 115 | } | ||
| 116 | diff --git a/cmd/nand.c b/cmd/nand.c | ||
| 117 | index 92d039af8f..97e117a979 100644 | ||
| 118 | --- a/cmd/nand.c | ||
| 119 | +++ b/cmd/nand.c | ||
| 120 | @@ -917,7 +917,7 @@ static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd, | ||
| 121 | #if defined(CONFIG_FIT) | ||
| 122 | /* This cannot be done earlier, we need complete FIT image in RAM first */ | ||
| 123 | if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { | ||
| 124 | - if (!fit_check_format (fit_hdr)) { | ||
| 125 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 126 | bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ); | ||
| 127 | puts ("** Bad FIT image format\n"); | ||
| 128 | return 1; | ||
| 129 | diff --git a/cmd/source.c b/cmd/source.c | ||
| 130 | index b6c709a3d2..71f71528ad 100644 | ||
| 131 | --- a/cmd/source.c | ||
| 132 | +++ b/cmd/source.c | ||
| 133 | @@ -107,7 +107,7 @@ int image_source_script(ulong addr, const char *fit_uname) | ||
| 134 | #if defined(CONFIG_FIT) | ||
| 135 | case IMAGE_FORMAT_FIT: | ||
| 136 | fit_hdr = buf; | ||
| 137 | - if (!fit_check_format (fit_hdr)) { | ||
| 138 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 139 | puts ("Bad FIT image format\n"); | ||
| 140 | return 1; | ||
| 141 | } | ||
| 142 | diff --git a/cmd/ximg.c b/cmd/ximg.c | ||
| 143 | index 159ba51648..ef738ebfa2 100644 | ||
| 144 | --- a/cmd/ximg.c | ||
| 145 | +++ b/cmd/ximg.c | ||
| 146 | @@ -136,7 +136,7 @@ do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) | ||
| 147 | "at %08lx ...\n", uname, addr); | ||
| 148 | |||
| 149 | fit_hdr = (const void *)addr; | ||
| 150 | - if (!fit_check_format(fit_hdr)) { | ||
| 151 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 152 | puts("Bad FIT image format\n"); | ||
| 153 | return 1; | ||
| 154 | } | ||
| 155 | diff --git a/common/image-fdt.c b/common/image-fdt.c | ||
| 156 | index 327a8c4c39..4105259212 100644 | ||
| 157 | --- a/common/image-fdt.c | ||
| 158 | +++ b/common/image-fdt.c | ||
| 159 | @@ -399,7 +399,7 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, | ||
| 160 | */ | ||
| 161 | #if CONFIG_IS_ENABLED(FIT) | ||
| 162 | /* check FDT blob vs FIT blob */ | ||
| 163 | - if (fit_check_format(buf)) { | ||
| 164 | + if (!fit_check_format(buf, IMAGE_SIZE_INVAL)) { | ||
| 165 | ulong load, len; | ||
| 166 | |||
| 167 | fdt_noffset = boot_get_fdt_fit(images, | ||
| 168 | diff --git a/common/image-fit.c b/common/image-fit.c | ||
| 169 | index 9637d747fb..402f08fc9d 100644 | ||
| 170 | --- a/common/image-fit.c | ||
| 171 | +++ b/common/image-fit.c | ||
| 172 | @@ -8,6 +8,8 @@ | ||
| 173 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | ||
| 174 | */ | ||
| 175 | |||
| 176 | +#define LOG_CATEGORY LOGC_BOOT | ||
| 177 | + | ||
| 178 | #ifdef USE_HOSTCC | ||
| 179 | #include "mkimage.h" | ||
| 180 | #include <time.h> | ||
| 181 | @@ -1550,49 +1552,41 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) | ||
| 182 | return (comp == image_comp); | ||
| 183 | } | ||
| 184 | |||
| 185 | -/** | ||
| 186 | - * fit_check_format - sanity check FIT image format | ||
| 187 | - * @fit: pointer to the FIT format image header | ||
| 188 | - * | ||
| 189 | - * fit_check_format() runs a basic sanity FIT image verification. | ||
| 190 | - * Routine checks for mandatory properties, nodes, etc. | ||
| 191 | - * | ||
| 192 | - * returns: | ||
| 193 | - * 1, on success | ||
| 194 | - * 0, on failure | ||
| 195 | - */ | ||
| 196 | -int fit_check_format(const void *fit) | ||
| 197 | +int fit_check_format(const void *fit, ulong size) | ||
| 198 | { | ||
| 199 | + int ret; | ||
| 200 | + | ||
| 201 | /* A FIT image must be a valid FDT */ | ||
| 202 | - if (fdt_check_header(fit)) { | ||
| 203 | - debug("Wrong FIT format: not a flattened device tree\n"); | ||
| 204 | - return 0; | ||
| 205 | + ret = fdt_check_header(fit); | ||
| 206 | + if (ret) { | ||
| 207 | + log_debug("Wrong FIT format: not a flattened device tree (err=%d)\n", | ||
| 208 | + ret); | ||
| 209 | + return -ENOEXEC; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* mandatory / node 'description' property */ | ||
| 213 | - if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) { | ||
| 214 | - debug("Wrong FIT format: no description\n"); | ||
| 215 | - return 0; | ||
| 216 | + if (!fdt_getprop(fit, 0, FIT_DESC_PROP, NULL)) { | ||
| 217 | + log_debug("Wrong FIT format: no description\n"); | ||
| 218 | + return -ENOMSG; | ||
| 219 | } | ||
| 220 | |||
| 221 | if (IMAGE_ENABLE_TIMESTAMP) { | ||
| 222 | /* mandatory / node 'timestamp' property */ | ||
| 223 | - if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { | ||
| 224 | - debug("Wrong FIT format: no timestamp\n"); | ||
| 225 | - return 0; | ||
| 226 | + if (!fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL)) { | ||
| 227 | + log_debug("Wrong FIT format: no timestamp\n"); | ||
| 228 | + return -ENODATA; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | /* mandatory subimages parent '/images' node */ | ||
| 233 | if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) { | ||
| 234 | - debug("Wrong FIT format: no images parent node\n"); | ||
| 235 | - return 0; | ||
| 236 | + log_debug("Wrong FIT format: no images parent node\n"); | ||
| 237 | + return -ENOENT; | ||
| 238 | } | ||
| 239 | |||
| 240 | - return 1; | ||
| 241 | + return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | - | ||
| 245 | /** | ||
| 246 | * fit_conf_find_compat | ||
| 247 | * @fit: pointer to the FIT format image header | ||
| 248 | @@ -1929,7 +1923,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr, | ||
| 249 | printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); | ||
| 250 | |||
| 251 | bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); | ||
| 252 | - if (!fit_check_format(fit)) { | ||
| 253 | + if (fit_check_format(fit, IMAGE_SIZE_INVAL)) { | ||
| 254 | printf("Bad FIT %s image format!\n", prop_name); | ||
| 255 | bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); | ||
| 256 | return -ENOEXEC; | ||
| 257 | diff --git a/common/splash_source.c b/common/splash_source.c | ||
| 258 | index f51ca5ddf3..bad9a7790a 100644 | ||
| 259 | --- a/common/splash_source.c | ||
| 260 | +++ b/common/splash_source.c | ||
| 261 | @@ -336,10 +336,10 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) | ||
| 262 | if (res < 0) | ||
| 263 | return res; | ||
| 264 | |||
| 265 | - res = fit_check_format(fit_header); | ||
| 266 | - if (!res) { | ||
| 267 | + res = fit_check_format(fit_header, IMAGE_SIZE_INVAL); | ||
| 268 | + if (res) { | ||
| 269 | debug("Could not find valid FIT image\n"); | ||
| 270 | - return -EINVAL; | ||
| 271 | + return res; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* Get the splash image node */ | ||
| 275 | diff --git a/common/update.c b/common/update.c | ||
| 276 | index a5879cb52c..f0848954e5 100644 | ||
| 277 | --- a/common/update.c | ||
| 278 | +++ b/common/update.c | ||
| 279 | @@ -286,7 +286,7 @@ int update_tftp(ulong addr, char *interface, char *devstring) | ||
| 280 | got_update_file: | ||
| 281 | fit = map_sysmem(addr, 0); | ||
| 282 | |||
| 283 | - if (!fit_check_format((void *)fit)) { | ||
| 284 | + if (fit_check_format((void *)fit, IMAGE_SIZE_INVAL)) { | ||
| 285 | printf("Bad FIT format of the update file, aborting " | ||
| 286 | "auto-update\n"); | ||
| 287 | return 1; | ||
| 288 | @@ -363,7 +363,7 @@ int fit_update(const void *fit) | ||
| 289 | if (!fit) | ||
| 290 | return -EINVAL; | ||
| 291 | |||
| 292 | - if (!fit_check_format((void *)fit)) { | ||
| 293 | + if (fit_check_format((void *)fit, IMAGE_SIZE_INVAL)) { | ||
| 294 | printf("Bad FIT format of the update file, aborting auto-update\n"); | ||
| 295 | return -EINVAL; | ||
| 296 | } | ||
| 297 | diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c | ||
| 298 | index 44e1ac54c3..18f99676d2 100644 | ||
| 299 | --- a/drivers/fpga/socfpga_arria10.c | ||
| 300 | +++ b/drivers/fpga/socfpga_arria10.c | ||
| 301 | @@ -565,10 +565,10 @@ static int first_loading_rbf_to_buffer(struct udevice *dev, | ||
| 302 | if (ret < 0) | ||
| 303 | return ret; | ||
| 304 | |||
| 305 | - ret = fit_check_format(buffer_p); | ||
| 306 | - if (!ret) { | ||
| 307 | + ret = fit_check_format(buffer_p, IMAGE_SIZE_INVAL); | ||
| 308 | + if (ret) { | ||
| 309 | debug("FPGA: No valid FIT image was found.\n"); | ||
| 310 | - return -EBADF; | ||
| 311 | + return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH); | ||
| 315 | diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c | ||
| 316 | index 84db6be624..81265ee356 100644 | ||
| 317 | --- a/drivers/net/fsl-mc/mc.c | ||
| 318 | +++ b/drivers/net/fsl-mc/mc.c | ||
| 319 | @@ -141,7 +141,7 @@ int parse_mc_firmware_fit_image(u64 mc_fw_addr, | ||
| 320 | return -EINVAL; | ||
| 321 | } | ||
| 322 | |||
| 323 | - if (!fit_check_format(fit_hdr)) { | ||
| 324 | + if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { | ||
| 325 | printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n"); | ||
| 326 | return -EINVAL; | ||
| 327 | } | ||
| 328 | diff --git a/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c | ||
| 329 | index 41999e176d..eee70a2e73 100644 | ||
| 330 | --- a/drivers/net/pfe_eth/pfe_firmware.c | ||
| 331 | +++ b/drivers/net/pfe_eth/pfe_firmware.c | ||
| 332 | @@ -160,7 +160,7 @@ static int pfe_fit_check(void) | ||
| 333 | return ret; | ||
| 334 | } | ||
| 335 | |||
| 336 | - if (!fit_check_format(pfe_fit_addr)) { | ||
| 337 | + if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) { | ||
| 338 | printf("PFE Firmware: Bad firmware image (bad FIT header)\n"); | ||
| 339 | ret = -1; | ||
| 340 | return ret; | ||
| 341 | diff --git a/include/image.h b/include/image.h | ||
| 342 | index 41473dbb9c..8c152c5c5f 100644 | ||
| 343 | --- a/include/image.h | ||
| 344 | +++ b/include/image.h | ||
| 345 | @@ -134,6 +134,9 @@ extern ulong image_load_addr; /* Default Load Address */ | ||
| 346 | extern ulong image_save_addr; /* Default Save Address */ | ||
| 347 | extern ulong image_save_size; /* Default Save Size */ | ||
| 348 | |||
| 349 | +/* An invalid size, meaning that the image size is not known */ | ||
| 350 | +#define IMAGE_SIZE_INVAL (-1UL) | ||
| 351 | + | ||
| 352 | enum ih_category { | ||
| 353 | IH_ARCH, | ||
| 354 | IH_COMP, | ||
| 355 | @@ -1141,7 +1144,23 @@ int fit_image_check_os(const void *fit, int noffset, uint8_t os); | ||
| 356 | int fit_image_check_arch(const void *fit, int noffset, uint8_t arch); | ||
| 357 | int fit_image_check_type(const void *fit, int noffset, uint8_t type); | ||
| 358 | int fit_image_check_comp(const void *fit, int noffset, uint8_t comp); | ||
| 359 | -int fit_check_format(const void *fit); | ||
| 360 | + | ||
| 361 | +/** | ||
| 362 | + * fit_check_format() - Check that the FIT is valid | ||
| 363 | + * | ||
| 364 | + * This performs various checks on the FIT to make sure it is suitable for | ||
| 365 | + * use, looking for mandatory properties, nodes, etc. | ||
| 366 | + * | ||
| 367 | + * If FIT_FULL_CHECK is enabled, it also runs it through libfdt to make | ||
| 368 | + * sure that there are no strange tags or broken nodes in the FIT. | ||
| 369 | + * | ||
| 370 | + * @fit: pointer to the FIT format image header | ||
| 371 | + * @return 0 if OK, -ENOEXEC if not an FDT file, -EINVAL if the full FDT check | ||
| 372 | + * failed (e.g. due to bad structure), -ENOMSG if the description is | ||
| 373 | + * missing, -ENODATA if the timestamp is missing, -ENOENT if the /images | ||
| 374 | + * path is missing | ||
| 375 | + */ | ||
| 376 | +int fit_check_format(const void *fit, ulong size); | ||
| 377 | |||
| 378 | int fit_conf_find_compat(const void *fit, const void *fdt); | ||
| 379 | |||
| 380 | diff --git a/tools/fit_common.c b/tools/fit_common.c | ||
| 381 | index cdf987d3c1..52b63296f8 100644 | ||
| 382 | --- a/tools/fit_common.c | ||
| 383 | +++ b/tools/fit_common.c | ||
| 384 | @@ -26,7 +26,8 @@ | ||
| 385 | int fit_verify_header(unsigned char *ptr, int image_size, | ||
| 386 | struct image_tool_params *params) | ||
| 387 | { | ||
| 388 | - if (fdt_check_header(ptr) != EXIT_SUCCESS || !fit_check_format(ptr)) | ||
| 389 | + if (fdt_check_header(ptr) != EXIT_SUCCESS || | ||
| 390 | + fit_check_format(ptr, IMAGE_SIZE_INVAL)) | ||
| 391 | return EXIT_FAILURE; | ||
| 392 | |||
| 393 | return EXIT_SUCCESS; | ||
| 394 | diff --git a/tools/fit_image.c b/tools/fit_image.c | ||
| 395 | index 06faeda7c2..d440d143c6 100644 | ||
| 396 | --- a/tools/fit_image.c | ||
| 397 | +++ b/tools/fit_image.c | ||
| 398 | @@ -883,7 +883,7 @@ static int fit_extract_contents(void *ptr, struct image_tool_params *params) | ||
| 399 | /* Indent string is defined in header image.h */ | ||
| 400 | p = IMAGE_INDENT_STRING; | ||
| 401 | |||
| 402 | - if (!fit_check_format(fit)) { | ||
| 403 | + if (fit_check_format(fit, IMAGE_SIZE_INVAL)) { | ||
| 404 | printf("Bad FIT image format\n"); | ||
| 405 | return -1; | ||
| 406 | } | ||
| 407 | diff --git a/tools/mkimage.h b/tools/mkimage.h | ||
| 408 | index 5b096a545b..0d3148444c 100644 | ||
| 409 | --- a/tools/mkimage.h | ||
| 410 | +++ b/tools/mkimage.h | ||
| 411 | @@ -29,6 +29,8 @@ | ||
| 412 | #define debug(fmt,args...) | ||
| 413 | #endif /* MKIMAGE_DEBUG */ | ||
| 414 | |||
| 415 | +#define log_debug(fmt, args...) debug(fmt, ##args) | ||
| 416 | + | ||
| 417 | static inline void *map_sysmem(ulong paddr, unsigned long len) | ||
| 418 | { | ||
| 419 | return (void *)(uintptr_t)paddr; | ||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27097-3.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-3.patch new file mode 100644 index 0000000000..86f7e8ce55 --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-3.patch | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | From 6f3c2d8aa5e6cbd80b5e869bbbddecb66c329d01 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:10 -0700 | ||
| 4 | Subject: [PATCH] image: Add an option to do a full check of the FIT | ||
| 5 | |||
| 6 | Some strange modifications of the FIT can introduce security risks. Add an | ||
| 7 | option to check it thoroughly, using libfdt's fdt_check_full() function. | ||
| 8 | |||
| 9 | Enable this by default if signature verification is enabled. | ||
| 10 | |||
| 11 | CVE-2021-27097 | ||
| 12 | |||
| 13 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 14 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 15 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 16 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 17 | |||
| 18 | CVE: CVE-2021-27097 | ||
| 19 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/6f3c2d8aa5e6cbd80b5e869bbbddecb66c329d01] | ||
| 20 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 21 | |||
| 22 | --- | ||
| 23 | common/Kconfig.boot | 20 ++++++++++++++++++++ | ||
| 24 | common/image-fit.c | 16 ++++++++++++++++ | ||
| 25 | 2 files changed, 36 insertions(+) | ||
| 26 | |||
| 27 | diff --git a/common/Kconfig.boot b/common/Kconfig.boot | ||
| 28 | index 5eaabdfc27..7532e55edb 100644 | ||
| 29 | --- a/common/Kconfig.boot | ||
| 30 | +++ b/common/Kconfig.boot | ||
| 31 | @@ -63,6 +63,15 @@ config FIT_ENABLE_SHA512_SUPPORT | ||
| 32 | SHA512 checksum is a 512-bit (64-byte) hash value used to check that | ||
| 33 | the image contents have not been corrupted. | ||
| 34 | |||
| 35 | +config FIT_FULL_CHECK | ||
| 36 | + bool "Do a full check of the FIT before using it" | ||
| 37 | + default y | ||
| 38 | + help | ||
| 39 | + Enable this do a full check of the FIT to make sure it is valid. This | ||
| 40 | + helps to protect against carefully crafted FITs which take advantage | ||
| 41 | + of bugs or omissions in the code. This includes a bad structure, | ||
| 42 | + multiple root nodes and the like. | ||
| 43 | + | ||
| 44 | config FIT_SIGNATURE | ||
| 45 | bool "Enable signature verification of FIT uImages" | ||
| 46 | depends on DM | ||
| 47 | @@ -70,6 +79,7 @@ config FIT_SIGNATURE | ||
| 48 | select RSA | ||
| 49 | select RSA_VERIFY | ||
| 50 | select IMAGE_SIGN_INFO | ||
| 51 | + select FIT_FULL_CHECK | ||
| 52 | help | ||
| 53 | This option enables signature verification of FIT uImages, | ||
| 54 | using a hash signed and verified using RSA. If | ||
| 55 | @@ -159,6 +169,15 @@ config SPL_FIT_PRINT | ||
| 56 | help | ||
| 57 | Support printing the content of the fitImage in a verbose manner in SPL. | ||
| 58 | |||
| 59 | +config SPL_FIT_FULL_CHECK | ||
| 60 | + bool "Do a full check of the FIT before using it" | ||
| 61 | + help | ||
| 62 | + Enable this do a full check of the FIT to make sure it is valid. This | ||
| 63 | + helps to protect against carefully crafted FITs which take advantage | ||
| 64 | + of bugs or omissions in the code. This includes a bad structure, | ||
| 65 | + multiple root nodes and the like. | ||
| 66 | + | ||
| 67 | + | ||
| 68 | config SPL_FIT_SIGNATURE | ||
| 69 | bool "Enable signature verification of FIT firmware within SPL" | ||
| 70 | depends on SPL_DM | ||
| 71 | @@ -168,6 +187,7 @@ config SPL_FIT_SIGNATURE | ||
| 72 | select SPL_RSA | ||
| 73 | select SPL_RSA_VERIFY | ||
| 74 | select SPL_IMAGE_SIGN_INFO | ||
| 75 | + select SPL_FIT_FULL_CHECK | ||
| 76 | |||
| 77 | config SPL_LOAD_FIT | ||
| 78 | bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)" | ||
| 79 | diff --git a/common/image-fit.c b/common/image-fit.c | ||
| 80 | index f6c0428a96..bcf395f6a1 100644 | ||
| 81 | --- a/common/image-fit.c | ||
| 82 | +++ b/common/image-fit.c | ||
| 83 | @@ -1580,6 +1580,22 @@ int fit_check_format(const void *fit, ulong size) | ||
| 84 | return -ENOEXEC; | ||
| 85 | } | ||
| 86 | |||
| 87 | + if (CONFIG_IS_ENABLED(FIT_FULL_CHECK)) { | ||
| 88 | + /* | ||
| 89 | + * If we are not given the size, make do wtih calculating it. | ||
| 90 | + * This is not as secure, so we should consider a flag to | ||
| 91 | + * control this. | ||
| 92 | + */ | ||
| 93 | + if (size == IMAGE_SIZE_INVAL) | ||
| 94 | + size = fdt_totalsize(fit); | ||
| 95 | + ret = fdt_check_full(fit, size); | ||
| 96 | + | ||
| 97 | + if (ret) { | ||
| 98 | + log_debug("FIT check error %d\n", ret); | ||
| 99 | + return -EINVAL; | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | /* mandatory / node 'description' property */ | ||
| 104 | if (!fdt_getprop(fit, 0, FIT_DESC_PROP, NULL)) { | ||
| 105 | log_debug("Wrong FIT format: no description\n"); | ||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27097-4.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-4.patch new file mode 100644 index 0000000000..060cac1cf6 --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27097-4.patch | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | From 124c255731c76a2b09587378b2bcce561bcd3f2d Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:11 -0700 | ||
| 4 | Subject: [PATCH] libfdt: Check for multiple/invalid root nodes | ||
| 5 | |||
| 6 | It is possible to construct a devicetree blob with multiple root nodes. | ||
| 7 | Update fdt_check_full() to check for this, along with a root node with an | ||
| 8 | invalid name. | ||
| 9 | |||
| 10 | CVE-2021-27097 | ||
| 11 | |||
| 12 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 13 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 14 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 15 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 16 | |||
| 17 | CVE: CVE-2021-27097 | ||
| 18 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/124c255731c76a2b09587378b2bcce561bcd3f2d] | ||
| 19 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 20 | |||
| 21 | --- | ||
| 22 | scripts/dtc/libfdt/fdt_ro.c | 17 +++++++++++++++++ | ||
| 23 | test/py/tests/test_vboot.py | 3 ++- | ||
| 24 | 2 files changed, 19 insertions(+), 1 deletion(-) | ||
| 25 | |||
| 26 | diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c | ||
| 27 | index d984bab036..efe7efe921 100644 | ||
| 28 | --- a/scripts/dtc/libfdt/fdt_ro.c | ||
| 29 | +++ b/scripts/dtc/libfdt/fdt_ro.c | ||
| 30 | @@ -867,6 +867,7 @@ int fdt_check_full(const void *fdt, size_t bufsize) | ||
| 31 | unsigned depth = 0; | ||
| 32 | const void *prop; | ||
| 33 | const char *propname; | ||
| 34 | + bool expect_end = false; | ||
| 35 | |||
| 36 | if (bufsize < FDT_V1_SIZE) | ||
| 37 | return -FDT_ERR_TRUNCATED; | ||
| 38 | @@ -887,6 +888,10 @@ int fdt_check_full(const void *fdt, size_t bufsize) | ||
| 39 | if (nextoffset < 0) | ||
| 40 | return nextoffset; | ||
| 41 | |||
| 42 | + /* If we see two root nodes, something is wrong */ | ||
| 43 | + if (expect_end && tag != FDT_END) | ||
| 44 | + return -FDT_ERR_BADLAYOUT; | ||
| 45 | + | ||
| 46 | switch (tag) { | ||
| 47 | case FDT_NOP: | ||
| 48 | break; | ||
| 49 | @@ -900,12 +905,24 @@ int fdt_check_full(const void *fdt, size_t bufsize) | ||
| 50 | depth++; | ||
| 51 | if (depth > INT_MAX) | ||
| 52 | return -FDT_ERR_BADSTRUCTURE; | ||
| 53 | + | ||
| 54 | + /* The root node must have an empty name */ | ||
| 55 | + if (depth == 1) { | ||
| 56 | + const char *name; | ||
| 57 | + int len; | ||
| 58 | + | ||
| 59 | + name = fdt_get_name(fdt, offset, &len); | ||
| 60 | + if (*name || len) | ||
| 61 | + return -FDT_ERR_BADLAYOUT; | ||
| 62 | + } | ||
| 63 | break; | ||
| 64 | |||
| 65 | case FDT_END_NODE: | ||
| 66 | if (depth == 0) | ||
| 67 | return -FDT_ERR_BADSTRUCTURE; | ||
| 68 | depth--; | ||
| 69 | + if (depth == 0) | ||
| 70 | + expect_end = true; | ||
| 71 | break; | ||
| 72 | |||
| 73 | case FDT_PROP: | ||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27138-1.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27138-1.patch new file mode 100644 index 0000000000..562f8151bb --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27138-1.patch | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | From 79af75f7776fc20b0d7eb6afe1e27c00fdb4b9b4 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:06 -0700 | ||
| 4 | Subject: [PATCH] fit: Don't allow verification of images with @ nodes | ||
| 5 | |||
| 6 | When searching for a node called 'fred', any unit address appended to the | ||
| 7 | name is ignored by libfdt, meaning that 'fred' can match 'fred@1'. This | ||
| 8 | means that we cannot be sure that the node originally intended is the one | ||
| 9 | that is used. | ||
| 10 | |||
| 11 | Disallow use of nodes with unit addresses. | ||
| 12 | |||
| 13 | Update the forge test also, since it uses @ addresses. | ||
| 14 | |||
| 15 | CVE-2021-27138 | ||
| 16 | |||
| 17 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 18 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 19 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 20 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 21 | |||
| 22 | CVE: CVE-2021-27138 | ||
| 23 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/79af75f7776fc20b0d7eb6afe1e27c00fdb4b9b4] | ||
| 24 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 25 | |||
| 26 | --- | ||
| 27 | common/image-fit-sig.c | 22 ++++++++++++++++++++-- | ||
| 28 | common/image-fit.c | 20 +++++++++++++++----- | ||
| 29 | test/py/tests/test_fit.py | 24 ++++++++++++------------ | ||
| 30 | test/py/tests/vboot_forge.py | 12 ++++++------ | ||
| 31 | 4 files changed, 53 insertions(+), 25 deletions(-) | ||
| 32 | |||
| 33 | diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c | ||
| 34 | index 897e04c7a3..34ebb8edfe 100644 | ||
| 35 | --- a/common/image-fit-sig.c | ||
| 36 | +++ b/common/image-fit-sig.c | ||
| 37 | @@ -149,6 +149,14 @@ static int fit_image_verify_sig(const void *fit, int image_noffset, | ||
| 38 | fdt_for_each_subnode(noffset, fit, image_noffset) { | ||
| 39 | const char *name = fit_get_name(fit, noffset, NULL); | ||
| 40 | |||
| 41 | + /* | ||
| 42 | + * We don't support this since libfdt considers names with the | ||
| 43 | + * name root but different @ suffix to be equal | ||
| 44 | + */ | ||
| 45 | + if (strchr(name, '@')) { | ||
| 46 | + err_msg = "Node name contains @"; | ||
| 47 | + goto error; | ||
| 48 | + } | ||
| 49 | if (!strncmp(name, FIT_SIG_NODENAME, | ||
| 50 | strlen(FIT_SIG_NODENAME))) { | ||
| 51 | ret = fit_image_check_sig(fit, noffset, data, | ||
| 52 | @@ -398,9 +406,10 @@ error: | ||
| 53 | return -EPERM; | ||
| 54 | } | ||
| 55 | |||
| 56 | -int fit_config_verify_required_sigs(const void *fit, int conf_noffset, | ||
| 57 | - const void *sig_blob) | ||
| 58 | +static int fit_config_verify_required_sigs(const void *fit, int conf_noffset, | ||
| 59 | + const void *sig_blob) | ||
| 60 | { | ||
| 61 | + const char *name = fit_get_name(fit, conf_noffset, NULL); | ||
| 62 | int noffset; | ||
| 63 | int sig_node; | ||
| 64 | int verified = 0; | ||
| 65 | @@ -408,6 +417,15 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset, | ||
| 66 | bool reqd_policy_all = true; | ||
| 67 | const char *reqd_mode; | ||
| 68 | |||
| 69 | + /* | ||
| 70 | + * We don't support this since libfdt considers names with the | ||
| 71 | + * name root but different @ suffix to be equal | ||
| 72 | + */ | ||
| 73 | + if (strchr(name, '@')) { | ||
| 74 | + printf("Configuration node '%s' contains '@'\n", name); | ||
| 75 | + return -EPERM; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | /* Work out what we need to verify */ | ||
| 79 | sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); | ||
| 80 | if (sig_node < 0) { | ||
| 81 | diff --git a/common/image-fit.c b/common/image-fit.c | ||
| 82 | index adc3e551de..c3dc814115 100644 | ||
| 83 | --- a/common/image-fit.c | ||
| 84 | +++ b/common/image-fit.c | ||
| 85 | @@ -1369,21 +1369,31 @@ error: | ||
| 86 | */ | ||
| 87 | int fit_image_verify(const void *fit, int image_noffset) | ||
| 88 | { | ||
| 89 | + const char *name = fit_get_name(fit, image_noffset, NULL); | ||
| 90 | const void *data; | ||
| 91 | size_t size; | ||
| 92 | - int noffset = 0; | ||
| 93 | char *err_msg = ""; | ||
| 94 | |||
| 95 | + if (strchr(name, '@')) { | ||
| 96 | + /* | ||
| 97 | + * We don't support this since libfdt considers names with the | ||
| 98 | + * name root but different @ suffix to be equal | ||
| 99 | + */ | ||
| 100 | + err_msg = "Node name contains @"; | ||
| 101 | + goto err; | ||
| 102 | + } | ||
| 103 | /* Get image data and data length */ | ||
| 104 | if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) { | ||
| 105 | err_msg = "Can't get image data/size"; | ||
| 106 | - printf("error!\n%s for '%s' hash node in '%s' image node\n", | ||
| 107 | - err_msg, fit_get_name(fit, noffset, NULL), | ||
| 108 | - fit_get_name(fit, image_noffset, NULL)); | ||
| 109 | - return 0; | ||
| 110 | + goto err; | ||
| 111 | } | ||
| 112 | |||
| 113 | return fit_image_verify_with_data(fit, image_noffset, data, size); | ||
| 114 | + | ||
| 115 | +err: | ||
| 116 | + printf("error!\n%s in '%s' image node\n", err_msg, | ||
| 117 | + fit_get_name(fit, image_noffset, NULL)); | ||
| 118 | + return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 122 | diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py | ||
| 123 | index 84b3f95850..6d5b43c3ba 100755 | ||
| 124 | --- a/test/py/tests/test_fit.py | ||
| 125 | +++ b/test/py/tests/test_fit.py | ||
| 126 | @@ -17,7 +17,7 @@ base_its = ''' | ||
| 127 | #address-cells = <1>; | ||
| 128 | |||
| 129 | images { | ||
| 130 | - kernel@1 { | ||
| 131 | + kernel-1 { | ||
| 132 | data = /incbin/("%(kernel)s"); | ||
| 133 | type = "kernel"; | ||
| 134 | arch = "sandbox"; | ||
| 135 | @@ -26,7 +26,7 @@ base_its = ''' | ||
| 136 | load = <0x40000>; | ||
| 137 | entry = <0x8>; | ||
| 138 | }; | ||
| 139 | - kernel@2 { | ||
| 140 | + kernel-2 { | ||
| 141 | data = /incbin/("%(loadables1)s"); | ||
| 142 | type = "kernel"; | ||
| 143 | arch = "sandbox"; | ||
| 144 | @@ -35,19 +35,19 @@ base_its = ''' | ||
| 145 | %(loadables1_load)s | ||
| 146 | entry = <0x0>; | ||
| 147 | }; | ||
| 148 | - fdt@1 { | ||
| 149 | + fdt-1 { | ||
| 150 | description = "snow"; | ||
| 151 | data = /incbin/("%(fdt)s"); | ||
| 152 | type = "flat_dt"; | ||
| 153 | arch = "sandbox"; | ||
| 154 | %(fdt_load)s | ||
| 155 | compression = "%(compression)s"; | ||
| 156 | - signature@1 { | ||
| 157 | + signature-1 { | ||
| 158 | algo = "sha1,rsa2048"; | ||
| 159 | key-name-hint = "dev"; | ||
| 160 | }; | ||
| 161 | }; | ||
| 162 | - ramdisk@1 { | ||
| 163 | + ramdisk-1 { | ||
| 164 | description = "snow"; | ||
| 165 | data = /incbin/("%(ramdisk)s"); | ||
| 166 | type = "ramdisk"; | ||
| 167 | @@ -56,7 +56,7 @@ base_its = ''' | ||
| 168 | %(ramdisk_load)s | ||
| 169 | compression = "%(compression)s"; | ||
| 170 | }; | ||
| 171 | - ramdisk@2 { | ||
| 172 | + ramdisk-2 { | ||
| 173 | description = "snow"; | ||
| 174 | data = /incbin/("%(loadables2)s"); | ||
| 175 | type = "ramdisk"; | ||
| 176 | @@ -67,10 +67,10 @@ base_its = ''' | ||
| 177 | }; | ||
| 178 | }; | ||
| 179 | configurations { | ||
| 180 | - default = "conf@1"; | ||
| 181 | - conf@1 { | ||
| 182 | - kernel = "kernel@1"; | ||
| 183 | - fdt = "fdt@1"; | ||
| 184 | + default = "conf-1"; | ||
| 185 | + conf-1 { | ||
| 186 | + kernel = "kernel-1"; | ||
| 187 | + fdt = "fdt-1"; | ||
| 188 | %(ramdisk_config)s | ||
| 189 | %(loadables_config)s | ||
| 190 | }; | ||
| 191 | @@ -410,7 +410,7 @@ def test_fit(u_boot_console): | ||
| 192 | |||
| 193 | # Try a ramdisk | ||
| 194 | with cons.log.section('Kernel + FDT + Ramdisk load'): | ||
| 195 | - params['ramdisk_config'] = 'ramdisk = "ramdisk@1";' | ||
| 196 | + params['ramdisk_config'] = 'ramdisk = "ramdisk-1";' | ||
| 197 | params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] | ||
| 198 | fit = make_fit(mkimage, params) | ||
| 199 | cons.restart_uboot() | ||
| 200 | @@ -419,7 +419,7 @@ def test_fit(u_boot_console): | ||
| 201 | |||
| 202 | # Configuration with some Loadables | ||
| 203 | with cons.log.section('Kernel + FDT + Ramdisk load + Loadables'): | ||
| 204 | - params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";' | ||
| 205 | + params['loadables_config'] = 'loadables = "kernel-2", "ramdisk-2";' | ||
| 206 | params['loadables1_load'] = ('load = <%#x>;' % | ||
| 207 | params['loadables1_addr']) | ||
| 208 | params['loadables2_load'] = ('load = <%#x>;' % | ||
| 209 | diff --git a/test/py/tests/vboot_forge.py b/test/py/tests/vboot_forge.py | ||
| 210 | index 0fb7ef4024..b41105bd0e 100644 | ||
| 211 | --- a/test/py/tests/vboot_forge.py | ||
| 212 | +++ b/test/py/tests/vboot_forge.py | ||
| 213 | @@ -376,12 +376,12 @@ def manipulate(root, strblock): | ||
| 214 | """ | ||
| 215 | Maliciously manipulates the structure to create a crafted FIT file | ||
| 216 | """ | ||
| 217 | - # locate /images/kernel@1 (frankly, it just expects it to be the first one) | ||
| 218 | + # locate /images/kernel-1 (frankly, it just expects it to be the first one) | ||
| 219 | kernel_node = root[0][0] | ||
| 220 | # clone it to save time filling all the properties | ||
| 221 | fake_kernel = kernel_node.clone() | ||
| 222 | # rename the node | ||
| 223 | - fake_kernel.name = b'kernel@2' | ||
| 224 | + fake_kernel.name = b'kernel-2' | ||
| 225 | # get rid of signatures/hashes | ||
| 226 | fake_kernel.children = [] | ||
| 227 | # NOTE: this simply replaces the first prop... either description or data | ||
| 228 | @@ -391,13 +391,13 @@ def manipulate(root, strblock): | ||
| 229 | root[0].children.append(fake_kernel) | ||
| 230 | |||
| 231 | # modify the default configuration | ||
| 232 | - root[1].props[0].value = b'conf@2\x00' | ||
| 233 | + root[1].props[0].value = b'conf-2\x00' | ||
| 234 | # clone the first (only?) configuration | ||
| 235 | fake_conf = root[1][0].clone() | ||
| 236 | # rename and change kernel and fdt properties to select the crafted kernel | ||
| 237 | - fake_conf.name = b'conf@2' | ||
| 238 | - fake_conf.props[0].value = b'kernel@2\x00' | ||
| 239 | - fake_conf.props[1].value = b'fdt@1\x00' | ||
| 240 | + fake_conf.name = b'conf-2' | ||
| 241 | + fake_conf.props[0].value = b'kernel-2\x00' | ||
| 242 | + fake_conf.props[1].value = b'fdt-1\x00' | ||
| 243 | # insert the new configuration under /configurations | ||
| 244 | root[1].children.append(fake_conf) | ||
| 245 | |||
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2021-27138-2.patch b/meta/recipes-bsp/u-boot/files/CVE-2021-27138-2.patch new file mode 100644 index 0000000000..946196c378 --- /dev/null +++ b/meta/recipes-bsp/u-boot/files/CVE-2021-27138-2.patch | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | From 3f04db891a353f4b127ed57279279f851c6b4917 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon Glass <sjg@chromium.org> | ||
| 3 | Date: Mon, 15 Feb 2021 17:08:12 -0700 | ||
| 4 | Subject: [PATCH] image: Check for unit addresses in FITs | ||
| 5 | |||
| 6 | Using unit addresses in a FIT is a security risk. Add a check for this | ||
| 7 | and disallow it. | ||
| 8 | |||
| 9 | CVE-2021-27138 | ||
| 10 | |||
| 11 | Signed-off-by: Simon Glass <sjg@chromium.org> | ||
| 12 | Reported-by: Bruce Monroe <bruce.monroe@intel.com> | ||
| 13 | Reported-by: Arie Haenel <arie.haenel@intel.com> | ||
| 14 | Reported-by: Julien Lenoir <julien.lenoir@intel.com> | ||
| 15 | |||
| 16 | CVE: CVE-2021-27138 | ||
| 17 | Upstream-Status: Backport[https://github.com/u-boot/u-boot/commit/3f04db891a353f4b127ed57279279f851c6b4917] | ||
| 18 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
| 19 | |||
| 20 | --- | ||
| 21 | common/image-fit.c | 56 +++++++++++++++++++++++++++++++++++++++++---- | ||
| 22 | test/py/tests/test_vboot.py | 9 ++++---- | ||
| 23 | 2 files changed, 57 insertions(+), 8 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/common/image-fit.c b/common/image-fit.c | ||
| 26 | index bcf395f6a1..28b3d2b191 100644 | ||
| 27 | --- a/common/image-fit.c | ||
| 28 | +++ b/common/image-fit.c | ||
| 29 | @@ -1568,6 +1568,34 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) | ||
| 30 | return (comp == image_comp); | ||
| 31 | } | ||
| 32 | |||
| 33 | +/** | ||
| 34 | + * fdt_check_no_at() - Check for nodes whose names contain '@' | ||
| 35 | + * | ||
| 36 | + * This checks the parent node and all subnodes recursively | ||
| 37 | + * | ||
| 38 | + * @fit: FIT to check | ||
| 39 | + * @parent: Parent node to check | ||
| 40 | + * @return 0 if OK, -EADDRNOTAVAIL is a node has a name containing '@' | ||
| 41 | + */ | ||
| 42 | +static int fdt_check_no_at(const void *fit, int parent) | ||
| 43 | +{ | ||
| 44 | + const char *name; | ||
| 45 | + int node; | ||
| 46 | + int ret; | ||
| 47 | + | ||
| 48 | + name = fdt_get_name(fit, parent, NULL); | ||
| 49 | + if (!name || strchr(name, '@')) | ||
| 50 | + return -EADDRNOTAVAIL; | ||
| 51 | + | ||
| 52 | + fdt_for_each_subnode(node, fit, parent) { | ||
| 53 | + ret = fdt_check_no_at(fit, node); | ||
| 54 | + if (ret) | ||
| 55 | + return ret; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + return 0; | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | int fit_check_format(const void *fit, ulong size) | ||
| 62 | { | ||
| 63 | int ret; | ||
| 64 | @@ -1589,10 +1617,27 @@ int fit_check_format(const void *fit, ulong size) | ||
| 65 | if (size == IMAGE_SIZE_INVAL) | ||
| 66 | size = fdt_totalsize(fit); | ||
| 67 | ret = fdt_check_full(fit, size); | ||
| 68 | + if (ret) | ||
| 69 | + ret = -EINVAL; | ||
| 70 | + | ||
| 71 | + /* | ||
| 72 | + * U-Boot stopped using unit addressed in 2017. Since libfdt | ||
| 73 | + * can match nodes ignoring any unit address, signature | ||
| 74 | + * verification can see the wrong node if one is inserted with | ||
| 75 | + * the same name as a valid node but with a unit address | ||
| 76 | + * attached. Protect against this by disallowing unit addresses. | ||
| 77 | + */ | ||
| 78 | + if (!ret && CONFIG_IS_ENABLED(FIT_SIGNATURE)) { | ||
| 79 | + ret = fdt_check_no_at(fit, 0); | ||
| 80 | |||
| 81 | + if (ret) { | ||
| 82 | + log_debug("FIT check error %d\n", ret); | ||
| 83 | + return ret; | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | if (ret) { | ||
| 87 | log_debug("FIT check error %d\n", ret); | ||
| 88 | - return -EINVAL; | ||
| 89 | + return ret; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | @@ -1955,10 +2000,13 @@ int fit_image_load(bootm_headers_t *images, ulong addr, | ||
| 94 | printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); | ||
| 95 | |||
| 96 | bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); | ||
| 97 | - if (fit_check_format(fit, IMAGE_SIZE_INVAL)) { | ||
| 98 | - printf("Bad FIT %s image format!\n", prop_name); | ||
| 99 | + ret = fit_check_format(fit, IMAGE_SIZE_INVAL); | ||
| 100 | + if (ret) { | ||
| 101 | + printf("Bad FIT %s image format! (err=%d)\n", prop_name, ret); | ||
| 102 | + if (CONFIG_IS_ENABLED(FIT_SIGNATURE) && ret == -EADDRNOTAVAIL) | ||
| 103 | + printf("Signature checking prevents use of unit addresses (@) in nodes\n"); | ||
| 104 | bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); | ||
| 105 | - return -ENOEXEC; | ||
| 106 | + return ret; | ||
| 107 | } | ||
| 108 | bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); | ||
| 109 | if (fit_uname) { | ||
diff --git a/meta/recipes-bsp/u-boot/u-boot-common.inc b/meta/recipes-bsp/u-boot/u-boot-common.inc index 5a8035f432..993478a73b 100644 --- a/meta/recipes-bsp/u-boot/u-boot-common.inc +++ b/meta/recipes-bsp/u-boot/u-boot-common.inc | |||
| @@ -15,6 +15,13 @@ PE = "1" | |||
| 15 | SRCREV = "c4fddedc48f336eabc4ce3f74940e6aa372de18c" | 15 | SRCREV = "c4fddedc48f336eabc4ce3f74940e6aa372de18c" |
| 16 | 16 | ||
| 17 | SRC_URI = "git://git.denx.de/u-boot.git \ | 17 | SRC_URI = "git://git.denx.de/u-boot.git \ |
| 18 | file://0001-add-valid-fdt-check.patch \ | ||
| 19 | file://CVE-2021-27097-1.patch \ | ||
| 20 | file://CVE-2021-27097-2.patch \ | ||
| 21 | file://CVE-2021-27097-3.patch \ | ||
| 22 | file://CVE-2021-27097-4.patch \ | ||
| 23 | file://CVE-2021-27138-1.patch \ | ||
| 24 | file://CVE-2021-27138-2.patch \ | ||
| 18 | " | 25 | " |
| 19 | 26 | ||
| 20 | S = "${WORKDIR}/git" | 27 | S = "${WORKDIR}/git" |
