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