Slide 1

Slide 1 text

Safe and Efficient Execution of LLVM-based Languages on the Java Virtual Machine Swiss LLVM Compiler and Code Generation Social 14. March 2019 Manuel Rigger Advanced Software Technologies Lab (Zhendong Su) @RiggerManuel

Slide 2

Slide 2 text

Bachelor and Master Thesis Topics 2 https://people.inf.ethz.ch/suz/mstopics.html

Slide 3

Slide 3 text

Unsafe Languages are Popular Rank Programming Language 1 Java 2 C 3 C++ 3 (TIOBE Index for November 2018)

Slide 4

Slide 4 text

Unsafe Languages are Popular Rank Programming Language 1 Java 2 C 3 C++ 3 C and C++ are considered unsafe (TIOBE Index for November 2018)

Slide 5

Slide 5 text

C/C++ is Widespread 4 Important software is written in unsafe languages

Slide 6

Slide 6 text

C/C++ is Responsible for Dangerous Vulnerabilities 5 Heartbleed Cloudbleed

Slide 7

Slide 7 text

C/C++ is Responsible for Dangerous Vulnerabilities 5 Heartbleed Cloudbleed Caused by buffer overflows, the most dangerous vulnerability in unsafe languages

Slide 8

Slide 8 text

What Makes a Language Unsafe? 6 Undefined Behavior (UB) “behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements “ (C99 standard)

Slide 9

Slide 9 text

Examples for Undefined Behavior Buffer overflow Use-after-free error Integer overflow 7

Slide 10

Slide 10 text

Buffer Overflows: Leaking Sensitive Data 8 long *arr = malloc(3 * sizeof(long)); arr: secret

Slide 11

Slide 11 text

Buffer Overflows: Leaking Sensitive Data 9 long *arr = malloc(3 * sizeof(long)); long dest[4]; memcpy(dest, arr, sizeof(dest)); arr: dest: secret

Slide 12

Slide 12 text

Buffer Overflows: Leaking Sensitive Data 9 long *arr = malloc(3 * sizeof(long)); long dest[4]; memcpy(dest, arr, sizeof(dest)); arr: dest: secret UB

Slide 13

Slide 13 text

Buffer Overflows: Leaking Sensitive Data 10 long *arr = malloc(3 * sizeof(long)); long dest[4]; memcpy(dest, arr, sizeof(dest)); arr: dest: secret secret

Slide 14

Slide 14 text

Buffer Overflows: Leaking Sensitive Data 10 long *arr = malloc(3 * sizeof(long)); long dest[4]; memcpy(dest, arr, sizeof(dest)); arr: dest: Heartbleed and Cloudbleed were such vulnerabilities secret secret

Slide 15

Slide 15 text

Buffer Overflows: Changing Control Flow 11 long *arr = malloc(3 * sizeof(long)); arrbefore : &func

Slide 16

Slide 16 text

Buffer Overflows: Changing Control Flow 12 long *arr = malloc(3 * sizeof(long)); arr[4] = 0xfe…; arrbefore : arrafter : &func 0xfe...

Slide 17

Slide 17 text

Buffer Overflows: Changing Control Flow 12 long *arr = malloc(3 * sizeof(long)); arr[4] = 0xfe…; arrbefore : arrafter : UB &func 0xfe...

Slide 18

Slide 18 text

Buffer Overflows: Changing Control Flow 12 long *arr = malloc(3 * sizeof(long)); arr[4] = 0xfe…; arrbefore : Allows attackers to change the program‘s control flow arrafter : UB &func 0xfe...

Slide 19

Slide 19 text

Use-after-free Error 13 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = …; UB

Slide 20

Slide 20 text

Use-after-free Error 13 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = …; UB Can overwrite another object if the memory was reallocated

Slide 21

Slide 21 text

Integer Overflow 14 int a = 1, b = INT_MAX; int val = a + b; UB

Slide 22

Slide 22 text

Integer Overflow 14 int a = 1, b = INT_MAX; int val = a + b; Can result in inconsistent/surprising behavior if UB is “optimized away“ UB

Slide 23

Slide 23 text

