Title: Samurai : Protecting Critical Heap Data in Unsafe Languages
1Samurai Protecting Critical Heap Data in Unsafe
Languages
- Karthik Pattabiraman, UIUC
- Vinod Grover, Microsoft Corpn.
- Benjamin Zorn, Microsoft Research
2Motivation
- C/C programs vulnerable to memory errors
- Buffer overflows
- Dangling pointers
- Double frees
- Uninitialized pointers etc.
- Result in program crashes, incorrect output
- Goal Harden C/C programs from memory errors
and provide Java/C-like guarantees - Protect from hardware transient errors in memory
3Existing Approaches
- C-Cured, Jones-Kelley, CRED, Dhurjati-Adve
- Abort program if a memory error occurs
- Failure-oblivious computing Rinard
- Hope that program will continue after memory
error with no untoward effects (Unsound) - Rx Treating bugs as allergies Zhou
- Restore program from checkpoint. Assumes error is
detected in a timely fashion (Unsound) - Diehard Probabilistic memory safety Berger,
Zorn - Recover from memory errors with sound semantics,
but requires process-level replication
4Main Idea
- Some application data is more important than
other data - Can be used to recover the state of the
application after a failure - Assumes existence of recovery mechanisms in the
application to reconstruct application state - Many apps have built-in error recovery that are
more effective than generic checkpointing and
recovery Chandra and Chen
Critical Data
Critical Data
Application Failure
5What is Critical Data ?
- Data that is important for correct execution of
application or data that is required to restart
the application after a crash - Banking application Account data critical GUI,
networking data not critical - Web-server Table of connections critical
connection state data may not be critical - Word-processor/Spreadsheet Document contents
critical internal data structures not critical - E-Commerce application Credit card data/shopping
cart contents more critical than user-preferences - Game User state such as score, level critical
state of game world not critical
6Outline
- Motivation
- Software Critical Memory (concept)
- Semantics
- Deployment
- Samurai (implementation)
- Experimental results
- Other applications of SCM
- Conclusions and future Work
7SCM (Software Critical Memory)
- Memory model to protect specific data in an
application (called critical data) - Critical data can be modified only at specific
locations in the program (verified stores) - Guarantees that critical data is not corrupted
unintentionally even if the program crashes - Assumptions
- Application can continue executing correctly
even if non-critical data is corrupted (or) - There exist recovery mechanisms to restart
application from correct critical data contents
8SCM Semantics
- Only verified stores can update critical data in
a consistent way - Unverified stores to critical data are undefined
- Verified loads of critical data will always read
the value written by a last verified store - Unverified loads of critical data are undefined
- Verified stores and loads of non-critical data
are treated as regular loads and stores - Unverified loads and stores of non-critical data
are treated as regular loads and stores too
9SCM Semantics Example
10SCM Deployment
- Programmer identifies critical data that needs to
be protected in the application - Programmer identifies locations in the code at
which this critical data is manipulated in the
form of verified loads and verified stores - SCM provides memory safety guarantees with
respect to verified loads and verified stores - Programmer provides other consistency checks
- Programmer optionally provides routines to
recover the application state from critical data
11Identification of Verified Loads/Stores
All references
- Potentially all locations that can read/write
critical data - Needs to be may-alias for correctness
- Must be close to the set of must-alias for
coverage - Could be done based on types
- Marks an entire type as critical
- Type-safety of subset of program that manipulates
critical data - Rest of program can be type-unsafe
May-alias
Must-alias
All references
Critical Type Pointers
Critical type references
12Example of SCM Deployment -1
- void add_to_list(Node start, Patient patient)
- Node list (Node) critical_malloc(
sizeof(Node) ) - verified_store (list-gtpatient,
sizeof(list-gtpatient), patient) - Node temp NULL
- verified_store (list-gtforward,
sizeof(list-gtforward), temp ) - verified_store (start-gtforward,
sizeof(start-gtforward), list ) - start-gtforward list
- start list
-
13Example of SCM Deployment -2
- void processPatients(Node start)
- Node list start
- while (list ! NULL)
- Patient p verified_load
(list-gtpatient, sizeof(list-gtpatient) ) - doProcessing(p)
- list verified_load (list-gtforward,
sizeof(list-gtforward) ) -
14Third-party Libraries/Untrusted Code
Function is allowed to execute correctly in
spite of memory errors !
- Function reads and writes critical data
- Changes confined to critical data the function is
allowed to modify - Operations
- unmap_critical
- promote
- Modifications must be vetted by assertions prior
to update
15SCM Advantages
- Requires only accesses to critical-data to be
type-safe/annotated - No runtime checks on non-critical accesses
- Can be deployed in an incremental fashion
- Versus all-or-nothing approach of systems such as
CCured - Protection even in presence of unsafe/third-party
library code, without requiring changes to
library function or aborting upon an error - SFI requires modifications to library
source/binary - Amenable to possible hardware implementation
16Limitations of SCM
- Errors in non-critical data can propagate to
critical data - Control-flow errors (does not replace
control-flow checking) - Data-consistency errors (assumes existence of
executable assertions and consistency checks) - Occurred rarely in random fault-injection
experiments - Malicious attackers
- No attempt made to hide critical data (privacy
issues) - Can defeat our software implementation of SCM
- Can still exploit memory errors in non-critical
data
17Outline
- Motivation
- Software Critical Memory (concept)
- Samurai (implementation)
- Experimental results
- Other applications of SCM
- Conclusions and future work
18Samurai SCM Implementation
- Implementation of SCM for dynamically-allocated
objects on the heap - Objects allocated using critical_malloc() and
critical_free() - Samurai keeps 3 copies of every object at random
locations in heap (to minimize correlated
corruption) - Pointers to copies stored as part of
heap-metadata at the beginning of each object - Built on top of the Diehard allocator
(unreplicated)
19Heap Organization (BIBOP)
Ptr
Start_8
- Similar to DieHard, HeapShield, PHKmalloc
- Given an internal pointer to an object, can we
figure out its start ? - Heap partitioned based on object size
(powers-of-two) at fixed addresses - Can use address and offset computation to
calculate starting address of objects in constant
time -
- ( (Ptr Start_8) / 8 ) 8
Samurai Heap
16
16
8
8
8
8
allocated
4
4
4
4
4
4
4
20Samurai Operations (continued)
base
Replica 1
- Critical malloc
- Allocates 3 objects with diehard
- Initializes metadata of parent object with shadow
pointers - Set valid bits of object
- Return base pointer to user
- Critical free
- Free all 3 copies on diehard heap
- Reset metadata of object
- Reset valid bits of object
Shadow pointer 1
base
Shadow pointer 2
Object contents
Samurai Heap
Replica 2
21Samurai Operations
base
- Verified stores
- Compute base address of object
- Check if object is valid
- Follow shadow pointers in metadata
- Update replicas with stored contents
- Verified loads
- Compute base address of object
- Check if object is valid
- Follow shadow pointers in metadata
- Check object with replicas
- Fix any errors found by voting on a per-byte
basis
Replica 1
Shadow pointer 1
base
Shadow pointer 2
Object Contents corrupted
V
Samurai Heap
error
Replica 2
22Considerations and Optimizations
- Considerations
- Metadata itself protected from memory errors
using checksums (backup copy in protected hash
table) - Consistency checks in implementation
- Bounds checking critical accesses
- Periodic scrubbing for infrequently accessed
objects - Optimizations
- Cache frequent metadata lookups for speed
- Compare with only one shadow on verified loads
- Periodically switch pointers to prevent error
accumulation in the other shadow - Adaptive voting strategy for repairing errors
- Exponential back-off based on object size
- Mainly used for errors in large objects
23Outline
- Motivation
- Software Critical Memory (concept)
- Samurai (implementation)
- Experimental results
- Other applications of SCM
- Conclusions and future work
24Benchmarks
- vpr Does place and route on FPGAs from netlist
- Made routing-resource graph critical
- crafty Plays a game of chess with the user
- Made cache of previously-seen board positions
critical - gzip Compress/Decompresses a file
- Made Huffman decoding table critical
- parser Checks syntactic correctness of English
sentences based on a dictionary - Made the dictionary data structures critical
- rayshade Renders a scene file
- Made the list of objects to be rendered critical
25Performance Measurement
- Measured baseline cost without Samurai (T1)
- Instrumented all loads and stores in program
- Phoenix plugin written by Vinod Grover for STM
- Measured cost of checking all loads, stores
- Found fraction of critical loads and stores
- Estimated fraction of checking critical loads and
stores - Measured Samurai overhead by deploying with and
without Samurai
26Results (Performance)
27Execution Characteristics
28Fault Injection Methodology
- Injections into critical data
- Corrupted objects on DieHard heap, one at a time
- Injected more faults into more populated heap
regions (Weighted fault-injection policy) - Outcome success, failure, false-positive
- Injections into non-critical data
- Measure propagation to critical data
- Corrupted results of random store instructions
- Compared memory traces of verified stores
- Outcomes control error, data error, pointer
error
29Fault-Injections into DieHard Heap
Samurai required a heap size of 4MB but recovered
from all faults successfully
30Fault Injection into Critical Data (vpr)
31Fault Injection into Non-Critical Data
32Summary of Samurai
- Implementation of SCM for heap-allocated data
- Robust runtime system for C/C
- Automated Phoenix compiler pass
- Identified critical data for five applications
- Low overheads for most applications (less than
10) - High tolerance for faults in critical data
- Over what is already provided by DieHard
(unreplicated) - Low probability of fault-propagation from
non-critical data to critical data for most
applications - No new assertions or consistency checks added
33Outline
- Motivation
- Software Critical Memory (concept)
- Samurai (implementation)
- Experimental results
- Other applications of SCM
- SCM/STM Integration
- Conclusions and future work
34SCM - Other Applications
- Detecting atomicity violations in concurrent
programs - Prototype implementation with Software
Transactional Memory (STM) - Exploring extension to Locks
- Proving properties of embedded program
- Assertions formulated w.r.p to embedded program
- Do not need to consider rest of program
- String immutability guarantees for security
- Compiler optimizations for performance
35SCM/STM Integration
- STM guarantees mutual exclusion for threads that
follow transaction protocol (Weak atomicity) - What about threads that dont follow the protocol
? - Currently no protection by software
implementations - Relies on static analysis to find such violations
- Main Idea Use SCM to detect accesses to shared
data outside the atomic section (Strong
atomicity) - Mark all shared data as critical
- Treat writes within atomic section as verified
stores - All other writes are unverified and do not affect
the value - Restore values if written outside atomic section
36SCM/STM Integration Example(Original STM program)
- // Total is a shared struct containing a
global int - while (element iter-gtget() )
- localSum element-gtvalue()
- atomic
- tmp Total-gtSum
- Total-gtSum tmp localSum
-
-
37SCM/STM Integration Example(With STM primitives
exposed)
- while ( element iter-gtget() )
- localSum element-gtvalue()
- void Tx TxStart()
- RestartLabel
- try TxRead(Total-gtSum)
- tmp Total-gtSum
- tmp tmp localSum
- TxWrite(Total-gtSum)
- TxCommit()
-
- catch (TxError errorCode)
- TxRollback(errorCode, Tx)
- goto RestartLabel
-
-
38SCM/STM Integration Example(with SCM and STM
primitives)
- while ( element iter-gtget() )
- localSum element-gtvalue()
- void Tx TxStart()
- RestartLabel
- try
- verified_load(Total-gtSum)
- TxRead(Total-gtSum)
- tmp Total-gtSum
- tmp tmp localSum
- TxWrite(Total-gtSum)
- verified_store(Total-gtSum, tmp)
- TxCommit()
-
- catch (TxError errorCode)
- TxRollback(errorCode, Tx)
- goto RestartLabel
-
-
39SCM/STM Performance Results
40SCM/STM Fault-Injection Results
41Related Work
- Address-Space Protection
- Virtual memory, Mondrian Memory Protection
- Kernel extensions SPIN, Vino, Software Fault
Isolation - STM Herlihy, Harris, Adl-Tabatabi
- Strong atomicity for Java programs Hindman,
Grossman - Memory Safety
- C-Cured, Cyclone, Jones-Kelley, CRED,
Dhurjati-Adve - Singularity approach, Pittsfield
- Error-Tolerance
- Rx, Failure-oblivious computing, Diehard
- N-version programming, Recovery Blocks
- Rio File Cache, Application-specific recovery
42Conclusions and Future Work
- SCM memory model
- New way of thinking about memory
- Allows selective protection of application data
- Memory safety for C/C programs
- Samurai for heap-allocated data
- Can be combined with STM / locks for detecting
concurrency violations - Applications to security, performance
optimizations etc. (future work)
43Tech Reports and Thanks
- Tech Reports
- Software Critical Memory All memory is not
created equal (in submission) - Samurai Protecting critical heap data for
unsafe languages (in submission) - Thanks
- Emery Berger, Mike Hicks, Pramod Joisha and Shaz
Quadeer