Commit 07b03b83 authored by Georgia Kouveli's avatar Georgia Kouveli Committed by Commit Bot

[builtins] Clear c_entry_fp when entering JS and at exception path

c_entry_fp is normally cleared in `LeaveExitFrame`, but we adjust
the frame without it in the exception path.

This can cause the SafeStackFrameIterator to assume we have an exit
frame and iterate over frames incorrectly, which for arm64 can
cause pointer authentication failures with CFI enabled. Even without
the pointer authentication failure, we iterate over frames incorrectly,
so make this change for other architectures too.

Also clear c_entry_fp in the beginning of JSEntry, after pushing it
on the stack. Not doing this doesn't cause pointer authentication
failures, but it will make the SafeStackFrameIterator assume we
are executing C++ and miss the JS frames on top.

Bug: v8:10026
Change-Id: Ie94834920f51e9f1cc5c1c775596726b61fc0507
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642256Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Georgia Kouveli <georgia.kouveli@arm.com>
Cr-Commit-Position: refs/heads/master@{#72458}
parent 6df1aec6
......@@ -530,13 +530,20 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// r0: root_register_value
__ mov(r7, Operand(StackFrame::TypeToMarker(type)));
__ mov(r6, Operand(StackFrame::TypeToMarker(type)));
__ Move(r5, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress,
__ Move(r4, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress,
masm->isolate()));
__ ldr(r5, MemOperand(r5));
__ ldr(r5, MemOperand(r4));
__ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | fp.bit() | lr.bit());
pushed_stack_space += 5 * kPointerSize /* r5, r6, r7, fp, lr */;
// Clear c_entry_fp, now we've pushed its previous value to the stack.
// If the c_entry_fp is not already zero and we don't clear it, the
// SafeStackFrameIterator will assume we are executing C++ and miss the JS
// frames on top.
__ mov(r5, Operand::Zero());
__ str(r5, MemOperand(r4));
Register scratch = r6;
// Set up frame pointer for the frame to be pushed.
......@@ -2502,6 +2509,16 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// underlying register is caller-saved and can be arbitrarily clobbered.
__ ResetSpeculationPoisonRegister();
// Clear c_entry_fp, like we do in `LeaveExitFrame`.
{
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire();
__ Move(scratch, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ mov(r1, Operand::Zero());
__ str(r1, MemOperand(scratch));
}
// Compute the handler entry address and jump to it.
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ Move(r1, pending_handler_entrypoint_address);
......
......@@ -643,6 +643,12 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
masm->isolate()));
__ Ldr(x10, MemOperand(x11)); // x10 = C entry FP.
// Clear c_entry_fp, now we've loaded its value to be pushed on the stack.
// If the c_entry_fp is not already zero and we don't clear it, the
// SafeStackFrameIterator will assume we are executing C++ and miss the JS
// frames on top.
__ Str(xzr, MemOperand(x11));
// Set js_entry_sp if this is the outermost JS call.
Label done;
ExternalReference js_entry_sp = ExternalReference::Create(
......@@ -2947,6 +2953,15 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// underlying register is caller-saved and can be arbitrarily clobbered.
__ ResetSpeculationPoisonRegister();
{
// Clear c_entry_fp, like we do in `LeaveExitFrame`.
UseScratchRegisterScope temps(masm);
Register scratch = temps.AcquireX();
__ Mov(scratch, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ Str(xzr, MemOperand(scratch));
}
// Compute the handler entry address and jump to it. We use x17 here for the
// jump target, as this jump can occasionally end up at the start of
// InterpreterEnterBytecodeDispatch, which when CFI is enabled starts with
......
......@@ -368,6 +368,12 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
IsolateAddressId::kCEntryFPAddress, masm->isolate());
__ push(__ ExternalReferenceAsOperand(c_entry_fp, edi));
// Clear c_entry_fp, now we've pushed its previous value to the stack.
// If the c_entry_fp is not already zero and we don't clear it, the
// SafeStackFrameIterator will assume we are executing C++ and miss the JS
// frames on top.
__ mov(__ ExternalReferenceAsOperand(c_entry_fp, edi), Immediate(0));
// Store the context address in the previously-reserved slot.
ExternalReference context_address = ExternalReference::Create(
IsolateAddressId::kContextAddress, masm->isolate());
......@@ -2759,6 +2765,11 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
__ bind(&skip);
// Clear c_entry_fp, like we do in `LeaveExitFrame`.
ExternalReference c_entry_fp_address = ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate());
__ mov(__ ExternalReferenceAsOperand(c_entry_fp_address, esi), Immediate(0));
// Compute the handler entry address and jump to it.
__ mov(edi, __ ExternalReferenceAsOperand(pending_handler_entrypoint_address,
edi));
......
......@@ -382,6 +382,12 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
{
Operand c_entry_fp_operand = masm->ExternalReferenceAsOperand(c_entry_fp);
__ Push(c_entry_fp_operand);
// Clear c_entry_fp, now we've pushed its previous value to the stack.
// If the c_entry_fp is not already zero and we don't clear it, the
// SafeStackFrameIterator will assume we are executing C++ and miss the JS
// frames on top.
__ movq(c_entry_fp_operand, Immediate(0));
}
// Store the context address in the previously-reserved slot.
......@@ -2697,6 +2703,13 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// underlying register is caller-saved and can be arbitrarily clobbered.
__ ResetSpeculationPoisonRegister();
// Clear c_entry_fp, like we do in `LeaveExitFrame`.
ExternalReference c_entry_fp_address = ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate());
Operand c_entry_fp_operand =
masm->ExternalReferenceAsOperand(c_entry_fp_address);
__ movq(c_entry_fp_operand, Immediate(0));
// Compute the handler entry address and jump to it.
__ movq(rdi,
masm->ExternalReferenceAsOperand(pending_handler_entrypoint_address));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment