Skip to content

Commit

Permalink
new exception handler adoption
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=269728
rdar://119256062

Reviewed by Keith Miller.

This adopts the new hardened mach exception mechanism which was
introduced in darwin recently. See the radar for more details.

* Source/JavaScriptCore/llint/LLIntData.cpp:
* Source/JavaScriptCore/llint/LLIntData.h:
* Source/JavaScriptCore/runtime/MachineContext.h:
(JSC::MachineContext::setInstructionPointer):
* Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp:
(JSC::Wasm::trapHandler):
* Source/WTF/WTF.xcodeproj/project.pbxproj:
* Source/WTF/wtf/PlatformHave.h:
* Source/WTF/wtf/PlatformJSCOnly.cmake:
* Source/WTF/wtf/PlatformMac.cmake:
* Source/WTF/wtf/PlatformRegisters.h:
* Source/WTF/wtf/threads/Signals.cpp:
(WTF::initMachExceptionHandlerThread):
(WTF::setExceptionPorts):
* Source/WebKit/Resources/SandboxProfiles/ios/com.apple.WebKit.WebContent.sb.in:
* Source/WebKit/WebProcess/com.apple.WebProcess.sb.in:

Canonical link: https://commits.webkit.org/276090@main
  • Loading branch information
Brandon Kayes authored and kmiller68 committed Mar 14, 2024
1 parent f7185dc commit 079bd31
Show file tree
Hide file tree
Showing 17 changed files with 264 additions and 54 deletions.
19 changes: 17 additions & 2 deletions Source/JavaScriptCore/jsc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3496,7 +3496,9 @@ int main(int argc, char** argv WTF_TZONE_EXTRA_MAIN_ARGS)

