High CVSS 5.5 webkit Bypass 🔧 Commit mapped

Overview

High
Severity
5.5
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionAn attacker with arbitrary read and write capability may be able to bypass Pointer Authentication
ComponentJSC
Sub-componentJSC Runtime
Bug ClassBypass
Tracker272750
Fix commit3e3d0883c849 (WebKit/WebKit) +42/-10
CWECWE-277
CVSS vectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
CISA KEVNot listed
CreditedManfred Paul (@_manfp) working with Trend Micro's Zero Day Initiative
Disclosed2024-05-13

Background

Pointer Authentication (PAC) / ARM64E
An ARM64E mitigation that signs pointers (e.g. return addresses) with a cryptographic MAC keyed by a context/modifier, so forged pointers fail authentication.
Signing gadget
A code sequence that signs a pointer using an attacker-controllable modifier register; abused to forge valid PACs for arbitrary pointers.
pacib vs pacizb / diversifier
pacib signs with a register-provided modifier; pacizb signs with a zero modifier. Using zero or the stack pointer removes the attacker-controllable input.

Root Cause Analysis

This hardens JavaScriptCore’s ARM64E pointer-authentication (PAC) usage against signing-gadget abuse, closing a PAC bypass usable by an attacker who already has arbitrary read/write. When the JIT reconstructs inlined call frames on OSR exit (reifyInlinedCallFrames in DFGOSRExitCompilerCommon) and fixes up arity (arityFixupGenerator in ThunkGenerators), it must re-sign the return-PC pointers with PAC.

Pre-patch, this re-signing passed an attacker-influenceable TAG/modifier held in a general-purpose register to the signing instruction (pacib): arityFixupGenerator generated a RANDOM tag (tempReturnPCTag = random()) into a register and signed with it, and reifyInlinedCallFrames used general-purpose temp registers (regT2/regT3/regT4) as the signing diversifier. An attacker with arbitrary read/write can hijack the register holding that modifier to turn the JIT’s signing sequence into a PAC signing gadget — signing an arbitrary pointer under a known/controlled context to forge a validly-signed return PC and defeat PAC-protected control flow.

The fix removes the controllable modifier: arityFixupGenerator now signs with a ZERO modifier via pacizb (jit.tagPtr(NoPtrTag, …), with the comment that passing a tag register to pacib could be hijacked into a PAC-bypass gadget), and reifyInlinedCallFrames, when Options::allowNonSPTagging() is false, uses the STACK POINTER as the signing diversifier (signingTagReg = sp) and LR as the return-PC register, carefully saving/restoring sp around the sequence.

The restored invariant is that JIT pointer re-signing uses a diversifier the attacker cannot control (zero, or the stack pointer), so the signing sequences cannot be repurposed to forge PACs. The regression tests exercise arity-fixup and OSR-exit return-PC signing paths.

Key insight
The JIT re-signed return PCs using an attacker-controllable modifier register (a random tag, or GPR temporaries), making the signing sequence a PAC-forging gadget; signing with a zero modifier (pacizb) or the stack pointer removes the controllable input.

Attack Path

  1. Obtain arbitrary read/write Start from a separate primitive giving arbitrary read/write in the WebContent process (the advisory’s stated precondition).
  2. Reach a JIT signing sequence Drive OSR exit / arity fixup so the JIT executes a return-PC PAC signing sequence.
  3. Hijack the modifier register Corrupt the general-purpose register holding the PAC tag/modifier (the random tag, or a temp register) that the signing instruction consumes.
  4. Forge a signed pointer Use the signing sequence as a gadget to sign an attacker-chosen pointer under a known context — a validly-signed return PC.
  5. Bypass PAC Redirect control flow to the forged pointer, defeating pointer authentication and continuing exploitation.

Impact Assessment

A PAC bypass on ARM64E in the WebContent process: given an existing arbitrary read/write, the JIT’s return-PC signing sequences could be turned into signing gadgets to forge authenticated pointers, defeating a core control-flow-integrity mitigation and enabling code execution. The advisory rates it high; it removes a key barrier that otherwise blocks exploitation of memory-corruption bugs.

Changed Functions

FunctionChangeNotes
if
Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
modified
if
Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
modified

