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