diff options
-rw-r--r-- | common/cmd_vbexport_test.c | 9 | ||||
-rw-r--r-- | common/cmd_vboot_twostop.c | 38 | ||||
-rw-r--r-- | include/chromeos/gbb.h | 14 | ||||
-rw-r--r-- | lib/chromeos/gbb.c | 52 |
4 files changed, 83 insertions, 30 deletions
diff --git a/common/cmd_vbexport_test.c b/common/cmd_vbexport_test.c index c267e12f47..cf7b9f95ac 100644 --- a/common/cmd_vbexport_test.c +++ b/common/cmd_vbexport_test.c @@ -403,10 +403,10 @@ static uint8_t *read_gbb_from_firmware(void) firmware_storage_t file; struct twostop_fmap fmap; void *gbb; - size_t size; + size_t gbb_size; gbb = fdt_decode_chromeos_alloc_region(gd->blob, - "google-binary-block", &size); + "google-binary-block", &gbb_size); if (!gbb) { VbExDebug("Failed to find gbb region!\n"); return NULL; @@ -423,12 +423,13 @@ static uint8_t *read_gbb_from_firmware(void) return NULL; } - if (gbb_init(gbb, &file, fmap.readonly.gbb.offset)) { + if (gbb_init(gbb, &file, fmap.readonly.gbb.offset, gbb_size)) { VbExDebug("Failed to read GBB!\n"); return NULL; } - if (gbb_read_bmp_block(gbb, &file, fmap.readonly.gbb.offset)) { + if (gbb_read_bmp_block(gbb, &file, fmap.readonly.gbb.offset, + gbb_size)) { VbExDebug("Failed to load BMP Block in GBB!\n"); return NULL; } diff --git a/common/cmd_vboot_twostop.c b/common/cmd_vboot_twostop.c index 8659b66b3a..2d8bf37e45 100644 --- a/common/cmd_vboot_twostop.c +++ b/common/cmd_vboot_twostop.c @@ -268,8 +268,8 @@ static void wipe_unused_memory(crossystem_data_t *cdata, static VbError_t twostop_init_vboot_library(firmware_storage_t *file, void *gbb, - uint32_t gbb_offset, crossystem_data_t *cdata, - VbCommonParams *cparams) + uint32_t gbb_offset, size_t gbb_size, + crossystem_data_t *cdata, VbCommonParams *cparams) { VbError_t err; VbInitParams iparams; @@ -297,11 +297,11 @@ twostop_init_vboot_library(firmware_storage_t *file, void *gbb, /* Load required information of GBB */ if (iparams.out_flags & VB_INIT_OUT_ENABLE_DISPLAY) - if (gbb_read_bmp_block(gbb, file, gbb_offset)) + if (gbb_read_bmp_block(gbb, file, gbb_offset, gbb_size)) return 1; if (cdata->boot_developer_switch || iparams.out_flags & VB_INIT_OUT_ENABLE_RECOVERY) { - if (gbb_read_recovery_key(gbb, file, gbb_offset)) + if (gbb_read_recovery_key(gbb, file, gbb_offset, gbb_size)) return 1; } @@ -402,8 +402,8 @@ out: static uint32_t twostop_select_and_set_main_firmware(struct twostop_fmap *fmap, - firmware_storage_t *file, - void *gbb, crossystem_data_t *cdata, + firmware_storage_t *file, void *gbb, + size_t gbb_size, crossystem_data_t *cdata, void *vb_shared_data, int *boot_mode, void **fw_blob_ptr, uint32_t *fw_size_ptr) { @@ -425,7 +425,7 @@ twostop_select_and_set_main_firmware(struct twostop_fmap *fmap, } if (twostop_init_vboot_library(file, gbb, fmap->readonly.gbb.offset, - cdata, &cparams) + gbb_size, cdata, &cparams) != VBERROR_SUCCESS) { VBDEBUG(PREFIX "failed to init vboot library\n"); return VB_SELECT_ERROR; @@ -513,7 +513,8 @@ twostop_jump(crossystem_data_t *cdata, void *fw_blob, uint32_t fw_size) static int twostop_init(struct twostop_fmap *fmap, firmware_storage_t *file, - void **gbbp, crossystem_data_t *cdata, void *vb_shared_data) + void **gbbp, size_t gbb_size, crossystem_data_t *cdata, + void *vb_shared_data) { cros_gpio_t wpsw, recsw, devsw; GoogleBinaryBlockHeader *gbbh; @@ -561,14 +562,14 @@ twostop_init(struct twostop_fmap *fmap, firmware_storage_t *file, /* Load basic parts of gbb blob */ #ifdef CONFIG_HARDWARE_MAPPED_SPI - if (gbb_init(gbbp, file, fmap->readonly.gbb.offset)) { + if (gbb_init(gbbp, file, fmap->readonly.gbb.offset, gbb_size)) { VBDEBUG(PREFIX "failed to read gbb\n"); goto out; } gbb = *gbbp; #else gbb = *gbbp; - if (gbb_init(gbb, file, fmap->readonly.gbb.offset)) { + if (gbb_init(gbb, file, fmap->readonly.gbb.offset, gbb_size)) { VBDEBUG(PREFIX "failed to read gbb\n"); goto out; } @@ -670,14 +671,14 @@ twostop_main_firmware(struct twostop_fmap *fmap, void *gbb, * @param verify 1 to verify data, 0 to skip this step * @return 0 if ok, -1 on error */ -static int setup_gbb_and_cdata(void **gbb, crossystem_data_t **cdata, - int verify) +static int setup_gbb_and_cdata(void **gbb, size_t *gbb_size, + crossystem_data_t **cdata, int verify) { size_t size; #ifndef CONFIG_HARDWARE_MAPPED_SPI *gbb = fdt_decode_chromeos_alloc_region(gd->blob, - "google-binary-block", &size); + "google-binary-block", gbb_size); if (!*gbb) { VBDEBUG(PREFIX "google-binary-block missing " @@ -717,23 +718,25 @@ twostop_boot(void) firmware_storage_t file; crossystem_data_t *cdata; void *gbb; + size_t gbb_size = 0; void *vb_shared_data; void *fw_blob = NULL; uint32_t fw_size = 0; uint32_t selection; int boot_mode = FIRMWARE_TYPE_NORMAL; - if (setup_gbb_and_cdata(&gbb, &cdata, 0)) + if (setup_gbb_and_cdata(&gbb, &gbb_size, &cdata, 0)) return VB_SELECT_ERROR; vb_shared_data = cdata->vb_shared_data; - if (twostop_init(&fmap, &file, &gbb, cdata, vb_shared_data)) { + if (twostop_init(&fmap, &file, &gbb, gbb_size, cdata, + vb_shared_data)) { VBDEBUG(PREFIX "failed to init twostop boot\n"); return VB_SELECT_ERROR; } selection = twostop_select_and_set_main_firmware(&fmap, &file, - gbb, cdata, vb_shared_data, + gbb, gbb_size, cdata, vb_shared_data, &boot_mode, &fw_blob, &fw_size); VBDEBUG(PREFIX "selection of bootstub: %s\n", str_selection(selection)); @@ -786,6 +789,7 @@ twostop_readwrite_main_firmware(void) struct twostop_fmap fmap; crossystem_data_t *cdata; void *gbb; + size_t gbb_size; if (fdt_decode_twostop_fmap(gd->blob, &fmap)) { VBDEBUG(PREFIX "failed to decode fmap\n"); @@ -796,7 +800,7 @@ twostop_readwrite_main_firmware(void) #ifdef CONFIG_HARDWARE_MAPPED_SPI gbb = (void *) (fmap.readonly.gbb.offset + fmap.flash_base); #endif - if (setup_gbb_and_cdata(&gbb, &cdata, 1)) + if (setup_gbb_and_cdata(&gbb, &gbb_size, &cdata, 1)) return VB_SELECT_ERROR; /* diff --git a/include/chromeos/gbb.h b/include/chromeos/gbb.h index c3bc304b38..d3770f51b1 100644 --- a/include/chromeos/gbb.h +++ b/include/chromeos/gbb.h @@ -22,9 +22,11 @@ * @param gbb Buffer for holding GBB * @param file Flashrom device handle * @param gbb_offset Offset of GBB in flashrom device + * @param gbb_size Size of the buffer holding GBB * @return zero if this succeeds, non-zero if this fails */ -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 /** @@ -33,10 +35,11 @@ int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset); * @param gbb Buffer for holding GBB * @param file Flashrom device handle * @param gbb_offset Offset of GBB in flashrom device + * @param gbb_size Size of the buffer holding GBB * @return zero if this succeeds, non-zero if this fails */ -int gbb_read_bmp_block(read_buf_type gbb, - firmware_storage_t *file, uint32_t gbb_offset); +int gbb_read_bmp_block(read_buf_type gbb, firmware_storage_t *file, + uint32_t gbb_offset, size_t gbb_size); /* * This loads the recovery key of GBB from flashrom. @@ -44,10 +47,11 @@ int gbb_read_bmp_block(read_buf_type gbb, * @param gbb Buffer for holding GBB * @param file Flashrom device handle * @param gbb_offset Offset of GBB in flashrom device + * @param gbb_size Size of the buffer holding GBB * @return zero if this succeeds, non-zero if this fails */ -int gbb_read_recovery_key(read_buf_type gbb, - firmware_storage_t *file, uint32_t gbb_offset); +int gbb_read_recovery_key(read_buf_type gbb, firmware_storage_t *file, + uint32_t gbb_offset, size_t gbb_size); #else diff --git a/lib/chromeos/gbb.c b/lib/chromeos/gbb.c index 25d5741318..77e524b2c1 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, |