Merge pull request #10710 from roboterspinne/fix/relinker-windows-gs-branch-targets

fix(relinker): refuse branches into trapped guest GS instructions on Windows
This commit is contained in:
Dean authored and GitHub committed 2026-10-25 21:50:25 +13:00
commit 28d2a461d2
2 files changed
+9 -4

No files matched your search

@@ -221,8 +221,14 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
}
report(9000);
for (const auto& [rva, length] : gsTraps)
std::sort(branchTargets.begin(), branchTargets.end());
branchTargets.erase(std::unique(branchTargets.begin(), branchTargets.end()), branchTargets.end());
for (const auto& [rva, length] : gsTraps) {
const auto target = std::upper_bound(branchTargets.begin(), branchTargets.end(), rva);
if (target != branchTargets.end() && *target < rva + length)
throw Domain::RelinkerException("Branch enters a guest GS instruction", *target);
trapInstruction(sections, rva, length);
}
if (tls == nullptr) {
if (!accesses.empty())
throw Domain::RelinkerException("Guest TLS access without PT_TLS");
@@ -274,9 +280,6 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
code.PatchBranch(skipCallback, code.GetRva());
code.Emit({0xc3});
std::sort(branchTargets.begin(), branchTargets.end());
branchTargets.erase(std::unique(branchTargets.begin(), branchTargets.end()), branchTargets.end());
std::uint64_t patched = 0;
for (const auto& access : accesses) {
if (patched % 256 == 0) report(9000 + 900 * patched / accesses.size());
@@ -777,6 +777,8 @@ def main():
conflicting[232:344] = unwind[232:344]
struct.pack_into("<H", conflicting, 56, 5)
convert("conflicting-function-extents", conflicting, "Code analysis: conflicting function ranges")
convert("branch-into-gs", make_image("register", "unwind", body=bytes.fromhex("74 01 65 48 8b 0c 25 78 03 00 00 c3")),
"Branch enters a guest GS instruction", error_offset=0x11243)
def check_gs_traps(cases):
for name, instruction, trapped in cases: