Runtime Monitoring of C Programs for Security and Correctness

Slides:



Advertisements
Similar presentations
Automatic Memory Management Noam Rinetzky Schreiber 123A /seminar/seminar1415a.html.
Advertisements

Lecture 16 Buffer Overflow modified from slides of Lawrie Brown.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
A Practical Dynamic Buffer Overflow Detector (CRED) Olatunji Ruwase Monica S. Lam Transmeta Corp. Stanford University Network and Distributed Security.
SAFECode SAFECode: Enforcing Alias Analysis for Weakly Typed Languages Dinakar Dhurjati University of Illinois at Urbana-Champaign Joint work with Sumant.
Introduction The Approach ’ s Overview A Language of Pointers The Type System Operational Semantics Type Safety Type Inference The Rest of C Experiments.
Securing software by enforcing data-flow integrity Manuel Costa Joint work with: Miguel Castro, Tim Harris Microsoft Research Cambridge University of Cambridge.
LIFT: A Low-Overhead Practical Information Flow Tracking System for Detecting Security Attacks Feng Qin, Cheng Wang, Zhenmin Li, Ho-seop Kim, Yuanyuan.
HARDBOUND: ARCHITECURAL SUPPORT FOR SPATIAL SAFETY OF THE C PROGRAMMING LANGUAGE Kyle Yan Yu Xing 2014/10/15.
May 9, 2001OSQ Retreat 1 Run-Time Type Checking for Pointers and Arrays in C Wes Weimer, George Necula Scott McPeak, S.P. Rahul, Raymond To.
Pointers Applications
MemTracker Efficient and Programmable Support for Memory Access Monitoring and Debugging Guru Venkataramani, Brandyn Roemer, Yan Solihin, Milos Prvulovic.
May 22, 2002OSQ Retreat 1 CCured: Taming C Pointers George Necula Scott McPeak Wes Weimer
Checking Memory Safety with BLAST Dirk Beyer, et al. FASE 2005 KAIST CS750b 2006 Fall Seonggun Kim.
Safety in the C programming Language Peter Wihl May 26 th, 2005 CS 297 Security and Programming Languages.
Security Exploiting Overflows. Introduction r See the following link for more info: operating-systems-and-applications-in-
CS 11 C track: lecture 5 Last week: pointers This week: Pointer arithmetic Arrays and pointers Dynamic memory allocation The stack and the heap.
EE4E. C++ Programming Lecture 1 From C to C++. Contents Introduction Introduction Variables Variables Pointers and references Pointers and references.
Types for Programs and Proofs Lecture 1. What are types? int, float, char, …, arrays types of procedures, functions, references, records, objects,...
Presentation of Failure- Oblivious Computing vs. Rx OS Seminar, winter 2005 by Lauge Wullf and Jacob Munk-Stander January 4 th, 2006.
Dynamic Memory Allocation Conventional array and other data declarations An incorrect attempt to size memory dynamically Requirement for dynamic allocation.
Computer Science Detecting Memory Access Errors via Illegal Write Monitoring Ongoing Research by Emre Can Sezer.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
1 Records Record aggregate of data elements –Possibly heterogeneous –Elements/slots are identified by names –Elements in same fixed order in all records.
C Programming Day 4. 2 Copyright © 2005, Infosys Technologies Ltd ER/CORP/CRS/LA07/003 Version No. 1.0 More on Pointers Constant Pointers Two ways to.
Buffer Overflow Proofing of Code Binaries By Ramya Reguramalingam Graduate Student, Computer Science Advisor: Dr. Gopal Gupta.
Highly Scalable Distributed Dataflow Analysis Joseph L. Greathouse Advanced Computer Architecture Laboratory University of Michigan Chelsea LeBlancTodd.
An Undergraduate Course on Software Bug Detection Tools and Techniques Eric Larson Seattle University March 3, 2006.
A Tool for Pro-active Defense Against the Buffer Overrun Attack D. Bruschi, E. Rosti, R. Banfi Presented By: Warshavsky Alex.
Protecting C Programs from Attacks via Invalid Pointer Dereferences Suan Hsi Yong, Susan Horwitz University of Wisconsin – Madison.
Debugging via Run-Time Type Checking Title Page Alexey Loginov, Suan Yong, Susan Horwitz, Thomas Reps University of Wisconsin - Madison.
1 Lecture07: Memory Model 5/2/2012 Slides modified from Yin Lou, Cornell CS2022: Introduction to C.
How to execute Program structure Variables name, keywords, binding, scope, lifetime Data types – type system – primitives, strings, arrays, hashes – pointers/references.
Sampling Dynamic Dataflow Analyses Joseph L. Greathouse Advanced Computer Architecture Laboratory University of Michigan University of British Columbia.
VM: Chapter 7 Buffer Overflows. csci5233 computer security & integrity (VM: Ch. 7) 2 Outline Impact of buffer overflows What is a buffer overflow? Types.
Chapter 10 Buffer Overflow 1. A very common attack mechanism o First used by the Morris Worm in 1988 Still of major concern o Legacy of buggy code in.
Language-Based Security: Overview of Types Deepak Garg Foundations of Security and Privacy October 27, 2009.
Overview Working directly with memory locations is beneficial. In C, pointers allow you to: change values passed as arguments to functions work directly.
Memory-Related Perils and Pitfalls in C
Optimistic Hybrid Analysis
Dynamic Allocation in C
Secure Coding Rules for C++ Copyright © 2016 Curt Hill
Content Coverity Static Analysis Use cases of Coverity Examples
Object Lifetime and Pointers
Dynamic Storage Allocation
CMSC 341 Lecture 2 – Dynamic Memory and Pointers (Review)
CMSC 345 Defensive Programming Practices from Software Engineering 6th Edition by Ian Sommerville.
Data Watch Presenter Information Jason Puncher and François Tétreault
Chapter 6 – Data Types CSCE 343.
Unusual Data Types CSC-3004 Introduction to Software Development
Debugging Memory Issues
Types for Programs and Proofs
CSE 3302 Programming Languages
Context-Sensitive Analysis
Type Checking, and Scopes
Seminar in automatic tools for analyzing programs with dynamic memory
Checking Memory Management
CSCI206 - Computer Organization & Programming
Clear1 and Clear2 clear1(int array[], int size) { int i; for (i = 0; i < size; i += 1) array[i] = 0; } clear2(int *array, int size) {
High Coverage Detection of Input-Related Security Faults
CS 465 Buffer Overflow Slides by Kent Seamons and Tim van der Horst
Pointers.
Covering CWE with Programming Languages and Tools
Code-Pointer Integrity
Introduction to Static Analyzer
CETS: Compiler-Enforced Temporal Safety for C
Course Overview PART I: overview material PART II: inside a compiler
Suan Hsi Yong University of Wisconsin – Madison
SPL – PS2 C++ Memory Handling.
CSE 3302 Programming Languages
Presentation transcript:

Runtime Monitoring of C Programs for Security and Correctness Suan Hsi Yong University of Wisconsin – Madison Ph.D. Committee: Susan Horwitz (advisor), Thomas Reps, Charles Fischer, Somesh Jha, James Smith

Errors in Software Software errors are undesirable may produce incorrect results may crash system may corrupt data may be vulnerable to attack Software errors are difficult to detect may be infrequently exercised may not noticeably alter observable output

Memory and Type Safety Memory safety: each dereference can only access ‘intended target’ spatial access errors (e.g., out-of-bounds array access) temporal access errors (e.g., stale pointer dereference) Type safety: operations can only be applied to values of certain types

Memory and Type Safety Useful for improving quality of software Tradeoff between efficiency and flexibility If too general, incurs a high runtime overhead to enforce If too restrictive, limits expressiveness and utility of language C language mandates but does not enforce memory and type safety programmer’s responsibility, error prone

Approaches for Finding Errors Static Approaches imprecise, not scalable Dynamic Approaches incomplete coverage, high runtime overhead This thesis: Dynamic approach, but use static analysis to improve overhead for testing/debugging, and for use in deployed software

This Thesis Explores… Runtime checking of memory and type safety in C programs Three manifestations Memory-Safety Enforcer (MSE): detects invalid dereferences Sensitive Location Checker (SLC): detects invalid writes to security-sensitive locations Runtime Type Checker (RTC): detects bugs manifested as type errors

Common Features Tagged memory Source-level instrumentation each byte of memory is tagged at runtime with information used to detect errors Source-level instrumentation approach is portable, compatible with uninstrumented libraries Static analysis identifies and eliminates unnecessary instrumentation

Architecture C source file runtime system/ libraries instru- mented C source file Instrumenter classifications Static Analysis C Compiler instru- mented exec- utable

Outline Introduction Memory-Safety Enforcer (MSE) Sensitive-Location Checker (SLC) Runtime Type Checker (RTC) Related Work Conclusion

Memory Safety p = &a p’s valid target is a *(p+i) valid only if it accesses a Spatial access error: out of bounds e.g., if i is negative or is too large Temporal access error: stale pointer e.g., if a had been freed prior to *(p+i)

Memory Safety Enforcer (MSE) Debugging Tool invalid access  programming error e.g., buffer overrun, stale pointer dereference Security Tool most attacks require invalid write to succeed (e.g., stack smashing attacks) halt execution when violation detected

Control Transfer Attacks Idea: overwrite sensitive location with address of malicious code Sensitive locations include return address (stack smashing) global offset table function pointers longjmp buffer exec call argument others…

Stack Smashing char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); p buf return address

