DieHard: Probabilistic Memory Safety for Unsafe Languages Emery D. Berger and Benjamin G. Zorn PLDI'06 Presented by Uri Kanonov 23.02.2014.

Slides:



Advertisements
Similar presentations
Dynamic Memory Management
Advertisements

The Interface Definition Language for Fail-Safe C Kohei Suenaga, Yutaka Oiwa, Eijiro Sumii, Akinori Yonezawa University of Tokyko.
Computer Security: Principles and Practice EECS710: Information Security Professor Hossein Saiedian Fall 2014 Chapter 10: Buffer Overflow.
Virtual Memory Chapter 18 S. Dandamudi To be used with S. Dandamudi, “Fundamentals of Computer Organization and Design,” Springer,  S. Dandamudi.
Virtual Memory Introduction to Operating Systems: Module 9.
5. Memory Management From: Chapter 5, Modern Compiler Design, by Dick Grunt et al.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Computer Systems Principles Dynamic Memory Management Emery Berger and Mark Corner.
Week 7 - Friday.  What did we talk about last time?  Allocating 2D arrays.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science 2007 Exterminator: Automatically Correcting Memory Errors with High Probability Gene.
Malloc Recitation Section K (Kevin Su) November 5 th, 2012.
DIEHARDER: SECURING THE HEAP. Previously in DieHard…  Increase Reliability by random positioning of data  Replicated Execution detects invalid memory.
Foundations of Network and Computer Security J J ohn Black Lecture #30 Nov 26 th 2007 CSCI 6268/TLEN 5831, Fall 2007.
By Gene Novark, Emery D. Berger and Benjamin G. Zorn Presented by Matthew Kent Exterminator: Automatically Correcting Memory Errors with High Probability.
CPSC 388 – Compiler Design and Construction
Stack-Based Buffer Overflows Attacker – Can take over a system remotely across a network. local malicious users – To elevate their privileges and gain.
By Emery D. Berger and Benjamin G. Zorn Presented by: David Roitman.
Teaching Buffer Overflow Ken Williams NC A&T State University.
1 1 Lecture 4 Structure – Array, Records and Alignment Memory- How to allocate memory to speed up operation Structure – Array, Records and Alignment Memory-
CS510 Advanced OS Seminar Class 10 A Methodology for Implementing Highly Concurrent Data Objects by Maurice Herlihy.
CS 333 Introduction to Operating Systems Class 18 - File System Performance Jonathan Walpole Computer Science Portland State University.
Memory Management 1 CS502 Spring 2006 Memory Management CS-502 Spring 2006.
CS-3013 & CS-502, Summer 2006 Memory Management1 CS-3013 & CS-502 Summer 2006.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science PLDI 2006 DieHard: Probabilistic Memory Safety for Unsafe Programming Languages Emery.
A. Frank - P. Weisberg Operating Systems Simple/Basic Paging.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science 2006 Exterminator: Automatically Correcting Memory Errors Gene Novark, Emery Berger.
Security Exploiting Overflows. Introduction r See the following link for more info: operating-systems-and-applications-in-
CS 346 – Chapter 8 Main memory –Addressing –Swapping –Allocation and fragmentation –Paging –Segmentation Commitment –Please finish chapter 8.
Dynamic Memory Allocation Questions answered in this lecture: When is a stack appropriate? When is a heap? What are best-fit, first-fit, worst-fit, and.
15-740/ Oct. 17, 2012 Stefan Muller.  Problem: Software is buggy!  More specific problem: Want to make sure software doesn’t have bad property.
Chapter 6 Buffer Overflow. Buffer Overflow occurs when the program overwrites data outside the bounds of allocated memory It was one of the first exploited.
Presentation of Failure- Oblivious Computing vs. Rx OS Seminar, winter 2005 by Lauge Wullf and Jacob Munk-Stander January 4 th, 2006.
IT253: Computer Organization Lecture 3: Memory and Bit Operations Tonga Institute of Higher Education.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
Chapter 8 – Main Memory (Pgs ). Overview  Everything to do with memory is complicated by the fact that more than 1 program can be in memory.
1 File Systems: Consistency Issues. 2 File Systems: Consistency Issues File systems maintains many data structures  Free list/bit vector  Directories.
8.1 Silberschatz, Galvin and Gagne ©2013 Operating System Concepts – 9 th Edition Paging Physical address space of a process can be noncontiguous Avoids.
1 Virtual Memory and Address Translation. 2 Review Program addresses are virtual addresses.  Relative offset of program regions can not change during.
1 Address Translation Memory Allocation –Linked lists –Bit maps Options for managing memory –Base and Bound –Segmentation –Paging Paged page tables Inverted.
University of Washington Today Finished up virtual memory On to memory allocation Lab 3 grades up HW 4 up later today. Lab 5 out (this afternoon): time.
Memory Management. Memory  Commemoration or Remembrance.
Virtual Memory 1 1.
A Tool for Pro-active Defense Against the Buffer Overrun Attack D. Bruschi, E. Rosti, R. Banfi Presented By: Warshavsky Alex.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Virtual Memory Hardware.
CS333 Intro to Operating Systems Jonathan Walpole.
CNIT 127: Exploit Development Ch 8: Windows Overflows Part 2.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Memory Management Overview.
Security Attacks Tanenbaum & Bo, Modern Operating Systems:4th ed., (c) 2013 Prentice-Hall, Inc. All rights reserved.
LECTURE 12 Virtual Memory. VIRTUAL MEMORY Just as a cache can provide fast, easy access to recently-used code and data, main memory acts as a “cache”
COMP091 – Operating Systems 1 Memory Management. Memory Management Terms Physical address –Actual address as seen by memory unit Logical address –Address.
Memory Management What if pgm mem > main mem ?. Memory Management What if pgm mem > main mem ? Overlays – program controlled.
Chapter 13 Recursion Copyright © 2016 Pearson, Inc. All rights reserved.
Non Contiguous Memory Allocation
Jonathan Walpole Computer Science Portland State University
Presented by: Daniel Taylor
Segmentation COMP 755.
Module 11: File Structure
Module 30 (Unix/Linux Security Issues II)
Lecture 12 Virtual Memory.
Chapter 9 – Real Memory Organization and Management
High Coverage Detection of Input-Related Security Faults
CETS: Compiler-Enforced Temporal Safety for C
CS5123 Software Validation and Quality Assurance
CS703 - Advanced Operating Systems
COMP755 Advanced Operating Systems
Memory Management Memory management is the art and the process of coordinating and controlling the use of memory in a computer system Why memory management?
Virtual Memory.
CSE 542: Operating Systems
Week 7 - Friday CS222.
Virtual Memory 1 1.
Presentation transcript:

