Matt DeVillier has submitted this change. ( https://review.coreboot.org/c/coreboot/+/84541?usp=email )
Change subject: drivers/efi/capsules: check for overflows of capsule sizes ......................................................................
drivers/efi/capsules: check for overflows of capsule sizes
As was pointed out in comments on CB:83422 [0], the code lacks overflow checks: - when computing size of capsules in a single capsule block - when computing size of capsules in all capsule blocks
If an overflow is triggered, the code might allocate a capsule buffer smaller than the data that's going to be written to it leading to overwriting memory after the buffer.
[0]: https://review.coreboot.org/c/coreboot/+/83422
Change-Id: I43d17d77197fc2cbd721d47941101551603c352a Signed-off-by: Sergii Dmytruk sergii.dmytruk@3mdeb.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/84541 Reviewed-by: Krystian Hebel krystian.hebel@3mdeb.com Reviewed-by: Paul Menzel paulepanter@mailbox.org Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M src/drivers/efi/capsules.c 1 file changed, 15 insertions(+), 1 deletion(-)
Approvals: Paul Menzel: Looks good to me, but someone else must approve Krystian Hebel: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/src/drivers/efi/capsules.c b/src/drivers/efi/capsules.c index e674e33..38178c6 100644 --- a/src/drivers/efi/capsules.c +++ b/src/drivers/efi/capsules.c @@ -344,7 +344,15 @@ goto error; }
- data_size += ALIGN_UP(capsule_hdr->CapsuleImageSize, CAPSULE_ALIGNMENT); + uint64_t capsule_size = + ALIGN_UP((uint64_t)capsule_hdr->CapsuleImageSize, CAPSULE_ALIGNMENT); + if (data_size + capsule_size < data_size) { /* overflow detection */ + printk(BIOS_ERR, + "capsules: capsules block size is too large (%#llx + %#llx) for uint64.\n", + data_size, capsule_size); + goto error; + } + data_size += capsule_size;
uint32_t size_left = capsule_hdr->CapsuleImageSize; while (size_left != 0) { @@ -384,6 +392,12 @@ }
/* Increase the size only on successful parsing of the capsule block. */ + if (*total_data_size + data_size < *total_data_size) { /* overflow detection */ + printk(BIOS_ERR, + "capsules: total capsule's size is too large (%#llx + %#llx) for uint64.\n", + *total_data_size, data_size); + goto error; + } *total_data_size += data_size;
return block;