LLVM  14.0.0git
X86LoadValueInjectionRetHardening.cpp
Go to the documentation of this file.
1 //===-- X86LoadValueInjectionRetHardening.cpp - LVI RET hardening for x86 --==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// Description: Replaces every `ret` instruction with the sequence:
10 /// ```
11 /// pop <scratch-reg>
12 /// lfence
13 /// jmp *<scratch-reg>
14 /// ```
15 /// where `<scratch-reg>` is some available scratch register, according to the
16 /// calling convention of the function being mitigated.
17 ///
18 //===----------------------------------------------------------------------===//
19 
20 #include "X86.h"
21 #include "X86InstrBuilder.h"
22 #include "X86Subtarget.h"
23 #include "llvm/ADT/Statistic.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/Support/Debug.h"
30 #include <bitset>
31 
32 using namespace llvm;
33 
34 #define PASS_KEY "x86-lvi-ret"
35 #define DEBUG_TYPE PASS_KEY
36 
37 STATISTIC(NumFences, "Number of LFENCEs inserted for LVI mitigation");
38 STATISTIC(NumFunctionsConsidered, "Number of functions analyzed");
39 STATISTIC(NumFunctionsMitigated, "Number of functions for which mitigations "
40  "were deployed");
41 
42 namespace {
43 
44 class X86LoadValueInjectionRetHardeningPass : public MachineFunctionPass {
45 public:
46  X86LoadValueInjectionRetHardeningPass() : MachineFunctionPass(ID) {}
47  StringRef getPassName() const override {
48  return "X86 Load Value Injection (LVI) Ret-Hardening";
49  }
50  bool runOnMachineFunction(MachineFunction &MF) override;
51 
52  static char ID;
53 };
54 
55 } // end anonymous namespace
56 
58 
59 bool X86LoadValueInjectionRetHardeningPass::runOnMachineFunction(
60  MachineFunction &MF) {
61  LLVM_DEBUG(dbgs() << "***** " << getPassName() << " : " << MF.getName()
62  << " *****\n");
63  const X86Subtarget *Subtarget = &MF.getSubtarget<X86Subtarget>();
64  if (!Subtarget->useLVIControlFlowIntegrity() || !Subtarget->is64Bit())
65  return false; // FIXME: support 32-bit
66 
67  // Don't skip functions with the "optnone" attr but participate in opt-bisect.
68  const Function &F = MF.getFunction();
69  if (!F.hasOptNone() && skipFunction(F))
70  return false;
71 
72  ++NumFunctionsConsidered;
73  const X86RegisterInfo *TRI = Subtarget->getRegisterInfo();
74  const X86InstrInfo *TII = Subtarget->getInstrInfo();
75 
76  bool Modified = false;
77  for (auto &MBB : MF) {
78  for (auto MBBI = MBB.begin(); MBBI != MBB.end(); ++MBBI) {
79  if (MBBI->getOpcode() != X86::RET64)
80  continue;
81 
82  unsigned ClobberReg = TRI->findDeadCallerSavedReg(MBB, MBBI);
83  if (ClobberReg != X86::NoRegister) {
84  BuildMI(MBB, MBBI, DebugLoc(), TII->get(X86::POP64r))
85  .addReg(ClobberReg, RegState::Define)
87  BuildMI(MBB, MBBI, DebugLoc(), TII->get(X86::LFENCE));
88  BuildMI(MBB, MBBI, DebugLoc(), TII->get(X86::JMP64r))
89  .addReg(ClobberReg);
90  MBB.erase(MBBI);
91  } else {
92  // In case there is no available scratch register, we can still read
93  // from RSP to assert that RSP points to a valid page. The write to RSP
94  // is also helpful because it verifies that the stack's write
95  // permissions are intact.
96  MachineInstr *Fence =
97  BuildMI(MBB, MBBI, DebugLoc(), TII->get(X86::LFENCE));
98  addRegOffset(BuildMI(MBB, Fence, DebugLoc(), TII->get(X86::SHL64mi)),
99  X86::RSP, false, 0)
100  .addImm(0)
101  ->addRegisterDead(X86::EFLAGS, TRI);
102  }
103 
104  ++NumFences;
105  Modified = true;
106  break;
107  }
108  }
109 
110  if (Modified)
111  ++NumFunctionsMitigated;
112  return Modified;
113 }
114 
115 INITIALIZE_PASS(X86LoadValueInjectionRetHardeningPass, PASS_KEY,
116  "X86 LVI ret hardener", false, false)
117 
119  return new X86LoadValueInjectionRetHardeningPass();
120 }
llvm::X86Subtarget::useLVIControlFlowIntegrity
bool useLVIControlFlowIntegrity() const
Definition: X86Subtarget.h:804
llvm::MachineInstr::addRegisterDead
bool addRegisterDead(Register Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI defined a register without a use.
Definition: MachineInstr.cpp:1958
llvm::MachineInstrBuilder::addImm
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Definition: MachineInstrBuilder.h:131
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
X86Subtarget.h
llvm::Function
Definition: Function.h:62
llvm::X86Subtarget::getInstrInfo
const X86InstrInfo * getInstrInfo() const override
Definition: X86Subtarget.h:566
X86InstrBuilder.h
Statistic.h
llvm::X86Subtarget
Definition: X86Subtarget.h:52
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
MachineBasicBlock.h
llvm::addRegOffset
static const MachineInstrBuilder & addRegOffset(const MachineInstrBuilder &MIB, unsigned Reg, bool isKill, int Offset)
addRegOffset - This function is used to add a memory reference of the form [Reg + Offset],...
Definition: X86InstrBuilder.h:157
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1559
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::MachineInstr::FrameDestroy
@ FrameDestroy
Definition: MachineInstr.h:84
llvm::MachineBasicBlock::erase
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
Definition: MachineBasicBlock.cpp:1301
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
X86.h
llvm::X86Subtarget::getRegisterInfo
const X86RegisterInfo * getRegisterInfo() const override
Definition: X86Subtarget.h:576
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:129
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
LoopDeletionResult::Modified
@ Modified
llvm::createX86LoadValueInjectionRetHardeningPass
FunctionPass * createX86LoadValueInjectionRetHardeningPass()
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:634
llvm::MachineInstrBuilder::setMIFlag
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
Definition: MachineInstrBuilder.h:278
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
PASS_KEY
#define PASS_KEY
Definition: X86LoadValueInjectionRetHardening.cpp:34
MachineFunctionPass.h
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:542
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition: MachineInstrBuilder.h:97
llvm::MachineFunction
Definition: MachineFunction.h:234
llvm::X86InstrInfo
Definition: X86InstrInfo.h:130
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
MBBI
MachineBasicBlock MachineBasicBlock::iterator MBBI
Definition: AArch64SLSHardening.cpp:75
llvm::RegState::Define
@ Define
Register definition.
Definition: MachineInstrBuilder.h:44
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:600
Function.h
INITIALIZE_PASS
INITIALIZE_PASS(X86LoadValueInjectionRetHardeningPass, PASS_KEY, "X86 LVI ret hardener", false, false) FunctionPass *llvm
Definition: X86LoadValueInjectionRetHardening.cpp:115
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:268
MachineInstrBuilder.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
llvm::X86Subtarget::is64Bit
bool is64Bit() const
Is this x86_64? (disregarding specific ABI / programming model)
Definition: X86Subtarget.h:612
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
MachineFunction.h
Debug.h
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:270
llvm::X86RegisterInfo
Definition: X86RegisterInfo.h:24
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38