static verification of memory safety for device drivers scott mcpeak george necula uc berkeley osq...

31
Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Post on 20-Dec-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Static Verification of Memory Safety for Device Drivers

Scott McPeak George Necula

UC Berkeley

OSQ Retreat, 5/15/03

Page 2: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Goal: Eliminate Low-level Bugs

• What properties?– Memory safety, including dangling references– Calling order restrictions (open/read, locks)

• Why?– Implicit spec– Shallow correctness proofs– Difficult to test and debug– Deallocation: an interesting heap assertion

Page 3: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Why Annotate?

• Exploit programmer knowledge– The information is there. Issue is convenience.

• Record design decisions– Would you program w/o typing declarations?

• Matter of cost/benefit– Annotation only needs to be more efficient than

testing and debugging (for these kinds of bugs)

Page 4: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Why is verification hard?

• Constructing models of the code– Choice of abstraction is very important

• Proving true predicates– Automatic vs. interactive theorem provers

• Knowing how to describe the program's heap invariants– Hard concepts: reachability, lack of sharing,

topmost in some set, acyclic, ...

Page 5: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Automatic Modeling

• Translate C into a language without pointers– Simulate them with sequences, etc.

• Example: uniform semantic modelM: int ! int[x = e] = x := [e][*p] = sel(M, p)[*p = e] = M := upd(M, p, [e])

Page 6: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Custom Semantic Models

• User provides the mapping from C as a set of pattern rules

• Can supply multiple mappings for the same syntax; choose by: type, name, module, etc.

• Can map from languages other than C

• Bridges gap between hand-constructed models and the real code

Page 7: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Example Models

• Java-like model [p!x] = sel(Foo_x, p) [p!x = e] = Foo_x := upd(Foo_x, p, [e])

• Functional model [cons(x,y)] = cons([x], [y]) [cdr(p)] = cdr([p])

class Foo { int x; int y;};

Page 8: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Integers

• 1. Simplify/simplex: rationals with integer heuristics– Practical, but unsound upon overflow

• 2. Same, but add no-overflow assertions– Sound, but perhaps little gain for effort

• 3. Integers with arithmetic mod 232

– For specialized circumstances

Page 9: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Semantic Model Soundness

• semantics: program ! abort / not abort– defines a language of non-aborting programs

• Need a trusted model, e.g. uniform semantics derived from C99 standard

• Custom model: uses higher-level concepts

• Soundness: custom µ trusted

Page 10: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Proving True Predicates

• Automatic theorem provers are incomplete– Our conclusion: not possible to avoid

incompleteness through clever choice of model

• Interactive provers are tedious

• Combination proof system– Try with automatic prover– If it fails, prove with interactive prover– Yield result as a new lemma for automatic

Page 11: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Describing Heap Invariants

• Label every object with a predicate name– At least one name for each type– Names for intermediate states, e.g. initialization– Break recursive invariants

• For every pointer, make a back pointer– Powerful, natural, local– Tree structure: only one back pointer– "Threaded heap"

Page 12: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Example: Threaded Heap

define global_inv() {

forall(Scull_Dev *p).

tag[p] == Scull_Dev_tag

==>

p->next!=NULL ==> p->next->prev == p;

/* ... */

}

Page 13: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Test case: "scull" driver

• An example driver; ~500 lines of C

• Extensive use of the heap, online allocation and deallocation

• Polymorphic use of file.private_data

• Array indices computed with div/mod

• Reactive (state transitions)

Page 14: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

"scull" results

• Verified after two days of work:– Casts, array accesses, deallocations

• Two bugs– Incorrect interpretation of return value– Security hole: read another proc's old data

• As much annotation as code– Already have techniques to eliminate 75% of it

Page 15: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Future Work

• Continued improvement in annotations– Aggregation, data hiding in "changes" clauses– Built-in back pointers– Left half / right half approach to array loops– Type qualifiers to distribute predicates– User-written annotation agents– Split memory into regions– Incorporate other heap shape formalisms

