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 // If the indirect call is called within catchpad or cleanuppad, 169 // we need to copy "funclet" bundle of the call. 170 SmallVector<llvm::OperandBundleDef, 1> Bundles; 171 if (auto Bundle = CB->getOperandBundle(LLVMContext::OB_funclet)) 172 Bundles.push_back(OperandBundleDef(*Bundle)); 173 174 // Load the global symbol as a pointer to the check function. 175 LoadInst *GuardCheckLoad = B.CreateLoad(GuardFnPtrType, GuardFnGlobal); 176 177 // Create new call instruction. The CFGuard check should always be a call, 178 // even if the original CallBase is an Invoke or CallBr instruction. 179 CallInst *GuardCheck = 180 B.CreateCall(GuardFnType, GuardCheckLoad, 181 {B.CreateBitCast(CalledOperand, B.getInt8PtrTy())}, Bundles); 182 183 // Ensure that the first argument is passed in the correct register 184 // (e.g. ECX on 32-bit X86 targets). 185 GuardCheck->setCallingConv(CallingConv::CFGuard_Check); 186 } 187 188 void CFGuard::insertCFGuardDispatch(CallBase *CB) { 189 190 assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() && 191 "Only applicable for Windows targets"); 192 assert(CB->isIndirectCall() && 193 "Control Flow Guard checks can only be added to indirect calls"); 194 195 IRBuilder<> B(CB); 196 Value *CalledOperand = CB->getCalledOperand(); 197 Type *CalledOperandType = CalledOperand->getType(); 198 199 // Cast the guard dispatch global to the type of the called operand. 200 PointerType *PTy = PointerType::get(CalledOperandType, 0); 201 if (GuardFnGlobal->getType() != PTy) 202 GuardFnGlobal = ConstantExpr::getBitCast(GuardFnGlobal, PTy); 203 204 // Load the global as a pointer to a function of the same type. 205 LoadInst *GuardDispatchLoad = B.CreateLoad(CalledOperandType, GuardFnGlobal); 206 207 // Add the original call target as a cfguardtarget operand bundle. 208 SmallVector<llvm::OperandBundleDef, 1> Bundles; 209 CB->getOperandBundlesAsDefs(Bundles); 210 Bundles.emplace_back("cfguardtarget", CalledOperand); 211 212 // Create a copy of the call/invoke instruction and add the new bundle. 213 assert((isa<CallInst>(CB) || isa<InvokeInst>(CB)) && 214 "Unknown indirect call type"); 215 CallBase *NewCB = CallBase::Create(CB, Bundles, CB); 216 217 // Change the target of the call to be the guard dispatch function. 218 NewCB->setCalledOperand(GuardDispatchLoad); 219 220 // Replace the original call/invoke with the new instruction. 221 CB->replaceAllUsesWith(NewCB); 222 223 // Delete the original call/invoke. 224 CB->eraseFromParent(); 225 } 226 227 bool CFGuard::doInitialization(Module &M) { 228 229 // Check if this module has the cfguard flag and read its value. 230 if (auto *MD = 231 mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) 232 cfguard_module_flag = MD->getZExtValue(); 233 234 // Skip modules for which CFGuard checks have been disabled. 235 if (cfguard_module_flag != 2) 236 return false; 237 238 // Set up prototypes for the guard check and dispatch functions. 239 GuardFnType = FunctionType::get(Type::getVoidTy(M.getContext()), 240 {Type::getInt8PtrTy(M.getContext())}, false); 241 GuardFnPtrType = PointerType::get(GuardFnType, 0); 242 243 // Get or insert the guard check or dispatch global symbols. 244 if (GuardMechanism == CF_Check) { 245 GuardFnGlobal = 246 M.getOrInsertGlobal("__guard_check_icall_fptr", GuardFnPtrType); 247 } else { 248 assert(GuardMechanism == CF_Dispatch && "Invalid CFGuard mechanism"); 249 GuardFnGlobal = 250 M.getOrInsertGlobal("__guard_dispatch_icall_fptr", GuardFnPtrType); 251 } 252 253 return true; 254 } 255 256 bool CFGuard::runOnFunction(Function &F) { 257 258 // Skip modules for which CFGuard checks have been disabled. 259 if (cfguard_module_flag != 2) 260 return false; 261 262 SmallVector<CallBase *, 8> IndirectCalls; 263 264 // Iterate over the instructions to find all indirect call/invoke/callbr 265 // instructions. Make a separate list of pointers to indirect 266 // call/invoke/callbr instructions because the original instructions will be 267 // deleted as the checks are added. 268 for (BasicBlock &BB : F.getBasicBlockList()) { 269 for (Instruction &I : BB.getInstList()) { 270 auto *CB = dyn_cast<CallBase>(&I); 271 if (CB && CB->isIndirectCall() && !CB->hasFnAttr("guard_nocf")) { 272 IndirectCalls.push_back(CB); 273 CFGuardCounter++; 274 } 275 } 276 } 277 278 // If no checks are needed, return early. 279 if (IndirectCalls.empty()) { 280 return false; 281 } 282 283 // For each indirect call/invoke, add the appropriate dispatch or check. 284 if (GuardMechanism == CF_Dispatch) { 285 for (CallBase *CB : IndirectCalls) { 286 insertCFGuardDispatch(CB); 287 } 288 } else { 289 for (CallBase *CB : IndirectCalls) { 290 insertCFGuardCheck(CB); 291 } 292 } 293 294 return true; 295 } 296 297 char CFGuard::ID = 0; 298 INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false) 299 300 FunctionPass *llvm::createCFGuardCheckPass() { 301 return new CFGuard(CFGuard::CF_Check); 302 } 303 304 FunctionPass *llvm::createCFGuardDispatchPass() { 305 return new CFGuard(CFGuard::CF_Dispatch); 306 } 307