mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
fix(relinker): restrict lea roots to unwind reachability (#7547)
This commit is contained in:
1 parent
b8fc47fd47
commit
6a82825008
3 files changed
+20
-26
No files matched your search
@@ -375,27 +375,7 @@ static std::vector<CodeRange> DiscoverRoutines(const std::vector<std::uint8_t>&
|
||||
pos += info.Length;
|
||||
}
|
||||
}
|
||||
for (std::size_t pos = 0; pos < limit;) {
|
||||
if (ContainsOffset(unwind, pos)) {
|
||||
const auto after = std::upper_bound(unwind.begin(), unwind.end(), pos, [](const std::size_t value, const CodeRange& range) { return value < range.Begin; });
|
||||
if (after != unwind.begin())
|
||||
pos = static_cast<std::size_t>(std::prev(after)->End);
|
||||
continue;
|
||||
}
|
||||
Codegen::DecodedInstructionInfo info;
|
||||
try {
|
||||
info = decoder.DecodeInstruction(code.data() + pos, limit - pos);
|
||||
} catch (const Codegen::CodegenException&) {
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
if (info.Length == 0 || info.Length > limit - pos) {
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
QueueInstructionTargets(pending, visited, unwind, info, code, pos, limit);
|
||||
pos += info.Length;
|
||||
}
|
||||
|
||||
std::set<std::size_t> explored;
|
||||
while (!pending.empty()) {
|
||||
const auto root = pending.back();
|
||||
|
||||
@@ -98,16 +98,29 @@ void CheckNoUnwindIndirectJumpSyscall(Domain::FileByteOffset origin) {
|
||||
|
||||
void CheckIndirectOnlyDynamicSyscall(Domain::FileByteOffset origin) {
|
||||
const Bytes code = {
|
||||
0xC3,
|
||||
0x0F, 0x78,
|
||||
0x90, 0x90,
|
||||
0xEB, 0x03,
|
||||
0x0F, 0x78, 0x00,
|
||||
0x48, 0x8D, 0x05, 0x02, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xE0,
|
||||
0x8B, 0x07,
|
||||
0x0F, 0x05,
|
||||
0xC3,
|
||||
};
|
||||
CheckForbiddenInstruction(code, origin, 16, {}, {{0, 1}});
|
||||
CheckForbiddenInstruction(code, origin, 16, {}, {{0, 2}});
|
||||
}
|
||||
|
||||
void CheckGapBranchToSyscall(Domain::FileByteOffset origin) {
|
||||
const Bytes code = {
|
||||
0xC3,
|
||||
0xEB, 0x03,
|
||||
0x00, 0x00, 0x00,
|
||||
0x8B, 0x07,
|
||||
0x0F, 0x05,
|
||||
0xC3,
|
||||
};
|
||||
TestProgress progress;
|
||||
const auto scanner = Relinker::MakeSyscallScanner(progress);
|
||||
Require(scanner->ScanCodeSectionForSyscalls(code, origin, code.size(), {}, {{0, 1}}).empty(), "Data gap branch falsely created a routine and rejected 0F 05");
|
||||
}
|
||||
|
||||
void CheckDirectCallAfterIndirectJump(Domain::FileByteOffset origin) {
|
||||
@@ -175,6 +188,7 @@ int main() {
|
||||
CheckDirectCallAfterIndirectJump(origin);
|
||||
CheckConditionalBranchAcrossGap(origin);
|
||||
CheckUnwindGapAndBoundedCallee(origin);
|
||||
CheckGapBranchToSyscall(origin);
|
||||
}
|
||||
std::cout << "Embedded-code-data known-gap and reachable-code controls passed\n";
|
||||
} catch (const std::exception& error) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- [Packed relative relocations](../../../core/relinker/relinker/src/parsing/RelrRelocations.cpp) require the table to fit in one file-backed PT_LOAD segment and each 8-byte storage unit to fit in one load segment. Units spanning load segments, overlapping RELR units and overlaps with RELA relocations are rejected; relocation composition is not implemented.
|
||||
|
||||
- The [syscall scanner](../../../core/relinker/relinker/src/analysis/SyscallScanner.cpp) discovers routine bounds from unwind ranges, direct branch targets, and address-taken `lea` targets ([#7547](https://github.com/boykopovar/AnyPS5/issues/7547)) so undecodable bytes in an inter-routine gap are not reported as an illegal instruction. Each unwind range is decoded from its start through its end, and direct branch and `lea` targets from it and from inter-routine gaps are followed until the next return, unconditional jump, indirect jump, or trap. Inside discovered routines, all syscalls are rejected, including dynamic RAX loads. In inter-routine gaps outside all discovered routines, embedded data does not trigger decode failures, and raw syscall bytes without a constant number are skipped and counted; stubs with constant syscall numbers in gaps remain detected. With no unwind ranges, discovery is not performed and every syscall byte pattern is rejected.
|
||||
- The [syscall scanner](../../../core/relinker/relinker/src/analysis/SyscallScanner.cpp) discovers routine bounds from unwind ranges, direct branch targets, and address-taken `lea` targets ([#7547](https://github.com/boykopovar/AnyPS5/issues/7547)) so undecodable bytes in an inter-routine gap are not reported as an illegal instruction. Each unwind range is decoded from its start through its end, and direct branch and `lea` targets reached from it are followed until the next return, unconditional jump, indirect jump, or trap. Inside discovered routines, all syscalls are rejected, including dynamic RAX loads. In inter-routine gaps outside all discovered routines, embedded data does not trigger decode failures, and raw syscall bytes without a constant number are skipped and counted; stubs with constant syscall numbers in gaps remain detected. With no unwind ranges, discovery is not performed and every syscall byte pattern is rejected.
|
||||
|
||||
- [Executable guest imports](../../../core/relinker/relinker/src/guest/GuestModuleBuilder.cpp) - on Linux and macOS, a relocated executable import resolved to one guest provider requires that module and its dependencies at startup, even when it was discovered through `--module-dir` without a DT_NEEDED entry. Unreferenced symbols and no-op relocations do not require an otherwise deferred module. Console module-start ordering is unmeasured.
|
||||
|
||||
|
||||
Reference in new issue
Block a user