IOS LLE: StarOS's panic words must not alias

LoadBootstrapELF accepted __panic_state and __panic_code at the same
address, or as two words sharing bytes: the code's store would then also
set the guard, and nothing could tell the two apart. They must now be two
non-overlapping words of the data segment, like the other checks, before
any byte is written. BootstrapELFTest.PanicWordsMustNotAlias: the same
word and three partial overlaps, all inside the data segment, are
rejected; adjacent words are accepted. With the rule disabled, the test
fails. (StarOS MMU-001 review of F1.)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Yaya48andClaude Opus 5.5 committed 2026-10-14 00:20:22 +02:00
1 parent 15da28ad7b
commit a62c65615a
2 files changed
+34 -2

No files matched your search

@@ -216,9 +216,14 @@ bool LoadBootstrapELF(std::span<const u8> image, ARMBus& bus, BootstrapELFInfo*
{
return Fail(error, "bootstrap ELF is missing the trace or fault symbols");
}
// The panic words are optional, but both or neither, as words of the data segment.
// The panic words are optional, but both or neither, as two distinct words of the data segment:
// aliased, the code's store would also set the guard, and a probe could not tell them apart.
const bool panic_words_overlap =
static_cast<u64>(parsed.panic_state) < static_cast<u64>(parsed.panic_code) + 4 &&
static_cast<u64>(parsed.panic_code) < static_cast<u64>(parsed.panic_state) + 4;
if ((parsed.panic_state != 0) != (parsed.panic_code != 0) ||
(parsed.panic_state != 0 && (!in_data(parsed.panic_state, 4) || !in_data(parsed.panic_code, 4))))
(parsed.panic_state != 0 && (!in_data(parsed.panic_state, 4) ||
!in_data(parsed.panic_code, 4) || panic_words_overlap)))
{
return Fail(error, "bootstrap ELF has an invalid panic symbol");
}
@@ -281,5 +281,32 @@ TEST(BootstrapELFTest, PanicWordsAreOptionalButBothInData)
EXPECT_TRUE(rejected.bytes.empty());
}
}
TEST(BootstrapELFTest, PanicWordsMustNotAlias)
{
BootstrapELFInfo info;
std::string error;
// The same word, or two words sharing bytes, in either order; all inside the 0x420-byte data
// segment, so only the aliasing rule rejects them.
for (const auto [state, code] :
{std::pair{DATA_BASE + 4, DATA_BASE + 4}, std::pair{DATA_BASE + 4, DATA_BASE + 6},
std::pair{DATA_BASE + 7, DATA_BASE + 4}, std::pair{DATA_BASE + 0x41c, DATA_BASE + 0x41a}})
{
RecordingBus rejected;
EXPECT_FALSE(LoadBootstrapELF(MakePanicImage(state, code), rejected, &info, &error))
<< std::hex << state << ' ' << code;
EXPECT_EQ(error, "bootstrap ELF has an invalid panic symbol");
EXPECT_TRUE(rejected.bytes.empty());
}
// Adjacent words do not alias.
for (const auto [state, code] :
{std::pair{DATA_BASE + 4, DATA_BASE + 8}, std::pair{DATA_BASE + 8, DATA_BASE + 4}})
{
RecordingBus bus;
EXPECT_TRUE(LoadBootstrapELF(MakePanicImage(state, code), bus, &info, &error)) << error;
EXPECT_EQ(info.panic_state, state);
EXPECT_EQ(info.panic_code, code);
}
}
} // namespace
} // namespace IOS::LLE