Detecting Invalid Access Fat Pointer Record information about what each pointer should point to Safe-C, CCured, Cyclone Tagged Memory (our approach) Record information about which locations may be valid targets of some pointer dereference also used by Purify

Fat Pointers associate information with pointer:   address and size of referent p buf 12 char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’);  buf  return address

Tagged Memory associates information with target rather than pointer    Tagged Memory associates information with target rather than pointer p char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’);  buf  return address  = valid target of unsafe dereference

Fat Pointer vs. Tagged Memory Fat Pointers Guaranteed to catch all spatial errors Difficult to catch temporal errors efficiently e.g., CCured uses garbage collection Tagged Memory Can detect both spatial and temporal errors efficiently Guaranteed only to catch invalid accesses to non-user memory But can improve with static analysis

Improving MSE Which dereferences to check? if static analysis can guarantee that *p is always valid, then *p need not be instrumented. classify dereferences into checked/unchecked Which locations to tag valid at runtime? if x can only be accessed directly or via unchecked dereference, then x need not be tagged valid classify locations into tracked/untracked

Checked Derefs/Tracked Locs  Checked Derefs/Tracked Locs naively: all dereferences are checked; all user-defined locations are tracked char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’);  p    buf   return address

Checked Derefs/Tracked Locs  Checked Derefs/Tracked Locs FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)();  p   buf   fp  Static Analysis: identify fewer checked derefs and tracked locations

