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