Page 16: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Conclusion

• Reason for optimism in each problem area– modeling: user chooses the abstraction– proving: use interactive and automatic together– describing: predicate labels and back pointers

are a start

• The challenge is not one of technology, but of communication

Page 17: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

(blank)

Page 18: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Vision

• Programmers know why their programs are (supposed to be) correct– Explanation will be in English, however

• Offer a way to conveniently express these reasons, then check them

• Make verification practical!

Page 19: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Our Approach

• Symbolic execution and strongest postcondition, with non-uniform semantics

• Explicit annotation at cutpoints: function boundaries, loop invariants

• Sound

• Linguistic innovation

Page 20: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Example Models

• Java-like model [p!x] = sel(Foo_x, p) [p!x = e] = Foo_x := upd(Foo_x, p, [e])

• Restricted form of interior pointers[y = f(&p!x)] = temp := f(sel(Foo_x, p))

y := first(temp);Foo_x := .. second(..) ..

• Functional model [cons(x,y)] = cons([x], [y])

class Foo { int x; int y;};

Page 21: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Basic Annotations

• Function pre- and postconditions– post can refer to pre-state values, return value

• Loop invariants

• void scribble_fives(int *p, int len) pre(0 < p < objct && 0 <= objsize[p] <= len) post(forall(int i). 0 <= i < len ==> mem[p,i]=5) changes(mem);

Page 22: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Annotation Extensions

• Global invariant: implicit in pre/post

• Automatic invariant strengthening

• Named predicates

• Aggregation, hiding for 'changes' clauses

• Left half / right half notation for arrays

• Predicates associated with type qualifiers

• User-written annotation assistants

Page 23: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Verification of scull

• Linux device driver, implements random-access files backed by RAM; ~500 lines

scull_devices

Page 24: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Allocation

• Key concept: allocation boundary

Mem

Foo_x

tag

0 objct

allocated

Page 25: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Role/Type tags

• tag: Addr ! int

• [p = (Foo *)malloc(sizeof Foo)] = p := objct; objct := objct + 1; tag := tag{objct := Foo_tag}

• C types are effectively first class in model

Page 26: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Role/Type tags

• Data structure invariants:8 p. sel(tag, p)=Scull_Dev_tag )

... p!next ...• Subtyping: sel(tag, p) <: My_Subclass_tag• Type-based disequality• Deallocation

[free(p)] = tag := upd(tag, p, 0)• Initialization

Page 27: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Threaded Heap

• Heap has a central spanning tree

• Invariant: for every tree pointer, the referent object names that pointer– using specification or ghost variables as needed

• Example: 8 p. sel(tag, p)=Scull_Dev_tag ) p!nextNULL ) p!next!prev = p

Page 28: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

scull bugs

• Wrong return code interpretation if (pipe_init() > 0) { /* recover from error */ }

• Leak trusted kernel data p = kmalloc(4000); memcpy(p+i, src, len);

Page 29: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

scull results

init 12 49 12.3 alloc/init top array

cleanup 8 50 9.0 dealloc top array

open 8 83 3.8 set private_data

close 1 4 0.7 file state to closed

read 15 330 18.5 int range checks

write 28 874 50.0 checks + data[] alloc

follow 7 46 6.0 list traversal, alloc

trim 38 461 24.5 dealloc list, data[]s

name paths preds time(s) description

117 1897 125.0

Page 30: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Future Work

• Annotate and verify more examples

• Implement a variety of abstraction mechanisms for annotation language

• Automated assistance for the edit-verify-diagnose cycle

• Prove the lemmas that we give to Simplify

Page 31: Static Verification of Memory Safety for Device Drivers Scott McPeak George Necula UC Berkeley OSQ Retreat, 5/15/03

Conclusion

• It is feasible to verify difficult properties (like lack of dangling refs) in real code

• Annotation burden is merely a symptom of inadequate annotation abstractions

• Prover's incompleteness can be overcome with lemmas proven with a more powerful prover