LLVM 23.0.0git
CFGuard.cpp
Go to the documentation of this file.
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
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"
23#include "llvm/Pass.h"
25
26using namespace llvm;
27
29
30#define DEBUG_TYPE "cfguard"
31
32STATISTIC(CFGuardCounter, "Number of Control Flow Guard checks added");
33
34constexpr StringRef GuardCheckFunctionName = "__guard_check_icall_fptr";
35constexpr StringRef GuardDispatchFunctionName = "__guard_dispatch_icall_fptr";
36
37namespace {
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.
42class CFGuardImpl {
43public:
44 using Mechanism = CFGuardPass::Mechanism;
45
46 /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG
47 /// check mechanism. When the image is loaded, the loader puts the appropriate
48 /// guard check function pointer in the __guard_check_icall_fptr global
49 /// symbol. This checks that the target address is a valid address-taken
50 /// function. The address of the target function is passed to the guard check
51 /// function in an architecture-specific register (e.g. ECX on 32-bit X86,
52 /// X15 on Aarch64, and R0 on ARM). The guard check function has no return
53 /// value (if the target is invalid, the guard check funtion will raise an
54 /// error).
55 ///
56 /// For example, the following LLVM IR:
57 /// \code
58 /// %func_ptr = alloca i32 ()*, align 8
59 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8
60 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8
61 /// %1 = call i32 %0()
62 /// \endcode
63 ///
64 /// is transformed to:
65 /// \code
66 /// %func_ptr = alloca i32 ()*, align 8
67 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8
68 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8
69 /// %1 = load void (i8*)*, void (i8*)** @__guard_check_icall_fptr
70 /// %2 = bitcast i32 ()* %0 to i8*
71 /// call cfguard_checkcc void %1(i8* %2)
72 /// %3 = call i32 %0()
73 /// \endcode
74 ///
75 /// For example, the following X86 assembly code:
76 /// \code
77 /// movl $_target_func, %eax
78 /// calll *%eax
79 /// \endcode
80 ///
81 /// is transformed to:
82 /// \code
83 /// movl $_target_func, %ecx
84 /// calll *___guard_check_icall_fptr
85 /// calll *%ecx
86 /// \endcode
87 ///
88 /// \param CB indirect call to instrument.
89 void insertCFGuardCheck(CallBase *CB);
90
91 /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG
92 /// dispatch mechanism. When the image is loaded, the loader puts the
93 /// appropriate guard check function pointer in the
94 /// __guard_dispatch_icall_fptr global symbol. This checks that the target
95 /// address is a valid address-taken function and, if so, tail calls the
96 /// target. The target address is passed in an architecture-specific register
97 /// (e.g. RAX on X86_64), with all other arguments for the target function
98 /// passed as usual.
99 ///
100 /// For example, the following LLVM IR:
101 /// \code
102 /// %func_ptr = alloca i32 ()*, align 8
103 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8
104 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8
105 /// %1 = call i32 %0()
106 /// \endcode
107 ///
108 /// is transformed to:
109 /// \code
110 /// %func_ptr = alloca i32 ()*, align 8
111 /// store i32 ()* @target_func, i32 ()** %func_ptr, align 8
112 /// %0 = load i32 ()*, i32 ()** %func_ptr, align 8
113 /// %1 = load i32 ()*, i32 ()** @__guard_dispatch_icall_fptr
114 /// %2 = call i32 %1() [ "cfguardtarget"(i32 ()* %0) ]
115 /// \endcode
116 ///
117 /// For example, the following X86_64 assembly code:
118 /// \code
119 /// leaq target_func(%rip), %rax
120 /// callq *%rax
121 /// \endcode
122 ///
123 /// is transformed to:
124 /// \code
125 /// leaq target_func(%rip), %rax
126 /// callq *__guard_dispatch_icall_fptr(%rip)
127 /// \endcode
128 ///
129 /// \param CB indirect call to instrument.
130 void insertCFGuardDispatch(CallBase *CB);
131
132 bool doInitialization(Module &M);
133 bool runOnFunction(Function &F);
134
135private:
136 // Only add checks if the module has them enabled.
138 Mechanism GuardMechanism = Mechanism::Check;
139 FunctionType *GuardFnType = nullptr;
140 PointerType *GuardFnPtrType = nullptr;
141 Constant *GuardFnGlobal = nullptr;
142};
143
144class CFGuard : public FunctionPass {
145 CFGuardImpl Impl;
146
147public:
148 static char ID;
149
150 // Default constructor required for the INITIALIZE_PASS macro.
151 CFGuard() : FunctionPass(ID) {}
152
153 bool doInitialization(Module &M) override { return Impl.doInitialization(M); }
154 bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); }
155};
156
157} // end anonymous namespace
158
159void CFGuardImpl::insertCFGuardCheck(CallBase *CB) {
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.
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, {CalledOperand}, Bundles);
181
182 // Ensure that the first argument is passed in the correct register
183 // (e.g. ECX on 32-bit X86 targets).
184 GuardCheck->setCallingConv(CallingConv::CFGuard_Check);
185}
186
187void CFGuardImpl::insertCFGuardDispatch(CallBase *CB) {
189 "Only applicable for Windows targets");
190 assert(CB->isIndirectCall() &&
191 "Control Flow Guard checks can only be added to indirect calls");
192
193 IRBuilder<> B(CB);
194 Value *CalledOperand = CB->getCalledOperand();
195 Type *CalledOperandType = CalledOperand->getType();
196
197 // Load the global as a pointer to a function of the same type.
198 LoadInst *GuardDispatchLoad = B.CreateLoad(CalledOperandType, GuardFnGlobal);
199
200 // Add the original call target as a cfguardtarget operand bundle.
202 CB->getOperandBundlesAsDefs(Bundles);
203 Bundles.emplace_back("cfguardtarget", CalledOperand);
204
205 // Create a copy of the call/invoke instruction and add the new bundle.
206 assert((isa<CallInst>(CB) || isa<InvokeInst>(CB)) &&
207 "Unknown indirect call type");
208 CallBase *NewCB = CallBase::Create(CB, Bundles, CB->getIterator());
209
210 // Change the target of the call to be the guard dispatch function.
211 NewCB->setCalledOperand(GuardDispatchLoad);
212
213 // Replace the original call/invoke with the new instruction.
214 CB->replaceAllUsesWith(NewCB);
215
216 // Delete the original call/invoke.
217 CB->eraseFromParent();
218}
219
220bool CFGuardImpl::doInitialization(Module &M) {
221 // Check if this module has the cfguard flag and read its value.
222 CFGuardModuleFlag = M.getControlFlowGuardMode();
223
224 // Skip modules for which CFGuard checks have been disabled.
225 if (CFGuardModuleFlag != ControlFlowGuardMode::Enabled)
226 return false;
227
228 // Determine the guard mechanism to use.
229 ControlFlowGuardMechanism MechanismOverride =
230 ControlFlowGuardMechanism::Automatic;
232 M.getModuleFlag("cfguard-mechanism")))
233 MechanismOverride =
234 static_cast<ControlFlowGuardMechanism>(CI->getZExtValue());
235 switch (MechanismOverride) {
236 case ControlFlowGuardMechanism::Check:
237 GuardMechanism = Mechanism::Check;
238 break;
239 case ControlFlowGuardMechanism::Dispatch:
240 GuardMechanism = Mechanism::Dispatch;
241 break;
242 default:
243 // X86_64 uses dispatch; all other architectures use check.
244 GuardMechanism =
245 M.getTargetTriple().isX86_64() ? Mechanism::Dispatch : Mechanism::Check;
246 break;
247 }
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 StringRef GuardFnName = GuardMechanism == Mechanism::Check
258 GuardFnGlobal = M.getOrInsertGlobal(GuardFnName, GuardFnPtrType, [&] {
259 auto *Var = new GlobalVariable(M, GuardFnPtrType, false,
260 GlobalVariable::ExternalLinkage, nullptr,
261 GuardFnName);
262 Var->setDSOLocal(true);
263 return Var;
264 });
265
266 return true;
267}
268
269bool CFGuardImpl::runOnFunction(Function &F) {
270 // Skip modules for which CFGuard checks have been disabled.
271 if (CFGuardModuleFlag != ControlFlowGuardMode::Enabled)
272 return false;
273
274 SmallVector<CallBase *, 8> IndirectCalls;
275
276 // Iterate over the instructions to find all indirect call/invoke/callbr
277 // instructions. Make a separate list of pointers to indirect
278 // call/invoke/callbr instructions because the original instructions will be
279 // deleted as the checks are added.
280 for (BasicBlock &BB : F) {
281 for (Instruction &I : BB) {
282 auto *CB = dyn_cast<CallBase>(&I);
283 if (CB && CB->isIndirectCall() && !CB->hasFnAttr("guard_nocf")) {
284 IndirectCalls.push_back(CB);
285 CFGuardCounter++;
286 }
287 }
288 }
289
290 // If no checks are needed, return early.
291 if (IndirectCalls.empty())
292 return false;
293
294 // For each indirect call/invoke, add the appropriate dispatch or check.
295 if (GuardMechanism == Mechanism::Dispatch) {
296 for (CallBase *CB : IndirectCalls)
297 insertCFGuardDispatch(CB);
298 } else {
299 for (CallBase *CB : IndirectCalls)
300 insertCFGuardCheck(CB);
301 }
302
303 return true;
304}
305
307 CFGuardImpl Impl;
308 bool Changed = Impl.doInitialization(*F.getParent());
309 Changed |= Impl.runOnFunction(F);
311}
312
313char CFGuard::ID = 0;
314INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false)
315
316FunctionPass *llvm::createCFGuardPass() { return new CFGuard(); }
317
322
325 return false;
326
327 StringRef Name = GV->getName();
328 return Name == GuardCheckFunctionName || Name == GuardDispatchFunctionName;
329}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
constexpr StringRef GuardCheckFunctionName
Definition CFGuard.cpp:34
constexpr StringRef GuardDispatchFunctionName
Definition CFGuard.cpp:35
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition CFGuard.cpp:306
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
CallingConv::ID getCallingConv() const
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
unsigned countOperandBundlesOfType(StringRef Name) const
Return the number of operand bundles with the tag Name attached to this instruction.
Value * getCalledOperand() const
static LLVM_ABI CallBase * Create(CallBase *CB, ArrayRef< OperandBundleDef > Bundles, InsertPosition InsertPt=nullptr)
Create a clone of CB with a different set of operand bundles and insert it before InsertPt.
void setCalledOperand(Value *V)
This is an important base class in LLVM.
Definition Constant.h:43
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
LinkageTypes getLinkage() const
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:281
A container for an operand bundle being viewed as a set of values rather than a set of uses.
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition Pass.h:128
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool isOSWindows() const
Tests whether the OS is Windows.
Definition Triple.h:692
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:318
self_iterator getIterator()
Definition ilist_node.h:123
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
Definition CallingConv.h:82
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:709
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI bool isCFGuardCall(const CallBase *CB)
Definition CFGuard.cpp:318
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool isCFGuardFunction(const GlobalValue *GV)
Definition CFGuard.cpp:323
ControlFlowGuardMode
Definition CodeGen.h:176
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI FunctionPass * createCFGuardPass()
Insert Control Flow Guard checks on indirect function calls.
Definition CFGuard.cpp:316
OperandBundleDefT< Value * > OperandBundleDef
Definition AutoUpgrade.h:34
ControlFlowGuardMechanism
Definition CodeGen.h:186
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.