Files Changed

  • Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
  • Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
  • Source/JavaScriptCore/jit/ThunkGenerators.cpp
  • Source/JavaScriptCore/llint/LLIntThunks.cpp
  • Source/JavaScriptCore/runtime/Options.cpp
  • Source/JavaScriptCore/runtime/OptionsList.h
  • Source/WTF/wtf/PtrTag.h
  • Source/WebKit/WebProcess/WebProcess.cpp
  • Tools/Scripts/run-jsc-stress-tests

Audit Directions

  • Register-modifier signing
    Grep JSC ARM64E codegen for tagPtr/pacib sequences that take the modifier from a general-purpose register an attacker could corrupt; prefer NoPtrTag (pacizb) or SP.
  • Return-PC re-signing paths
    Audit all OSR-exit / thunk / arity-fixup return-PC untag/validate/tag sequences for use of non-SP tagging under allowNonSPTagging().
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
index 6925f04bc3d6..3f9233b2de58 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
@@ -65,6 +65,12 @@ public:
 
     ALWAYS_INLINE void tagPtr(PtrTag tag, RegisterID target)
     {
+        if (!tag) {
+            m_assembler.pacizb(target);
+            return;
+        }
+
+        RELEASE_ASSERT(Options::allowNonSPTagging());
         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
         move(TrustedImm64(tag), tagGPR);
         m_assembler.pacib(target, tagGPR);
@@ -76,11 +82,17 @@ public:
             m_assembler.pacibsp();
             return;
         }
+        RELEASE_ASSERT(Options::allowNonSPTagging());
         m_assembler.pacib(target, tag);
     }
 
     ALWAYS_INLINE void untagPtr(PtrTag tag, RegisterID target)
     {
+        if (!tag) {
+            m_assembler.autizb(target);
+            return;
+        }
+
         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
         move(TrustedImm64(tag), tagGPR);
         m_assembler.autib(target, tagGPR);
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
index 4e0d005cc08a..a597735bfaf7 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
@@ -254,6 +254,16 @@ void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit)
     ASSERT(JITCode::isBaselineCode(jit.baselineCodeBlock()->jitType()));
     jit.storePtr(AssemblyHelpers::TrustedImmPtr(jit.baselineCodeBlock()), AssemblyHelpers::addressFor(CallFrameSlot::codeBlock));
 
+    GPRReg returnPCReg = GPRInfo::regT5;
+#if CPU(ARM64E)
+    GPRReg signingTagReg = GPRInfo::regT2;
+    if (!Options::allowNonSPTagging()) {
+        returnPCReg = ARM64Registers::lr;
+        signingTagReg = MacroAssembler::stackPointerRegister;
+        // We could save/restore lr here but we don't need to because the LLInt/Baseline will load it from the stack before returning anyway.
+    }
+#endif
+
     const CodeOrigin* codeOrigin;
     for (codeOrigin = &exit.m_codeOrigin; codeOrigin && codeOrigin->inlineCallFrame(); codeOrigin = codeOrigin->inlineCallFrame()->getCallerSkippingTailCalls()) {
         InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame();
@@ -266,15 +276,25 @@ void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit)
 
         if (!trueCaller) {
             ASSERT(inlineCallFrame->isTail());
-            jit.loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT3);
+            jit.loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), returnPCReg);
 #if CPU(ARM64E)
+            if (!Options::allowNonSPTagging()) {
+                JIT_COMMENT(jit, "lldb dynamic execution / posix signals could trash your stack"); // We don't have to worry about signals because they shouldn't fire in WebContent process in this window.
+                jit.move(MacroAssembler::stackPointerRegister, GPRInfo::regT4);
+            }
+
             jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, GPRInfo::regT2);
-            jit.untagPtr(GPRInfo::regT2, GPRInfo::regT3);
-            jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->returnPCOffset() + sizeof(void*)), GPRInfo::callFrameRegister, GPRInfo::regT2);
-            jit.validateUntaggedPtr(GPRInfo::regT3, GPRInfo::regT4);
-            jit.tagPtr(GPRInfo::regT2, GPRInfo::regT3);
+            jit.untagPtr(GPRInfo::regT2, returnPCReg);
+            jit.validateUntaggedPtr(returnPCReg, GPRInfo::regT2);
+            jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->returnPCOffset() + sizeof(CPURegister)), GPRInfo::callFrameRegister, signingTagReg);
+            jit.tagPtr(signingTagReg, returnPCReg);
+
+            if (!Options::allowNonSPTagging()) {
+                JIT_COMMENT(jit, "lldb dynamic execution / posix signals are ok again");
+                jit.move(GPRInfo::regT4, MacroAssembler::stackPointerRegister);
+            }
 #endif
