LLVM 24.0.0git
KCFI.cpp
Go to the documentation of this file.
1//===---- KCFI.cpp - Implements Kernel Control-Flow Integrity (KCFI) ------===//
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// This pass implements Kernel Control-Flow Integrity (KCFI) indirect call
10// check lowering. For each call instruction with a cfi-type attribute, it
11// emits an arch-specific check before the call, and bundles the check and
12// the call to prevent unintentional modifications.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/CodeGen/KCFI.h"
17#include "llvm/ADT/Statistic.h"
25#include "llvm/IR/Module.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "kcfi"
31#define KCFI_PASS_NAME "Insert KCFI indirect call checks"
32
33STATISTIC(NumKCFIChecksAdded, "Number of indirect call checks added");
34
35namespace {
36class KCFI {
37public:
38 bool run(MachineFunction &MF);
39
40private:
41 /// Machine instruction info used throughout the class.
42 const TargetInstrInfo *TII = nullptr;
43
44 /// Target lowering for arch-specific parts.
45 const TargetLowering *TLI = nullptr;
46
47 /// Emits a KCFI check before an indirect call.
48 /// \returns true if the check was added and false otherwise.
49 bool emitCheck(MachineBasicBlock &MBB,
51};
52
53class MachineKCFILegacy : public MachineFunctionPass {
54public:
55 static char ID;
56
57 MachineKCFILegacy() : MachineFunctionPass(ID) {}
58
59 StringRef getPassName() const override { return KCFI_PASS_NAME; }
60 bool runOnMachineFunction(MachineFunction &MF) override {
61 return KCFI().run(MF);
62 }
63
64 void getAnalysisUsage(AnalysisUsage &AU) const override {
65 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
67 }
68};
69
70char MachineKCFILegacy::ID = 0;
71} // end anonymous namespace
72
73INITIALIZE_PASS(MachineKCFILegacy, DEBUG_TYPE, KCFI_PASS_NAME, false, false)
74
75FunctionPass *llvm::createKCFIPass() { return new MachineKCFILegacy(); }
76
86
87bool KCFI::emitCheck(MachineBasicBlock &MBB,
89 assert(TII && "Target instruction info was not initialized");
90 assert(TLI && "Target lowering was not initialized");
91
92 // If the call instruction is bundled, we can only emit a check safely if
93 // it's the first instruction in the bundle.
94 if (MBBI->isBundled() && !std::prev(MBBI)->isBundle())
95 report_fatal_error("Cannot emit a KCFI check for a bundled call");
96
97 // Emit a KCFI check for the call instruction at MBBI. The implementation
98 // must unfold memory operands if applicable.
99 MachineInstr *Check = TLI->EmitKCFICheck(MBB, MBBI, TII);
100
101 // Clear the original call's CFI type.
102 assert(MBBI->isCall() && "Unexpected instruction type");
103 MBBI->setCFIType(*MBB.getParent(), 0);
104
105 // If not already bundled, bundle the check and the call to prevent
106 // further changes.
107 if (!MBBI->isBundled())
108 finalizeBundle(MBB, Check->getIterator(), std::next(MBBI->getIterator()));
109
110 ++NumKCFIChecksAdded;
111 return true;
112}
113
114bool KCFI::run(MachineFunction &MF) {
115 const Module *M = MF.getFunction().getParent();
116 if (!M->getModuleFlag("kcfi"))
117 return false;
118
119 const auto &SubTarget = MF.getSubtarget();
120 TII = SubTarget.getInstrInfo();
121 TLI = SubTarget.getTargetLowering();
122
123 bool Changed = false;
124 for (MachineBasicBlock &MBB : MF) {
125 // Use instr_iterator because we don't want to skip bundles.
126 for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
127 MIE = MBB.instr_end();
128 MII != MIE; ++MII) {
129 if (MII->isCall() && MII->getCFIType())
130 Changed |= emitCheck(MBB, MII);
131 }
132 }
133
134 return Changed;
135}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define KCFI_PASS_NAME
Definition KCFI.cpp:31
This file contains the declaration of the MachineKCFI class, which is a Machine Pass that implements ...
#define DEBUG_TYPE
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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
This file describes how to lower LLVM code to machine code.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Module * getParent()
Get the module that this global value is contained inside of...
Instructions::iterator instr_iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Definition KCFI.cpp:77
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
TargetInstrInfo - Interface to description of machine instruction set.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Changed
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI FunctionPass * createKCFIPass()
Lowers KCFI operand bundles for indirect calls.
Definition KCFI.cpp:75
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163