Page MenuHomePhabricator

[AArch64] Avoid incompatibility between SLSBLR mitigation and BTI codegen.
ClosedPublic

Authored by kristof.beyls on Jun 8 2020, 8:18 AM.

Details

Summary

A "BTI c" instruction only allows jumping/calling to using a BLR* instruction.
However, the SLSBLR mitigation changes a BLR to a BR to implement the
function call. Therefore, a "BTI c" check that passed before could
trigger after the BLR->BL change done by the SLSBLR mitigation.
However, if the register used in BR is X16 or X17, this trigger will not
fire (see ArmARM for further details).

Therefore, this patch simply changes the function stubs for the SLSBLR
mitigation from
__llvm_slsblr_thunk_x<N>:

br x<N>
SpeculationBarrier

to
__llvm_slsblr_thunk_x<N>:

mov x16, x<N>
br  x16
SpeculationBarrier

Diff Detail

Event Timeline

kristof.beyls created this revision.Jun 8 2020, 8:18 AM

I have the same concern as in D81402: will this still work if the call to the thunk goes through a long-branch veneer or PLT, which could clobber x16 and x17?

llvm/lib/Target/AArch64/AArch64FastISel.cpp
3274 ↗(On Diff #269248)

Do we need to conditionally emit BLRCallX16X17 here too?

3307 ↗(On Diff #269248)

Again, might we need to emit BLRCallX16X17 here?

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
1129 ↗(On Diff #269248)

Why is this hard-coded to BLRCallX16X17, never BLRCall?

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
6562 ↗(On Diff #269248)

Would it be possible for a BLRCallX16X17 to reach here?

llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
779 ↗(On Diff #269248)

Same as fast-sel, do we need to emit BLRCallX16X17 here?

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
2874 ↗(On Diff #269248)

Same as fast-sel, do we need to emit BLRCallX16X17 here?

kristof.beyls edited the summary of this revision. (Show Details)

Based on the review feedback that using X16 or X17 could be problematic since a linker can clobber those registers on a call, this patch goes for a different approach to achieve compatibility with BTI-enabled callees.
It simply moves the register to be called always to be in X16, and then does BR X16.
It seems it's simplest to do that unconditionally, as it may not always be easy to find out if the call target has been BTI-enabled.

ostannard accepted this revision.Jun 10 2020, 8:28 AM

LGTM.

I think we could make this conditional based on whether the caller has BTI enabled, because:

  • If the caller has BTI enabled, then we correctly use X16 for a BTI callee, or wastefully (but still with correct behaviour) use X16 for a non-BTI callee.
  • If the caller has BTI disabled, then it must be in a page with BTI disabled, and so is able to use BR with any register, even if the destination is BTI-protected.

This relies on the caller and thunk being allocated in memory with the same BTI state, which I expect to be a safe assumption.

This patch still looks good by itself, the above would just be an optimisation and can be done later.

This revision is now accepted and ready to land.Jun 10 2020, 8:28 AM
This revision was automatically updated to reflect the committed changes.