1 //===-- CFGuard.cpp - Control Flow Guard checks -----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file contains the IR transform to add Microsoft's Control Flow Guard
11 /// checks on Windows targets.
13 //===----------------------------------------------------------------------===//
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"
27 using OperandBundleDef
= OperandBundleDefT
<Value
*>;
29 #define DEBUG_TYPE "cfguard"
31 STATISTIC(CFGuardCounter
, "Number of Control Flow Guard checks added");
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
{
43 enum Mechanism
{ CF_Check
, CF_Dispatch
};
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
;
52 // Recommended constructor used to specify the type of guard mechanism.
53 CFGuard(Mechanism Var
) : FunctionPass(ID
) {
54 initializeCFGuardPass(*PassRegistry::getPassRegistry());
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
68 /// For example, the following LLVM IR:
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()
76 /// is transformed to:
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()
87 /// For example, the following X86 assembly code:
89 /// movl $_target_func, %eax
93 /// is transformed to:
95 /// movl $_target_func, %ecx
96 /// calll *___guard_check_icall_fptr
100 /// \param CB indirect call to instrument.
101 void insertCFGuardCheck(CallBase
*CB
);
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
112 /// For example, the following LLVM IR:
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()
120 /// is transformed to:
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) ]
129 /// For example, the following X86_64 assembly code:
131 /// leaq target_func(%rip), %rax
135 /// is transformed to:
137 /// leaq target_func(%rip), %rax
138 /// callq *__guard_dispatch_icall_fptr(%rip)
141 /// \param CB indirect call to instrument.
142 void insertCFGuardDispatch(CallBase
*CB
);
144 bool doInitialization(Module
&M
) override
;
145 bool runOnFunction(Function
&F
) override
;
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;
156 } // end anonymous namespace
158 void CFGuard::insertCFGuardCheck(CallBase
*CB
) {
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");
166 Value
*CalledOperand
= CB
->getCalledOperand();
168 // Load the global symbol as a pointer to the check function.
169 LoadInst
*GuardCheckLoad
= B
.CreateLoad(GuardFnPtrType
, GuardFnGlobal
);
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())});
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
);
182 void CFGuard::insertCFGuardDispatch(CallBase
*CB
) {
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");
190 Value
*CalledOperand
= CB
->getCalledOperand();
191 Type
*CalledOperandType
= CalledOperand
->getType();
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
);
198 // Load the global as a pointer to a function of the same type.
199 LoadInst
*GuardDispatchLoad
= B
.CreateLoad(CalledOperandType
, GuardFnGlobal
);
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
);
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
);
211 // Change the target of the call to be the guard dispatch function.
212 NewCB
->setCalledOperand(GuardDispatchLoad
);
214 // Replace the original call/invoke with the new instruction.
215 CB
->replaceAllUsesWith(NewCB
);
217 // Delete the original call/invoke.
218 CB
->eraseFromParent();
221 bool CFGuard::doInitialization(Module
&M
) {
223 // Check if this module has the cfguard flag and read its value.
225 mdconst::extract_or_null
<ConstantInt
>(M
.getModuleFlag("cfguard")))
226 cfguard_module_flag
= MD
->getZExtValue();
228 // Skip modules for which CFGuard checks have been disabled.
229 if (cfguard_module_flag
!= 2)
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);
237 // Get or insert the guard check or dispatch global symbols.
238 if (GuardMechanism
== CF_Check
) {
240 M
.getOrInsertGlobal("__guard_check_icall_fptr", GuardFnPtrType
);
242 assert(GuardMechanism
== CF_Dispatch
&& "Invalid CFGuard mechanism");
244 M
.getOrInsertGlobal("__guard_dispatch_icall_fptr", GuardFnPtrType
);
250 bool CFGuard::runOnFunction(Function
&F
) {
252 // Skip modules for which CFGuard checks have been disabled.
253 if (cfguard_module_flag
!= 2)
256 SmallVector
<CallBase
*, 8> IndirectCalls
;
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
);
272 // If no checks are needed, return early.
273 if (IndirectCalls
.empty()) {
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
);
283 for (CallBase
*CB
: IndirectCalls
) {
284 insertCFGuardCheck(CB
);
291 char CFGuard::ID
= 0;
292 INITIALIZE_PASS(CFGuard
, "CFGuard", "CFGuard", false, false)
294 FunctionPass
*llvm::createCFGuardCheckPass() {
295 return new CFGuard(CFGuard::CF_Check
);
298 FunctionPass
*llvm::createCFGuardDispatchPass() {
299 return new CFGuard(CFGuard::CF_Dispatch
);