8219993: AArch64: Compiled CI stubs are unsafely modified

Reviewed-by: adinn
This commit is contained in:
Andrew Haley 2019-04-05 09:53:07 -04:00
parent 71164a973b
commit 79218415bc
6 changed files with 41 additions and 18 deletions

View file

@ -34,6 +34,7 @@
#include "c1/c1_ValueStack.hpp" #include "c1/c1_ValueStack.hpp"
#include "ci/ciArrayKlass.hpp" #include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp" #include "ci/ciInstance.hpp"
#include "code/compiledIC.hpp"
#include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSet.hpp"
#include "gc/shared/cardTableBarrierSet.hpp" #include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectedHeap.hpp"
@ -2063,11 +2064,10 @@ void LIR_Assembler::emit_static_call_stub() {
int start = __ offset(); int start = __ offset();
__ relocate(static_stub_Relocation::spec(call_pc)); __ relocate(static_stub_Relocation::spec(call_pc));
__ mov_metadata(rmethod, (Metadata*)NULL); __ emit_static_call_stub();
__ movptr(rscratch1, 0);
__ br(rscratch1);
assert(__ offset() - start <= call_stub_size(), "stub too big"); assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
<= call_stub_size(), "stub too big");
__ end_a_stub(); __ end_a_stub();
} }

View file

@ -69,7 +69,9 @@ friend class ArrayCopyStub;
void deoptimize_trap(CodeEmitInfo *info); void deoptimize_trap(CodeEmitInfo *info);
enum { enum {
_call_stub_size = 12 * NativeInstruction::instruction_size, // call stub: CompiledStaticCall::to_interp_stub_size() +
// CompiledStaticCall::to_trampoline_stub_size()
_call_stub_size = 13 * NativeInstruction::instruction_size,
_call_aot_stub_size = 0, _call_aot_stub_size = 0,
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
_deopt_handler_size = 7 * NativeInstruction::instruction_size _deopt_handler_size = 7 * NativeInstruction::instruction_size

View file

@ -61,15 +61,15 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
// Don't create a Metadata reloc if we're generating immutable PIC. // Don't create a Metadata reloc if we're generating immutable PIC.
if (cbuf.immutable_PIC()) { if (cbuf.immutable_PIC()) {
__ movptr(rmethod, 0); __ movptr(rmethod, 0);
} else {
__ mov_metadata(rmethod, (Metadata*)NULL);
}
#else
__ mov_metadata(rmethod, (Metadata*)NULL);
#endif
__ movptr(rscratch1, 0); __ movptr(rscratch1, 0);
__ br(rscratch1); __ br(rscratch1);
} else
#endif
{
__ emit_static_call_stub();
}
assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big"); assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big");
__ end_a_stub(); __ end_a_stub();
return base; return base;
@ -77,7 +77,8 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
#undef __ #undef __
int CompiledStaticCall::to_interp_stub_size() { int CompiledStaticCall::to_interp_stub_size() {
return 7 * NativeInstruction::instruction_size; // isb; movk; movz; movz; movk; movz; movz; br
return 8 * NativeInstruction::instruction_size;
} }
int CompiledStaticCall::to_trampoline_stub_size() { int CompiledStaticCall::to_trampoline_stub_size() {
@ -159,7 +160,8 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
} }
// Creation also verifies the object. // Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
#ifndef PRODUCT #ifndef PRODUCT
NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
@ -184,7 +186,8 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
assert(stub != NULL, "stub not found"); assert(stub != NULL, "stub not found");
assert(CompiledICLocker::is_safe(stub), "mt unsafe call"); assert(CompiledICLocker::is_safe(stub), "mt unsafe call");
// Creation also verifies the object. // Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
method_holder->set_data(0); method_holder->set_data(0);
} }
@ -201,7 +204,8 @@ void CompiledDirectStaticCall::verify() {
address stub = find_stub(false /* is_aot */); address stub = find_stub(false /* is_aot */);
assert(stub != NULL, "no stub found for static call"); assert(stub != NULL, "no stub found for static call");
// Creation also verifies the object. // Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
// Verify state. // Verify state.

View file

@ -812,6 +812,18 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
return stub_start_addr; return stub_start_addr;
} }
void MacroAssembler::emit_static_call_stub() {
// CompiledDirectStaticCall::set_to_interpreted knows the
// exact layout of this stub.
isb();
mov_metadata(rmethod, (Metadata*)NULL);
// Jump to the entry point of the i2c stub.
movptr(rscratch1, 0);
br(rscratch1);
}
void MacroAssembler::c2bool(Register x) { void MacroAssembler::c2bool(Register x) {
// implements x == 0 ? 0 : 1 // implements x == 0 ? 0 : 1
// note: must only look at least-significant byte of x // note: must only look at least-significant byte of x

View file

@ -607,6 +607,7 @@ public:
static int patch_narrow_klass(address insn_addr, narrowKlass n); static int patch_narrow_klass(address insn_addr, narrowKlass n);
address emit_trampoline_stub(int insts_call_instruction_offset, address target); address emit_trampoline_stub(int insts_call_instruction_offset, address target);
void emit_static_call_stub();
// The following 4 methods return the offset of the appropriate move instruction // The following 4 methods return the offset of the appropriate move instruction

View file

@ -232,7 +232,11 @@ void NativeCall::insert(address code_pos, address entry) { Unimplemented(); }
//------------------------------------------------------------------- //-------------------------------------------------------------------
void NativeMovConstReg::verify() { void NativeMovConstReg::verify() {
// make sure code pattern is actually mov reg64, imm64 instructions if (! (nativeInstruction_at(instruction_address())->is_movz() ||
is_adrp_at(instruction_address()) ||
is_ldr_literal_at(instruction_address())) ) {
fatal("should be MOVZ or ADRP or LDR (literal)");
}
} }