F-12873: update_disk: FSP low-mem check reuses validated slot_max

The final image-size check re-derived the low-memory limit with a
uint32 subtraction and no ordering check, so an inverted tolum
wrapped into a near-2^32 limit and accepted any image. Compare the
tolum/load_address ordering in 32-bit (low-memory) form when
computing slot_max, and reuse that validated value in the check.
Add a unit test for the inverted-tolum case (fails closed, both
slots rejected).
pull/883/head
Daniele Lacamera 2026-09-07 14:40:35 +02:00
parent 173bb298e9
commit 394f160a83
2 changed files with 30 additions and 8 deletions

View File

@ -547,11 +547,15 @@ void RAMFUNCTION wolfBoot_start(void)
* The header sits ahead of the payload in the same file, hence the
* IMAGE_HEADER_SIZE. */
#if defined(WOLFBOOT_FSP)
/* Fail closed on an inverted tolum: the subtraction would otherwise wrap
* to a near-2^64 bound, which is the opposite of a cap. */
if ((uintptr_t)(stage2_params->tolum) > (uintptr_t)load_address) {
slot_max = (uint64_t)(uintptr_t)(stage2_params->tolum) -
(uint64_t)(uintptr_t)load_address;
/* Fail closed on an inverted tolum: with tolum at or below the load
* address there is no low-memory window, so the cap is zero. Both
* are low-memory addresses, so compare them in their 32-bit form.
* The subtraction would otherwise wrap into a near-2^32 bound, which
* is the opposite of a cap. */
if ((uint32_t)(uintptr_t)(stage2_params->tolum) >
(uint32_t)(uintptr_t)load_address) {
slot_max = (uint64_t)(uint32_t)(uintptr_t)(stage2_params->tolum) -
(uint64_t)(uint32_t)(uintptr_t)load_address;
}
else {
slot_max = 0;
@ -697,9 +701,10 @@ void RAMFUNCTION wolfBoot_start(void)
#endif
#ifdef WOLFBOOT_FSP
/* Verify image size fits in low memory */
if (os_image.fw_size > ((uint32_t)(stage2_params->tolum) -
(uint32_t)(uintptr_t)load_address)) {
/* Verify image size fits in low memory. Reuse the validated
* slot_max: it is zero when tolum is inverted, where the raw
* subtraction would wrap into a near-2^32 limit. */
if (os_image.fw_size > slot_max) {
wolfBoot_printf("Image size %u doesn't fit in low memory\r\n",
os_image.fw_size);
selected ^= 1;

View File

@ -236,6 +236,22 @@ START_TEST(test_fsp_both_slots_oversized_panics)
}
END_TEST
START_TEST(test_fsp_inverted_tolum_rejects_both_slots)
{
/* tolum below the load address inverts the low-memory limit. The
* limit must fail closed (no slot may load), not wrap into a
* near-2^32 limit that accepts any image. */
reset_mocks();
mock_stage2_params.tolum =
(uint32_t)((uintptr_t)load_buffer - 1);
wolfBoot_start();
ck_assert_int_gt(wolfBoot_panicked, 0);
ck_assert_int_eq(mock_do_boot_called, 0);
}
END_TEST
START_TEST(test_fsp_fitting_slot_boots)
{
/* Both slots fit and versions are equal: primary (A) boots. */
@ -258,6 +274,7 @@ Suite *wolfboot_suite(void)
tcase_add_test(tc, test_fsp_oversized_slot_falls_back_to_other_slot);
tcase_add_test(tc, test_fsp_both_slots_oversized_panics);
tcase_add_test(tc, test_fsp_inverted_tolum_rejects_both_slots);
tcase_add_test(tc, test_fsp_fitting_slot_boots);
suite_add_tcase(s, tc);