diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chromeos/gbb.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/lib/chromeos/gbb.c b/lib/chromeos/gbb.c index 25d57413185..77e524b2c1c 100644 --- a/lib/chromeos/gbb.c +++ b/lib/chromeos/gbb.c @@ -16,16 +16,39 @@ #define PREFIX "gbb: " -int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset) +int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset, + size_t gbb_size) { #ifndef CONFIG_HARDWARE_MAPPED_SPI GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; + uint32_t hwid_end; + uint32_t rootkey_end; if (file->read(file, gbb_offset, sizeof(*gbbh), gbbh)) { VBDEBUG(PREFIX "failed to read GBB header\n"); return 1; } + hwid_end = gbbh->hwid_offset + gbbh->hwid_size; + rootkey_end = gbbh->rootkey_offset + gbbh->rootkey_size; + if (hwid_end < gbbh->hwid_offset || hwid_end > gbb_size || + rootkey_end < gbbh->rootkey_offset || + rootkey_end > gbb_size) { + VBDEBUG(PREFIX "%s: invalid gbb header entries\n", __func__); + VBDEBUG(PREFIX " hwid_end=%x\n", hwid_end); + VBDEBUG(PREFIX " gbbh->hwid_offset=%x\n", gbbh->hwid_offset); + VBDEBUG(PREFIX " gbb_size=%x\n", gbb_size); + VBDEBUG(PREFIX " rootkey_end=%x\n", rootkey_end); + VBDEBUG(PREFIX " gbbh->rootkey_offset=%x\n", + gbbh->rootkey_offset); + VBDEBUG(PREFIX " %d, %d, %d, %d\n", + hwid_end < gbbh->hwid_offset, + hwid_end >= gbb_size, + rootkey_end < gbbh->rootkey_offset, + rootkey_end >= gbb_size); + return 1; + } + if (file->read(file, gbb_offset + gbbh->hwid_offset, gbbh->hwid_size, gbb + gbbh->hwid_offset)) { @@ -40,6 +63,7 @@ int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset) return 1; } #else + /* No data is actually moved in this case so no bounds checks. */ if (file->read(file, gbb_offset, sizeof(GoogleBinaryBlockHeader), gbb)) { VBDEBUG(PREFIX "failed to read GBB header\n"); @@ -51,9 +75,16 @@ int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset) } #ifndef CONFIG_HARDWARE_MAPPED_SPI -int gbb_read_bmp_block(void *gbb, firmware_storage_t *file, uint32_t gbb_offset) +int gbb_read_bmp_block(void *gbb, firmware_storage_t *file, uint32_t gbb_offset, + size_t gbb_size) { GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; + uint32_t bmpfv_end = gbbh->bmpfv_offset + gbbh->bmpfv_size; + + if (bmpfv_end < gbbh->bmpfv_offset || bmpfv_end > gbb_size) { + VBDEBUG(PREFIX "%s: invalid gbb header entries\n", __func__); + return 1; + } if (file->read(file, gbb_offset + gbbh->bmpfv_offset, gbbh->bmpfv_size, @@ -65,10 +96,23 @@ int gbb_read_bmp_block(void *gbb, firmware_storage_t *file, uint32_t gbb_offset) return 0; } -int gbb_read_recovery_key(void *gbb, - firmware_storage_t *file, uint32_t gbb_offset) +int gbb_read_recovery_key(void *gbb, firmware_storage_t *file, + uint32_t gbb_offset, size_t gbb_size) { GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; + uint32_t rkey_end = gbbh->recovery_key_offset + + gbbh->recovery_key_size; + + if (rkey_end < gbbh->recovery_key_offset || rkey_end > gbb_size) { + VBDEBUG(PREFIX "%s: invalid gbb header entries\n", __func__); + VBDEBUG(PREFIX " gbbh->recovery_key_offset=%x\n", + gbbh->recovery_key_offset); + VBDEBUG(PREFIX " gbbh->recovery_key_size=%x\n", + gbbh->recovery_key_size); + VBDEBUG(PREFIX " rkey_end=%x\n", rkey_end); + VBDEBUG(PREFIX " gbb_size=%x\n", gbb_size); + return 1; + } if (file->read(file, gbb_offset + gbbh->recovery_key_offset, gbbh->recovery_key_size, |