Checked Dereferences Writes Only vs. Read/Write write-only checks catches most attacks; significantly improving overhead Flow-insensitive analysis: *p is checked if: p is assigned a non-pointer value, or p is the result of pointer arithmetic, or p may point to stack or freed heap location a[i]  *(a+i)

Example: Checked Dereferences FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); dereferences: *p checked *fp unchecked

Tracked Locations locations that may be validly accessed via checked dereference fewer tracked locations means better performance and coverage less overhead to mark and clear valid tag increase likelihood of catching invalid access identify with points-to analysis [Das’00] for each checked dereference *p, all locations in p’s points-to set are tracked

Example: Tracked Locations FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p buf fp locations: untracked tracked p buf points-to graph: foo fp dereferences: *p unsafe *fp safe

Example: Tracked Locations  Example: Tracked Locations FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)();  p  buf    fp p buf fp locations: untracked tracked p buf points-to graph: foo fp dereferences: *p unsafe *fp safe 

Summary of MSE Coverage Attack target MSE Unoptimized MSE + Static Analysis Return address yes Function pointer no likely exec argument maybe

Evaluation: Runtime Overhead

Flow-Sensitive Analyses Redundant Checks Analysis *(p+i) = ...; *(p+i) = ...; //- don’t instrument Pointer Range Analysis track range of possible values for each pointer *p = ...; p  a:char[10], [3,7] if *p is definitely in-bounds, don’t instrument

