mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 15:17:25 +00:00
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
This commit is contained in:
@@ -71,6 +71,7 @@ add_llvm_library(LLVMCodeGen
|
||||
MachineSink.cpp
|
||||
MachineTraceMetrics.cpp
|
||||
MachineVerifier.cpp
|
||||
NoopInsertion.cpp
|
||||
OcamlGC.cpp
|
||||
OptimizePHIs.cpp
|
||||
PHIElimination.cpp
|
||||
|
||||
@@ -51,6 +51,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
|
||||
initializeMachineSchedulerPass(Registry);
|
||||
initializeMachineSinkingPass(Registry);
|
||||
initializeMachineVerifierPassPass(Registry);
|
||||
initializeNoopInsertionPass(Registry);
|
||||
initializeOptimizePHIsPass(Registry);
|
||||
initializePHIEliminationPass(Registry);
|
||||
initializePeepholeOptimizerPass(Registry);
|
||||
|
||||
101
lib/CodeGen/NoopInsertion.cpp
Normal file
101
lib/CodeGen/NoopInsertion.cpp
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user