Slide 1

Slide 1 text

Sulong, and Thanks For All the Bugs Finding Errors in C Programs by Abstracting from the Native Execution Model Manuel Rigger1, Roland Schatz2, René Mayrhofer1, Matthias Grimmer2, Hanspeter Mössenböck1 1 Johannes Kepler University Linz, Austria 2 Oracle Labs, Austria ASPLOS ’18, March 27, 2018, Williamsburg, VA, USA

Slide 2

Slide 2 text

Claim: Unsafe Languages can be Executed Safely and Efficiently on the Java Virtual Machine 2

Slide 3

Slide 3 text

Claim: Unsafe Languages can be Executed Safely and Efficiently on the Java Virtual Machine 3

Slide 4

Slide 4 text

What are Unsafe Languages? 4 Unsafe Languages Do not specify an operation for all inputs e.g., C Safe Languages Strictly define all operations e.g., Java (Felleisen et al. 1999)

Slide 5

Slide 5 text

Buffer Overflows 5 int *arr = malloc(3 * sizeof(int)); arr[5] = …

Slide 6

Slide 6 text

Buffer Overflows 5 int *arr = malloc(3 * sizeof(int)); arr[5] = … C Undefined Behavior

Slide 7

Slide 7 text

Buffer Overflows 5 int *arr = malloc(3 * sizeof(int)); arr[5] = … Java C Undefined Behavior ArrayIndexOutOfBoundsException int[] arr = new int[3]; arr[5] = …

Slide 8

Slide 8 text

Use-after-free Errors 6 free(arr); arr[0] = …

Slide 9

Slide 9 text

Use-after-free Errors 6 free(arr); arr[0] = … C Undefined Behavior

Slide 10

Slide 10 text

Use-after-free Errors 6 free(arr); arr[0] = … C Undefined Behavior NullPointerException Java arr = null; arr[0] =

Slide 11

Slide 11 text

Idea 7 Map the semantics of a C Program to Java to automatically detect memory safety errors

Slide 12

Slide 12 text

State of the Art 8 a.out Clang/GCC C ./a.out Hello world!

Slide 13

Slide 13 text

State of the Art Compile-time instrumentation • AddressSanitizer (ASan) (Serebryany et al. 2012) • SoftBound+CETS (Nagarakatte et al. 2009, 2010) 8 a.out Clang/GCC C ./a.out Hello world!

Slide 14

Slide 14 text

State of the Art Compile-time instrumentation • AddressSanitizer (ASan) (Serebryany et al. 2012) • SoftBound+CETS (Nagarakatte et al. 2009, 2010) 8 a.out Clang/GCC C ./a.out Hello world! Run-time instrumentation • Valgrind (Nethercote et al. 2007) • Dr. Memory (Bruening et al. 2011)

Slide 15

Slide 15 text

State of the Art 9 a.out Clang/GCC C ./a.out Hello world! Such tools were very helpful in finding bugs in widely used code

Slide 16

Slide 16 text

