Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge branch '2021-02-15-fix-CVE-2021-27097-CVE-2021-27138'
  • Loading branch information
trini committed Feb 16, 2021
2 parents 6144438 + 3f04db8 commit b6f4c75
Show file tree
Hide file tree
Showing 27 changed files with 781 additions and 101 deletions.
2 changes: 1 addition & 1 deletion arch/arm/cpu/armv8/sec_firmware.c
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/bootefi.c
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions cmd/bootm.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/disk.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion cmd/fpga.c
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/nand.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion cmd/source.c
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/ximg.c
Expand Up @@ -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;
}
Expand Down
20 changes: 20 additions & 0 deletions common/Kconfig.boot
Expand Up @@ -63,13 +63,23 @@ 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 RSA_VERIFY
select IMAGE_SIGN_INFO
select FIT_FULL_CHECK
help
This option enables signature verification of FIT uImages,
using a hash signed and verified using RSA. If
Expand Down Expand Up @@ -159,6 +169,15 @@ 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
Expand All @@ -168,6 +187,7 @@ config SPL_FIT_SIGNATURE
select SPL_RSA
select SPL_RSA_VERIFY
select SPL_IMAGE_SIGN_INFO
select SPL_FIT_FULL_CHECK

config SPL_LOAD_FIT
bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)"
Expand Down
11 changes: 11 additions & 0 deletions common/fdt_region.c
Expand Up @@ -43,6 +43,7 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
int depth = -1;
int want = 0;
int base = fdt_off_dt_struct(fdt);
bool expect_end = false;

end = path;
*end = '\0';
Expand All @@ -59,6 +60,10 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
tag = fdt_next_tag(fdt, offset, &nextoffset);
stop_at = nextoffset;

/* If we see two root nodes, something is wrong */
if (expect_end && tag != FDT_END)
return -FDT_ERR_BADLAYOUT;

switch (tag) {
case FDT_PROP:
include = want >= 2;
Expand All @@ -81,6 +86,10 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
if (depth == FDT_MAX_DEPTH)
return -FDT_ERR_BADSTRUCTURE;
name = fdt_get_name(fdt, offset, &len);

/* The root node must have an empty name */
if (!depth && *name)
return -FDT_ERR_BADLAYOUT;
if (end - path + 2 + len >= path_len)
return -FDT_ERR_NOSPACE;
if (end != path + 1)
Expand Down Expand Up @@ -108,6 +117,8 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
while (end > path && *--end != '/')
;
*end = '\0';
if (depth == -1)
expect_end = true;
break;

case FDT_END:
Expand Down
2 changes: 1 addition & 1 deletion common/image-fdt.c
Expand Up @@ -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,
Expand Down
22 changes: 20 additions & 2 deletions common/image-fit-sig.c
Expand Up @@ -149,6 +149,14 @@ static int fit_image_verify_sig(const void *fit, int image_noffset,
fdt_for_each_subnode(noffset, fit, image_noffset) {
const char *name = fit_get_name(fit, noffset, NULL);

/*
* We don't support this since libfdt considers names with the
* name root but different @ suffix to be equal
*/
if (strchr(name, '@')) {
err_msg = "Node name contains @";
goto error;
}
if (!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
ret = fit_image_check_sig(fit, noffset, data,
Expand Down Expand Up @@ -398,16 +406,26 @@ static int fit_config_verify_sig(const void *fit, int conf_noffset,
return -EPERM;
}

int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
const void *sig_blob)
static int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
const void *sig_blob)
{
const char *name = fit_get_name(fit, conf_noffset, NULL);
int noffset;
int sig_node;
int verified = 0;
int reqd_sigs = 0;
bool reqd_policy_all = true;
const char *reqd_mode;

/*
* We don't support this since libfdt considers names with the
* name root but different @ suffix to be equal
*/
if (strchr(name, '@')) {
printf("Configuration node '%s' contains '@'\n", name);
return -EPERM;
}

/* Work out what we need to verify */
sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
Expand Down

0 comments on commit b6f4c75

Please sign in to comment.