1 //===-- CFGuard.cpp - Control Flow Guard checks -----------------*- C++ -*-===// 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 /// \file 10 /// This file contains the IR transform to add Microsoft's Control Flow Guard 11 /// checks on Windows targets. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Transforms/CFGuard.h" 16 #include "llvm/ADT/SmallVector.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/IR/CallingConv.h" 20 #include "llvm/IR/IRBuilder.h" 21 #include "llvm/IR/Instruction.h" 22 #include "llvm/InitializePasses.h" 23 #include "llvm/Pass.h" 24 25 using namespace llvm; 26 27 using OperandBundleDef = OperandBundleDefT<Value *>; 28 29 #define DEBUG_TYPE "cfguard" 30 31 STATISTIC(CFGuardCounter, "Number of Control Flow Guard checks added"); 32 33 namespace { 34 35 /// Adds Control Flow Guard (CFG) checks on indirect function calls/invokes. 36 /// These checks ensure that the target address corresponds to the start of an 37 /// address-taken function. X86_64 targets use the CF_Dispatch mechanism. X86, 38 /// ARM, and AArch64 targets use the CF_Check machanism. 39 class CFGuard : public FunctionPass { 40 public: 41 static char ID; 42 43 enum Mechanism { CF_Check, CF_Dispatch }; 44 45 // Default constructor required for the INITIALIZE_PASS macro. 46 CFGuard() : FunctionPass(ID) { 47 initializeCFGuardPass(*PassRegistry::getPassRegistry()); 48 // By default, use the guard check mechanism. 49 GuardMechanism = CF_Check; 50 } 51 52 // Recommended constructor used to specify the type of guard mechanism. 53 CFGuard(Mechanism Var) : FunctionPass(ID) { 54 initializeCFGuardPass(*PassRegistry::getPassRegistry()); 55 GuardMechanism = Var; 56 } 57 58 /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG 59 /// check mechanism. When the image is loaded, the loader puts the appropriate 60 /// guard check function pointer in the __guard_check_icall_fptr global 61 /// symbol. This checks that the target address is a valid address-taken 62 /// function. The address of the target function is passed to the guard check 63 /// function in an architecture-specific register (e.g. ECX on 32-bit X86, 64 /// X15 on Aarch64, and R0 on ARM). The guard check function has no return 65 /// value (if the target is invalid, the guard check funtion will raise an 66 /// error). 67 /// 68 /// For example, the following LLVM IR: 69 /// \code 70 /// %func_ptr = alloca i32 ()*, align 8 71 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8 72 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8 73 /// %1 = call i32 %0() 74 /// \endcode 75 /// 76 /// is transformed to: 77 /// \code 78 /// %func_ptr = alloca i32 ()*, align 8 79 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8 80 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8 81 /// %1 = load void (i8*)*, void (i8*)** @__guard_check_icall_fptr 82 /// %2 = bitcast i32 ()* %0 to i8* 83 /// call cfguard_checkcc void %1(i8* %2) 84 /// %3 = call i32 %0() 85 /// \endcode 86 /// 87 /// For example, the following X86 assembly code: 88 /// \code 89 /// movl $_target_func, %eax 90 /// calll *%eax 91 /// \endcode 92 /// 93 /// is transformed to: 94 /// \code 95 /// movl $_target_func, %ecx 96 /// calll *___guard_check_icall_fptr 97 /// calll *%ecx 98 /// \endcode 99 /// 100 /// \param CB indirect call to instrument. 101 void insertCFGuardCheck(CallBase *CB); 102 103 /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG 104 /// dispatch mechanism. When the image is loaded, the loader puts the 105 /// appropriate guard check function pointer in the 106 /// __guard_dispatch_icall_fptr global symbol. This checks that the target 107 /// address is a valid address-taken function and, if so, tail calls the 108 /// target. The target address is passed in an architecture-specific register 109 /// (e.g. RAX on X86_64), with all other arguments for the target function 110 /// passed as usual. 111 /// 112 /// For example, the following LLVM IR: 113 /// \code 114 /// %func_ptr = alloca i32 ()*, align 8 115 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8 116 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8 117 /// %1 = call i32 %0() 118 /// \endcode 119 /// 120 /// is transformed to: 121 /// \code 122 /// %func_ptr = alloca i32 ()*, align 8 123 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8 124 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8 125 /// %1 = load i32 ()*, i32 ()** @__guard_dispatch_icall_fptr 126 /// %2 = call i32 %1() [ "cfguardtarget"(i32 ()* %0) ] 127 /// \endcode 128 /// 129 /// For example, the following X86_64 assembly code: 130 /// \code 131 /// leaq target_func(%rip), %rax 132 /// callq *%rax 133 /// \endcode 134 /// 135 /// is transformed to: 136 /// \code 137 /// leaq target_func(%rip), %rax 138 /// callq *__guard_dispatch_icall_fptr(%rip) 139 /// \endcode 140 /// 141 /// \param CB indirect call to instrument. 142 void insertCFGuardDispatch(CallBase *CB); 143 144 bool doInitialization(Module &M) override; 145 bool runOnFunction(Function &F) override; 146 147 private: 148 // Only add checks if the module has the cfguard=2 flag. 149 int cfguard_module_flag = 0; 150 Mechanism GuardMechanism = CF_Check; 151 FunctionType *GuardFnType = nullptr; 152 PointerType *GuardFnPtrType = nullptr; 153 Constant *GuardFnGlobal = nullptr; 154 }; 155 156 } // end anonymous namespace 157 158 void CFGuard::insertCFGuardCheck(CallBase *CB) { 159 160 assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() && 161 "Only applicable for Windows targets"); 162 assert(CB->isIndirectCall() && 163 "Control Flow Guard checks can only be added to indirect calls"); 164 165 IRBuilder<> B(CB); 166 Value *CalledOperand = CB->getCalledOperand(); 167 168 // Load the global symbol as a pointer to the check function. 169 LoadInst *GuardCheckLoad = B.CreateLoad(GuardFnPtrType, GuardFnGlobal); 170 171 // Create new call instruction. The CFGuard check should always be a call, 172 // even if the original CallBase is an Invoke or CallBr instruction. 173 CallInst *GuardCheck = 174 B.CreateCall(GuardFnType, GuardCheckLoad, 175 {B.CreateBitCast(CalledOperand, B.getInt8PtrTy())}); 176 177 // Ensure that the first argument is passed in the correct register 178 // (e.g. ECX on 32-bit X86 targets). 179 GuardCheck->setCallingConv(CallingConv::CFGuard_Check); 180 } 181 182 void CFGuard::insertCFGuardDispatch(CallBase *CB) { 183 184 assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() && 185 "Only applicable for Windows targets"); 186 assert(CB->isIndirectCall() && 187 "Control Flow Guard checks can only be added to indirect calls"); 188 189 IRBuilder<> B(CB); 190 Value *CalledOperand = CB->getCalledOperand(); 191 Type *CalledOperandType = CalledOperand->getType(); 192 193 // Cast the guard dispatch global to the type of the called operand. 194 PointerType *PTy = PointerType::get(CalledOperandType, 0); 195 if (GuardFnGlobal->getType() != PTy) 196 GuardFnGlobal = ConstantExpr::getBitCast(GuardFnGlobal, PTy); 197 198 // Load the global as a pointer to a function of the same type. 199 LoadInst *GuardDispatchLoad = B.CreateLoad(CalledOperandType, GuardFnGlobal); 200 201 // Add the original call target as a cfguardtarget operand bundle. 202 SmallVector<llvm::OperandBundleDef, 1> Bundles; 203 CB->getOperandBundlesAsDefs(Bundles); 204 Bundles.emplace_back("cfguardtarget", CalledOperand); 205 206 // Create a copy of the call/invoke instruction and add the new bundle. 207 assert((isa<CallInst>(CB) || isa<InvokeInst>(CB)) && 208 "Unknown indirect call type"); 209 CallBase *NewCB = CallBase::Create(CB, Bundles, CB); 210 211 // Change the target of the call to be the guard dispatch function. 212 NewCB->setCalledOperand(GuardDispatchLoad); 213 214 // Replace the original call/invoke with the new instruction. 215 CB->replaceAllUsesWith(NewCB); 216 217 // Delete the original call/invoke. 218 CB->eraseFromParent(); 219 } 220 221 bool CFGuard::doInitialization(Module &M) { 222 223 // Check if this module has the cfguard flag and read its value. 224 if (auto *MD = 225 mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) 226 cfguard_module_flag = MD->getZExtValue(); 227 228 // Skip modules for which CFGuard checks have been disabled. 229 if (cfguard_module_flag != 2) 230 return false; 231 232 // Set up prototypes for the guard check and dispatch functions. 233 GuardFnType = FunctionType::get(Type::getVoidTy(M.getContext()), 234 {Type::getInt8PtrTy(M.getContext())}, false); 235 GuardFnPtrType = PointerType::get(GuardFnType, 0); 236 237 // Get or insert the guard check or dispatch global symbols. 238 if (GuardMechanism == CF_Check) { 239 GuardFnGlobal = 240 M.getOrInsertGlobal("__guard_check_icall_fptr", GuardFnPtrType); 241 } else { 242 assert(GuardMechanism == CF_Dispatch && "Invalid CFGuard mechanism"); 243 GuardFnGlobal = 244 M.getOrInsertGlobal("__guard_dispatch_icall_fptr", GuardFnPtrType); 245 } 246 247 return true; 248 } 249 250 bool CFGuard::runOnFunction(Function &F) { 251 252 // Skip modules for which CFGuard checks have been disabled. 253 if (cfguard_module_flag != 2) 254 return false; 255 256 SmallVector<CallBase *, 8> IndirectCalls; 257 258 // Iterate over the instructions to find all indirect call/invoke/callbr 259 // instructions. Make a separate list of pointers to indirect 260 // call/invoke/callbr instructions because the original instructions will be 261 // deleted as the checks are added. 262 for (BasicBlock &BB : F.getBasicBlockList()) { 263 for (Instruction &I : BB.getInstList()) { 264 auto *CB = dyn_cast<CallBase>(&I); 265 if (CB && CB->isIndirectCall() && !CB->hasFnAttr("guard_nocf")) { 266 IndirectCalls.push_back(CB); 267 CFGuardCounter++; 268 } 269 } 270 } 271 272 // If no checks are needed, return early. 273 if (IndirectCalls.empty()) { 274 return false; 275 } 276 277 // For each indirect call/invoke, add the appropriate dispatch or check. 278 if (GuardMechanism == CF_Dispatch) { 279 for (CallBase *CB : IndirectCalls) { 280 insertCFGuardDispatch(CB); 281 } 282 } else { 283 for (CallBase *CB : IndirectCalls) { 284 insertCFGuardCheck(CB); 285 } 286 } 287 288 return true; 289 } 290 291 char CFGuard::ID = 0; 292 INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false) 293 294 FunctionPass *llvm::createCFGuardCheckPass() { 295 return new CFGuard(CFGuard::CF_Check); 296 } 297 298 FunctionPass *llvm::createCFGuardDispatchPass() { 299 return new CFGuard(CFGuard::CF_Dispatch); 300 } 301