-            jit.storePtr(GPRInfo::regT3, AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
+            jit.storePtr(returnPCReg, AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
             jit.loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, CallFrame::callerFrameOffset()), GPRInfo::regT3);
             callerFrameGPR = GPRInfo::regT3;
         } else {
@@ -291,10 +311,20 @@ void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit)
             }
 
 #if CPU(ARM64E)
-            jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->returnPCOffset() + sizeof(void*)), GPRInfo::callFrameRegister, GPRInfo::regT2);
-            jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget.untaggedPtr()), GPRInfo::regT4);
-            jit.tagPtr(GPRInfo::regT2, GPRInfo::regT4);
-            jit.storePtr(GPRInfo::regT4, AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
+            if (!Options::allowNonSPTagging()) {
+                JIT_COMMENT(jit, "lldb dynamic execution / posix signals could trash your stack"); // We don't have to worry about signals because they shouldn't fire in WebContent process in this window.
+                jit.move(MacroAssembler::stackPointerRegister, GPRInfo::regT4);
+            }
+
+            jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->returnPCOffset() + sizeof(CPURegister)), GPRInfo::callFrameRegister, signingTagReg);
+            jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget.untaggedPtr()), returnPCReg);
+            jit.tagPtr(signingTagReg, returnPCReg);
+            jit.storePtr(returnPCReg, AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
+
+            if (!Options::allowNonSPTagging()) {
+                JIT_COMMENT(jit, "lldb dynamic execution / posix signals are ok again");
+                jit.move(GPRInfo::regT4, MacroAssembler::stackPointerRegister);
+            }
 #else
             jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget.untaggedPtr()), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
 #endif
diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
index 9908140dfea1..d7a2126d53a7 100644
--- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp
+++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
@@ -626,9 +626,9 @@ MacroAssemblerCodeRef<JITThunkPtrTag> arityFixupGenerator(VM& vm)
     jit.addPtr(JSInterfaceJIT::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, extraTemp);
     jit.untagPtr(extraTemp, GPRInfo::regT3);
     jit.validateUntaggedPtr(GPRInfo::regT3, extraTemp);
