OLD | NEW |
1 //===- SandboxIndirectCalls.cpp - Apply CFI to indirect function calls ----===// | 1 //===- SandboxIndirectCalls.cpp - Apply CFI to indirect function calls ----===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This is a pass which applies basic control-flow integrity enforcement to | 10 // This is a pass which applies basic control-flow integrity enforcement to |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 }; | 60 }; |
61 } // namespace | 61 } // namespace |
62 | 62 |
63 static inline size_t RoundToPowerOf2(size_t n) { | 63 static inline size_t RoundToPowerOf2(size_t n) { |
64 if (isPowerOf2_64(n)) | 64 if (isPowerOf2_64(n)) |
65 return n; | 65 return n; |
66 else | 66 else |
67 return NextPowerOf2(n); | 67 return NextPowerOf2(n); |
68 } | 68 } |
69 | 69 |
70 static inline bool IsPtrToIntUse(const Function::user_iterator &FuncUser) { | 70 static inline bool IsPtrToIntUse(const Use &FuncUse) { |
71 if (isa<PtrToIntInst>(*FuncUser)) | 71 if (isa<PtrToIntInst>(FuncUse.getUser())) |
72 return true; | 72 return true; |
73 else if (ConstantExpr *Expr = dyn_cast<ConstantExpr>(*FuncUser)) | 73 else if (auto *Expr = dyn_cast<ConstantExpr>(FuncUse.getUser())) |
74 return Expr->getOpcode() == Instruction::PtrToInt; | 74 return Expr->getOpcode() == Instruction::PtrToInt; |
75 else | 75 else |
76 return false; | 76 return false; |
77 } | 77 } |
78 | 78 |
79 // Function use is a direct call if the user is a call instruction and | 79 // Function use is a direct call if the user is a call instruction and |
80 // the function is its last operand. | 80 // the function is its last operand. |
81 static inline bool IsDirectCallUse(const Function::user_iterator &FuncUser) { | 81 static inline bool IsDirectCallUse(const Use &FuncUse) { |
82 if (CallInst *Call = dyn_cast<CallInst>(*FuncUser)) | 82 if (auto *Call = dyn_cast<CallInst>(FuncUse.getUser())) { |
83 return FuncUser.getOperandNo() == Call->getNumArgOperands(); | 83 return FuncUse.getOperandNo() == Call->getNumOperands() - 1; |
84 else | 84 } |
85 return false; | 85 return false; |
86 } | 86 } |
87 | 87 |
88 bool SandboxIndirectCalls::runOnModule(Module &M) { | 88 bool SandboxIndirectCalls::runOnModule(Module &M) { |
89 typedef SmallVector<Constant*, 16> FunctionVector; | 89 typedef SmallVector<Constant*, 16> FunctionVector; |
90 DataLayout DL(&M); | 90 DataLayout DL(&M); |
91 Type *I32 = Type::getInt32Ty(M.getContext()); | 91 Type *I32 = Type::getInt32Ty(M.getContext()); |
92 Type *IntPtrType = DL.getIntPtrType(M.getContext()); | 92 Type *IntPtrType = DL.getIntPtrType(M.getContext()); |
93 | 93 |
94 // First, we find all address-taken functions and assign each an index. | 94 // First, we find all address-taken functions and assign each an index. |
95 // Pointers in code are then immediately replaced with these indices, even | 95 // Pointers in code are then immediately replaced with these indices, even |
96 // though the tables have not been created yet. | 96 // though the tables have not been created yet. |
97 FunctionVector AddrTakenFuncs; | 97 FunctionVector AddrTakenFuncs; |
98 for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { | 98 for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { |
99 bool HasIndirectUse = false; | 99 bool HasIndirectUse = false; |
100 Constant *Index = ConstantInt::get(IntPtrType, AddrTakenFuncs.size() + 1); | 100 Constant *Index = ConstantInt::get(IntPtrType, AddrTakenFuncs.size() + 1); |
101 for (Function::user_iterator User = Func->user_begin(), | 101 for (auto &Use : Func->uses()) { |
102 E = Func->user_end(); | 102 if (IsPtrToIntUse(Use)) { |
103 User != E; ++User) { | |
104 if (IsPtrToIntUse(User)) { | |
105 HasIndirectUse = true; | 103 HasIndirectUse = true; |
106 (*User)->replaceAllUsesWith(Index); | 104 Use.getUser()->replaceAllUsesWith(Index); |
107 if (Instruction *UserInst = dyn_cast<Instruction>(*User)) | 105 if (auto *UserInst = dyn_cast<Instruction>(Use.getUser())) |
108 UserInst->eraseFromParent(); | 106 UserInst->eraseFromParent(); |
109 } else if (!IsDirectCallUse(User)) { | 107 } else if (!IsDirectCallUse(Use)) { |
110 report_fatal_error("SandboxIndirectCalls: Invalid reference to " | 108 report_fatal_error("SandboxIndirectCalls: Invalid reference to " |
111 "function @" + Func->getName()); | 109 "function @" + Func->getName()); |
112 } | 110 } |
113 } | 111 } |
114 | 112 |
115 if (HasIndirectUse) | 113 if (HasIndirectUse) |
116 AddrTakenFuncs.push_back(Func); | 114 AddrTakenFuncs.push_back(Func); |
117 } | 115 } |
118 | 116 |
119 // Return if no address-taken functions have been found. | 117 // Return if no address-taken functions have been found. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 if (IntToPtrInst *Cast = dyn_cast<IntToPtrInst>(Callee)) { | 167 if (IntToPtrInst *Cast = dyn_cast<IntToPtrInst>(Callee)) { |
170 Value *FuncIndex = Cast->getOperand(0); | 168 Value *FuncIndex = Cast->getOperand(0); |
171 PointerType *FuncType = cast<PointerType>(Cast->getType()); | 169 PointerType *FuncType = cast<PointerType>(Cast->getType()); |
172 Constant *GlobalVar = TableGlobals[FuncType]; | 170 Constant *GlobalVar = TableGlobals[FuncType]; |
173 | 171 |
174 Value *FuncPtr; | 172 Value *FuncPtr; |
175 if (GlobalVar) { | 173 if (GlobalVar) { |
176 Instruction *MaskedIndex = | 174 Instruction *MaskedIndex = |
177 BinaryOperator::CreateAnd(FuncIndex, IndexMask, "", Call); | 175 BinaryOperator::CreateAnd(FuncIndex, IndexMask, "", Call); |
178 Value *Indexes[] = { ConstantInt::get(I32, 0), MaskedIndex }; | 176 Value *Indexes[] = { ConstantInt::get(I32, 0), MaskedIndex }; |
179 Instruction *TableElemPtr = | 177 Instruction *TableElemPtr = GetElementPtrInst::Create( |
180 GetElementPtrInst::Create(GlobalVar, Indexes, "", Call); | 178 cast<PointerType>(GlobalVar->getType())->getElementType(), |
| 179 GlobalVar, Indexes, "", Call); |
181 FuncPtr = CopyDebug(new LoadInst(TableElemPtr, "", Call), Cast); | 180 FuncPtr = CopyDebug(new LoadInst(TableElemPtr, "", Call), Cast); |
182 } else { | 181 } else { |
183 // There is no function table for this signature, i.e. the module | 182 // There is no function table for this signature, i.e. the module |
184 // does not contain a function which could be called at this site. | 183 // does not contain a function which could be called at this site. |
185 // We replace the pointer with a null and put a trap in front of | 184 // We replace the pointer with a null and put a trap in front of |
186 // the call because it should never be called. | 185 // the call because it should never be called. |
187 CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), | 186 CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), |
188 "", Call); | 187 "", Call); |
189 FuncPtr = ConstantPointerNull::get(FuncType); | 188 FuncPtr = ConstantPointerNull::get(FuncType); |
190 } | 189 } |
(...skipping 10 matching lines...) Expand all Loading... |
201 return true; | 200 return true; |
202 } | 201 } |
203 | 202 |
204 char SandboxIndirectCalls::ID = 0; | 203 char SandboxIndirectCalls::ID = 0; |
205 INITIALIZE_PASS(SandboxIndirectCalls, "minsfi-sandbox-indirect-calls", | 204 INITIALIZE_PASS(SandboxIndirectCalls, "minsfi-sandbox-indirect-calls", |
206 "Add CFI to indirect calls", false, false) | 205 "Add CFI to indirect calls", false, false) |
207 | 206 |
208 ModulePass *llvm::createSandboxIndirectCallsPass() { | 207 ModulePass *llvm::createSandboxIndirectCallsPass() { |
209 return new SandboxIndirectCalls(); | 208 return new SandboxIndirectCalls(); |
210 } | 209 } |
OLD | NEW |