From be96cb7bd072c17ada88c45ebb283dd8959ebaa0 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 21 Feb 2024 15:38:43 -0800 Subject: [PATCH] FEXLoader: Allocate the second 4GB of virtual memory when executing 32-bit Spurred on by #3421. To ensure that applications don't take advantage of small address wrap around, allocate the second 4GB of virtual memory. Some context. Linux always reserves the first 16KB of virtual address space (unless you tinker with some settings which nobody should do). Example of 32-bit code: lea eax, [0xffff_0000] mov ebx, [eax + 0x1_0000] The address calculated by the mov will wrap around to 0x0 which will result in SIGSEGV. If FEX messes up zero extensions then it would try to access 0x1_0000_0000 instead. This could result in a 32-bit application potentially accessing some FEX memory instead of crashing. Add this safety net which will still SIGSEGV and we will be able to see the crash. --- Source/Tools/FEXLoader/FEXLoader.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Tools/FEXLoader/FEXLoader.cpp b/Source/Tools/FEXLoader/FEXLoader.cpp index 50802af35..3da79567d 100644 --- a/Source/Tools/FEXLoader/FEXLoader.cpp +++ b/Source/Tools/FEXLoader/FEXLoader.cpp @@ -417,11 +417,17 @@ int main(int argc, char **argv, char **const envp) { fextl::unique_ptr Allocator; fextl::vector Base48Bit; + fextl::vector Low4GB; if (Loader.Is64BitMode()) { // Destroy the 48th bit if it exists Base48Bit = FEXCore::Allocator::Steal48BitVA(); } else { + // Reserve [0x1_0000_0000, 0x2_0000_0000). + // Safety net if 32-bit address calculation overflows in to 64-bit range. + constexpr uint64_t First64BitAddr = 0x1'0000'0000ULL; + Low4GB = FEXCore::Allocator::StealMemoryRegion(First64BitAddr, First64BitAddr + First64BitAddr); + // Setup our userspace allocator FEXCore::Allocator::SetupHooks(); Allocator = FEX::HLE::CreatePassthroughAllocator(); @@ -578,6 +584,8 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Allocator::ClearHooks(); FEXCore::Allocator::ReclaimMemoryRegion(Base48Bit); + FEXCore::Allocator::ReclaimMemoryRegion(Low4GB); + // Allocator is now original system allocator FEXCore::Telemetry::Shutdown(Program.ProgramName); FEXCore::Profiler::Shutdown();