Integer Overflow 15 void pause() { int a = 0; // run until overflow while (a < a + 1) { a++; } }

Slide 24

Slide 24 text

Integer Overflow 15 void pause() { int a = 0; // run until overflow while (a < a + 1) { a++; } } What’s the compilation output of Clang/GCC? 1. The function works as expected by the programmer 2. The function body is optimized away 3. The function results in an endless loop 4. It depends on the optimization level

Slide 25

Slide 25 text

Integer Overflow 16 void pause() { int a = 0; // run until overflow while (a < a + 1) { a++; } }

Slide 26

Slide 26 text

Integer Overflow 16 void pause() { int a = 0; // run until overflow while (a < a + 1) { a++; } } mov dword ptr [rsp - 4], 0 jmp loop_header loop_body: add dword ptr [rsp - 4], 1 loop_header: mov eax, dword ptr [rsp - 4] mov ecx, dword ptr [rsp - 4] add ecx, 1 cmp eax, ecx jl loop_body ret -O0

Slide 27

Slide 27 text

Integer Overflow 16 void pause() { int a = 0; // run until overflow while (a < a + 1) { a++; } } loop: jmp loop mov dword ptr [rsp - 4], 0 jmp loop_header loop_body: add dword ptr [rsp - 4], 1 loop_header: mov eax, dword ptr [rsp - 4] mov ecx, dword ptr [rsp - 4] add ecx, 1 cmp eax, ecx jl loop_body ret -O3 -O0

Slide 28

Slide 28 text

Ticking Timebombs 17

Slide 29

Slide 29 text

Ticking Timebombs 17 A future compiler compiler optimization might exploit additional UB

Slide 30

Slide 30 text

Ticking Timebombs 17 https://blog.regehr.org/ A future compiler compiler optimization might exploit additional UB

Slide 31

Slide 31 text

Goal of my PhD 18 Tackle UB by safely and efficiently executing unsafe languages on the JVM

Slide 32

Slide 32 text

Goal of my PhD 19 Tackle UB by safely and efficiently executing unsafe languages on the JVM

Slide 33

Slide 33 text

Goal of my PhD 19 Tackle UB by safely and efficiently executing unsafe languages on the JVM Well-defined semantics even for errors and corner cases

Slide 34

Slide 34 text

Idea 20

Slide 35

Slide 35 text

21 Lenient C Safe Sulong and its Bug-finding Mode Introspection

Slide 36

Slide 36 text

22 Lenient C Safe Sulong and its Bug-finding Mode Automatic approaches Introspection

Slide 37

Slide 37 text

23 Lenient C Safe Sulong and its Bug-finding Mode Introspection Terminate the program Continue execution

Slide 38

Slide 38 text

24 Lenient C Safe Sulong and its Bug-finding Mode Introspection Manual approach

Slide 39

Slide 39 text

25 Safe Sulong and its Bug-finding Mode

Slide 40

Slide 40 text

Existing Approaches 26 Instrumentation- based bug-finding tools Symbolic execution Safe languages Hardware security Static analysis Attacker mitigation

Slide 41

Slide 41 text

Existing Approaches 27 Instrumentation- based bug-finding tools Symbolic execution Safe languages Hardware security Static analysis Attacker mitigation

Slide 42

Slide 42 text

Existing Approaches 27 Instrumentation- based bug-finding tools Symbolic execution Safe languages Hardware security Static analysis Attacker mitigation • LLVM’s AddressSanitizer (Serebryany et al. 2012) • Memcheck (Nethercote et al. 2007) • SoftBound+CETS (Nagarakatte et al. 2009, 2010) • Dr. Memory (Bruening et al. 2011)

Slide 43

Slide 43 text

State of the Art: Instrumentation-based Tools 28 a.out Clang/GCC C ./a.out Hello world!

Slide 44

Slide 44 text

State of the Art: Instrumentation-based Tools Compile-time instrumentation • AddressSanitizer • SoftBound+CETS 28 a.out Clang/GCC C ./a.out Hello world!

Slide 45

Slide 45 text

State of the Art: Instrumentation-based Tools Compile-time instrumentation • AddressSanitizer • SoftBound+CETS 28 a.out Clang/GCC C ./a.out Hello world! Run-time instrumentation • Memcheck • Dr. Memory

Slide 46

Slide 46 text

Conundrum: Finding Bugs vs. Performance 29 a.out Clang/GCC C ./a.out Hello world!

Slide 47

Slide 47 text

Conundrum: Finding Bugs vs. Performance 29 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 48

Slide 48 text

Conundrum: Finding Bugs vs. Performance 30 To find all bugs, developers need to disable compiler optimizations

Slide 49

Slide 49 text

Lack of Abstraction 31 a.out Clang/GCC C ./a.out Hello world! Checks omitted/forgotten result in overlooked bugs

Slide 50

Slide 50 text

Map Data Structures and Operations to Java 32 long *arr = malloc(3 * sizeof(long)); arr[4] = …

Slide 51

Slide 51 text

Map Data Structures and Operations to Java 32 long *arr = malloc(3 * sizeof(long)); arr[4] = … Map to Java Code

Slide 52

Slide 52 text

Map Data Structures and Operations to Java 32 long[] arr = new long[3]; arr[4] = … long *arr = malloc(3 * sizeof(long)); arr[4] = … Map to Java Code

Slide 53

Slide 53 text

Map Data Structures and Operations to Java 32 long[] arr = new long[3]; arr[4] = … long *arr = malloc(3 * sizeof(long)); arr[4] = … Map to Java Code The semantics of an out-of- bounds access are well specified

Slide 54

Slide 54 text

Map Data Structures and Operations to Java 32 long[] arr = new long[3]; arr[4] = … long *arr = malloc(3 * sizeof(long)); arr[4] = … Map to Java Code ArrayIndexOutOfBoundsException The semantics of an out-of- bounds access are well specified

Slide 55

Slide 55 text

Map Data Structures and Operations to Java 32 long[] arr = new long[3]; arr[4] = … long *arr = malloc(3 * sizeof(long)); arr[4] = … Map to Java Code ArrayIndexOutOfBoundsException The semantics of an out-of- bounds access are well specified Automatic bounds checks that cannot be optimized away

Slide 56

Slide 56 text

33 (Rigger et al. 2018)

Slide 57

Slide 57 text

34 速 龙

Slide 58

Slide 58 text

34 速 龙 Fast/rapid

Slide 59

Slide 59 text

34 速 龙 Dragon Fast/rapid

Slide 60

Slide 60 text

34 速 龙 Velocisaurus Dragon Fast/rapid

Slide 61

Slide 61 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... [Languages other than C?]

Slide 62

Slide 62 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... (Lattner et al. 2004) [Languages other than C?]

Slide 63

Slide 63 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... (Lattner et al. 2004) We disable compiler optimizations of the front ends [Languages other than C?]

Slide 64

Slide 64 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... (Lattner et al. 2004) We disable compiler optimizations of the front ends [Languages other than C?]

Slide 65

Slide 65 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... (Lattner et al. 2004) Targeting LLVM IR allows executing multiple unsafe languages [Languages other than C?]

Slide 66

Slide 66 text

Execution of LLVM IR 35 Safe Execution Platform LLVM IR Clang C C++ GCC Fortran Other LLVM frontend ... (Lattner et al. 2004) Targeting LLVM IR allows executing multiple unsafe languages [Languages other than C?]

Slide 67

Slide 67 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] [Completenesss vs. Soundness] [Languages other than C?]

Slide 68

Slide 68 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] [Completenesss vs. Soundness] [Languages other than C?]

Slide 69

Slide 69 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM (Würthinger et al. 2012, 2017) [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] [Completenesss vs. Soundness] [Languages other than C?]

Slide 70

Slide 70 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM (Würthinger et al. 2012, 2017) Using Truffle and Graal, we can minimize the instrumentation overhead [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] [Completenesss vs. Soundness] [Languages other than C?]

Slide 71

Slide 71 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM (Würthinger et al. 2012, 2017) [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] [Completenesss vs. Soundness] [Languages other than C?]

Slide 72

Slide 72 text

Execution of LLVM IR 36 LLVM IR Interpreter Truffle LLVM IR Graal JVM (Würthinger et al. 2012, 2017) [How does the compilation work?] [Array bounds check elimination] [Optimizations Overview] Safe Sulong can rely on the underlying JVM • Automatic checks • Safe optimizations • Abstraction from the underlying machine and OS [Completenesss vs. Soundness] [Languages other than C?]

Slide 73

Slide 73 text

{0, 0, 0} Address offset = 0 data I64Array contents Prevent Out-Of-Bounds Accesses 37 long *arr = malloc(3 * sizeof(long)); [How do we know the type?] [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Array bounds check elimination] [Strict-aliasing rule]

Slide 74

Slide 74 text

Prevent Out-Of-Bounds Accesses 38 long *arr = malloc(3 * sizeof(long)); arr[4] = … {0, 0, 0} Address offset = 4 data I64Array contents [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Array bounds check elimination] [Strict-aliasing rule]

Slide 75

Slide 75 text

Prevent Out-Of-Bounds Accesses contents[4] → ArrayIndexOutOfBoundsException 38 long *arr = malloc(3 * sizeof(long)); arr[4] = … {0, 0, 0} Address offset = 4 data I64Array contents [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Array bounds check elimination] [Strict-aliasing rule]

Slide 76

Slide 76 text

Prevent Use-after-Free Errors 39 long *arr = malloc(3 * sizeof(long)); free(arr); {0, 0, 0} Address offset = 0 data I64Array contents [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Strict-aliasing rule]

Slide 77

Slide 77 text

Prevent Use-after-Free Errors 40 long *arr = malloc(3 * sizeof(long)); free(arr); Address offset = 0 data I64Array contents=null [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Strict-aliasing rule]

Slide 78

Slide 78 text

Prevent Use-after-Free Errors 41 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = … Address offset = 0 data I64Array contents=null [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Strict-aliasing rule]

Slide 79

Slide 79 text

Prevent Use-after-Free Errors contents[0] → NullPointerException 42 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = … Address offset = 0 data I64Array contents=null [What other errors can Safe Sulong detect?] [Pointer to an integer?] [Strict-aliasing rule]

Slide 80

Slide 80 text

Prevent Integer Overflows 43 int a = 1, b = INT_MAX; int val = a + b; Math.addExact(a, b); [What other errors can Safe Sulong detect?] [Pointer to an integer?]

Slide 81

Slide 81 text

Prevent Integer Overflows 43 int a = 1, b = INT_MAX; int val = a + b; Math.addExact(a, b); ArithmeticException [What other errors can Safe Sulong detect?] [Pointer to an integer?]

Slide 82

Slide 82 text

Safe Optimizations 44 ArrayIndexOutOfBoundsException NullPointerException ArithmeticException Exceptions are visible side effects and cannot be optimized away

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

Example Program 45 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 .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR Clang

Slide 85

Slide 85 text

46 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 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 86

Slide 86 text

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

Slide 87

Slide 87 text

47 write %2 add read %i.0 1 Abstract Syntax Tree Implementation of Operations

Slide 88

Slide 88 text

47 write %2 add read %i.0 1 Abstract Syntax Tree class LLVMI32LiteralNode extends LLVMExpressionNode { final int literal; public LLVMI32LiteralNode(int literal) { this.literal = literal; } @Override public int executeI32(VirtualFrame frame) { return literal; } } Executable AST node Implementation of Operations

Slide 89

Slide 89 text

47 write %2 add read %i.0 1 Abstract Syntax Tree class LLVMI32LiteralNode extends LLVMExpressionNode { final int literal; public LLVMI32LiteralNode(int literal) { this.literal = literal; } @Override public int executeI32(VirtualFrame frame) { return literal; } } Executable AST node Implementation of Operations

Slide 90

Slide 90 text

47 write %2 add read %i.0 1 Abstract Syntax Tree class LLVMI32LiteralNode extends LLVMExpressionNode { final int literal; public LLVMI32LiteralNode(int literal) { this.literal = literal; } @Override public int executeI32(VirtualFrame frame) { return literal; } } Executable AST node Nodes return their result in an execute() method Implementation of Operations (Würthinger et al. 2012)

Slide 91

Slide 91 text

48 Abstract Syntax Tree write %2 add read %i.0 1 Implementation of Operations

Slide 92

Slide 92 text

48 Abstract Syntax Tree @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) class LLVMI32AddNode extends LLVMExpressionNode { @Specialization protected int executeI32(int left, int right) { return left + right; } } Executable AST node write %2 add read %i.0 1 Implementation of Operations

Slide 93

Slide 93 text

48 Abstract Syntax Tree @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) class LLVMI32AddNode extends LLVMExpressionNode { @Specialization protected int executeI32(int left, int right) { return left + right; } } Executable AST node write %2 add read %i.0 1 Implementation of Operations

Slide 94

Slide 94 text

48 Abstract Syntax Tree @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) class LLVMI32AddNode extends LLVMExpressionNode { @Specialization protected int executeI32(int left, int right) { return left + right; } } Executable AST node write %2 add read %i.0 1 A DSL allows a declarative style of specifying and executing nodes Implementation of Operations (Humer et al. 2015)