DieHard: Probabilistic Memory Safety for Unsafe Languages Emery D. Berger and Benjamin G. Zorn PLDI'06 Presented by Uri Kanonov

Outline Introduction Suggested Solution Evaluation Related work Conclusions Musings… Discussion

Introduction Interested in “unsafe” languages: C/C++ Why are those languages popular? – Native code is faster than interpreted code – Allow for more efficient optimizations – Fine grained control (memory/execution) – Can do a lot of hacky stuff !

Resulting Problems Programmers take control of (almost) everything (memory, resources, code flow…) But they often… – Forget to handle the resources properly – Are unaware of their runtime environment (memory layout, how to the heap works) – Write poor code that leads to bugs End result – Security vulnerabilities – Crashes

Goal Efficiently detect /prevent such bugs Multiple approaches: – Detect statically – Countermeasures to avoid the bugs – Detect at runtime and Tolerate Perform a controlled crash – Ignore

Proposed Solution: DieHard Takes on a “hardening” approach: – Dangling pointers – Buffer overflows – Heap metadata overwrites – Uninitialized reads – Invalid frees – Double frees

DieHard Heap allocator based on “probabilistic memory safety” Ideal: an infinite heap – Never freeing – Infinite spacing Practical: heap M times larger than required

In Practice How allocations work? – Heap initialized to random data – Objects allocated at random locations across the heap Separate heap metadata Run multiple copies to detect uninitialized reads

Initialization Heap size: M times the needed size 12 regions – Powers of two from 8 bytes to 16KB – Larger objects allocated separately – Filled up to 1/M of its size Heap meta-data – Separate – Bitmap per region consisting of bit per object

