aboutsummaryrefslogtreecommitdiff
path: root/src/lib/fmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/fmap.c')
-rw-r--r--src/lib/fmap.c27
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;
}