Slide 95

Slide 95 text

49 Abstract Syntax Tree write %2 add read %i.0 1 Implementation of Operations

Slide 96

Slide 96 text

49 Abstract Syntax Tree @NodeChild("valueNode") class LLVMWriteI32Node extends LLVMExpressionNode { final FrameSlot slot; public LLVMWriteI32Node(FrameSlot slot) { this.slot = slot; } @Specialization public void writeI32(VirtualFrame frame, int value) { frame.setInt(slot, value); } } Executable AST node write %2 add read %i.0 1 Implementation of Operations

Slide 97

Slide 97 text

49 Abstract Syntax Tree @NodeChild("valueNode") class LLVMWriteI32Node extends LLVMExpressionNode { final FrameSlot slot; public LLVMWriteI32Node(FrameSlot slot) { this.slot = slot; } @Specialization public void writeI32(VirtualFrame frame, int value) { frame.setInt(slot, value); } } Executable AST node write %2 add read %i.0 1 Implementation of Operations

Slide 98

Slide 98 text

49 Abstract Syntax Tree @NodeChild("valueNode") class LLVMWriteI32Node extends LLVMExpressionNode { final FrameSlot slot; public LLVMWriteI32Node(FrameSlot slot) { this.slot = slot; } @Specialization public void writeI32(VirtualFrame frame, int value) { frame.setInt(slot, value); } } Executable AST node write %2 add read %i.0 1 Local variables are represented by an array-like VirtualFrame object Implementation of Operations

