Skip to content

Commit 6e117a5

Browse files
committed
update_disk.c: enforce bound over memcpy
1 parent 7a76369 commit 6e117a5

5 files changed

Lines changed: 356 additions & 3 deletions

File tree

config/examples/zynq7000_sdcard.config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ ELF=1
4141
# Stage payload at low DDR (clear of wolfBoot at 0x04000000-0x040FFFFF).
4242
WOLFBOOT_LOAD_ADDRESS=0x10000000
4343

44+
# Cap on the RAM load region. The disk image payload is copied to
45+
# WOLFBOOT_LOAD_ADDRESS before its header is authenticated, so the on-disk
46+
# fw_size must be bounded first (see src/update_disk.c). This is an example
47+
# config not tied to a real board, so the cap is just a sane sanity bound:
48+
# 700 MB is far larger than any realistic FIT image yet keeps the load well
49+
# clear of a 32-bit wrap back onto wolfBoot at 0x04000000. Size it to your
50+
# board's DDR (top_of_DDR - WOLFBOOT_LOAD_ADDRESS) for a real target.
51+
WOLFBOOT_RAMBOOT_MAX_SIZE=0x2BC00000
52+
4453
# DTB load address (Linux only, used by update_disk.c when a FIT image
4554
# carries a DTB). Ignored for bare-metal and for the appended-DTB Linux
4655
# flow. 16 MB clear of WOLFBOOT_LOAD_ADDRESS.

config/examples/zynqmp_sdcard.config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ WOLFBOOT_ORIGIN=0x8000000
129129
# Load Partition to RAM Address (Linux kernel loads here)
130130
WOLFBOOT_LOAD_ADDRESS?=0x10000000
131131

132+
# Cap on the RAM load region. The disk image payload is copied to
133+
# WOLFBOOT_LOAD_ADDRESS before its header is authenticated, so the on-disk
134+
# fw_size must be bounded first (see src/update_disk.c). This is an example
135+
# config not tied to a real board, so the cap is just a sane sanity bound:
136+
# 700 MB is far larger than any realistic FIT image yet keeps the load well
137+
# clear of a 32-bit wrap back onto wolfBoot. Size it to your board's DDR
138+
# (top_of_DDR - WOLFBOOT_LOAD_ADDRESS) for a real target.
139+
WOLFBOOT_RAMBOOT_MAX_SIZE=0x2BC00000
140+
132141
# DTS (Device Tree) load address
133142
WOLFBOOT_LOAD_DTS_ADDRESS?=0x1000
134143

src/update_disk.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ static uint8_t disk_encrypt_nonce[ENCRYPT_NONCE_SIZE];
9494
#define DISK_BLOCK_SIZE 512
9595
#endif
9696

97+
#if !defined(WOLFBOOT_FSP) && !defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
98+
# error "WOLFBOOT_RAMBOOT_MAX_SIZE required to bound the disk image RAM load"
99+
#endif
100+
97101
#ifdef DISK_ENCRYPT
98102

99103
/* Module-level storage for encryption key */
@@ -430,11 +434,26 @@ void RAMFUNCTION wolfBoot_start(void)
430434
continue;
431435
}
432436

437+
/* Bound the UNAUTHENTICATED image length before it drives the disk
438+
* read into the RAM load region. An attacker controlling the boot
439+
* media could otherwise declare an arbitrary fw_size and overrun the
440+
* load region before any integrity or signature check runs. Mirrors
441+
* the cap update_ram.c applies to RAMBOOT loads; on FSP the tolum
442+
* check below applies in addition (whichever is tighter wins). */
443+
#ifdef WOLFBOOT_RAMBOOT_MAX_SIZE
444+
if (os_image.fw_size > WOLFBOOT_RAMBOOT_MAX_SIZE) {
445+
wolfBoot_printf("Image size %u exceeds max RAM load size\r\n",
446+
os_image.fw_size);
447+
selected ^= 1;
448+
continue;
449+
}
450+
#endif
451+
433452
#ifdef WOLFBOOT_FSP
434453
/* Verify image size fits in low memory */
435454
if (os_image.fw_size > ((uint32_t)(stage2_params->tolum) -
436455
(uint32_t)(uintptr_t)load_address)) {
437-
wolfBoot_printf("Image size %d doesn't fit in low memory\r\n",
456+
wolfBoot_printf("Image size %u doesn't fit in low memory\r\n",
438457
os_image.fw_size);
439458
break;
440459
}

tools/unit-tests/Makefile

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128
5252
unit-update-flash-hook \
5353
unit-update-flash-self-update \
5454
unit-update-flash-enc unit-update-ram unit-update-ram-enc unit-update-ram-enc-nopart unit-update-ram-nofixed unit-update-ram-noramboot unit-update-flash-hwswap unit-pkcs11_store unit-psa_store unit-disk \
55-
unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-fwtpm-stub unit-tpm-rsa-exp \
55+
unit-update-disk unit-update-disk-oob unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-fwtpm-stub unit-tpm-rsa-exp \
5656
unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \
5757
unit-tpm-blob unit-policy-create unit-policy-sign unit-rot-auth unit-sdhci-response-bits \
5858
unit-sdhci-disk-unaligned unit-sign-encrypted-output \
@@ -186,7 +186,15 @@ unit-update-ram-nofixed:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN \
186186
-DWOLFBOOT_RAMBOOT_MAX_SIZE=WOLFBOOT_PARTITION_SIZE \
187187
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT \
188188
-DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
189-
unit-update-disk:CFLAGS+=-DMOCK_PARTITIONS -DPRINTF_ENABLED \
189+
# Bound the non-FSP disk load to this test's 64-byte load_buffer (TEST_PAYLOAD_SIZE),
190+
# the cap update_disk.c now requires; all images here are exactly that size.
191+
unit-update-disk:CFLAGS+=-DMOCK_PARTITIONS -DPRINTF_ENABLED -DWOLFBOOT_RAMBOOT_MAX_SIZE=0x40 \
192+
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
193+
# Non-FSP disk-boot OOB regression (CRIT-03). WOLFBOOT_RAMBOOT_MAX_SIZE is the
194+
# cap the loader applies to the unauthenticated header fw_size before loading to
195+
# RAM, the same bound update_disk.c and update_ram.c enforce.
196+
unit-update-disk-oob:CFLAGS+=-DMOCK_PARTITIONS -DPRINTF_ENABLED \
197+
-DWOLFBOOT_RAMBOOT_MAX_SIZE=0x1000 \
190198
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
191199
unit-string:CFLAGS+=-fno-builtin
192200

@@ -511,6 +519,9 @@ unit-update-flash-hwswap: ../../include/target.h unit-update-flash-hwswap.c
511519
unit-update-disk: ../../include/target.h unit-update-disk.c
512520
gcc -o $@ unit-update-disk.c $(CFLAGS) $(LDFLAGS)
513521

522+
unit-update-disk-oob: ../../include/target.h unit-update-disk-oob.c
523+
gcc -o $@ unit-update-disk-oob.c $(CFLAGS) $(LDFLAGS)
524+
514525
unit-pkcs11_store: ../../include/target.h unit-pkcs11_store.c
515526
gcc -o $@ $(WOLFCRYPT_SRC) unit-pkcs11_store.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
516527

0 commit comments

Comments
 (0)