From dc35e23b00ace3ef7d7ec5361c81855f6acd490d 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..7dd609bfe2 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, siginfo_t const &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