Slide 99

Slide 99 text

50 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 100

Slide 100 text

50 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 101

Slide 101 text

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

Slide 102

Slide 102 text

Example Program 51 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } LLVM IR An AST interpreter cannot represent goto statements

Slide 103

Slide 103 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Interpreter 52 int blockIndex = 0; while (blockIndex != -1) blockIndex = blocks[blockIndex].execute (); Interpreter implementation

Slide 104

Slide 104 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Interpreter 53 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } Program execution

Slide 105

Slide 105 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Interpreter 54 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } Program execution

Slide 106

Slide 106 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Interpreter 55 define void @processRequests () #0 { ; ( basic block 0) br label %1 ; :1 ( basic block 1) %i .0 = phi i32 [ 0, %0 ], [ %2 , %1 ] call void @processPacket () %2 = add nsw i32 %i .0, 1 %3 = icmp slt i32 %2 , 10000 br i1 %3 , label %1 , label %4 ; :4 ( basic block 2) ret void } Program execution (Rigger et al. 2016 VMIL)

Slide 107

Slide 107 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Compiler 56 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 Partially evaluated interpreter (pseudo code) Graal

Slide 108

Slide 108 text

Block0 Block1 Block2 Basic Block Dispatch Node 1 2 -1 1 Compiler 56 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 Partially evaluated interpreter (pseudo code) Graal further optimizes the partially evaluated interpreter Graal