-    PtrTag tempReturnPCTag = static_cast<PtrTag>(random());
-    jit.move(JSInterfaceJIT::TrustedImmPtr(tempReturnPCTag), extraTemp);
-    jit.tagPtr(extraTemp, GPRInfo::regT3);
+    // We don't want to pass a tag register to pacib because it could get hijacked to make a PAC bypass gadget so we use pacizb instead.
+    static_assert(NoPtrTag == static_cast<PtrTag>(0));
+    jit.tagPtr(NoPtrTag, GPRInfo::regT3);
     jit.storePtr(GPRInfo::regT3, JSInterfaceJIT::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
 #endif
     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
@@ -697,18 +697,35 @@ MacroAssemblerCodeRef<JITThunkPtrTag> arityFixupGenerator(VM& vm)
 
 #if CPU(ARM64E)
     jit.loadPtr(JSInterfaceJIT::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT3);
-    jit.move(JSInterfaceJIT::TrustedImmPtr(tempReturnPCTag), extraTemp);
-    jit.untagPtr(extraTemp, GPRInfo::regT3);
-    jit.validateUntaggedPtr(GPRInfo::regT3, extraTemp);
-    jit.addPtr(JSInterfaceJIT::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, extraTemp);
-    jit.tagPtr(extraTemp, GPRInfo::regT3);
-    jit.storePtr(GPRInfo::regT3, JSInterfaceJIT::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
+    if (Options::allowNonSPTagging()) {
+        static_assert(NoPtrTag == static_cast<PtrTag>(0));
+        jit.untagPtr(NoPtrTag, GPRInfo::regT3);
+        jit.validateUntaggedPtr(GPRInfo::regT3, extraTemp);
+        jit.addPtr(JSInterfaceJIT::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, extraTemp);
+        jit.tagPtr(extraTemp, GPRInfo::regT3);
+        jit.storePtr(GPRInfo::regT3, JSInterfaceJIT::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
+    } else {
+        jit.move(ARM64Registers::lr, JSInterfaceJIT::argumentGPR0);
+        jit.move(ARM64Registers::sp, JSInterfaceJIT::argumentGPR1);
+        JIT_COMMENT(jit, "lldb dynamic execution / posix signals could trash your stack"); // We don't have to worry about signals because they shouldn't fire in WebContent process in this window.
+        jit.addPtr(JSInterfaceJIT::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, ARM64Registers::sp);
+        jit.move(GPRInfo::regT3, ARM64Registers::lr);
+        static_assert(NoPtrTag == static_cast<PtrTag>(0));
+        jit.untagPtr(NoPtrTag, ARM64Registers::lr);
+        jit.validateUntaggedPtr(ARM64Registers::lr, extraTemp);
+        jit.tagReturnAddress();
+        jit.storePtr(ARM64Registers::lr, JSInterfaceJIT::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
+        JIT_COMMENT(jit, "lldb dynamic execution / posix signals are ok again");
+        jit.move(JSInterfaceJIT::argumentGPR1, ARM64Registers::sp);
+        jit.move(JSInterfaceJIT::argumentGPR0, ARM64Registers::lr);
+    }
 #endif
 
 #if CPU(X86_64)
     jit.push(JSInterfaceJIT::regT4);
 #endif
     jit.ret();
+
 #else // USE(JSVALUE64) section above, USE(JSVALUE32_64) section below.
     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
     jit.load32(JSInterfaceJIT::addressFor(CallFrameSlot::argumentCountIncludingThis), JSInterfaceJIT::argumentGPR2);
diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp
index 2755f55bd14a..b64efb690d0c 100644
--- a/Source/JavaScriptCore/llint/LLIntThunks.cpp
+++ b/Source/JavaScriptCore/llint/LLIntThunks.cpp
@@ -668,9 +668,22 @@ MacroAssemblerCodeRef<NativeToJITGatePtrTag> tagGateThunk(void* pointer)
 {
     CCallHelpers jit;
 
-    jit.addPtr(CCallHelpers::TrustedImm32(16), GPRInfo::callFrameRegister, GPRInfo::regT3);
-    jit.tagPtr(GPRInfo::regT3, ARM64Registers::lr);
-    jit.storePtr(ARM64Registers::lr, CCallHelpers::Address(GPRInfo::callFrameRegister, 8));
+    GPRReg signingTagReg = GPRInfo::regT3;
+    if (!Options::allowNonSPTagging()) {
+        JIT_COMMENT(jit, "lldb dynamic execution / posix signals could trash your stack"); // We don't have to worry about signals because they shouldn't fire in WebContent process in this window.
+        jit.move(MacroAssembler::stackPointerRegister, GPRInfo::regT3);
+        signingTagReg = MacroAssembler::stackPointerRegister;
+    }
+
+    jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, signingTagReg);
+    jit.tagPtr(signingTagReg, ARM64Registers::lr);
+    jit.storePtr(ARM64Registers::lr, CCallHelpers::Address(GPRInfo::callFrameRegister, sizeof(CPURegister)));
+
+    if (!Options::allowNonSPTagging()) {
+        JIT_COMMENT(jit, "lldb dynamic execution / posix signals are ok again");
+        jit.move(GPRInfo::regT3, MacroAssembler::stackPointerRegister);
+    }
+
     jit.move(CCallHelpers::TrustedImmPtr(pointer), GPRInfo::regT3);
     jit.farJump(GPRInfo::regT3, OperationPtrTag);
 
@@ -682,8 +695,8 @@ MacroAssemblerCodeRef<NativeToJITGatePtrTag> untagGateThunk(void* pointer)
 {
     CCallHelpers jit;
 
-    jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, 8), ARM64Registers::lr);
-    jit.addPtr(CCallHelpers::TrustedImm32(16), GPRInfo::callFrameRegister, GPRInfo::regT3);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, sizeof(CPURegister)), ARM64Registers::lr);
+    jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, GPRInfo::regT3);
     jit.untagPtr(GPRInfo::regT3, ARM64Registers::lr);
     jit.validateUntaggedPtr(ARM64Registers::lr, GPRInfo::regT3);
     jit.move(CCallHelpers::TrustedImmPtr(pointer), GPRInfo::regT3);
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 93a7a0519ac1..0b9f2404f445 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -912,6 +912,11 @@ void Options::notifyOptionsChanged()
     }
 #endif
 
+    // We can't use our pacibsp system while using posix signals because the signal handler could trash our stack during reifyInlinedCallFrames.
+    // If we have JITCage we don't need to restrict ourselves to pacibsp.
+    if (!Options::useMachForExceptions() || Options::useJITCage())
+        Options::allowNonSPTagging() = true;
+
     if (!Options::useWasmFaultSignalHandler())
         Options::useWebAssemblyFastMemory() = false;
 