Motivation Why use regions per object size? – To prevent external fragmentation – Knowing the region tells you the object size – Powers of two -> efficient calculations Why separate heap metadata? – Security

Pseudo-code 1void DieHardInitHeap (int MaxHeapSize) { 2// Initialize the random number generator 3 // with a truly random number. 4rng.setSeed (realRandomSource); 5// Clear counters and allocation bitmaps 6 // for each size class. 7 for (c = 0; c < NumClasses; c++) { 8 inUse[c] = 0; 9 isAllocated[c].clear(); 10 } 11 // Get the heap memory. 12 heap = mmap (NULL, MaxHeapSize); 13 // REPLICATED: fill with random values 14 for (i = 0; i < MaxHeapSize; i += 4) 15 ((long *) heap)[i] = rng.next(); 16}

Allocation Allocating large objects with mmap – Use “guard” (no-rw) pages Locating empty slot in object’s region – Fails if region is full (OOM) – Expected time to find an empty slot: Slot filled with random values Occupying entire slot even if object is smaller

1void * DieHardMalloc (size_t sz) { 2 if (sz > MaxObjectSize) 3 return allocateLargeObject(sz); 4 c = sizeClass (sz); 5 if (inUse[c] == PartitionSize / (M * sz)) 6 // At threshold: no more memory. 7 return NULL; 8 do { // Probe for a free slot. 9 index = rng.next() % bitmap size; 10 if (!isAllocated[c][index]) { 11 // Found one, pick pointer corresponding to slot. 12 ptr = PartitionStart + index * sz; 13 inUse[c]++; // Mark it allocated. 14 isAllocated[c][index] = true; 15 // REPLICATED: fill with random values. 16 for (i = 0; i < getSize(c); i += 4) 17 ((long *) ptr)[i] = rng.next(); 18 return ptr; 19 } 20 } while (true); 21 } Pseudo-Code

Deallocation If address lies inside heap: – If “large object” object, it is deallocated – Otherwise, ignored Assertions: – Object offset from region start is multiple of size – The object must be allocated Eventually slot is marked as free

Pseudo-code 1void DieHardFree (void * ptr) { 2 if (ptr is not in the heap area) 3 freeLargeObject(ptr); 4 c = partition ptr is in; 5 index = slot corresponding to ptr; 6 // Free only if currently allocated; 7 if (offset correct && isAllocated[c][index]) { 8 inUse[c]--; // Mark it free. 9 isAllocated[c][index] = false; 10 } // else, ignore 11}

Secure strcpy Override strcpy/strncpy to prevent buffer overflows Doesn’t mitigate other risks: – memcpy / memmove – User defined functions 1void foo(char* user_input) { 2 char* buffer = (char*)malloc(100); 3strcpy(buffer, user_input); 4}

Replication Assumption – Program’s output depends on data it reads – Uninitialized data -> different outputs amongst replicas Output is buffered and voted on (majority voting)

Replication (cont.) Non-agreeing replicas are terminated Implementation limitations : – What if a replica enters an infinite loop – Non-deterministic or environment dependent programs are not supported – Significant memory/CPU overhead

Correctness Does DieHard follow through on its promises? Heap metadata overwrites – Separate metadata Invalid/double frees – Deallocation performs the required validations Uninitialized reads – Probabilistically Dangling pointers and Buffer overflows – Probabilistically – Yep…

Masking Buffer Overflows Lets analyze how DieHard deals with buffer overflows Some notations first: – - Heap expansion factor – - Number of replicas – - Max heap size – - Maximum live size – - Remaining free space – - Number of objects’ worth of bytes overflowed

Heap Layout

Masking Buffer Overflows (cont.) Theorem: Proof: – Odds of objects overwriting at least one live object are 1 minus the odds of them overwriting no live objects: – Masking requires that at least one replica of the replicas not overwrite any live objects, alternatively all of them overwriting at least one live object:

Probability of Avoiding Buffer Overflows

Runtime Complexity Initialization / Deallocation – No significant runtime overhead Allocation: – “Mild” impact due to the empty slot search Accessing allocated memory – No “spatial locality” -> many TLB misses – Need the heap to fit into the physical RAM

Memory Complexity Heap size – 12M times more memory is required Object size rounding – Up to X2 memory is used – Same approach used in many allocators Heap metadata takes up little very little space Segregated regions – Eliminate external fragmentation

DieHard was evaluated on two criteria: – Runtime overhead (complexity) – Error avoidance (correctness) We will elaborate on each in detail Evaluation

Benchmark suite: – SPECint2000 – Allocation-intensive benchmarks (100K - 1.7M allocations per sec) Heap size: 384MB with ½ available for allocation Operating Systems – StandAlone: Windows XP & Linux – Repliacted: Solaris Runtime Overhead Evaluation

Linux: – DieHard – Native (GNU libc) allocator – Boehm-Demers-Weiser garbage collector Windows XP: – DieHard – Native allocator Solaris – Replicated version Experiments

Runtime on Linux

High overhead (16.5% to 63%): – Allocation intensive applications – Wide usage of different object sizes -> TLB misses Low overhead: – General purpose (SPECint2000) benchmarks Linux Results

Runtime on Windows XP

Surprise! – DieHard performs on average like the default allocator The authors’ explanation – Windows XP’s allocator is much slower than GNU libc’s – The compiler on Windows XP (Visual Studio) produces more efficient code than g++ on Linux Interesting question – How would DieHard perform on modern Windows? Windows XP Results

Experiment – Use a 16-core Solaris server – Run 16 replicates of the allocation-intensive benchmarks Results – One benchmark terminated by DieHard due to an uninitialized read – Rest of the benchmarks incurred 50% runtime overhead – Process creation overhead would be amortized by longer-running benchmarks Solaris Results

Version of the Squid web cache server containing a buffer overflow bug Results – DieHard contains this overflow – GNU libc allocator and the BDW collector crash Impressive! – Interesting to see DieHard pitted against more bugs Error Avoidance – Real Scenario

Performed on a UNIX machine Single allocation-intensive benchmark strcpy and strncpy were not overriden MITM’ing allocations – Buffer overflows: Caused by under-allocating buffers – Dangling pointers: Freeing an object sooner than its actual free Error Avoidance – Injected Faults

One out of every two objects is freed ten allocations too early Results – Default allocator (GNU libc) The benchmark failed to complete all 10 times – DieHard Ran correctly 9 out of 10 times Dangling Pointers - Results

Under-allocating by 4 bytes one out of every 100 allocations for >= 32 bytes Results – Default allocator 9 crashes and one infinite loop – DieHard 10 successful runs Buffer Overflows - Results

Runtime overhead – Is suitable for general purpose applications – Is NOT suitable for allocation-intensive ones – The replicated version scales well to computers with a large number of processors Error avoidance – Seems to contain well both artificial and real faults Evaluation Conclusions

Related work – Fail-Stop Approach Prototype – CCured / Cyclone Idea – Provide type/memory safety to C/C++ using runtime checks and static analysis Pros – May detect other errors that DieHard can’t Cons – Requires code modification – May abort errors that DieHard can “contain”

Related work – Failure Masking Idea – Ignore illegal writes and manufacture values for uninitialized reads. Pros – May incur less overhead than DieHard Cons – May result in unpredictable program behavior

Related work - Rollback Prototype – Rx Idea – Utilize logging and rollbacks to restart programs after detectable errors (like a crash) Pros – May incur less overhead than DieHard Cons – Rollbacks aren’t suitable for every program – Not all errors are detectable externally

Conclusions “Probabilistic memory safety” has its merits! – Especially revolutionary for 2006… DieHard can contain avoid/contain certain errors but at a high cost – Not suitable for all applications DieHard uses many common-practice techniques – Separation of heap meta-data – Separate regions by object size Meaning… they work!

Musings… Nowadays when RAM is usually not an issue DieHard can be a suitable solution for general purpose applications Randomness is useful against “bugs” but not against those who try to exploit them Modern OS use more efficient/simple ways to protect against overflows – Heap cookies! – For example: iOS 6

iOS 6 Heap Cookies

alloc( ) ensures next_pointer matches encoded pointer at end of block – Tries both cookies – If poisoned cookie matches, check whole block for modification of sentinel (0xdeadbeef) values Next pointer and cookie replaced by 0xdeadbeef when allocated

Questions?

Discussion What do you think about DieHard? – Is it practical? – Would you use it in your application? Is heap cookie solution secure enough? Any other suggestions?