1 //===---- KCFI.cpp - Implements Kernel Control-Flow Integrity (KCFI) ------===//
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 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineInstrBundle.h"
20 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #include "llvm/CodeGen/TargetInstrInfo.h"
22 #include "llvm/CodeGen/TargetLowering.h"
23 #include "llvm/CodeGen/TargetSubtargetInfo.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/InitializePasses.h"
29 #define DEBUG_TYPE "kcfi"
30 #define KCFI_PASS_NAME "Insert KCFI indirect call checks"
32 STATISTIC(NumKCFIChecksAdded
, "Number of indirect call checks added");
35 class KCFI
: public MachineFunctionPass
{
39 KCFI() : MachineFunctionPass(ID
) {}
41 StringRef
getPassName() const override
{ return KCFI_PASS_NAME
; }
42 bool runOnMachineFunction(MachineFunction
&MF
) override
;
45 /// Machine instruction info used throughout the class.
46 const TargetInstrInfo
*TII
= nullptr;
48 /// Target lowering for arch-specific parts.
49 const TargetLowering
*TLI
= nullptr;
51 /// Emits a KCFI check before an indirect call.
52 /// \returns true if the check was added and false otherwise.
53 bool emitCheck(MachineBasicBlock
&MBB
,
54 MachineBasicBlock::instr_iterator I
) const;
58 } // end anonymous namespace
60 INITIALIZE_PASS(KCFI
, DEBUG_TYPE
, KCFI_PASS_NAME
, false, false)
62 FunctionPass
*llvm::createKCFIPass() { return new KCFI(); }
64 bool KCFI::emitCheck(MachineBasicBlock
&MBB
,
65 MachineBasicBlock::instr_iterator MBBI
) const {
66 assert(TII
&& "Target instruction info was not initialized");
67 assert(TLI
&& "Target lowering was not initialized");
69 // If the call instruction is bundled, we can only emit a check safely if
70 // it's the first instruction in the bundle.
71 if (MBBI
->isBundled() && !std::prev(MBBI
)->isBundle())
72 report_fatal_error("Cannot emit a KCFI check for a bundled call");
74 // Emit a KCFI check for the call instruction at MBBI. The implementation
75 // must unfold memory operands if applicable.
76 MachineInstr
*Check
= TLI
->EmitKCFICheck(MBB
, MBBI
, TII
);
78 // Clear the original call's CFI type.
79 assert(MBBI
->isCall() && "Unexpected instruction type");
80 MBBI
->setCFIType(*MBB
.getParent(), 0);
82 // If not already bundled, bundle the check and the call to prevent
84 if (!MBBI
->isBundled())
85 finalizeBundle(MBB
, Check
->getIterator(), std::next(MBBI
->getIterator()));
91 bool KCFI::runOnMachineFunction(MachineFunction
&MF
) {
92 const Module
*M
= MF
.getFunction().getParent();
93 if (!M
->getModuleFlag("kcfi"))
96 const auto &SubTarget
= MF
.getSubtarget();
97 TII
= SubTarget
.getInstrInfo();
98 TLI
= SubTarget
.getTargetLowering();
100 bool Changed
= false;
101 for (MachineBasicBlock
&MBB
: MF
) {
102 // Use instr_iterator because we don't want to skip bundles.
103 for (MachineBasicBlock::instr_iterator MII
= MBB
.instr_begin(),
104 MIE
= MBB
.instr_end();
106 if (MII
->isCall() && MII
->getCFIType())
107 Changed
|= emitCheck(MBB
, MII
);