Flow-Sensitive Analyses remind ppl: lower is better

Flow-Sensitive Analyses

Analysis Time Slowdown

MSE Static Analysis Summary Unoptimized MSE high runtime overhead only catches invalid access to non-user memory Flow-insensitive (Extended Points-To Analysis) low runtime overhead, scalable analysis Flow-sensitive Analyses 20% improvement, but analysis not scalable Write-only faster than read-write checking

Comparison with Other Tools (runtime overhead)

Summary of MSE Tool for detecting invalid pointer dereferences that has low runtime overhead does not report false positives is portable, and does not require programmer changes to source code protects against a wide range of vulnerabilities, including stack smashing and erroneous free

Outline Introduction Memory-Safety Enforcer (MSE) Sensitive-Location Checker (SLC) Runtime Type Checker (RTC) Related Work Conclusion

Two Approaches to Security MSE: Try to detect all invalid accesses including invalid accesses that are not vulnerable to attack SLC: Detect only invalid accesses to sensitive locations return address, function pointers, longjmp buffers, exec call arguments related work: StackGuard – protects only return address on the activation record

SLC vs MSE: classification identify unsafe dereferences, then compute tracked locations dereferences locations w *p x *q y *r z (points-to edges)

SLC vs MSE: classification identify sensitive locations, then compute unchecked dereferences dereferences locations w *p x *q y *r z (points-to edges)

Example char safe_buf[8]; char vuln_buf[8]; strcpy(vuln_buf, “ls”);   char safe_buf[8]; char vuln_buf[8]; strcpy(vuln_buf, “ls”); gets(safe_buf); system(vuln_buf); not sensitive safe _buf sensitive unchecked vuln _buf checked use same color blocks as previous… return address 

SLC vs MSE: instrumentation SLC must set/clear tag of sensitive locations, while MSE must set/clear tag of tracked locations In general, much fewer sensitive locations that tracked locations, so SLC is faster SLC must set/clear tag of return address on activation record may slow down SLC compared to MSE

Runtime Overhead: SLC vs MSE Average: SLC=37.7%, MSE=54.1%

SLC: The Bad News In some of the benchmarks (ijpeg, li, perl, gap), over 90% of the dereferences were not checked i.e., they may point to a sensitive location due to imprecision of points-to analysis could be improved with better points-to analysis Good news: can tell from static analysis whether SLC will be effective for a given program

SLC vs MSE Memory Safety Enforcer (MSE) detects invalid accesses that may not be vulnerable to attack may prevent new as-yet-undiscovered methods of attack Sensitive Location Checker (SLC) targets specific locations known (a priori) to be vulnerable to attack better runtime overhead because of limited scope

Outline Introduction Memory-Safety Enforcer (MSE) Sensitive-Location Checker (SLC) Runtime Type Checker (RTC) Related Work Conclusion

Runtime Type Checking Idea is to detect runtime type violations value of one type is used in context of incompatible type Scalar types only (structs and arrays broken down into components) Debugging tool, for use during development/testing Higher overhead acceptable (~20x) Related tools: Purify, Insure++, Valgrind

Error Example 1: Union union U { int u1; int *u2; } u; int *p; u.u1 = 20; // write int into u.u1 p = u.u2; // copy int from u.u2 -- suspicious! *p = 0; // bad pointer deref -- error!

Example 2: Bad Pointer Access int *intArray = (int *) malloc(15 * sizeof(int)); int **ptrArray = (int **) malloc(15 * sizeof(int *)); User memory intArray ptrArray

Example 2: Bad Pointer Access int *i, sumEven = 0; for(i = intArray; ...; i += 2) sumEven += *i; i User memory intArray ptrArray ORIGINAL i intArray ptrArray padding PURIFY User memory

