git-subtree-dir: Security Research and Development with LLVM - Andrew Reiter git-subtree-mainline: aa7a9fc1e16c3c5be7ba312c4b4e37775e005101 git-subtree-split: 0605b5174c2bc286d3e95d6c0df620800bef96c7
139 строки
4.5 KiB
Markdown
139 строки
4.5 KiB
Markdown
|
|
# intflip
|
|
|
|
Currently, what this does is replaces all 8, 16, 32, and 64 bit integers arguments to functions
|
|
with possibly randomly changed values. The purpose is to re-run test suites
|
|
with the modified application in order to simulate the low-probability bit or
|
|
more flips that could occur in certain extreme situations. The aim is to perform
|
|
some basic analysis as to the stability of the code given random changes.
|
|
|
|
## Aside
|
|
|
|
- I do not do much of anything with being sane about memory usage. You're warned. :-P
|
|
|
|
- The way I do the RNG bit is possibly overkill. *shrug*. ISO C standard
|
|
one should be fine.
|
|
|
|
- The randomizer insertion could just be C code that gets linked in, but
|
|
going through the generation and insertion of a function is a good
|
|
exercise.
|
|
|
|
# Requirements
|
|
|
|
- LLVM 3.9.0 (should work with 3.8 & 4.0)
|
|
|
|
# Building
|
|
|
|
$ make jsoncpp
|
|
$ make
|
|
|
|
# Process
|
|
|
|
All executables listed below are supposed to be in your path. You will
|
|
``compile'' to IR and then work on that. I would follow the basic steps
|
|
and then determine how you want to handle performing the analysis. The
|
|
analysis would be a combination of running unit, or other, tests with
|
|
the injected randomizers and analyzing how those runs performed given
|
|
the probability distribution you are looking at.
|
|
|
|
## Passes
|
|
|
|
This is a list of passes available. They are intended to be used per the
|
|
``basic steps'' section below.
|
|
|
|
- -lift-constant-int-args
|
|
- -inject-randomizers
|
|
- -replace-ints-visitor
|
|
- -replace-ints-iterate
|
|
- -replace-ints-cgpass
|
|
|
|
## Basic Work Flow
|
|
|
|
*Setup replace.cfg*
|
|
|
|
The file replace.cfg informs the passes how to setup the random integer replacement action. As the
|
|
key, you specify the function that will have any call instructions /in/ it that have at least one
|
|
integer argument, replaced to use an integer value that is randomly selected.
|
|
|
|
Each value is a dict that should have the keys/values:
|
|
- "analyze" : true|false
|
|
- "type" : 0|1 ... 0 for randomly replace with random value. 1 for randomly replace with random bit flipp
|
|
- "mean" : we are dealing with 32-bit integers, and compare <= mean on random number.
|
|
The for
|
|
{
|
|
"foo" : {
|
|
"analyze" : true,
|
|
"type" : 0,
|
|
"mean" : 500
|
|
}
|
|
}
|
|
|
|
*Compile your code to IR*
|
|
|
|
> clang++-3.9 -emit-llvm -o foo.bc -c foo.c
|
|
|
|
Of course with a larger code base there will be more work involved.
|
|
There is a tool that is out there to help with, at least, the merging
|
|
of multiple bitcode files, it may be found [link](https://github.com/travitch/whole-program-llvm "whole-program-llvm").
|
|
|
|
*Lift ConstantInt to local variable*
|
|
|
|
> opt-3.9 -load built/libIntFlip.so -lift-constant-ints -o foo2.bc < foo.bc
|
|
|
|
This will convert constant integers into local variables. This helps
|
|
the next step of replacing integers used with randomizer function as
|
|
there is no special casing for constant integers.. we just go after
|
|
the local vars.
|
|
|
|
*Inject the randomizer functions*
|
|
|
|
> opt-3.9 -load built/libIntFlip.so -inject-randomizers -o foo3.bc < foo2.bc
|
|
|
|
This generates the functions that will possibly change integer values
|
|
and injects them into the bitcode file. We could just link in code, but
|
|
we do this to demonstrate some writing of our own functions via the API.
|
|
|
|
*Modify integer arguments to use randomizer functions*
|
|
|
|
> opt-3.9 -load built/libIntFlip.so -replace-ints -o foo4.bc < foo3.bc
|
|
|
|
*Build the executable*
|
|
|
|
> llc-3.9 -o=foo4.s foo4.bc
|
|
> clang++-3.9 -o foo4 foo4.s
|
|
|
|
or however you want...
|
|
|
|
*Dump IR from resultant bitcode file*
|
|
|
|
> llvm-dis-3.9 -o=foo.ll test/foo.bc
|
|
|
|
You can do the above for each bitcode file and compare them.
|
|
|
|
|
|
# Some things one might wish to do
|
|
|
|
- Wrap all and use a pass manager
|
|
-- add pass dependencies for ordering
|
|
- Improved control over configurations
|
|
- Build out a whole test run harness
|
|
-- run test cases that have known outcomes (typically, just unit tests and some other)
|
|
-- adjusting probability distribution mean and seeing how that impacts results
|
|
- Improved probability distributions..
|
|
-- evolutionary (evolve with execution steps)
|
|
- Overall model of app that is intelligently injected based on a model of a specific event
|
|
-- that would be like a model based on a real gamma ray birst or something weird
|
|
- Randomly change instructions
|
|
-- Could be done in a few ways, but would want to be arch specific
|
|
-- to find all 1-bit mutatable instructions for instruction i, find all instructions j st dist(i,j) = 1
|
|
-- similar for 2 bit.. just make dist(i,j) = 2...
|
|
-- Then lift those sets to IR
|
|
-- so.. you attempt to fix it in IR.. this will not always work because of ``nice graph'' desires.
|
|
- whatever.
|
|
|
|
|
|
# Inspirational credits
|
|
- NASA
|
|
- John Regehr (Utah)
|
|
- Gamma rays, alpha particles
|