Slide 109

Slide 109 text

Evaluation Hypotheses • Effectiveness: Safe Sulong detects bugs that are overlooked by other tools • Performance: Safe Sulong’s performance overhead is “reasonable” 57

Slide 110

Slide 110 text

Effectiveness: Errors in GitHub Projects 58 http://ssw.jku.at/General/Staff/ManuelRigger/ASPLOS18-SafeSulong-Bugs.csv 68 errors in (small) open-source projects

Slide 111

Slide 111 text

Effectiveness: Errors in GitHub Projects • Valgrind detected half of the errors • 8 errors not found by LLVM’s AddressSanitizer (and Valgrind) • Compiler optimizations (ASan –O3) prevented the detection of 4 additional bugs 59 [What are the other errors?] [Completenesss vs. Soundness] [Comparison tools]

Slide 112

Slide 112 text

Effectiveness: Errors in GitHub Projects 60 int main(int argc, char** argv) { printf("%d %s\n", argc, argv[5]); } Out-of-bounds accesses to argv are not instrumented by ASan [What are the other errors?] [Comparison tools]

Slide 113

Slide 113 text

Effectiveness: Errors in GitHub Projects 61 https://github.com/google/sanitizers/issues/762

Slide 114

Slide 114 text

Effectiveness: Errors in GitHub Projects • 8 errors not found by LLVM’s AddressSanitizer and Valgrind 62 int main(int argc, char** argv) { printf("%d %s\n", argc, argv[5]); } In Safe Sulong instrumentation cannot be omitted by design [What are the other errors?] [Completenesss vs. Soundness] [Comparison tools]

Slide 115

Slide 115 text

Peak Performance 63 lower is better

Slide 116

Slide 116 text

Peak Performance 63 lower is better Safe Sulong‘s performance is mostly between Clang –O0 and Clang –O3, and mostly faster than ASan –O0

