From 73ca4f8314a47b7f5d610cf0bfbe6f8ae24077bc Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 16 Dec 2024 10:40:33 -0800 Subject: [PATCH] Linux/FaultSafeUserMemAccess: Break out fault safe handler This is going to get used by gdbserver soon for ensuring memory accesses are fault safe, because it tries to read outside of correct memory bounds at times. --- .../LinuxSyscalls/SignalDelegator.cpp | 14 ++------------ .../Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h | 13 +++++++++++++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp index b556690abc..51abf11619 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp @@ -578,18 +578,8 @@ void SignalDelegator::HandleGuestSignal(FEX::HLE::ThreadStateObject* ThreadObjec ERROR_AND_DIE_FMT("X86 shouldn't hit this InterruptFaultPage"); #endif } - } else if (Signal == SIGSEGV && (SigInfo.si_code == SEGV_MAPERR || SigInfo.si_code == SEGV_ACCERR) && - FaultSafeUserMemAccess::IsFaultLocation(ArchHelpers::Context::GetPc(UContext))) { - // If you want to emulate EFAULT behaviour then enable this if-statement. - // Do this once we find an application that depends on this. - if constexpr (false) { - // Return from the subroutine, returning EFAULT. - ArchHelpers::Context::SetArmReg(UContext, 0, EFAULT); - ArchHelpers::Context::SetPc(UContext, ArchHelpers::Context::GetArmReg(UContext, 30)); - return; - } else { - ERROR_AND_DIE_FMT("Received invalid data to syscall. Crashing now!"); - } + } else if (FaultSafeUserMemAccess::TryHandleSafeFault(Signal, SigInfo, UContext)) { + ERROR_AND_DIE_FMT("Received invalid data to syscall. Crashing now!"); } else { if (IsAsyncSignal(&SigInfo, Signal) && MustDeferSignal) { // If the signal is asynchronous (as determined by si_code) and FEX is in a state of needing diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h index 5417a3c6ec..db8d5363c0 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h @@ -12,6 +12,7 @@ desc: Glue logic, STRACE magic #include "LinuxSyscalls/LinuxAllocator.h" #include "LinuxSyscalls/ThreadManager.h" #include "LinuxSyscalls/Seccomp/SeccompEmulator.h" +#include "ArchHelpers/MContext.h" #include #include @@ -674,6 +675,18 @@ namespace FaultSafeUserMemAccess { } #endif bool IsFaultLocation(uint64_t PC); + + static inline bool TryHandleSafeFault(int Signal, const siginfo_t& SigInfo, void* UContext) { + if (Signal == SIGSEGV && (SigInfo.si_code == SEGV_MAPERR || SigInfo.si_code == SEGV_ACCERR) && + FaultSafeUserMemAccess::IsFaultLocation(ArchHelpers::Context::GetPc(UContext))) { + // Return from the subroutine, returning EFAULT. + ArchHelpers::Context::SetArmReg(UContext, 0, EFAULT); + ArchHelpers::Context::SetPc(UContext, ArchHelpers::Context::GetArmReg(UContext, 30)); + return true; + } + + return false; + } } // namespace FaultSafeUserMemAccess } // namespace FEX::HLE