#if OS(UNIX)
if (getenv("JS_SHELL_WAIT_FOR_SIGUSR2_TO_EXIT")) {
initializeSignalHandling();
uint32_t key = 0;
int mask = 0;
initializeSignalHandling(key, mask);
addSignalHandler(Signal::Usr, SignalHandler([&] (Signal, SigInfo&, PlatformRegisters&) {
dataLogLn("Signal handler hit, we can exit now.");
waitToExit.signal();
Expand Down Expand Up @@ -3970,7 +3972,19 @@ void CommandLine::parseArguments(int argc, char** argv)
}
if (!strcmp(arg, "-s")) {
#if OS(UNIX)
initializeSignalHandling();
uint32_t key = 0;
int mask = 0;
#if HAVE(MACH_EXCEPTIONS)
mask |= toMachMask(Signal::IllegalInstruction);
mask |= toMachMask(Signal::AccessFault);
mask |= toMachMask(Signal::FloatingPoint);
mask |= toMachMask(Signal::Breakpoint);
#if !OS(DARWIN)
mask |= toMachMask(Signal::Abort);
#endif // !OS(DARWIN)
#endif // HAVE(MACH_EXCEPTIONS)

initializeSignalHandling(key, mask);

SignalAction (*exit)(Signal, SigInfo&, PlatformRegisters&) = [] (Signal, SigInfo&, PlatformRegisters&) {
dataLogLn("Signal handler hit. Exiting with status 0");
Expand All @@ -3993,6 +4007,7 @@ void CommandLine::parseArguments(int argc, char** argv)
addSignalHandler(Signal::Abort, SignalHandler(exit));
activateSignalHandlersFor(Signal::Abort);
#endif
finalizeSignalHandlers();
#endif
continue;
}
Expand Down
10 changes: 9 additions & 1 deletion Source/JavaScriptCore/runtime/InitializeThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ void initialize()

if (Wasm::isSupported() || !Options::usePollingTraps()) {
// JSLock::lock() can call registerThreadForMachExceptionHandling() which crashes if this has not been called first.
initializeSignalHandling();
int mask = 0;
#if CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
JSC::Wasm::MachExceptionSigningKey keygen;
uint32_t signingKey = keygen.randomSigningKey;
mask |= toMachMask(Signal::AccessFault);
#else
uint32_t signingKey = 0;
#endif // defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
initializeSignalHandling(signingKey, mask);

if (!Options::usePollingTraps())
VMTraps::initializeSignals();
Expand Down
16 changes: 16 additions & 0 deletions Source/JavaScriptCore/runtime/MachineContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ template<typename T = void*> T framePointer(const PlatformRegisters&);
inline CodePtr<PlatformRegistersLRPtrTag> linkRegister(const PlatformRegisters&);
inline std::optional<CodePtr<PlatformRegistersPCPtrTag>> instructionPointer(const PlatformRegisters&);
inline void setInstructionPointer(PlatformRegisters&, CodePtr<CFunctionPtrTag>);
inline void setInstructionPointer(PlatformRegisters&, void *);

template<size_t N> void*& argumentPointer(PlatformRegisters&);
template<size_t N> void* argumentPointer(const PlatformRegisters&);
Expand Down Expand Up @@ -457,12 +458,27 @@ inline void setInstructionPointer(PlatformRegisters& regs, CodePtr<CFunctionPtrT
{
#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value.taggedPtr());
#elif USE(DARWIN_REGISTER_MACROS) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
__darwin_arm_thread_state64_set_presigned_pc_fptr(regs, value.taggedPtr());
#elif USE(DARWIN_REGISTER_MACROS)
__darwin_arm_thread_state64_set_pc_fptr(regs, value.taggedPtr());
#else
instructionPointerImpl(regs) = value.taggedPtr();
#endif
}

inline void setInstructionPointer(PlatformRegisters& regs, void* value)
{
#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value);
#elif USE(DARWIN_REGISTER_MACROS) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
__darwin_arm_thread_state64_set_presigned_pc_fptr(regs, value);
#elif USE(DARWIN_REGISTER_MACROS)
__darwin_arm_thread_state64_set_pc_fptr(regs, value);
#else
instructionPointerImpl(regs) = value;
#endif
}
#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)


Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/runtime/VMTraps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class VMTraps::SignalSender final : public AutomaticThread {
, m_vm(vm)
{
activateSignalHandlersFor(Signal::AccessFault);
finalizeSignalHandlers();
}

static void initializeSignals()
Expand Down
23 changes: 23 additions & 0 deletions Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,30 @@
#include "WasmExceptionType.h"
#include "WasmMemory.h"
#include "WasmThunks.h"
#include <wtf/CodePtr.h>
#include <wtf/CryptographicallyRandomNumber.h>
#include <wtf/HashSet.h>
#include <wtf/Lock.h>
#include <wtf/threads/Signals.h>

namespace JSC { namespace Wasm {

using WTF::CodePtr;

void* presignedTrampoline = { };

#if CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
MachExceptionSigningKey::MachExceptionSigningKey()
{
// Sign the trampoline pointer using a random diversifier and stash it away before webcontent has started so that
// even a PAC signing gadget cannot fake this random diversifier
randomSigningKey = WTF::cryptographicallyRandomNumber<uint32_t>() & __DARWIN_ARM_THREAD_STATE64_USER_DIVERSIFIER_MASK;
uint64_t diversifier = ptrauth_blend_discriminator((void *)(unsigned long)randomSigningKey, ptrauth_string_discriminator("pc"));
presignedTrampoline = JSC::LLInt::getCodePtr<CFunctionPtrTag>(wasm_throw_from_fault_handler_trampoline_reg_instance).untaggedPtr();
presignedTrampoline = ptrauth_sign_unauthenticated(presignedTrampoline, ptrauth_key_function_pointer, diversifier);
}
#endif // CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)

namespace {
namespace WasmFaultSignalHandlerInternal {
static constexpr bool verbose = false;
Expand Down Expand Up @@ -96,7 +114,11 @@ static SignalAction trapHandler(Signal signal, SigInfo& sigInfo, PlatformRegiste
};

if (didFaultInWasm(faultingInstruction)) {
#if defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
MachineContext::setInstructionPointer(context, presignedTrampoline);
#else
MachineContext::setInstructionPointer(context, LLInt::getCodePtr<CFunctionPtrTag>(wasm_throw_from_fault_handler_trampoline_reg_instance));
#endif
return SignalAction::Handled;
}
}
Expand All @@ -115,6 +137,7 @@ void activateSignalingMemory()
return;

activateSignalHandlersFor(Signal::AccessFault);
WTF::finalizeSignalHandlers();
});
}

Expand Down
9 changes: 8 additions & 1 deletion Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
namespace JSC {

namespace Wasm {

#if ENABLE(WEBASSEMBLY)
void activateSignalingMemory();
void prepareSignalingMemory();
Expand All @@ -37,4 +36,12 @@ inline void activateSignalingMemory() { }
inline void prepareSignalingMemory() { }
#endif // ENABLE(WEBASSEMBLY)

#if CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
class MachExceptionSigningKey {
public:
uint32_t randomSigningKey = { };
MachExceptionSigningKey();
};
#endif // CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)

} } // namespace JSC::Wasm
3 changes: 3 additions & 0 deletions Source/WTF/WTF.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -4058,13 +4058,15 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 5D247B7014689C4700E78B76 /* DebugRelease.xcconfig */;
buildSettings = {
OTHER_MIGFLAGS = "-DMACH_EXC_SERVER_TASKIDTOKEN_STATE";
};
name = Debug;
};
5D247B6514689B8600E78B76 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 5D247B7014689C4700E78B76 /* DebugRelease.xcconfig */;
buildSettings = {
OTHER_MIGFLAGS = "-DMACH_EXC_SERVER_TASKIDTOKEN_STATE";
};
name = Release;
};
Expand All @@ -4086,6 +4088,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 5D247B6E14689C4700E78B76 /* Base.xcconfig */;
buildSettings = {
OTHER_MIGFLAGS = "-DMACH_EXC_SERVER_TASKIDTOKEN_STATE";
};
name = Production;
};
Expand Down
2 changes: 1 addition & 1 deletion Source/WTF/wtf/PlatformJSCOnly.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ elseif (APPLE)
${WTF_DERIVED_SOURCES_DIR}/mach_excUser.c
MAIN_DEPENDENCY mac/MachExceptions.defs
WORKING_DIRECTORY ${WTF_DERIVED_SOURCES_DIR}
COMMAND mig -sheader MachExceptionsServer.h MachExceptions.defs
COMMAND mig -DMACH_EXC_SERVER_TASKIDTOKEN_STATE -sheader MachExceptionsServer.h MachExceptions.defs
VERBATIM)
list(APPEND WTF_SOURCES
cocoa/MemoryFootprintCocoa.cpp
Expand Down
2 changes: 1 addition & 1 deletion Source/WTF/wtf/PlatformMac.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ add_custom_command(
${WTF_DERIVED_SOURCES_DIR}/mach_excUser.c
MAIN_DEPENDENCY mac/MachExceptions.defs
WORKING_DIRECTORY ${WTF_DERIVED_SOURCES_DIR}
COMMAND mig -sheader MachExceptionsServer.h MachExceptions.defs
COMMAND mig -DMACH_EXC_SERVER_TASKIDTOKEN_STATE -sheader MachExceptionsServer.h MachExceptions.defs
VERBATIM)
list(APPEND WTF_SOURCES
${WTF_DERIVED_SOURCES_DIR}/mach_excServer.c
Expand Down
8 changes: 8 additions & 0 deletions Source/WTF/wtf/PlatformRegisters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ void* threadStateLRInternal(PlatformRegisters& regs)

void* threadStatePCInternal(PlatformRegisters& regs)
{
#if CPU(ARM64E) && defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
// If userspace has modified the PC and set it to the presignedTrampoline,
// we want to avoid authing the value as it is using a custom ptrauth signing scheme.
_STRUCT_ARM_THREAD_STATE64* ts = &(regs);
if (!(ts->__opaque_flags & __DARWIN_ARM_THREAD_STATE64_FLAGS_KERNEL_SIGNED_PC))
return nullptr;
#endif // defined(EXCEPTION_STATE_IDENTITY_PROTECTED)

void* candidatePC = arm_thread_state64_get_pc_fptr(regs);

#if USE(UNTAGGED_THREAD_STATE_PTR)
Expand Down
6 changes: 6 additions & 0 deletions Source/WTF/wtf/PlatformRegisters.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <wtf/StdLibExtras.h>

#if OS(DARWIN)
#include <mach/exception_types.h>
#include <mach/thread_act.h>
#include <signal.h>
#elif OS(WINDOWS)
Expand Down Expand Up @@ -130,8 +131,13 @@ using WTF::threadStatePCInternal;
#define WTF_READ_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs) \
threadStatePCInternal(const_cast<PlatformRegisters&>(regs))

#if defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
#define WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, newPointer) \
arm_thread_state64_set_pc_presigned_fptr(regs, newPointer)
#else // defined(EXCEPTION_STATE_IDENTITY_PROTECTED)
#define WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, newPointer) \
arm_thread_state64_set_pc_fptr(regs, newPointer)
#endif // defined(EXCEPTION_STATE_IDENTITY_PROTECTED)

#define WTF_READ_MACHINE_CONTEXT_SP_WITH_PROFILE(machineContext) \
WTF_READ_PLATFORM_REGISTERS_SP_WITH_PROFILE(machineContext->__ss)
Expand Down
Loading

0 comments on commit 079bd31

Please sign in to comment.