Slide 117

Slide 117 text

Warmup Performance 64 0 10 20 30 40 50 60 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 Iterations per second Second Meteor benchmark ASan (Clang O0) Safe Sulong Valgrind

Slide 118

Slide 118 text

Symbolic execution Hardware security Static analysis Attacker mitigation Existing Approaches 65 Instrumentation- based bug-finding tools Safe languages Safe Sulong improves upon aspects of existing bug-finding tools • Safe optimizations • Abstraction from the native execution model

Slide 119

Slide 119 text

Symbolic execution Hardware security Static analysis Attacker mitigation Existing Approaches 66 Instrumentation- based bug-finding tools Safe languages Safe Sulong leverages a safe implementation language for its bug-finding capabilities

Slide 120

Slide 120 text

Limitations/Selected Threats to Validity • Lack of support for binary libraries • Generalizability of the benchmark results • Relied on a custom libc for evaluation • Lacks common low-level features 67

Slide 121

Slide 121 text

68 Lenient C

Slide 122

Slide 122 text

Defined Behavior in C 69 C11 Implementing the semantics described in the standard is (often) relatively straightforward int arr[3]; int result = &arr[0] < &arr[2];

Slide 123

Slide 123 text

Relational Comparison of Pointers 70 a: Address offset pointee b: Address offset pointee < integer_rep(a) < integer_rep(b)

Slide 124

Slide 124 text

Integer Representation: Safe Sulong 71 integer_rep(a) = a.offset int arr[3]; int result = &arr[0] < &arr[2]; Can anyone see where our implementation could break programs? {0, 0, 0} Address offset = 2 data I64Array contents

Slide 125

Slide 125 text

72 Response % of Respondants Yes 33% Yes, but it shouldn’t 12% No, but there might well be 29% No, that would be crazy 16% Don’t know 8% [Do you know code that uses] relational comparison (with <, >, <=, or >=) of two pointers to separately allocated objects (of compatible object types)? (Memarian et al. 2016) Code Relies on Undefined Behavior

Slide 126

Slide 126 text

Problem 73 Programmers often rely on Undefined Behavior being defined C11

Slide 127

Slide 127 text

Problem 73 Programmers often rely on Undefined Behavior being defined C11

Slide 128

Slide 128 text

Idea 74 Goal: Continue execution in the presence of UB and make common otherwise undefined patterns work

Slide 129

Slide 129 text

Lenient C Programs written in C Valid Lenient C Programs Valid C Programs 75

Slide 130

Slide 130 text

{0, 0, 0} Address offset = 2 data I64Array contents Integer Representation: Lenient C 76 integer_rep(a) = (long) System.identityHashCode(a.pointee) << 32 | offset;

Slide 131

Slide 131 text

{0, 0, 0} Address offset = 2 data I64Array contents Integer Representation: Lenient C 76 Breaks antisymmetry as different objects might have the same hash code  integer_rep(a) = (long) System.identityHashCode(a.pointee) << 32 | offset;

Slide 132

Slide 132 text

{0, 0, 0} Address address data I64Array contents offset = 2 address Integer Representation: Lenient C 77 integer_rep(a) = a.pointee.address

Slide 133

Slide 133 text

{0, 0, 0} Address address data I64Array contents offset = 2 address Integer Representation: Lenient C 77 integer_rep(a) = a.pointee.address Need to assign distinct addresses ☺

Slide 134

Slide 134 text

Address offset = 0 data I64Array contents {0, 0, 0} Mitigate Use-after-Free Errors 78 long *arr = malloc(3 * sizeof(long)); free(arr);

Slide 135

Slide 135 text

Address offset = 0 data I64Array contents {0, 0, 0} Mitigate Use-after-Free Errors 79 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = …

Slide 136

Slide 136 text

Address offset = 0 data I64Array contents {0, 0, 0} Mitigate Use-after-Free Errors contents[0] = … 79 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = …

Slide 137

Slide 137 text

Address offset = 0 data I64Array contents {0, 0, 0} Mitigate Use-after-Free Errors contents[0] = … 79 long *arr = malloc(3 * sizeof(long)); free(arr); arr[0] = … The GC will collect the object when it is no longer referenced

Slide 138

Slide 138 text

Mitigate Integer Overflows 80 int a = 1, b = INT_MAX; int val = a + b; a + b

Slide 139

Slide 139 text

Mitigate Integer Overflows 80 int a = 1, b = INT_MAX; int val = a + b; a + b INT_MIN