Example 3: Custom Allocator char * myMalloc(size_t size) { static char *myMemory, *current; ... if(first_time){ myMemory = (char *) malloc(BLKSIZE); } return &myMemory[current += size];

Example 3: Custom Allocator int *intArray = (int *) myMalloc(10 * sizeof(int)); int **ptrArray = (int **) myMalloc(10 * sizeof(int *)); i User memory intArray ptrArray ORIGINAL myMemory i User memory myMemory PURIFY

Example 4: Simulated Inheritance struct Base { int a1; int a2; } base; struct Sub { int b1; int b2; char b3; } sub; : f(&base); f(&sub); void f(struct Base *s) { s->a1 = ... s->a2 = ... }

Example 4: Simulated Inheritance struct Base { int a1; int a2; } base; struct Sub { int b1; float f1; int b2; char b3; } sub; : f(&base); f(&sub); void f(struct Base *s) { s->a1 = ... s->a2 = ... }

Runtime Type-Checking Track type of values in memory store in mirror of memory: 4 bits for each byte unalloc, uninit, integral, real, pointer, zero Warning when type of value assigned does not match expected type Error when bad runtime type is used

Runtime Type Checking Tool (memory) (mirror) k . . . unalloc f p int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k );

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit f . . . unalloc p . . . unalloc instrument a declaration

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit f . . . unalloc uninit p . . . unalloc instrument a declaration

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit f . . . unalloc 2.3 float uninit p . . . unalloc uninit instrument an assignment

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit f . . . unalloc 2.3 float uninit p . . . unalloc ( &f ) uninit pointer instrument an assignment

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit f . . . unalloc 2.3 OK float uninit p . . . unalloc ( &f ) pointer uninit instrument a use (of a pointer)

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc uninit OK f . . . unalloc 2.3 float uninit p . . . unalloc ( &f ) pointer uninit instrument a pointer dereference

Runtime Type Checking Tool (memory) (mirror) int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); warning! k . . . unalloc 2.3 float uninit f . . . unalloc 2.3 float uninit p . . . unalloc ( &f ) uninit pointer instrument an assignment

Runtime Type Checking Tool (memory) (mirror) error! int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); k . . . unalloc 2.3 uninit float f . . . unalloc 2.3 float uninit p . . . unalloc ( &f ) uninit pointer instrument a use (of an int)

Runtime Type Checking Found errors in SPEC 95, SPEC 2000, and Solaris utilities But, overhead is high 4x-170x slowdown, average 43.5x Use Static Analysis Flow insensitive: Type Flow Analysis Flow sensitive: redundant checks, may-be-uninitialized

Type Flow Analysis Classify lvalue expressions into: safe: runtime type always equals static type no instrumentation needed type-unsafe: always in-bounds, but runtime type may not equal static type must be instrumented to check runtime type mem-unsafe: may violate memory safety must be fully instrumented (including check that dereference does not access unalloc memory) maybe use examples to illustrate each classification

Type Flow Analysis Classify locations into: untracked: runtime type always equals static type no instrumentation needed tracked: runtime type always equals static type, but may be accessed by unsafe dereference initialize mirror to static type, but type doesn’t change unsafe: may cause type-safety error at runtime initialize mirror to uninit; type may change at runtime

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations >

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute points-to set for each pointer Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations pt p {f}

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations x x 5.0 VALUEfloat VALUEinit &i VALUEvalid-ptr int nodes

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations *p *p y+z VALUEint p+i VALUEptr &i VALUEvalid-ptr nodes

Type-Flow Analysis Points-to Analysis Build Assignment Graph x = y; Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations x y = *p = 5.0; VALUEfloat = *p x = y + z; VALUEint = x edges

Type-Flow Analysis Points-to Analysis Build Assignment Graph T = “uninitialized” Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations valid-ptr init pointer int char float …  |  = “multiply-typed”

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations float VALUEfloat T(x)  T(y) T(y) x y =

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations T(*p)  T(k) {k} p pt *p y = *p {k} p pt k T(k)  T(y)

} Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations poss-type(x)  static-type(x)  x type-unsafe int k; float f = 2.3; int *p = &f; k = *p; } poss-type(k) = float k type-unsafe static-type(k) = int

} Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations poss-type(x)  static-type(x)  x type-unsafe int k; float f = 2.3; int *p = &f; k = *p; } poss-type(*p) = float *p type-unsafe static-type(*p) = int

Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations 2. poss-type(p) ≠ valid-ptr  *p mem-unsafe int *p = &k; p = p + 1; *p = 5;  *p mem-unsafe

} Type-Flow Analysis Points-to Analysis Build Assignment Graph Compute Possible Types Classify Expressions and Locations 3.*p unsafe,  x tracked {x} p pt int k; float f = 2.3; int *p = &f; k = *p; } *p unsafe f tracked p may-point-to f

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); tracked f safe p type-unsafe k type-unsafe *p Instrumentation: w/o using type-flow analysis

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); tracked f safe p type-unsafe k type-unsafe *p Instrumentation: using type-flow analysis