Can we do better? 10 a.out Clang/GCC C ./a.out Hello world! Static compilers: optimize code based on Undefined Behavior Bug-finding tools: find bugs assuming that violations are visible side effects (Wang et al. 2012, D'Silva 2015)

Slide 17

Slide 17 text

Can we do better? 10 a.out Clang/GCC C ./a.out Hello world! Static compilers: optimize code based on Undefined Behavior Bug-finding tools: find bugs assuming that violations are visible side effects (Wang et al. 2012, D'Silva 2015)

Slide 18

Slide 18 text

Can we do better? 10 a.out Clang/GCC C ./a.out Hello world! Static compilers: optimize code based on Undefined Behavior Bug-finding tools: find bugs assuming that violations are visible side effects struct sock *sk = tun->sk; if (!tun) return POLLERR; (Wang et al. 2012, D'Silva 2015)

Slide 19

Slide 19 text

Can we do better? 10 a.out Clang/GCC C ./a.out Hello world! Static compilers: optimize code based on Undefined Behavior Bug-finding tools: find bugs assuming that violations are visible side effects struct sock *sk = tun->sk; if (!tun) return POLLERR; (Wang et al. 2012, D'Silva 2015)

Slide 20

Slide 20 text

Can we do better? 11 a.out Clang/GCC C ./a.out Hello world! Current approaches do not abstract from the underlying machine/native execution model

Slide 21

Slide 21 text

Can we do better? 11 a.out Clang/GCC C ./a.out Hello world! Current approaches do not abstract from the underlying machine/native execution model Manually adding instrumentation is error-prone

Slide 22

Slide 22 text

Claim: Unsafe Languages can be Executed Safely and Efficiently on the Java Virtual Machine 12

Slide 23

Slide 23 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0

Slide 24

Slide 24 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0

Slide 25

Slide 25 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM We are currently using a custom libc implementation (without system calls) -O0

Slide 26

Slide 26 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM (Lattner 2004) -O0

Slide 27

Slide 27 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM (Lattner 2004) Executing LLVM IR allows us to also execute other unsafe languages -O0

Slide 28

Slide 28 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0

Slide 29

Slide 29 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0

Slide 30

Slide 30 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0 Unaware of the underlying machine, execution model, and ABI

Slide 31

Slide 31 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM (Würthinger et al. 2013) -O0

Slide 32

Slide 32 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM (Würthinger et al. 2013) -O0 Truffle and Graal allow Safe Sulong to reach “native speeds”

Slide 33

Slide 33 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0

Slide 34

Slide 34 text

System Overview 13 LLVM IR Interpreter LLVM IR Clang program.c libc.c Truffle Graal JVM -O0 All checks are automatically performed by the underlying JVM

Slide 35

Slide 35 text

Prevent Out-Of-Bounds Accesses 14 int *arr = malloc(3 * sizeof(int)) arr[5] = … ManagedAddress offset=5 data I32Array contents {0, 0, 0}

Slide 36

Slide 36 text

Prevent Out-Of-Bounds Accesses contents[5]  ArrayIndexOutOfBoundsException 14 int *arr = malloc(3 * sizeof(int)) arr[5] = … ManagedAddress offset=5 data I32Array contents {0, 0, 0}

Slide 37

Slide 37 text

ManagedAddress offset=0 data I32Array contents=null Prevent Use-After-Free Errors 15 free(arr); arr[0] = …

Slide 38

Slide 38 text

ManagedAddress offset=0 data I32Array contents=null Prevent Use-After-Free Errors 15 free(arr); arr[0] = …

Slide 39

Slide 39 text

ManagedAddress offset=0 data I32Array contents=null Prevent Use-After-Free Errors contents[0] NullPointerException 15 free(arr); arr[0] = …

Slide 40

Slide 40 text

ManagedAddress offset=0 data I32Array contents=null Prevent Use-After-Free Errors contents[0] NullPointerException 15 free(arr); arr[0] = … Safe Sulong can detect other categories of errors (e.g., double-free errors)

Slide 41

Slide 41 text

Evaluation • Found 68 errors in small open-source projects • Safe Sulong found 8 errors that were both not found by ASan and Valgrind • Compiler optimizations (ASan –O3) prevented the detection of 4 additional bugs • Valgrind detected half of the errors 16

Slide 42

Slide 42 text

Evaluation: Example ASan 17 int main(int argc, char** argv) { printf("%d %s\n", argc, argv[100]); } ASan does not instrument the main() arguments since they are allocated by libc https://github.com/google/sanitizers/issues/762

Slide 43

Slide 43 text

Claim: Unsafe Languages can be Executed Safely and Efficiently on the Java Virtual Machine 18

Slide 44

Slide 44 text

Example Program 19 void processRequests () { int i = 0; do { processPacket (); i ++; } while (i < 10000) ; } C

Slide 45

Slide 45 text

Example Program 19 void processRequests () { int i = 0; do { processPacket (); i ++; } while (i < 10000) ; } define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Clang C

Slide 46

Slide 46 text

20 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Implementation of Operations

Slide 47

Slide 47 text

20 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Executable Abstract Syntax Tree Implementation of Operations write %2 add read %i 1

Slide 48

Slide 48 text

21 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Implementation of Basic Blocks

Slide 49

Slide 49 text

21 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Executable Abstract Syntax Tree Implementation of Basic Blocks Block1

Slide 50

Slide 50 text

Implementation of Control Flow Support 22 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR

Slide 51

Slide 51 text

Implementation of Control Flow Support 22 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1

Slide 52

Slide 52 text

Compilation • For frequently executed functions • Partial evaluation: inline execute methods of the graph (recursively) • Further optimize the graph 23 Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1

Slide 53

Slide 53 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Compiler 24 int blockIndex = 0; block0: blockIndex = 1 %i.0 = 0 block1: while (true): processPacket() %2 = %i.0 + 1 %3 = %2 < 10000 if %3: blockIndex = 1 %i.0 = %2 continue; else: blockIndex = 2 block2: blockIndex = -1 return Unrolling of the interpreter loop

Slide 54

Slide 54 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Compiler 24 int blockIndex = 0; block0: blockIndex = 1 %i.0 = 0 block1: while (true): processPacket() %2 = %i.0 + 1 %3 = %2 < 10000 if %3: blockIndex = 1 %i.0 = %2 continue; else: blockIndex = 2 block2: blockIndex = -1 return Unrolling of the interpreter loop Graal further optimizes the partially evaluated interpreter

Slide 55

Slide 55 text

Safe Semantics • Safe by design: errors result in exceptions • Invalid memory accesses are not optimized away 25

Slide 56

Slide 56 text

Evaluation: Peak Performance 26 lower is better

Slide 57

Slide 57 text

Evaluation: Peak Performance 27 lower is better

Slide 58

Slide 58 text

Evaluation: Peak Performance 27 Small benchmarks since Safe Sulong failed executing SPEC  preliminary results lower is better

Slide 59

Slide 59 text

Evaluation: Peak Performance 28 lower is better

Slide 60

Slide 60 text

Evaluation: Peak Performance 28 Baseline is Clang –O0, Safe Sulong is faster in all but one case lower is better

Slide 61

Slide 61 text

Evaluation: Peak Performance 29 lower is better

Slide 62

Slide 62 text

Evaluation: Peak Performance 29 Safe Sulong is close to Clang –O3 in some cases lower is better

Slide 63

Slide 63 text

Evaluation: Peak Performance 30 lower is better

Slide 64

Slide 64 text

Evaluation: Peak Performance 30 Safe Sulong –O0 is mostly faster than ASan –O0 lower is better

Slide 65

Slide 65 text

Future Work and Summary 31

Slide 66

Slide 66 text

32 Executing libc and Other System Libraries

Slide 67

Slide 67 text

32 asm("rdtsc":"=a"(tickl),"=d"(tickh)); Inline assembly Executing libc and Other System Libraries (Rigger et al. 2018)

Slide 68

Slide 68 text

32 if (__builtin_expect(x, 0)) foo (); asm("rdtsc":"=a"(tickl),"=d"(tickh)); Inline assembly Executing libc and Other System Libraries Compiler builtins (Rigger et al. 2018)

Slide 69

Slide 69 text

32 if (__builtin_expect(x, 0)) foo (); asm("rdtsc":"=a"(tickl),"=d"(tickh)); Inline assembly Executing libc and Other System Libraries Compiler builtins getcwd(buf, size); System calls (Rigger et al. 2018)

Slide 70

Slide 70 text

32 if (__builtin_expect(x, 0)) foo (); asm("rdtsc":"=a"(tickl),"=d"(tickh)); Inline assembly Executing libc and Other System Libraries Compiler builtins getcwd(buf, size); System calls Implementing them will allow Safe Sulong to execute existing libcs (and SPEC) (Rigger et al. 2018)

Slide 71

Slide 71 text

Summary 33 @RiggerManuel Approaches are based on “unsafe” compilers Safe Sulong automatically detects errors It reaches good peak performance We are still working on completeness

Slide 72

Slide 72 text

Bibliography • Matthias Felleisen and Shriram Krishnamurthi. 1999. Safety in Programming Languages. Technical Report. Rice University. • Konstantin Serebryany, Derek Bruening, Alexander Potapenko, and Dmitry Vyukov. 2012. AddressSanitizer: a fast address sanity checker. In Proceedings of the 2012 USENIX conference on Annual Technical Conference (USENIX ATC'12). USENIX Association, Berkeley, CA, USA, 28-28. • Santosh Nagarakatte, Jianzhou Zhao, Milo M.K. Martin, and Steve Zdancewic. 2009. SoftBound: highly compatible and complete spatial memory safety for c. In Proceedings of the 30th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '09). ACM, New York, NY, USA, 245-258. • Santosh Nagarakatte, Jianzhou Zhao, Milo M.K. Martin, and Steve Zdancewic. 2010. CETS: compiler enforced temporal safety for C. In Proceedings of the 2010 international symposium on Memory management (ISMM '10). ACM, New York, NY, USA, 31-40. • Nicholas Nethercote and Julian Seward. 2007. Valgrind: a framework for heavyweight dynamic binary instrumentation. In Proceedings of the 28th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '07). • Derek Bruening and Qin Zhao. 2011. Practical memory checking with Dr. Memory. In Proceedings of the 9th Annual IEEE/ACM International Symposium on Code Generation and Optimization (CGO '11). IEEE Computer Society, Washington, DC, USA, 213-223. • Xi Wang, Haogang Chen, Alvin Cheung, Zhihao Jia, Nickolai Zeldovich, and M. Frans Kaashoek. 2012. Undefined behavior: what happened to my code?. In Proceedings of the Asia-Pacific Workshop on Systems (APSYS '12). ACM, New York, NY, USA, Article 9, 7 pages. • Vijay D'Silva, Mathias Payer, and Dawn Song. 2015. The Correctness-Security Gap in Compiler Optimization. In Proceedings of the 2015 IEEE Security and Privacy Workshops (SPW '15). IEEE Computer Society, Washington, DC, USA, 73-87. • Thomas Würthinger, Christian Wimmer, Andreas Wöß, Lukas Stadler, Gilles Duboscq, Christian Humer, Gregor Richards, Doug Simon, and Mario Wolczko. 2013. One VM to rule them all. In Proceedings of the 2013 ACM international symposium on New ideas, new paradigms, and reflections on programming & software (Onward! 2013). ACM, New York, NY, USA, 187-204. • Chris Lattner and Vikram Adve. 2004. LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation. In Proceedings of the international symposium on Code generation and optimization: feedback-directed and runtime optimization(CGO '04). IEEE Computer Society, Washington, DC, USA. • Manuel Rigger and Stefan Marr and Stephen Kell and David Leopoldseder and Hanspeter Mössenböck, (2018) An Analysis of x86-64 Inline Assembly in C Programs. In: 14th ACM SIGPLAN/SIGOPS International Conference on Virtual Execution Environments, 25 March 2018, Williamsburg, VA, USA. 34