Slide 140

Slide 140 text

Existing Approaches 81 Instrumentation- based bug-finding tools Symbolic execution Hardware security Static analysis Safe languages Attacker mitigation Lenient C assigns semantics to otherwise undefined behavior (cf. Friendly C)

Slide 141

Slide 141 text

Existing Approaches 82 Instrumentation- based bug-finding tools Symbolic execution Hardware security Static analysis Safe languages Attacker mitigation Increases robustness of programs without terminating execution

Slide 142

Slide 142 text

83 Introspection

Slide 143

Slide 143 text

Idea 84 int *arr = malloc(sizeof (int) * 10); … arr[4] = … ;

Slide 144

Slide 144 text

Idea 84 int *arr = malloc(sizeof (int) * 10); … arr[4] = … ;

Slide 145

Slide 145 text

Idea 84 Records metadata int *arr = malloc(sizeof (int) * 10); … arr[4] = … ; arr.size = 40

Slide 146

Slide 146 text

Idea 84 Records metadata int *arr = malloc(sizeof (int) * 10); … arr[4] = … ; arr.size = 40 Checks accesses

Slide 147

Slide 147 text

Idea 84 Records metadata int *arr = malloc(sizeof (int) * 10); … arr[4] = … ; arr.size = 40 Checks accesses int size = size_right(str);

Slide 148

Slide 148 text

Idea 84 Records metadata int *arr = malloc(sizeof (int) * 10); … arr[4] = … ; arr.size = 40 Checks accesses Query meta data From the tool int size = size_right(str);

Slide 149

Slide 149 text

Introspection Functions 85 int *arr = malloc(sizeof (int) * 10) ; int *ptr = &(arr[4]); printf ("%ld\n", size_right(ptr)); // prints 24 _size_right() sizeof(int) * 10

Slide 150

Slide 150 text

Introspection Functions 85 int *arr = malloc(sizeof (int) * 10) ; int *ptr = &(arr[4]); printf ("%ld\n", size_right(ptr)); // prints 24 _size_right() sizeof(int) * 10 We also designed introspection functions for other meta data

Slide 151

Slide 151 text

Example: strlen() 86 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; }

Slide 152

Slide 152 text

Example: strlen() 86 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } P r o g r a m m i n g \0 ... ...

Slide 153

Slide 153 text

Example: strlen() 86 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } P r o g r a m m i n g \0 ... ...

Slide 154

Slide 154 text

Example: strlen() 86 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } 11 P r o g r a m m i n g \0 ... ...

Slide 155

Slide 155 text

Example: strlen() 87 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } P r o g r a m m i n g ... ...

Slide 156

Slide 156 text

Example: strlen() 87 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } P r o g r a m m i n g ... ...

Slide 157

Slide 157 text

Example: strlen() 87 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } P r o g r a m m i n g ... ... ==16497==ERROR: AddressSanitizer: stack-buffer- overflow on address 0x7ffc59c0ef63 READ of size 1 at 0x7ffc59c0ef63 thread T0 #0 0x4e7442 in strlen /home/manuel/test.c:10:12 #1 0x4e7392 in main /home/manuel/test.c:5:5

Slide 158

Slide 158 text

Mitigate Errors 88 What about systems with high- availability requirements?

Slide 159

Slide 159 text

Idea 89 Goal: Allow programmers to manually implement a failure-oblivious computation logic

Slide 160

Slide 160 text

size_t strlen(const char *str) { size_t len = 0; while ( size_right(str) > 0 && *str != '\0') { len++; str++; } return len; } Example: strlen() 90 P r o g r a m m i n g ... ...

Slide 161

Slide 161 text

size_t strlen(const char *str) { size_t len = 0; while ( size_right(str) > 0 && *str != '\0') { len++; str++; } return len; } Example: strlen() 90 P r o g r a m m i n g ... ...

Slide 162

Slide 162 text

size_t strlen(const char *str) { size_t len = 0; while ( size_right(str) > 0 && *str != '\0') { len++; str++; } return len; } Example: strlen() 90 11 P r o g r a m m i n g ... ...

Slide 163

Slide 163 text

size_t strlen(const char *str) { size_t len = 0; while ( size_right(str) > 0 && *str != '\0') { len++; str++; } return len; } Example: strlen() 90 11 P r o g r a m m i n g ... ... We enhanced a libc to deal with unterminated strings

Slide 164

Slide 164 text