RTC Runtime Overhead

Flow-sensitive Refinements May-be-uninitialized analysis needed to detect uses of uninitialized data analysis and runtime overhead both slow not worthwhile: better to use unoptimized Redundant checks analysis for each use of x, if error is reported, tag of x is corrected to prevent cascading errors y = x + 1; z = x + 2; //check of x is redundant >

RTC Runtime Overhead

Analysis Time

Outline Introduction Memory-Safety Enforcer (MSE) Sensitive-Location Checker (SLC) Runtime Type Checker (RTC) Related Work Conclusion

Related Work Run-time Error Detection Reducing Instrumentation Purify, Insure++, Valgrind Safe C, CCured, Cyclone Safe languages (Java), dynamically-typed languages (Lisp) Reducing Instrumentation Java (remove array-bounds checks) Lisp and Scheme (remove tag-handling operations, e.g., Henglein) CCured (remove pointer checks: Necula et al) more detailed slides on, e.g., range analysis

Conclusion Finding errors and vulnerabilities is difficult Three related runtime monitoring approaches Sensitive location checker: efficient, security-oriented Memory-safety enforcer: efficient, security or debugging Runtime type-checker: slow, for debugging Effective in detecting errors Static analysis to improve runtime overhead Flow-insensitive: scalable, significant improvements Flow-sensitive: modest improvements, not scalable

Future Work Better static analysis: fewer unsafe and tracked locations escape analysis / scope analysis better points-to analysis Different mechanism for tagging e.g. hash lookup Apply ideas to other languages and environments e.g. absorb overhead on multiprocessor

Runtime Monitoring of C Programs for Security and Correctness END Suan Hsi Yong University of Wisconsin – Madison Ph.D. Committee: Susan Horwitz (advisor), Thomas Reps, Charles Fischer, Somesh Jha, James Smith

Index Start / Mem & Type Safety / Architecture MSE / Ctl-xfer Attack / Fat Pointers / Classification / Flow-sensitive / Results SLC / Example / Results RTC / Union / MyMalloc / Inheritance / Example / Type-Flow / Results Related / Conclusion / Future MSE example / CCured wild / Type-Flow example / MBU

Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0];  Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0];  Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0];  Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)();  buf  fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0];  Example: Allocation FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p  buf  fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Checking Writes  Example: Checking Writes FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p   buf  fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Checking Writes  Example: Checking Writes FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p  buf  fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Checking Writes  Example: Checking Writes FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)(); p  buf   fp p buf fp locations: untracked tracked pointers: unsafe safe p fp

Example: Checking Writes  Example: Checking Writes FN_PTR fp = &foo; char buf[12]; char *p = &buf[0]; do { *p = getchar(); } while(*p++ != ‘\0’); (*fp)();  p  buf   fp p buf fp locations: untracked tracked pointers: unsafe safe p fp 

Back

} CCured WILD Pointers int i; int *p; int *q1, *q2; q1 = i; q1 = (int)&p; q2 = &i; } q1 WILD => q2 WILD

Back

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); {f} p pt 1. Points-to analysis

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); VALUEfloat f = VALUEvalid-ptr p = *p k = {f} p pt 2. Assignment graph

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); float float VALUEfloat f = valid-ptr valid-ptr VALUEvalid-ptr p = float float *p k = T(*p)  T(f) {f} p pt 3. Runtime types

Type-Flow Analysis: Example int k; float f; int *p; f = 2.3; p = (int *)&f; k = *p; print_int( k ); float tracked f valid-ptr safe p float type-unsafe k float type-unsafe *p {f} p pt 4. Type-safety levels

Back

May-be-uninitialized Analysis

May-be-uninitialized Analysis

May-be-uninitialized Analysis

Back