From 2ad3605cdb965e1e0e57fed1dbf522198f818027 Mon Sep 17 00:00:00 2001 From: Gabriel A Date: Wed, 12 Jul 2023 16:16:40 -0300 Subject: [PATCH] Use alternate stack for the segfault handler too --- src/Ryujinx.Cpu/Nce/NceCpuContext.cs | 3 +- src/Ryujinx.Cpu/Nce/NceExecutionContext.cs | 13 ++- .../AndroidSignalHandlerRegistration.cs | 87 ------------------- src/Ryujinx.Cpu/Signal/NativeSignalHandler.cs | 20 +---- .../Signal/UnixSignalHandlerRegistration.cs | 10 ++- 5 files changed, 22 insertions(+), 111 deletions(-) delete mode 100644 src/Ryujinx.Cpu/Signal/AndroidSignalHandlerRegistration.cs diff --git a/src/Ryujinx.Cpu/Nce/NceCpuContext.cs b/src/Ryujinx.Cpu/Nce/NceCpuContext.cs index 7eeed1bc8..0498a21eb 100644 --- a/src/Ryujinx.Cpu/Nce/NceCpuContext.cs +++ b/src/Ryujinx.Cpu/Nce/NceCpuContext.cs @@ -117,9 +117,8 @@ namespace Ryujinx.Cpu.Nce int tableIndex = NceThreadTable.Register(_getTpidrEl0(), nec.NativeContextPtr); nec.SetStartAddress(address); - nec.RegisterAlternateStack(); _threadStart(nec.NativeContextPtr); - nec.UnregisterAlternateStack(); + nec.Exit(); NceThreadTable.Unregister(tableIndex); } diff --git a/src/Ryujinx.Cpu/Nce/NceExecutionContext.cs b/src/Ryujinx.Cpu/Nce/NceExecutionContext.cs index 402e44a2d..eafd7ff98 100644 --- a/src/Ryujinx.Cpu/Nce/NceExecutionContext.cs +++ b/src/Ryujinx.Cpu/Nce/NceExecutionContext.cs @@ -102,9 +102,18 @@ namespace Ryujinx.Cpu.Nce ref var storage = ref _context.GetStorage(); storage.X[30] = address; storage.HostThreadHandle = NceThreadPal.GetCurrentThreadHandle(); + + RegisterAlternateStack(); } - public void RegisterAlternateStack() + public void Exit() + { + _context.GetStorage().HostThreadHandle = IntPtr.Zero; + + UnregisterAlternateStack(); + } + + private void RegisterAlternateStack() { // We need to use an alternate stack to handle the suspend signal, // as the guest stack may be in a state that is not suitable for the signal handlers. @@ -113,7 +122,7 @@ namespace Ryujinx.Cpu.Nce NativeSignalHandler.InstallUnixAlternateStackForCurrentThread(_alternateStackMemory.GetPointer(0UL, AlternateStackSize), AlternateStackSize); } - public void UnregisterAlternateStack() + private void UnregisterAlternateStack() { NativeSignalHandler.UninstallUnixAlternateStackForCurrentThread(); _alternateStackMemory.Dispose(); diff --git a/src/Ryujinx.Cpu/Signal/AndroidSignalHandlerRegistration.cs b/src/Ryujinx.Cpu/Signal/AndroidSignalHandlerRegistration.cs deleted file mode 100644 index a3f1ea740..000000000 --- a/src/Ryujinx.Cpu/Signal/AndroidSignalHandlerRegistration.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Cpu.Signal -{ - static class AndroidSignalHandlerRegistration - { - [StructLayout(LayoutKind.Sequential, Pack = 8)] - public unsafe struct SigSet - { - fixed long sa_mask[16]; - } - - [StructLayout(LayoutKind.Sequential, Pack = 8)] - public struct SigAction - { - public int sa_flags; - public IntPtr sa_handler; - public SigSet sa_mask; - public IntPtr sa_restorer; - } - - private const int SIGSEGV = 11; - private const int SA_SIGINFO = 0x00000004; - - [DllImport("libc", SetLastError = true)] - private static extern int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction); - - [DllImport("libc", SetLastError = true)] - private static extern int sigaction(int signum, IntPtr sigAction, out SigAction oldAction); - - [DllImport("libc", SetLastError = true)] - private static extern int sigemptyset(ref SigSet set); - - public static SigAction GetSegfaultExceptionHandler() - { - int result = sigaction(SIGSEGV, IntPtr.Zero, out SigAction old); - - if (result != 0) - { - throw new InvalidOperationException($"Could not get SIGSEGV sigaction. Error: {result}"); - } - - return old; - } - - public static SigAction RegisterExceptionHandler(IntPtr action, int userSignal = -1) - { - SigAction sig = new SigAction - { - sa_handler = action, - sa_flags = SA_SIGINFO - }; - - sigemptyset(ref sig.sa_mask); - - int result = sigaction(SIGSEGV, ref sig, out SigAction old); - - if (result != 0) - { - throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}"); - } - - if (userSignal != -1) - { - result = sigaction(userSignal, ref sig, out SigAction oldu); - - if (oldu.sa_handler != IntPtr.Zero) - { - throw new InvalidOperationException($"SIG{userSignal} is already in use."); - } - - if (result != 0) - { - throw new InvalidOperationException($"Could not register SIG{userSignal} sigaction. Error: {result}"); - } - } - - return old; - } - - public static bool RestoreExceptionHandler(SigAction oldAction) - { - return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0; - } - } -} diff --git a/src/Ryujinx.Cpu/Signal/NativeSignalHandler.cs b/src/Ryujinx.Cpu/Signal/NativeSignalHandler.cs index 531a0a56a..0acc07f57 100644 --- a/src/Ryujinx.Cpu/Signal/NativeSignalHandler.cs +++ b/src/Ryujinx.Cpu/Signal/NativeSignalHandler.cs @@ -100,25 +100,13 @@ namespace Ryujinx.Cpu.Signal if (customSignalHandlerFactory != null) { - _signalHandlerPtr = customSignalHandlerFactory(Ryujinx.Common.SystemInfo.SystemInfo.IsAndroid() ? - AndroidSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler : - UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr); + _signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr); } - if (Ryujinx.Common.SystemInfo.SystemInfo.IsAndroid()) - { - var old = AndroidSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr); + var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr); - config.UnixOldSigaction = (nuint)(ulong)old.sa_handler; - config.UnixOldSigaction3Arg = old.sa_flags & 4; - } - else - { - var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr); - - config.UnixOldSigaction = (nuint)(ulong)old.sa_handler; - config.UnixOldSigaction3Arg = old.sa_flags & 4; - } + config.UnixOldSigaction = (nuint)(ulong)old.sa_handler; + config.UnixOldSigaction3Arg = old.sa_flags & 4; } else { diff --git a/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs b/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs index ca4da38db..456e9d582 100644 --- a/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs +++ b/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs @@ -43,6 +43,7 @@ namespace Ryujinx.Cpu.Signal private const int SA_SIGINFO = 0x00000004; private const int SA_ONSTACK = 0x08000000; private const int SS_DISABLE = 2; + private const int SS_AUTODISARM = 1 << 31; [LibraryImport("libc", SetLastError = true)] private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction); @@ -102,7 +103,7 @@ namespace Ryujinx.Cpu.Signal SigActionBionic sig = new() { sa_handler = action, - sa_flags = SA_SIGINFO + sa_flags = SA_SIGINFO | SA_ONSTACK, }; sigemptyset(ref sig.sa_mask); @@ -122,7 +123,7 @@ namespace Ryujinx.Cpu.Signal SigAction sig = new SigAction { sa_handler = action, - sa_flags = SA_SIGINFO + sa_flags = SA_SIGINFO | SA_ONSTACK, }; sigemptyset(ref sig.sa_mask); @@ -153,6 +154,7 @@ namespace Ryujinx.Cpu.Signal Stack stack = new() { ss_sp = stackPtr, + ss_flags = SS_AUTODISARM, ss_size = (IntPtr)stackSize }; @@ -197,7 +199,7 @@ namespace Ryujinx.Cpu.Signal if (oldu.sa_handler != IntPtr.Zero) { - throw new SystemException($"SIG{sigNum} is already in use."); + throw new InvalidOperationException($"SIG{sigNum} is already in use."); } if (result != 0) @@ -219,7 +221,7 @@ namespace Ryujinx.Cpu.Signal if (oldu.sa_handler != IntPtr.Zero) { - throw new SystemException($"SIG{sigNum} is already in use."); + throw new InvalidOperationException($"SIG{sigNum} is already in use."); } if (result != 0)