@@ -1282,6 +1287,11 @@ void Options::assertOptionsAreCoherent()
         coherent = false;
         dataLogLn("Bytecode profiler is not concurrent JIT safe.");
     }
+    if (!allowNonSPTagging() && !useMachForExceptions()) {
+        coherent = false;
+        dataLog("INCOHERENT OPTIONS: can't restrict pointer tagging to pacibsp and use posix signals");
+    }
+
     if (!coherent)
         CRASH();
 }
diff --git a/Source/JavaScriptCore/runtime/OptionsList.h b/Source/JavaScriptCore/runtime/OptionsList.h
index 49f206ebff54..10deddc9065a 100644
--- a/Source/JavaScriptCore/runtime/OptionsList.h
+++ b/Source/JavaScriptCore/runtime/OptionsList.h
@@ -477,6 +477,7 @@ bool hasCapacityToUseLargeGigacage();
     v(Bool, usePollingTraps, false, Normal, "use polling (instead of signalling) VM traps"_s) \
     \
     v(Bool, useMachForExceptions, true, Normal, "Use mach exceptions rather than signals to handle faults and pass thread messages. (This does nothing on platforms without mach)"_s) \
+    v(Bool, allowNonSPTagging, true, Normal, "allow use of the pacib instruction instead of just pacibsp (This can break lldb/posix signals as it puts live data below SP)"_s) \
     \
     v(Bool, useICStats, false, Normal, nullptr) \
     \
diff --git a/Source/WTF/wtf/PtrTag.h b/Source/WTF/wtf/PtrTag.h
index 54807c8f5fcb..e0d29d240e2a 100644
--- a/Source/WTF/wtf/PtrTag.h
+++ b/Source/WTF/wtf/PtrTag.h
@@ -50,7 +50,7 @@ enum class PACKeyType {
     FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \
 
 enum PtrTag : uintptr_t {
-    NoPtrTag,
+    NoPtrTag = 0, // Note: We use the 0 tag for temporarily holding the return PC during JSC's arity fixup.
     CFunctionPtrTag,
 };
 
diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp
index 6d1e7ef4068a..7de1fd39cf8f 100644
--- a/Source/WebKit/WebProcess/WebProcess.cpp
+++ b/Source/WebKit/WebProcess/WebProcess.cpp
@@ -363,6 +363,12 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter
 {
     WTF::setProcessPrivileges({ });
 
+    {
+        JSC::Options::AllowUnfinalizedAccessScope scope;
+        JSC::Options::allowNonSPTagging() = false;
+        JSC::Options::notifyOptionsChanged();
+    }
+
     MessagePortChannelProvider::setSharedProvider(WebMessagePortChannelProvider::singleton());
     
     platformInitializeProcess(parameters);
diff --git a/Tools/Scripts/run-jsc-stress-tests b/Tools/Scripts/run-jsc-stress-tests
index 18c87c5f10c8..d522b6de4fed 100755
--- a/Tools/Scripts/run-jsc-stress-tests
+++ b/Tools/Scripts/run-jsc-stress-tests
@@ -1130,6 +1130,7 @@ BASE_MODES = [
         "misc-ftl-no-cjit",
         [
             "--useDataICInFTL=true",
+            "--allowNonSPTagging=false",
         ] +
         FTL_OPTIONS +
         NO_CJIT_OPTIONS
@@ -1157,6 +1158,7 @@ BASE_MODES = [
             "--airForceIRCAllocator=true",
             "--useDataICInFTL=true",
             "--forceUnlinkedDFG=true",
+            "--allowNonSPTagging=false",
         ] +
         FTL_OPTIONS +
         NO_CJIT_OPTIONS
@@ -1218,6 +1220,7 @@ BASE_MODES = [
             "--useRandomizingExecutableIslandAllocation=true",
             "--forcePolyProto=true",
             "--useDataICInFTL=true",
+            "--allowNonSPTagging=false",
         ] +
         FTL_OPTIONS +
         EAGER_OPTIONS +
@@ -1281,6 +1284,7 @@ BASE_MODES = [
         "ftl-no-cjit-no-access-inlining",
         [
             "--useAccessInlining=false",
+            "--allowNonSPTagging=false",
         ] +
         FTL_OPTIONS +
         NO_CJIT_OPTIONS
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker.