K-Miner Uncovering Memory Corruption in Linux David Gens Simon Schmitt Ahmad-Reza Sadeghi Cyber Security Center (CYSEC) Technische Universität Darmstadt Lucas Davi Universität of Duisburg-Essen
Why Static Analysis?
Big Picture KERNEL FILES COMPILER Memory Corruption: Use-After-Free Double Free Use-After-Return Memory Leaks OS HARDWARE
Big Picture KERNEL FILES COMPILER Attacke r Memory Corruption: Use-After-Free Double Free Use-After-Return Memory Leaks OS HARDWARE Static Analysis at compile time. Dynamic Analysis at run time.
Data-Flow Analysis: Graphs void main() { int a = 1; int *p; if (a!= 0) p = &a; Entry: int a = 1 int main *p printf p = &a } printf( %d\n, *p); Call Graph printf( %d\n, *p); Control-Flow Graph
Data-Flow Analysis: Graphs void main() { int a = 1; int *p; Pointer p Obj_p Obj_a a a p=&a Stack } if (a!= 0) p = &a; printf( %d\n, *p); p phi *p Pointer Value-Flow Constraint Assignment Graph Graph
Source-Sink Analysis kalloc_x p alloc SOURCE void main() { int *p = alloc(); p=alloc() if (p!= NULL) free(p); free SINK } free(p); phi free SINK There exists a path that reaches two sinks.
Scalability and Precision High Complexity + + + Context-Sensitive Field-Sensitive Inter-Procedural Analysis Low Complexity
Kernel Static Analysis - History Sparse [by Torvalds] APISAN [Yun et al. USENIX 16] Smatch [by Charpenter] Coccinelle [Padioleau et al. EuroSys 08] EBA [Abal et al. Springer 17] 2002 2003 2008 2016 2017
Linux Kernel: Lines of Code 25M 20M 15M 10M Lines of Code 5M 0 M 1.0 1.2 2.0 2.2 2.6 3.0 3.2 3.6 3.19 4.0 4.2 4.6 4.10 4.12 Version
Contributions and Challenges Analysis Format Large Codebase Expandability Data-Flow Analysis Different Kernel Versions Transformation of the kernel source into the LLVM intermediate representation Scaling inter-procedural Data-Flow Analysis to millions of kernel code lines A modular design, adding new checkers is straightforward Combine existing and novel approaches for inter-procedural bug checkers Reports of different kernel versions can be managed using a web-based interface
Enabling Data-Flow Analysis Idea: Partitioning the kernel along the system call API System calls are the interface between user- and kernelspace Attacke r Syscall API Vulnerabilities have to be exploited though system calls KERNEL Driver API HARDWARE
Enabling Data-Flow Analysis Idea: Partitioning the kernel along the system call API System calls are the interface between user- and kernelspace Attacke r Vulnerabilities have to be exploited though system calls HARDWARE
Enabling Data-Flow Analysis Idea: Partitioning the kernel along the system call API System calls are the interface between user- and kernelspace Attacke r Vulnerabilities have to be exploited though system calls HARDWARE
Enabling Data-Flow Analysis Idea: Partitioning the kernel along the system call API System calls are the interface between user- and kernelspace Attacke r Vulnerabilities have to be exploited though system calls HARDWARE
Design and Workflow KERNEL FILES COMPILER MAKE FILE IR Pre-Processing Model Memory Obj Define Contexts Init Contexts K-MINER
Design and Workflow KERNEL FILES COMPILER MAKE FILE IR K-MINER Pre-Processing Model Memory Obj Define Contexts Init Contexts Partitioner Report Engine Bug Checker global_x global_y Memory-Corruption Report: Use-After-Return: global_x -> local_y
Implementation Details K-Miner builds on top of LLVM and SVF Environment Setup: Register allocation sites by using a list of kernel allocation functions for dynamically allocated objects Context Handling: Defines syscalls and initcalls contexts Performs a call-graph analysis and pointer analysis Multi-Level reduction of relevant partitions Bug Checker: Exploit LLVM s Pass-Infrastructure Covers Use-After-Return, Double-Free and Memory-Leaks Performs particular analysis and several validation checks
Use-After-Return Checker void sys_foo() { do_foo() return } 6 global_p local_x void do_foo() { int local_x = 1 add_x(&local_x) if(cond()) remove_x() return } 3 5 null remove_x 4 add_x 2 3 1 void add_x(int *p) { global_p = p } 1 2 do_foo 5 void remove_foo() { 6 global_p = NULL } 4 Value-Flow Graph
Use-After-Return Checker void sys_foo() { do_foo() return } 6 global_p local_x void do_foo() { int local_x = 1 add_x(&local_x) if(cond()) remove_x() return } 3 5 null remove_x 4 add_x 2 3 1 void add_x(int *p) { global_p = p } 1 2 do_foo 5 void remove_foo() { 6 global_p = NULL } 4 Value-Flow Graph
Evaluation Coverage: Four Kernel Versions ca. 300 system calls Scalability: Ø 25 min. per system call Ø 12 GB memory usage Real-world Impact: CVE-2014-3153 (UAR) CVE-2015-8962 (DFree) Extensibility: Additional bug checkers can be added as Passes Version MLoC Functions Run-Time Globals Memory Locals UAR MLeak Total Pointer DFree v3.19 15.5 1667/9933 796.69s 124/13624 8.765 GB 6967/419554 7/40 3/131 97248/5689390 1/13 v4.02 2086/104247 16.3 1435.62s 122/14771 13.23 GB 9309/451451 11/46 2/106 127894/571316 0/19 v4.06 2208/104430 17.1 1502.54s 126/14989 11.76 GB 9947/453052 3/50 2/104 133313/6174471 0/31 v4.10 2246/120794 22.1 2312.14s 157/16530 12.86 GB 9873/518394 0/65 1/105 128253/7091977 0/22
https://github.com/ssl-tud/k-miner
https://github.com/ssl-tud/k-miner Questions?