-
Notifications
You must be signed in to change notification settings - Fork 0
/
INSTRUCTIONS.txt
82 lines (68 loc) · 3.17 KB
/
INSTRUCTIONS.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
To start, run `git clone https://github.com/kkysen/SmartNeuralFuzzer.git`.
You need CMake >3.14 and Ninja installed.
To build, run `make cmake && cd build && ninja main`.
To install fuzz.autotools, add SmartNeuralFuzzer/bin to $PATH.
If you want to make a Release instead of Debug build,
change buildType in Makefile to Release.
To run, you need clang installed (I'm using v8.0.0, but any recent version should suffice),
and then LLVM 9.0.0 installed, with its opt in $PATH as opt-9.
To run on an autotools project, cd to that project and run `fuzz.autotools`.
This has been tested on ccache, GNU binutils, and GNU coreutils.
The LDFLAGS used by the Makefile is sometimes lost,
so if linking is unsuccessful, you need to write the correct LDFLAGS
to the file `__LDFLAGS.txt` (in the same directory) and re-run `fuzz.autotools`.
To build GNU binutils or coreutils, just run `fuzz.binutils` or `fuzz.coreutils` anywhere.
The sources will be downloaded, compiled, and instrumented.
If fuzz.autotools runs successfully, it will generate for each target executable a ${target}.coverage executable,
the normal, non-instrumented executable, as well as the intermediate LLVM bitcode files.
${target}.blocks.map is also generated, which is a source map of the block numbers outputted
with their containing function and line and column number (if the target was compiled with debug info).
Running ${target}.coverage runs exactly the same as ${target},
except some intercepted libc syscalls functions are printed to stdout,
and then coverage.out.dir is generated, with the following format:
coverage.out.dir/
${program name as invoked}/
${process ID}/
${thread ID}/
block/
blocks.bin
branch/
counts.bin
single.bin
nonSingle.bin
I'm still working on writing parsers for this binary output.
Caveats:
The instrumented program shouldn't make raw syscalls (libc wrapper or direct) to:
fork
vfork
clone
clone2
execve
execveat
exit
exit_group
fork
kill (when SIGKILL/SIGSTOPing yourself)
reboot
rt_sigaction (for SIGILL)
rt_sigprocmask (when masking SIGILL)
rt_sigqueueinfo (when sending SIGKILL/SIGSTOP to yourself)
rt_tgsigqueueinfo (when sending SIGKILL/SIGSTOP to yourself)
sigaction (for SIGILL)
signal (for SIGILL)
sigprocmask (when masking SIGILL)
tgkill (when SIGKILL/SIGSTOPing yourself)
tkill (when SIGKILL/SIGSTOPing yourself)
vfork
and shouldn't call the libc clone() directly.
kill -9 (SIGKILL) also shouldn't be used on the program.
The runtime needs to flush data to disk before terminating,
and it needs to duplicate itself and restart when cloned.
Therefore, calls to clone()-like functions need to be intercepted,
and program termination (exit(), kill(), exec...()) need to be intercepted.
The runtime also uses SIGILL to communicate between threads to cleanup,
so the program can't depend on receiving and handling a non-hardware-generated SIGILL.
This is why sigaction and sigprocmask can't be directly used with SIGILL.
Circumventing these interceptions for signals and termination
will cause coverage data loss, and circumventing these interceptions for clone()
will cause undefined behavior and likely a SIGSEGV or some other error.