Implementation in Tools LLVM’s AddressSanitizer SoftBound Intel MPX’s based bounds instrumentation Safe Sulong 91

Slide 165

Slide 165 text

Evaluation: Effectiveness 92 Dnsmasq CVE-2017-14493 CVE-2017-14496 CVE-2017-9047 Libxml2 CVE-2017-16352 LightFTP CVE-2017-1000218

Slide 166

Slide 166 text

Evaluation: Effectiveness 92 Dnsmasq CVE-2017-14493 CVE-2017-14496 CVE-2017-9047 Libxml2 CVE-2017-16352 LightFTP CVE-2017-1000218 Execution # CVEs Could continue 4 Terminated 1

Slide 167

Slide 167 text

CVE-2017-9047 (Libxml2) 93 if (content->name != NULL) strcat(buf, (char *) content->name);

Slide 168

Slide 168 text

CVE-2017-9047 (Libxml2) 93 if (content->name != NULL) strcat(buf, (char *) content->name); The parser printed a truncated error message, similar to the fixed version

Slide 169

Slide 169 text

Hardware security Existing Approaches 94 Instrumentation- based bug-finding tools Symbolic execution Safe languages Static analysis Attacker mitigation

Slide 170

Slide 170 text

Hardware security Existing Approaches 94 Instrumentation- based bug-finding tools Symbolic execution Safe languages Static analysis Extension of Failure-oblivious Computing (Rinard et al. 2004) Attacker mitigation

Slide 171

Slide 171 text

95 GraalVM

Slide 172

Slide 172 text

GraalVM 96

Slide 173

Slide 173 text

Sulong as Part of GraalVM 97 Java Virtual Machine Graal Compiler Truffle Framework https://www.graalvm.org/ TruffleRuby Graal.js Graal.python FastR (Würthinger et al. 2016)

Slide 174

Slide 174 text

Sulong as Part of GraalVM 97 Java Virtual Machine Graal Compiler Truffle Framework https://www.graalvm.org/ TruffleRuby Graal.js Graal.python FastR Optimization Boundary (Würthinger et al. 2016)

Slide 175

Slide 175 text

Sulong as Part of GraalVM 98 Java Virtual Machine Graal Compiler Truffle Framework https://www.graalvm.org/ TruffleRuby Graal.js Graal.python FastR Optimization Boundary Java Native Interface (Würthinger et al. 2016)

Slide 176

Slide 176 text

Sulong as Part of GraalVM 99 Java Virtual Machine Graal Compiler Truffle Framework https://www.graalvm.org/ TruffleRuby Graal.js Graal.python FastR Optimization Boundary LLVM IR Interpreter LLVM IR Clang Flang (Würthinger et al. 2016)

Slide 177

Slide 177 text

Sulong and GraalVM 100

Slide 178

Slide 178 text

Sulong and GraalVM 100

Slide 179

Slide 179 text

Sulong Key Collaborators 101 Jacob Kreindl Raphael Mosaner Roland Schatz Josef Eisl Christian Häubl Matthias Grimmer Thomas Pointhuber Daniel Pekarek Chris Seaton Lukas Stadler Florian Angerer David Gnedt https://github.com/graalvm/sulong/graphs/contributors Swapnil Gaikwad

Slide 180

Slide 180 text

Sulong Key Collaborators 102 Jacob Kreindl Raphael Mosaner Roland Schatz Josef Eisl Christian Häubl Matthias Grimmer Thomas Pointhuber Daniel Pekarek Chris Seaton Lukas Stadler Florian Angerer David Gnedt Swapnil Gaikwad EuroLLVM 2019 Talk LLVM IR in GraalVM: Multi-Level, Polyglot Debugging with Sulong https://github.com/graalvm/sulong/graphs/contributors

Slide 181

Slide 181 text

Sulong Key Collaborators 103 Jacob Kreindl Raphael Mosaner Roland Schatz Josef Eisl Christian Häubl Matthias Grimmer Thomas Pointhuber Daniel Pekarek Chris Seaton Lukas Stadler Florian Angerer David Gnedt Swapnil Gaikwad EuroLLVM 2019 Talk Sulong: An experience report of using the "other end" of LLVM in GraalVM. https://github.com/graalvm/sulong/graphs/contributors

Slide 182

Slide 182 text

Summary 104 UB is problematic Existing approaches can “optimize” UB “away” Execute C/C++ on the JVM! Automatic checks detect UB But: Programs often invoke UB Metadata for manual checks GraalVM