fmap: Die immediately on verification failure

A recent security audit has exposed a TOCTOU risk in the FMAP
verification code: if the flash returns a tampered FMAP during the first
setup_preram_cache(), we will abort generating the cache but only after
already filling the persistent CAR/SRAM region with the tampered
version. Then we will fall back into the direct access path, which could
succeed if the flash now returns the original valid FMAP. In later
stages, we will just use the data from the persistent CAR/SRAM region as
long as it looks like an FMAP without verifying the hash again (because
the hash is only linked into the initial stage).

This patch fixes the issue by just calling die() immediately if FMAP
hash verification fails. When the verification fails, there's no
recourse anyway -- if we're not dying here we would be dying in
cbfs_get_boot_device() instead. There is no legitimate scenario where
it would still be possible to continue booting after this hash
verification fails.

Change-Id: I59ec91c3e5a59fdd960b0ba54ae5f15ddb850480
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/78903
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Julius Werner 2023-11-02 15:44:12 -07:00
parent 5bc5b1d024
commit 682cb3b564
1 changed files with 3 additions and 1 deletions

View File

@ -38,8 +38,10 @@ static int verify_fmap(const struct fmap *fmap)
if (!CONFIG(CBFS_VERIFICATION) || !ENV_INITIAL_STAGE || done) if (!CONFIG(CBFS_VERIFICATION) || !ENV_INITIAL_STAGE || done)
return 0; /* Only need to check hash in first stage. */ return 0; /* Only need to check hash in first stage. */
/* On error we need to die right here, lest we risk a TOCTOU attack where the cache is
filled with a tampered FMAP but the later fallback path is fed a valid one. */
if (metadata_hash_verify_fmap(fmap, FMAP_SIZE) != VB2_SUCCESS) if (metadata_hash_verify_fmap(fmap, FMAP_SIZE) != VB2_SUCCESS)
return -1; die("FMAP verification failure");
done = true; done = true;
return 0; return 0;