xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/CFGuard/CFGuard.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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