1 //===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This pass instruments indirect calls with checks to ensure that these calls 9 // pass through the appropriate jump-instruction table generated by 10 // JumpInstrTables. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H 15 #define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H 16 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Pass.h" 20 #include "llvm/Target/TargetOptions.h" 21 #include <string> 22 23 namespace llvm { 24 25 class AnalysisUsage; 26 class BasicBlock; 27 class Constant; 28 class Function; 29 class Instruction; 30 class Module; 31 class Value; 32 33 /// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to 34 /// prepend checks to indirect calls to make sure that these calls target valid 35 /// locations. 36 class ForwardControlFlowIntegrity : public ModulePass { 37 public: 38 static char ID; 39 40 ForwardControlFlowIntegrity(); 41 ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT, 42 CFIntegrity CFIType, 43 bool CFIEnforcing, std::string CFIFuncName); 44 ~ForwardControlFlowIntegrity() override; 45 46 /// Runs the CFI pass on a given module. This works best if the module in 47 /// question is the result of link-time optimization (see lib/LTO). 48 bool runOnModule(Module &M) override; getPassName()49 const char *getPassName() const override { 50 return "Forward Control-Flow Integrity"; 51 } 52 void getAnalysisUsage(AnalysisUsage &AU) const override; 53 54 private: 55 typedef SmallVector<Instruction *, 64> CallSet; 56 57 /// A structure that is used to keep track of constant table information. 58 struct CFIConstants { 59 Constant *StartValue; 60 Constant *MaskValue; 61 Constant *Size; 62 }; 63 64 /// A map from function type to the base of the table for this type and a mask 65 /// for the table 66 typedef DenseMap<FunctionType *, CFIConstants> CFITables; 67 68 CallSet IndirectCalls; 69 70 /// The type of jumptable implementation. 71 JumpTable::JumpTableType JTType; 72 73 /// The type of CFI check to add before each indirect call. 74 CFIntegrity CFIType; 75 76 /// A value that controls whether or not CFI violations cause a halt. 77 bool CFIEnforcing; 78 79 /// The name of the function to call in case of a CFI violation when 80 /// CFIEnforcing is false. There is a default function that ignores 81 /// violations. 82 std::string CFIFuncName; 83 84 /// The alignment of each entry in the table, from JumpInstrTableInfo. The 85 /// JumpInstrTableInfo class always makes this a power of two. 86 uint64_t ByteAlignment; 87 88 /// The base-2 logarithm of ByteAlignment, needed for some of the transforms 89 /// (like CFIntegrity::Ror) 90 unsigned LogByteAlignment; 91 92 /// Adds checks to each indirect call site to make sure that it is calling a 93 /// function in our jump table. 94 void updateIndirectCalls(Module &M, CFITables &CFIT); 95 96 /// Walks the instructions to find all the indirect calls. 97 void getIndirectCalls(Module &M); 98 99 /// Adds a function that handles violations in non-enforcing mode 100 /// (!CFIEnforcing). The default warning function simply returns, since the 101 /// exact details of how to handle CFI violations depend on the application. 102 void addWarningFunction(Module &M); 103 104 /// Rewrites a function pointer in a call/invoke instruction to force it into 105 /// a table. 106 void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr, 107 Constant *JumpTableStart, Constant *JumpTableMask, 108 Constant *JumpTableSize); 109 110 /// Inserts a check and a call to a warning function at a given instruction 111 /// that must be an indirect call. 112 void insertWarning(Module &M, BasicBlock *Block, Instruction *I, 113 Value *FunPtr); 114 }; 115 116 ModulePass * 117 createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT, 118 CFIntegrity CFIType, 119 bool CFIEnforcing, StringRef CFIFuncName); 120 } 121 122 #endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H 123