diff options
Diffstat (limited to 'src/lib/fmap.c')
-rw-r--r-- | src/lib/fmap.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/lib/fmap.c b/src/lib/fmap.c index 377123afdc..2abe138cdd 100644 --- a/src/lib/fmap.c +++ b/src/lib/fmap.c @@ -4,6 +4,7 @@ #include <cbmem.h> #include <console/console.h> #include <fmap.h> +#include <metadata_hash.h> #include <stddef.h> #include <string.h> #include <symbols.h> @@ -27,9 +28,20 @@ uint64_t get_fmap_flash_offset(void) return FMAP_OFFSET; } -static int check_signature(const struct fmap *fmap) +static int verify_fmap(const struct fmap *fmap) { - return memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature)); + if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) + return -1; + + static bool done = false; + if (!CONFIG(CBFS_VERIFICATION) || !ENV_INITIAL_STAGE || done) + return 0; /* Only need to check hash in first stage. */ + + if (metadata_hash_verify_fmap(fmap, FMAP_SIZE) != VB2_SUCCESS) + return -1; + + done = true; + return 0; } static void report(const struct fmap *fmap) @@ -63,10 +75,12 @@ static void setup_preram_cache(struct mem_region_device *cache_mrdev) if (!(ENV_INITIAL_STAGE)) { /* NOTE: This assumes that the first stage will make at least one FMAP access (usually from finding CBFS). */ - if (!check_signature(fmap)) + if (!verify_fmap(fmap)) goto register_cache; printk(BIOS_ERR, "ERROR: FMAP cache corrupted?!\n"); + if (CONFIG(TOCTOU_SAFETY)) + die("TOCTOU safety relies on FMAP cache"); } /* In case we fail below, make sure the cache is invalid. */ @@ -80,7 +94,7 @@ static void setup_preram_cache(struct mem_region_device *cache_mrdev) /* memlayout statically guarantees that the FMAP_CACHE is big enough. */ if (rdev_readat(boot_rdev, fmap, FMAP_OFFSET, FMAP_SIZE) != FMAP_SIZE) return; - if (check_signature(fmap)) + if (verify_fmap(fmap)) return; report(fmap); @@ -111,8 +125,9 @@ static int find_fmap_directory(struct region_device *fmrd) if (fmap == NULL) return -1; - if (check_signature(fmap)) { - printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset); + if (verify_fmap(fmap)) { + printk(BIOS_ERR, "FMAP missing or corrupted at offset 0x%zx!\n", + offset); rdev_munmap(boot, fmap); return -1; } |