Add Forward Control-Flow Integrity.

This commit adds a new pass that can inject checks before indirect calls to
make sure that these calls target known locations. It supports three types of
checks and, at compile time, it can take the name of a custom function to call
when an indirect call check fails. The default failure function ignores the
error and continues.

This pass incidentally moves the function JumpInstrTables::transformType from
private to public and makes it static (with a new argument that specifies the
table type to use); this is so that the CFI code can transform function types
at call sites to determine which jump-instruction table to use for the check at
that site.

Also, this removes support for jumptables in ARM, pending further performance
analysis and discussion.

Review: http://reviews.llvm.org/D4167



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221708 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tom Roeder
2014-11-11 21:08:02 +00:00
parent 6d093fd78a
commit 63dea2c952
29 changed files with 873 additions and 133 deletions

View File

@@ -39,13 +39,14 @@ class Module;
/// jmp f_orig@PLT
/// \endverbatim
///
/// Support for an architecture depends on two functions in TargetInstrInfo:
/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the
/// appropriate instructions for the jump statement (an unconditional branch)
/// and for padding to make the table have a size that is a power of two. This
/// padding uses a trap instruction to ensure that calls to this area halt the
/// program. The default implementations of these functions call
/// llvm_unreachable.
/// Support for an architecture depends on three functions in TargetInstrInfo:
/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter
/// uses these to generate the appropriate instructions for the jump statement
/// (an unconditional branch) and for padding to make the table have a size that
/// is a power of two. This padding uses a trap instruction to ensure that calls
/// to this area halt the program. The default implementations of these
/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound,
/// which returns 0 by default.
class JumpInstrTables : public ModulePass {
public:
static char ID;
@@ -64,6 +65,14 @@ public:
/// Checks to see if there is already a table for the given FunctionType.
bool hasTable(FunctionType *FunTy);
/// Maps the function into a subset of function types, depending on the
/// jump-instruction table style selected from JumpTableTypes in
/// JumpInstrTables.cpp. The choice of mapping determines the number of
/// jump-instruction tables generated by this pass. E.g., the simplest mapping
/// converts every function type into void f(); so, all functions end up in a
/// single table.
static FunctionType *transformType(JumpTable::JumpTableType JTT,
FunctionType *FunTy);
private:
/// The metadata used while a jump table is being built
struct TableMeta {
@@ -76,14 +85,6 @@ private:
typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;
/// Maps the function into a subset of function types, depending on the
/// jump-instruction table style selected from JumpTableTypes in
/// JumpInstrTables.cpp. The choice of mapping determines the number of
/// jump-instruction tables generated by this pass. E.g., the simplest mapping
/// converts every function type into void f(); so, all functions end up in a
/// single table.
FunctionType *transformType(FunctionType *FunTy);
/// The current state of functions and jump entries in the table(s).
JumpMap Metadata;