[x86/SLH] Extract the logic to trace predicate state through calls to

a helper function with a nice overview comment. NFC.

This is a preperatory refactoring to implementing another component of
mitigation here that was descibed in the design document but hadn't been
implemented yet.

llvm-svn: 338016
This commit is contained in:
Chandler Carruth 2018-07-26 09:42:57 +00:00
parent f8823f3ccc
commit 1387159b93
1 changed files with 39 additions and 19 deletions

View File

@ -207,6 +207,7 @@ private:
DebugLoc Loc); DebugLoc Loc);
unsigned hardenPostLoad(MachineInstr &MI); unsigned hardenPostLoad(MachineInstr &MI);
void hardenReturnInstr(MachineInstr &MI); void hardenReturnInstr(MachineInstr &MI);
void tracePredStateThroughCall(MachineInstr &MI);
void hardenIndirectCallOrJumpInstr( void hardenIndirectCallOrJumpInstr(
MachineInstr &MI, MachineInstr &MI,
SmallDenseMap<unsigned, unsigned, 32> &AddrRegToHardenedReg); SmallDenseMap<unsigned, unsigned, 32> &AddrRegToHardenedReg);
@ -1588,25 +1589,7 @@ void X86SpeculativeLoadHardeningPass::tracePredStateThroughBlocksAndHarden(
// state into a call and recovering it after the call returns unless this // state into a call and recovering it after the call returns unless this
// is a tail call. // is a tail call.
assert(MI.isCall() && "Should only reach here for calls!"); assert(MI.isCall() && "Should only reach here for calls!");
auto InsertPt = MI.getIterator(); tracePredStateThroughCall(MI);
DebugLoc Loc = MI.getDebugLoc();
// First, we transfer the predicate state into the called function by
// merging it into the stack pointer. This will kill the current def of
// the state.
unsigned StateReg = PS->SSA.GetValueAtEndOfBlock(&MBB);
mergePredStateIntoSP(MBB, InsertPt, Loc, StateReg);
// If this call is also a return, it is a tail call and we don't need
// anything else to handle it so just continue.
if (MI.isReturn())
continue;
// We need to step past the call and recover the predicate
// state from SP after the return, and make this new state available.
++InsertPt;
unsigned NewStateReg = extractPredStateFromSP(MBB, InsertPt, Loc);
PS->SSA.AddAvailableValue(&MBB, NewStateReg);
} }
HardenPostLoad.clear(); HardenPostLoad.clear();
@ -2148,6 +2131,43 @@ void X86SpeculativeLoadHardeningPass::hardenReturnInstr(MachineInstr &MI) {
mergePredStateIntoSP(MBB, InsertPt, Loc, PS->SSA.GetValueAtEndOfBlock(&MBB)); mergePredStateIntoSP(MBB, InsertPt, Loc, PS->SSA.GetValueAtEndOfBlock(&MBB));
} }
/// Trace the predicate state through a call.
///
/// There are several layers of this needed to handle the full complexity of
/// calls.
///
/// First, we need to send the predicate state into the called function. We do
/// this by merging it into the high bits of the stack pointer.
///
/// For tail calls, this is all we need to do.
///
/// For calls where we might return to control flow, we further need to extract
/// the predicate state built up within that function from the high bits of the
/// stack pointer, and make that the newly available predicate state.
void X86SpeculativeLoadHardeningPass::tracePredStateThroughCall(
MachineInstr &MI) {
MachineBasicBlock &MBB = *MI.getParent();
auto InsertPt = MI.getIterator();
DebugLoc Loc = MI.getDebugLoc();
// First, we transfer the predicate state into the called function by merging
// it into the stack pointer. This will kill the current def of the state.
unsigned StateReg = PS->SSA.GetValueAtEndOfBlock(&MBB);
mergePredStateIntoSP(MBB, InsertPt, Loc, StateReg);
// If this call is also a return, it is a tail call and we don't need anything
// else to handle it so just continue.
// FIXME: We should also handle noreturn calls.
if (MI.isReturn())
return;
// We need to step past the call and recover the predicate state from SP after
// the return, and make this new state available.
++InsertPt;
unsigned NewStateReg = extractPredStateFromSP(MBB, InsertPt, Loc);
PS->SSA.AddAvailableValue(&MBB, NewStateReg);
}
/// An attacker may speculatively store over a value that is then speculatively /// An attacker may speculatively store over a value that is then speculatively
/// loaded and used as the target of an indirect call or jump instruction. This /// loaded and used as the target of an indirect call or jump instruction. This
/// is called Spectre v1.2 or Bounds Check Bypass Store (BCBS) and is described /// is called Spectre v1.2 or Bounds Check Bypass Store (BCBS) and is described