From a7b100291931f351d87e4297c8742103e40c81ea Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 2 Mar 2026 13:37:23 +0100 Subject: [PATCH 1/2] Fix image len bound check in update_ram.c --- src/update_ram.c | 4 ++ tools/unit-tests/unit-update-ram.c | 75 ++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/update_ram.c b/src/update_ram.c index 77f7f25b00..f2b38052c4 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -82,6 +82,10 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst) /* determine size of partition */ img_size = wolfBoot_image_size((uint8_t*)dst); + if (img_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) { + wolfBoot_printf("Invalid image size %u at %p\n", img_size, src); + return -1; + } /* Read the entire image into RAM */ wolfBoot_printf("Loading image %d bytes from %p to %p...", diff --git a/tools/unit-tests/unit-update-ram.c b/tools/unit-tests/unit-update-ram.c index 2de99a6b05..4550f59419 100644 --- a/tools/unit-tests/unit-update-ram.c +++ b/tools/unit-tests/unit-update-ram.c @@ -203,6 +203,69 @@ START_TEST (test_empty_panic) END_TEST +START_TEST (test_ramboot_invalid_header) +{ + struct wolfBoot_image img; + uint8_t bad_magic[4] = { 'G', 'O', 'L', 'F' }; + int ret; + + reset_mock_stats(); + prepare_flash(); + ext_flash_unlock(); + ext_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS, bad_magic, sizeof(bad_magic)); + ext_flash_lock(); + + memset(&img, 0, sizeof(img)); + ret = wolfBoot_ramboot(&img, + (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS, wolfboot_ram); + ck_assert_int_eq(ret, -1); + cleanup_flash(); +} +END_TEST + +START_TEST (test_ramboot_oversize_rejected) +{ + struct wolfBoot_image img; + uint32_t too_large = WOLFBOOT_PARTITION_SIZE; + int ret; + + reset_mock_stats(); + prepare_flash(); + add_payload(PART_BOOT, 1, TEST_SIZE_SMALL); + + ext_flash_unlock(); + ext_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + 4, + (const uint8_t *)&too_large, 4); + ext_flash_lock(); + + memset(&img, 0, sizeof(img)); + ret = wolfBoot_ramboot(&img, + (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS, wolfboot_ram); + ck_assert_int_eq(ret, -1); + cleanup_flash(); +} +END_TEST + +START_TEST (test_ramboot_success) +{ + struct wolfBoot_image img; + int ret; + + reset_mock_stats(); + prepare_flash(); + add_payload(PART_BOOT, 1, TEST_SIZE_SMALL); + + memset(&img, 0, sizeof(img)); + ret = wolfBoot_ramboot(&img, + (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS, wolfboot_ram); + ck_assert_int_eq(ret, 0); + ck_assert_int_eq(img.not_ext, 1); + ck_assert_int_eq(get_version_ramloaded(), 1); + cleanup_flash(); +} +END_TEST + + START_TEST (test_sunnyday_noupdate) { reset_mock_stats(); @@ -423,6 +486,9 @@ Suite *wolfboot_suite(void) /* Test cases */ TCase *empty_panic = tcase_create("Empty partition panic test"); + TCase *ramboot_invalid_header = tcase_create("Ramboot invalid header"); + TCase *ramboot_oversize = tcase_create("Ramboot oversize"); + TCase *ramboot_success = tcase_create("Ramboot success"); TCase *sunnyday_noupdate = tcase_create("Sunny day test with no update available"); TCase *forward_update_samesize = @@ -446,6 +512,9 @@ Suite *wolfboot_suite(void) tcase_add_test(empty_panic, test_empty_panic); + tcase_add_test(ramboot_invalid_header, test_ramboot_invalid_header); + tcase_add_test(ramboot_oversize, test_ramboot_oversize_rejected); + tcase_add_test(ramboot_success, test_ramboot_success); tcase_add_test(sunnyday_noupdate, test_sunnyday_noupdate); tcase_add_test(forward_update_samesize, test_forward_update_samesize); tcase_add_test(forward_update_tolarger, test_forward_update_tolarger); @@ -463,6 +532,9 @@ Suite *wolfboot_suite(void) suite_add_tcase(s, empty_panic); + suite_add_tcase(s, ramboot_invalid_header); + suite_add_tcase(s, ramboot_oversize); + suite_add_tcase(s, ramboot_success); suite_add_tcase(s, sunnyday_noupdate); suite_add_tcase(s, forward_update_samesize); suite_add_tcase(s, forward_update_tolarger); @@ -480,6 +552,9 @@ Suite *wolfboot_suite(void) /* Set timeout for tests */ tcase_set_timeout(empty_panic, 5); + tcase_set_timeout(ramboot_invalid_header, 5); + tcase_set_timeout(ramboot_oversize, 5); + tcase_set_timeout(ramboot_success, 5); tcase_set_timeout(sunnyday_noupdate, 5); tcase_set_timeout(forward_update_samesize, 5); tcase_set_timeout(forward_update_tolarger, 5); From 00bf88b69d0fa13d278e61438981c3e3945a1de3 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 2 Mar 2026 14:18:23 +0100 Subject: [PATCH 2/2] Added upper limit for NO_PARTITIONS builds --- Makefile | 1 + config/examples/polarfire_mpfs250.config | 1 + config/examples/raspi3-encrypted.config | 1 + config/examples/raspi3.config | 1 + config/examples/versal_vmk180_sdcard.config | 1 + include/target.h.in | 3 +++ src/update_ram.c | 10 ++++++++++ 7 files changed, 18 insertions(+) diff --git a/Makefile b/Makefile index ab8db988ec..d2c30541f4 100644 --- a/Makefile +++ b/Makefile @@ -604,6 +604,7 @@ include/target.h: $(TARGET_H_TEMPLATE) FORCE sed -e "s/@WOLFBOOT_DTS_UPDATE_ADDRESS@/$(WOLFBOOT_DTS_UPDATE_ADDRESS)/g" | \ sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \ sed -e "s/@WOLFBOOT_LOAD_DTS_ADDRESS@/$(WOLFBOOT_LOAD_DTS_ADDRESS)/g" | \ + sed -e "s/@WOLFBOOT_RAMBOOT_MAX_SIZE@/$(WOLFBOOT_RAMBOOT_MAX_SIZE)/g" | \ sed -e "s/@WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS@/$(WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS)/g" \ > $@ diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index 4b3ec64ff9..5c3ca74059 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -62,6 +62,7 @@ WOLFBOOT_LOAD_ADDRESS?=0x8E000000 # Partition layout for PolarFire SoC MPFS250T # Using update_disk loader we just need to specify the partition number or A/B WOLFBOOT_NO_PARTITIONS=1 +WOLFBOOT_RAMBOOT_MAX_SIZE=0x80000000 CFLAGS_EXTRA+=-DBOOT_PART_A=1 CFLAGS_EXTRA+=-DBOOT_PART_B=2 # Speed up disk partition read (512KB chunks - max DMA size) diff --git a/config/examples/raspi3-encrypted.config b/config/examples/raspi3-encrypted.config index 74ee2d87a7..c42f0fcc96 100644 --- a/config/examples/raspi3-encrypted.config +++ b/config/examples/raspi3-encrypted.config @@ -10,6 +10,7 @@ PKA?=0 WOLFTPM?=0 WOLFBOOT_NO_PARTITIONS=1 +WOLFBOOT_RAMBOOT_MAX_SIZE=0x20000000 WOLFBOOT_PARTITION_BOOT_ADDRESS=0x140000 WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x1140000 WOLFBOOT_PARTITION_SWAP_ADDRESS=0xFFFFFFFF diff --git a/config/examples/raspi3.config b/config/examples/raspi3.config index 60ca6bb3cb..26cd77f7ca 100644 --- a/config/examples/raspi3.config +++ b/config/examples/raspi3.config @@ -13,5 +13,6 @@ NO_XIP?=1 NO_QNX?=1 WOLFBOOT_SECTOR_SIZE=0x400 WOLFBOOT_NO_PARTITIONS=1 +WOLFBOOT_RAMBOOT_MAX_SIZE=0x20000000 WOLFBOOT_LOAD_ADDRESS?=0x3080000 WOLFBOOT_LOAD_DTS_ADDRESS?=0x400000 diff --git a/config/examples/versal_vmk180_sdcard.config b/config/examples/versal_vmk180_sdcard.config index 3201a76252..0db3ab2d93 100644 --- a/config/examples/versal_vmk180_sdcard.config +++ b/config/examples/versal_vmk180_sdcard.config @@ -66,6 +66,7 @@ CROSS_COMPILE=aarch64-none-elf- # These are 0-based indices into the parsed partition array: # part[0]=boot, part[1]=OFP_A, part[2]=OFP_B, part[3]=rootfs WOLFBOOT_NO_PARTITIONS=1 +WOLFBOOT_RAMBOOT_MAX_SIZE=0x80000000 CFLAGS_EXTRA+=-DBOOT_PART_A=1 CFLAGS_EXTRA+=-DBOOT_PART_B=2 diff --git a/include/target.h.in b/include/target.h.in index 8458fb9ab3..00069b8cd5 100644 --- a/include/target.h.in +++ b/include/target.h.in @@ -116,6 +116,9 @@ /* Load address in RAM for staged OS (update_ram only) */ #define WOLFBOOT_LOAD_ADDRESS @WOLFBOOT_LOAD_ADDRESS@ #endif + +/* Optional RAM-boot image size cap for targets without partitions */ +#define WOLFBOOT_RAMBOOT_MAX_SIZE @WOLFBOOT_RAMBOOT_MAX_SIZE@ #define WOLFBOOT_LOAD_DTS_ADDRESS @WOLFBOOT_LOAD_DTS_ADDRESS@ diff --git a/src/update_ram.c b/src/update_ram.c index f2b38052c4..d415fc7602 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -82,10 +82,20 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst) /* determine size of partition */ img_size = wolfBoot_image_size((uint8_t*)dst); +#if defined(WOLFBOOT_NO_PARTITIONS) +# ifndef WOLFBOOT_RAMBOOT_MAX_SIZE +# error "WOLFBOOT_RAMBOOT_MAX_SIZE required when WOLFBOOT_NO_PARTITIONS=1" +# endif + if (img_size > WOLFBOOT_RAMBOOT_MAX_SIZE) { + wolfBoot_printf("Invalid image size %u at %p\n", img_size, src); + return -1; + } +#elif defined(WOLFBOOT_PARTITION_SIZE) if (img_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) { wolfBoot_printf("Invalid image size %u at %p\n", img_size, src); return -1; } +#endif /* Read the entire image into RAM */ wolfBoot_printf("Loading image %d bytes from %p to %p...",