mirror of https://github.com/wolfSSL/wolfBoot.git
F-11028: panic when both RAM-boot images fail verification
The RAM boot loop switched to the other partition on a verification failure (active ^= 1, continue) with a comment claiming the failing image was invalidated, but nothing was invalidated: wolfBoot_fallback_is_possible() only sees that both partitions carry nonzero versions. Two present but invalid images therefore alternated indefinitely, re-verifying forever. (The flash path does not have this hole because it erases the failing partition, which zeroes its version and makes the second fallback check fail.) Track the candidates attempted this boot: once both partitions have failed, panic with a clear message. Same-version images are used in the regression test so the anti-rollback guard cannot mask the alternation. unit-update-ram gains test_both_images_corrupted_panics: both partitions carry valid-version images with corrupted digests; the boot must panic after exactly two attempts. Pre-fix the loop ran unbounded (process had to be killed; ~60k partition switches in 30 s). Verification: - Built: unit-update-ram, unit-update-ram-enc, unit-update-ram-nofixed, unit-update-ram-uboot all compile. - Tested: unit-update-ram 20/20, unit-update-ram-nofixed 3/3, unit-update-ram-uboot 5/5; the new test shows Boot fail, Update fail, panic. - Pitfalls: attempt tracking is per boot session (local), no new persistent state; the flash path is untouched. - Style: cstyle-check.sh flag count on both changed files is unchanged from the pre-change versions (pre-existing FMT/R1). - Message: F-11028: prefix, no co-author trailers. - Note: unit-update-ram.c defines 21 tests but wires 20 into the suite (test_forward_update_samesize_notrigger was never added); pre-existing, left as-is.pull/870/head
parent
e02a734e72
commit
e108d4e86c
|
|
@ -269,6 +269,9 @@ static int uboot_legacy_header_valid(const uint8_t *hdr, uint32_t total)
|
|||
void RAMFUNCTION wolfBoot_start(void)
|
||||
{
|
||||
int active = -1, ret = 0;
|
||||
/* Candidates already tried this boot; a failed RAM image cannot be
|
||||
* erased to invalidate it like the flash path does. */
|
||||
int tried_boot = 0, tried_update = 0;
|
||||
struct wolfBoot_image os_image;
|
||||
BENCHMARK_DECLARE();
|
||||
#ifdef WOLFBOOT_UBOOT_LEGACY
|
||||
|
|
@ -425,12 +428,24 @@ backup_on_failure:
|
|||
wolfBoot_printf("Impossible recovery with fallback.\n");
|
||||
wolfBoot_panic();
|
||||
break;
|
||||
} else {
|
||||
/* Invalidate failing image and switch to the other partition */
|
||||
active ^= 1;
|
||||
wolfBoot_printf("Active is now: %d\n", active);
|
||||
continue;
|
||||
}
|
||||
if (active == PART_BOOT)
|
||||
tried_boot = 1;
|
||||
else
|
||||
tried_update = 1;
|
||||
if (tried_boot && tried_update) {
|
||||
/* Both partitions were tried and both failed: the images that
|
||||
* made fallback look possible are invalid, and nothing left to
|
||||
* boot. */
|
||||
wolfBoot_printf(
|
||||
"Both images failed verification; no valid image to boot.\n");
|
||||
wolfBoot_panic();
|
||||
break;
|
||||
}
|
||||
/* Switch to the other partition */
|
||||
active ^= 1;
|
||||
wolfBoot_printf("Active is now: %d\n", active);
|
||||
continue;
|
||||
}
|
||||
#ifdef UNIT_TEST
|
||||
if (wolfBoot_panicked != 0) {
|
||||
|
|
|
|||
|
|
@ -476,6 +476,32 @@ START_TEST (test_invalid_sha) {
|
|||
cleanup_flash();
|
||||
}
|
||||
|
||||
START_TEST (test_both_images_corrupted_panics) {
|
||||
uint8_t bad_digest[SHA256_DIGEST_SIZE];
|
||||
reset_mock_stats();
|
||||
prepare_flash();
|
||||
/* Same version in both partitions: after a failure the loop must not
|
||||
* be stopped by the anti-rollback guard, only by noticing that both
|
||||
* candidates have already failed. */
|
||||
add_payload(PART_BOOT, 2, TEST_SIZE_SMALL);
|
||||
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);
|
||||
|
||||
/* Corrupt both digests: two present images (nonzero versions, so the
|
||||
* fallback check passes) that both fail verification. The boot loop
|
||||
* must panic once both have been tried, not alternate forever. */
|
||||
memset(bad_digest, 0xBA, SHA256_DIGEST_SIZE);
|
||||
ext_flash_unlock();
|
||||
ext_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + DIGEST_TLV_OFF_IN_HDR + 4, bad_digest, SHA256_DIGEST_SIZE);
|
||||
ext_flash_write(WOLFBOOT_PARTITION_UPDATE_ADDRESS + DIGEST_TLV_OFF_IN_HDR + 4, bad_digest, SHA256_DIGEST_SIZE);
|
||||
ext_flash_lock();
|
||||
|
||||
wolfBoot_start();
|
||||
ck_assert(!wolfBoot_staged_ok);
|
||||
ck_assert_int_eq(wolfBoot_panicked, 1);
|
||||
cleanup_flash();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_emergency_rollback_to_older_version_denied) {
|
||||
uint8_t testing_flags[5] = { IMG_STATE_TESTING, 'B', 'O', 'O', 'T' };
|
||||
reset_mock_stats();
|
||||
|
|
@ -597,6 +623,7 @@ Suite *wolfboot_suite(void)
|
|||
TCase *emergency_rollback_failure_due_to_bad_update = tcase_create("Emergency rollback failure due to bad update");
|
||||
TCase *empty_boot_partition_update = tcase_create("Empty boot partition update");
|
||||
TCase *empty_boot_but_update_sha_corrupted_denied = tcase_create("Empty boot partition but update SHA corrupted");
|
||||
TCase *both_images_corrupted = tcase_create("Both images corrupted");
|
||||
|
||||
|
||||
|
||||
|
|
@ -620,6 +647,7 @@ Suite *wolfboot_suite(void)
|
|||
tcase_add_test(emergency_rollback_failure_due_to_bad_update, test_emergency_rollback_failure_due_to_bad_update);
|
||||
tcase_add_test(empty_boot_partition_update, test_empty_boot_partition_update);
|
||||
tcase_add_test(empty_boot_but_update_sha_corrupted_denied, test_empty_boot_but_update_sha_corrupted_denied);
|
||||
tcase_add_test(both_images_corrupted, test_both_images_corrupted_panics);
|
||||
|
||||
|
||||
|
||||
|
|
@ -642,6 +670,7 @@ Suite *wolfboot_suite(void)
|
|||
suite_add_tcase(s, emergency_rollback_failure_due_to_bad_update);
|
||||
suite_add_tcase(s, empty_boot_partition_update);
|
||||
suite_add_tcase(s, empty_boot_but_update_sha_corrupted_denied);
|
||||
suite_add_tcase(s, both_images_corrupted);
|
||||
|
||||
|
||||
/* Set timeout for tests */
|
||||
|
|
@ -664,6 +693,7 @@ Suite *wolfboot_suite(void)
|
|||
tcase_set_timeout(emergency_rollback_failure_due_to_bad_update, 5);
|
||||
tcase_set_timeout(empty_boot_partition_update, 5);
|
||||
tcase_set_timeout(empty_boot_but_update_sha_corrupted_denied, 5);
|
||||
tcase_set_timeout(both_images_corrupted, 5);
|
||||
|
||||
|
||||
return s;
|
||||
|
|
|
|||
Loading…
Reference in New Issue