LLVM 23.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"
24#include "llvm/IR/Module.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "kcfi"
30#define KCFI_PASS_NAME "Insert KCFI indirect call checks"
31
32STATISTIC(NumKCFIChecksAdded, "Number of indirect call checks added");
33
34namespace {
35class KCFI {
36public:
37 bool run(MachineFunction &MF);
38
39private:
40 /// Machine instruction info used throughout the class.
41 const TargetInstrInfo *TII = nullptr;
42
43 /// Target lowering for arch-specific parts.
44 const TargetLowering *TLI = nullptr;
45
46 /// Emits a KCFI check before an indirect call.
47 /// \returns true if the check was added and false otherwise.
48 bool emitCheck(MachineBasicBlock &MBB,
50};
51
52class MachineKCFILegacy : public MachineFunctionPass {
53public:
54 static char ID;
55
56 MachineKCFILegacy() : MachineFunctionPass(ID) {}
57
58 StringRef getPassName() const override { return KCFI_PASS_NAME; }
59 bool runOnMachineFunction(MachineFunction &MF) override {
60 return KCFI().run(MF);
61 }
62};
63
64char MachineKCFILegacy::ID = 0;
65} // end anonymous namespace
66
67INITIALIZE_PASS(MachineKCFILegacy, DEBUG_TYPE, KCFI_PASS_NAME, false, false)
68
69FunctionPass *llvm::createKCFIPass() { return new MachineKCFILegacy(); }
70
80
81bool KCFI::emitCheck(MachineBasicBlock &MBB,
83 assert(TII && "Target instruction info was not initialized");
84 assert(TLI && "Target lowering was not initialized");
85
86 // If the call instruction is bundled, we can only emit a check safely if
87 // it's the first instruction in the bundle.
88 if (MBBI->isBundled() && !std::prev(MBBI)->isBundle())
89 report_fatal_error("Cannot emit a KCFI check for a bundled call");
90
91 // Emit a KCFI check for the call instruction at MBBI. The implementation
92 // must unfold memory operands if applicable.
93 MachineInstr *Check = TLI->EmitKCFICheck(MBB, MBBI, TII);
94
95 // Clear the original call's CFI type.
96 assert(MBBI->isCall() && "Unexpected instruction type");
97 MBBI->setCFIType(*MBB.getParent(), 0);
98
99 // If not already bundled, bundle the check and the call to prevent
100 // further changes.
101 if (!MBBI->isBundled())
102 finalizeBundle(MBB, Check->getIterator(), std::next(MBBI->getIterator()));
103
104 ++NumKCFIChecksAdded;
105 return true;
106}
107
108bool KCFI::run(MachineFunction &MF) {
109 const Module *M = MF.getFunction().getParent();
110 if (!M->getModuleFlag("kcfi"))
111 return false;
112
113 const auto &SubTarget = MF.getSubtarget();
114 TII = SubTarget.getInstrInfo();
115 TLI = SubTarget.getTargetLowering();
116
117 bool Changed = false;
118 for (MachineBasicBlock &MBB : MF) {
119 // Use instr_iterator because we don't want to skip bundles.
120 for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
121 MIE = MBB.instr_end();
122 MII != MIE; ++MII) {
123 if (MII->isCall() && MII->getCFIType())
124 Changed |= emitCheck(MBB, MII);
125 }
126 }
127
128 return Changed;
129}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define KCFI_PASS_NAME
Definition KCFI.cpp:30
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.
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...
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Definition KCFI.cpp:71
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:69
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163