diff options
author | JF Bastien <jfb@google.com> | 2015-01-14 01:07:26 +0000 |
---|---|---|
committer | JF Bastien <jfb@google.com> | 2015-01-14 01:07:26 +0000 |
commit | 21befa7761c9e0983a85603ec0ec35e58441fadf (patch) | |
tree | ccc7d52873b3e8e7b54ec5170f058259ea859f54 /lib/CodeGen | |
parent | 7a4708e0eb025148a872f5de2d1e6c51483615ff (diff) |
Insert random noops to increase security against ROP attacks (llvm)
A pass that adds random noops to X86 binaries to introduce diversity with the goal of increasing security against most return-oriented programming attacks.
Command line options:
-noop-insertion // Enable noop insertion.
-noop-insertion-percentage=X // X% of assembly instructions will have a noop prepended (default: 50%, requires -noop-insertion)
-max-noops-per-instruction=X // Randomly generate X noops per instruction. ie. roll the dice X times with probability set above (default: 1). This doesn't guarantee X noop instructions.
In addition, the following 'quick switch' in clang enables basic diversity using default settings (currently: noop insertion and schedule randomization; it is intended to be extended in the future).
-fdiversify
This is the llvm part of the patch.
clang part: D3393
http://reviews.llvm.org/D3392
Patch by Stephen Crane (@rinon)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225908 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGen.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/NoopInsertion.cpp | 101 | ||||
-rw-r--r-- | lib/CodeGen/Passes.cpp | 3 |
4 files changed, 106 insertions, 0 deletions
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 48bf3545e73..672b6bae2dd 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -71,6 +71,7 @@ add_llvm_library(LLVMCodeGen MachineSink.cpp MachineTraceMetrics.cpp MachineVerifier.cpp + NoopInsertion.cpp OcamlGC.cpp OptimizePHIs.cpp PHIElimination.cpp diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp index 307dec548fc..fdb89438115 100644 --- a/lib/CodeGen/CodeGen.cpp +++ b/lib/CodeGen/CodeGen.cpp @@ -51,6 +51,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeMachineSchedulerPass(Registry); initializeMachineSinkingPass(Registry); initializeMachineVerifierPassPass(Registry); + initializeNoopInsertionPass(Registry); initializeOptimizePHIsPass(Registry); initializePHIEliminationPass(Registry); initializePeepholeOptimizerPass(Registry); diff --git a/lib/CodeGen/NoopInsertion.cpp b/lib/CodeGen/NoopInsertion.cpp new file mode 100644 index 00000000000..f2291b8e99c --- /dev/null +++ b/lib/CodeGen/NoopInsertion.cpp @@ -0,0 +1,101 @@ +//===- NoopInsertion.cpp - Noop Insertion ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass adds fine-grained diversity by displacing code using randomly +// placed (optionally target supplied) Noop instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/NoopInsertion.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Target/TargetInstrInfo.h" +using namespace llvm; + +#define DEBUG_TYPE "noop-insertion" + +static cl::opt<unsigned> NoopInsertionPercentage( + "noop-insertion-percentage", + cl::desc("Percentage of instructions that have Noops prepended"), + cl::init(25)); // Default is a good balance between entropy and + // performance impact + +static cl::opt<unsigned> MaxNoopsPerInstruction( + "max-noops-per-instruction", + llvm::cl::desc("Maximum number of Noops per instruction"), + llvm::cl::init(1)); + +STATISTIC(InsertedNoops, + "Total number of noop type instructions inserted for diversity"); + +char NoopInsertion::ID = 0; +char &llvm::NoopInsertionID = NoopInsertion::ID; +INITIALIZE_PASS(NoopInsertion, "noop-insertion", + "Noop Insertion for fine-grained code randomization", false, + false) + +NoopInsertion::NoopInsertion() : MachineFunctionPass(ID) { + initializeNoopInsertionPass(*PassRegistry::getPassRegistry()); + + // clamp percentage to 100 + if (NoopInsertionPercentage > 100) + NoopInsertionPercentage = 100; +} + +void NoopInsertion::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool NoopInsertion::runOnMachineFunction(MachineFunction &Fn) { + // The RNG must be initialized on first use so we have a Module to + // construct it from + if (!RNG) + RNG.reset(Fn.getFunction()->getParent()->createRNG(this)); + + const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); + + unsigned FnInsertedNoopCount = 0; + + for (auto &BB : Fn) { + MachineBasicBlock::iterator FirstTerm = BB.getFirstTerminator(); + + for (MachineBasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; + ++I) { + if (I->isPseudo()) + continue; + + // Insert random number of Noop-like instructions. + for (unsigned i = 0; i < MaxNoopsPerInstruction; i++) { + if (Distribution(*RNG) >= NoopInsertionPercentage) + continue; + + TII->insertNoop(BB, I, *RNG); + + ++FnInsertedNoopCount; + } + + if (I == FirstTerm) + break; + } + } + + InsertedNoops += FnInsertedNoopCount; + + return FnInsertedNoopCount > 0; +} diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp index 28e9f847a9d..a5d32103d7c 100644 --- a/lib/CodeGen/Passes.cpp +++ b/lib/CodeGen/Passes.cpp @@ -583,6 +583,9 @@ void TargetPassConfig::addMachinePasses() { addPass(createGCInfoPrinter(dbgs()), false, false); } + if (TM->Options.NoopInsertion) + addPass(&NoopInsertionID); + // Basic block placement. if (getOptLevel() != CodeGenOpt::None) addBlockPlacement(); |