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/MachineInstrBundle.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/CodeGen/TargetInstrInfo.h"
21 #include "llvm/CodeGen/TargetLowering.h"
22 #include "llvm/CodeGen/TargetSubtargetInfo.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/InitializePasses.h"
28 #define DEBUG_TYPE "kcfi"
29 #define KCFI_PASS_NAME "Insert KCFI indirect call checks"
31 STATISTIC(NumKCFIChecksAdded
, "Number of indirect call checks added");
34 class KCFI
: public MachineFunctionPass
{
38 KCFI() : MachineFunctionPass(ID
) {}
40 StringRef
getPassName() const override
{ return KCFI_PASS_NAME
; }
41 bool runOnMachineFunction(MachineFunction
&MF
) override
;
44 /// Machine instruction info used throughout the class.
45 const TargetInstrInfo
*TII
= nullptr;
47 /// Target lowering for arch-specific parts.
48 const TargetLowering
*TLI
= nullptr;
50 /// Emits a KCFI check before an indirect call.
51 /// \returns true if the check was added and false otherwise.
52 bool emitCheck(MachineBasicBlock
&MBB
,
53 MachineBasicBlock::instr_iterator I
) const;
57 } // end anonymous namespace
59 INITIALIZE_PASS(KCFI
, DEBUG_TYPE
, KCFI_PASS_NAME
, false, false)
61 FunctionPass
*llvm::createKCFIPass() { return new KCFI(); }
63 bool KCFI::emitCheck(MachineBasicBlock
&MBB
,
64 MachineBasicBlock::instr_iterator MBBI
) const {
65 assert(TII
&& "Target instruction info was not initialized");
66 assert(TLI
&& "Target lowering was not initialized");
68 // If the call instruction is bundled, we can only emit a check safely if
69 // it's the first instruction in the bundle.
70 if (MBBI
->isBundled() && !std::prev(MBBI
)->isBundle())
71 report_fatal_error("Cannot emit a KCFI check for a bundled call");
73 // Emit a KCFI check for the call instruction at MBBI. The implementation
74 // must unfold memory operands if applicable.
75 MachineInstr
*Check
= TLI
->EmitKCFICheck(MBB
, MBBI
, TII
);
77 // Clear the original call's CFI type.
78 assert(MBBI
->isCall() && "Unexpected instruction type");
79 MBBI
->setCFIType(*MBB
.getParent(), 0);
81 // If not already bundled, bundle the check and the call to prevent
83 if (!MBBI
->isBundled())
84 finalizeBundle(MBB
, Check
->getIterator(), std::next(MBBI
->getIterator()));
90 bool KCFI::runOnMachineFunction(MachineFunction
&MF
) {
91 const Module
*M
= MF
.getFunction().getParent();
92 if (!M
->getModuleFlag("kcfi"))
95 const auto &SubTarget
= MF
.getSubtarget();
96 TII
= SubTarget
.getInstrInfo();
97 TLI
= SubTarget
.getTargetLowering();
100 for (MachineBasicBlock
&MBB
: MF
) {
101 // Use instr_iterator because we don't want to skip bundles.
102 for (MachineBasicBlock::instr_iterator MII
= MBB
.instr_begin(),
103 MIE
= MBB
.instr_end();
105 if (MII
->isCall() && MII
->getCFIType())
106 Changed
|= emitCheck(MBB
, MII
);