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/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" 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "kcfi" 30 #define KCFI_PASS_NAME "Insert KCFI indirect call checks" 31 32 STATISTIC(NumKCFIChecksAdded, "Number of indirect call checks added"); 33 34 namespace { 35 class KCFI : public MachineFunctionPass { 36 public: 37 static char ID; 38 39 KCFI() : MachineFunctionPass(ID) {} 40 41 StringRef getPassName() const override { return KCFI_PASS_NAME; } 42 bool runOnMachineFunction(MachineFunction &MF) override; 43 44 private: 45 /// Machine instruction info used throughout the class. 46 const TargetInstrInfo *TII = nullptr; 47 48 /// Target lowering for arch-specific parts. 49 const TargetLowering *TLI = nullptr; 50 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; 55 }; 56 57 char KCFI::ID = 0; 58 } // end anonymous namespace 59 60 INITIALIZE_PASS(KCFI, DEBUG_TYPE, KCFI_PASS_NAME, false, false) 61 62 FunctionPass *llvm::createKCFIPass() { return new KCFI(); } 63 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"); 68 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"); 73 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); 77 78 // Clear the original call's CFI type. 79 assert(MBBI->isCall() && "Unexpected instruction type"); 80 MBBI->setCFIType(*MBB.getParent(), 0); 81 82 // If not already bundled, bundle the check and the call to prevent 83 // further changes. 84 if (!MBBI->isBundled()) 85 finalizeBundle(MBB, Check->getIterator(), std::next(MBBI->getIterator())); 86 87 ++NumKCFIChecksAdded; 88 return true; 89 } 90 91 bool KCFI::runOnMachineFunction(MachineFunction &MF) { 92 const Module *M = MF.getFunction().getParent(); 93 if (!M->getModuleFlag("kcfi")) 94 return false; 95 96 const auto &SubTarget = MF.getSubtarget(); 97 TII = SubTarget.getInstrInfo(); 98 TLI = SubTarget.getTargetLowering(); 99 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(); 105 MII != MIE; ++MII) { 106 if (MII->isCall() && MII->getCFIType()) 107 Changed |= emitCheck(MBB, MII); 108 } 109 } 110 111 return Changed; 112 } 113