Matt Suiche 0c9e8df91c Add 'Security Research and Development with LLVM - Andrew Reiter/' from commit '0605b5174c2bc286d3e95d6c0df620800bef96c7'
git-subtree-dir: Security Research and Development with LLVM - Andrew Reiter
git-subtree-mainline: aa7a9fc1e16c3c5be7ba312c4b4e37775e005101
git-subtree-split: 0605b5174c2bc286d3e95d6c0df620800bef96c7
2017-04-29 17:11:06 +04:00

4.5 KiB

The code will look for any/all pointer function arguments and will insert an assert(ptr != NULL); statement. It shows looking at functions, their arguments, a function pass, declaring a function, and inserting code. Why? Eh. A few reasons that are BS, but mostly to help learn API.

Build and Run

This requires LLVM and Clang 3.8, 3.9, or 4.0 releases. You should review the Makefile to setup the LLVM path and version.

$ make
$ make tests
$ cd tests

If you do not specify a configuration file, the code will look for all functions and their arguments. If you specify a configuration file, it will specify the function and the argument to check. The tests/ex0b.... files are those in which a configuration file was specified and the ex0a are those in which none was specified.. so you should see a difference

Example running by hand

$ clang -g -emit-llvm -c -o FOO.bc FOO.c
$ opt -load built/libnpassert.so -null-ptr-assert -o FOO_assertall.bc < FOO.bc
$ opt -load built/libnpassert.so -null-ptr-assert -npa-target-config FOO.cfg -o FOO_assertbyconfigfile.bc < FOO.bc
$ clang -g -o FOO_assertall FOO_assertall.bc
$ clang -g -o FOO_assertbyconfigfile FOO_assertbyconfigfile.bc 

The last clang steps generate an runnable executable. Use llvm-dis on bitcode (.bc) files to get the human readable IR to view the differences. One may also use the -npa-use-function option which will tell the pass to create a separate function to perform the assertion in.

So with the above instead of getting a crash like:

(gdb) r
Starting program: /home/hoser/code/npassert/test/ex02 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400549 in foo (s=0x0) at test/ex02.c:16
16              return s->one;
(gdb) disass foo
Dump of assembler code for function foo:
   0x0000000000400530 <+0>:     push   %rbp
   0x0000000000400531 <+1>:     mov    %rsp,%rbp
   0x0000000000400534 <+4>:     sub    $0x10,%rsp
   0x0000000000400538 <+8>:     mov    %rdi,-0x8(%rbp)
   0x000000000040053c <+12>:    callq  0x400420 <random@plt>
   0x0000000000400541 <+17>:    mov    %rax,-0x10(%rbp)
   0x0000000000400545 <+21>:    mov    -0x8(%rbp),%rax
=> 0x0000000000400549 <+25>:    mov    (%rax),%eax
   0x000000000040054b <+27>:    add    $0x10,%rsp
   0x000000000040054f <+31>:    pop    %rbp
   0x0000000000400550 <+32>:    retq   
End of assembler dump.
(gdb) 

You would get a crash early in the function..

(gdb) r
Starting program: /home/hoser/code/npassert/test/ex02a 
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400554 in foo (s=0x0) at test/ex02.c:12
12      {
(gdb) disass foo
Dump of assembler code for function foo:
   0x0000000000400530 <+0>:     push   %rbp
   0x0000000000400531 <+1>:     mov    %rsp,%rbp
   0x0000000000400534 <+4>:     sub    $0x20,%rsp
   0x0000000000400538 <+8>:     cmp    $0x0,%rdi
   0x000000000040053c <+12>:    mov    %rdi,-0x8(%rbp)
   0x0000000000400540 <+16>:    jne    0x400558 <foo+40>
   0x0000000000400546 <+22>:    xor    %eax,%eax
   0x0000000000400548 <+24>:    mov    %eax,%ecx
   0x000000000040054a <+26>:    mov    %rsp,%rdx
   0x000000000040054d <+29>:    add    $0xfffffffffffffff0,%rdx
   0x0000000000400551 <+33>:    mov    %rdx,%rsp
=> 0x0000000000400554 <+36>:    mov    (%rcx),%eax
   0x0000000000400556 <+38>:    mov    %eax,(%rdx)
   0x0000000000400558 <+40>:    mov    %rsp,%rax
   0x000000000040055b <+43>:    add    $0xfffffffffffffff0,%rax
   0x000000000040055f <+47>:    mov    %rax,%rsp
   0x0000000000400562 <+50>:    mov    %rsp,%rcx
   0x0000000000400565 <+53>:    add    $0xfffffffffffffff0,%rcx
   0x0000000000400569 <+57>:    mov    %rcx,%rsp
   0x000000000040056c <+60>:    mov    -0x8(%rbp),%rdx
   0x0000000000400570 <+64>:    mov    %rdx,(%rax)
   0x0000000000400573 <+67>:    mov    %rax,-0x10(%rbp)
   0x0000000000400577 <+71>:    mov    %rcx,-0x18(%rbp)
   0x000000000040057b <+75>:    callq  0x400420 <random@plt>
   0x0000000000400580 <+80>:    mov    -0x18(%rbp),%rcx
   0x0000000000400584 <+84>:    mov    %rax,(%rcx)
   0x0000000000400587 <+87>:    mov    -0x10(%rbp),%rax
   0x000000000040058b <+91>:    mov    (%rax),%rdx
   0x000000000040058e <+94>:    mov    (%rdx),%eax
   0x0000000000400590 <+96>:    mov    %rbp,%rsp
   0x0000000000400593 <+99>:    pop    %rbp
   0x0000000000400594 <+100>:   retq   

Or if you add the -npa-use-function option

(gdb) r
Starting program: /home/hoser/code/npassert/test/ex02c 

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005b3 in __NPA_assert_8__ ()
(gdb) 

it will fault in the assertion function.