350 likes | 481 Views
Temporal-Safety Proofs for Systems Code. Thomas A. Henzinger Ranjit Jhala Rupak Majumdar George Necula Westley Weimer Grégoire Sutre UC Berkeley. Reliability & Trust. Reliability (verification): Check that the system is “bug free” Low level systems code
E N D
Temporal-Safety Proofs for Systems Code Thomas A. Henzinger Ranjit Jhala Rupak Majumdar George Necula Westley Weimer Grégoire Sutre UC Berkeley
Reliability & Trust • Reliability (verification): • Check that the system is “bug free” • Low level systems code • Locking disciplines, interface specs, … • Temporal, path-sensitive properties • Model checking • Trust (certification): • Questionable code written by third parties: • device drivers, mobile code • Model checkers are buggy (!) • Simply, efficiently checkable • avoid redoing verification
Our Work • Verification: making model checking scale • Lazy Abstraction [POPL ’02] • Certification: • Proof carrying code based mechanism • PCC requires annotations • Lazy Abstraction: • Automatically generates annotations • Provides a small decomposition of the proof • BLAST • Verifying/certifying device drivers
Abstraction Seed Abstraction Program NO YES (Trace) SAFE Feasible Explanation BUG ??? Verification: Abstraction-Refinement Abstract Is model unsafe ? Check Refine Why infeasible ? Infeasible [Kurshan et al, Clarke et al, SLAM,...]
Init ERROR STATES Model Checking & Abstraction • Partition the state space • Existentially lift transition relation
Model Checking & Abstraction • Problem: Abstraction too coarse • Solution: Refine abstraction Init ERROR STATES
Model Checking & Abstraction • Problem: Abstraction too coarse • Solution: Refine abstraction Init ERROR STATES
Reachable States Abstract Only Where Required • Abstraction is very expensive • Why abstract regions that are never visited ? • On-the-fly abstraction: driven by the search Init ERROR STATES
Refine Only Where Required • Why be precise everywhere ? • Don’t refine error-free regions Init ERROR STATES ERROR FREE
Refine Only Where Required • Why be precise everywhere ? • Don’t refine error-free regions • Different precision for different regions • Local Refinement : driven by the search Init ERROR STATES ERROR FREE
Benefits of Lazy Abstraction • Abstract only where required • Reachable state space maybe very sparse • Construct the abstraction on-the-fly • Use greater precision only where required • Different precisions/abstractions for different regions • Refine locally • Reuse work from earlier phases • Batch-oriented ) lose work from previous runs • Integrate the three phases
lock() unlock() unlock() lock() Example Example ( ) { 1: do { lock(); old = new; 2: if (*) { 3: unlock(); new ++; } 4: } while ( new != old); 5: unlock (); return; } Q: Is Error Reachable ?
1 [>] 2 [>] [new!=old] 3 unlock() new++ 4 [new==old] 5 unlock() ret Example:CFA lock(); old = new Example ( ) { 1: do { lock(); old = new; 2: if (*) { 3: unlock(); new ++; } 4: } while ( new != old); 5: unlock (); return; }
1 lock() 2 3 4 5 unlock() unlock() lock() ret Example:CFA Example ( ) { 1: do { lock(); old = new; 2: if (*) { 3: unlock(); new ++; } 4: } while ( new != old); 5: unlock (); return; } Q: Is Error Reachable ?
1 lock(); old = new 2 [>] [new!=old] [>] unlock() new++ 2 LOCK=1 [new==old] unlock() new++ 3 5 3 LOCK=1 unlock() 4 [new==old] 4 LOCK=0 5 LOCK=0 ret Err LOCK=0 Step 1: Search 1 LOCK=0 lock(); old = new [>] unlock() Set of predicates: LOCK=0, LOCK=1
1 LOCK=0 2 LOCK=1 3 LOCK=1 Err States that can = PRE( ,ops) 4 LOCK=0 Err RnÆPRE( ,ops) = Æ? 5 LOCK=0 ops n Err Step 2:Analyze Counterexample Q: When can: States at node n = Rn Err LOCK=0
1 lock(); old = new 2 1 LOCK=0 Ænew+1 = new LOCK=0 [>] [new!=old] [>] unlock() new++ LOCK=1 Æ new+1 = old 2 LOCK=1 [>] [new==old] 3 5 LOCK=1 Æ new +1 = old 3 LOCK=1 unlock(); new++ unlock() 4 4 LOCK=0 Err RnÆPRE( ,ops) = Æ? 5 LOCK=0 ret Err LOCK=0 Step 2:Analyze Counterexample lock(); old = new LOCK=0 Æ new = old [new==old] LOCK=0 unlock()
1 lock(); old = new 2 1 LOCK=0 [>] [new!=old] [>] unlock() new++ 2 LOCK=1 [new==old] 3 5 3 LOCK=1 unlock() 4 4 LOCK=0 5 LOCK=0 ret Err LOCK=0 Step 2:Analyze Counterexample LOCK=0 Ænew+1 = new LOCK=1 Æ new+1 = old LOCK=1 Æ new +1 = old LOCK=0 Æ new = old LOCK=0 Track the predicate: new = old LOCK=0
1 lock(); old = new 2 1 LOCK=0 [>] [new!=old] [>] unlock() new++ 2 LOCK=1 Æ new = old [new==old] [>] 3 5 3 LOCK=1 Æ new = old unlock() new++ unlock() 4 4 LOCK=0 Æ: new = old 5 1 ? LOCK=0 Æ: new = old µ LOCK =0 ret Step 3: Resume Search lock(); old = new [new!=old] [new==old] Set of predicates: LOCK=0, LOCK=1, new = old
1 lock(); old = new 2 1 LOCK=0 [>] ERROR Unreachable [new!=old] [>] 2 unlock() new++ LOCK=1 Æ new = old [new==old] 3 5 3 LOCK=1 Æ new = old unlock() 4 LOCK=1 Æ new=old 4 4 LOCK=0 Æ: new = old 5 1 ? 5 1 ? ret ret LOCK=0Æ new=old Step 3: Resume Search Set of predicates: LOCK=0, LOCK=1, new = old LOCK=0 Æ: new = old
1 LOCK=0 Ænew+1 = new LOCK=0 lock(); old = new 2 LOCK=1 [>] unlock(); new++ 3 LOCK=1 [new==old] 4 LOCK=0 unlock() 5 LOCK=0 Err LOCK=0 Predicate Discovery • Information lost in substitution • Keep substitutions explicit • Ask a proof of unsatisfiability • Pick predicates appearing in proof
0 1 6 2 7 3 8 4 9 10 5 11 ret Local Refinement Example ( ) { 0: if (*) { 6: do { got_lock = 0; 7: if (*) { 8: lock(); got_lock ++; } 9: if (got_lock) { 10: unlock(); } 11: } while (*) ; } 1: do { lock(); old = new; 2: if (*) { 3: unlock(); new ++; } 4: } while ( new != old); 5: unlock (); return; } 6: do { got_lock = 0; 7: if (*) { 8: lock(); got_lock ++; } 9: if (got_lock) { 10: unlock(); } 11: } while (*) ; } 1: do { lock(); old = new; 2: if (*) { 3: unlock(); new ++; } 4: } while ( new != old); 5: unlock (); return; }
0 0 LOCK=0 6 [>] [>] 1 7 1 LOCK=0 6 2 LOCK=0 8 9 3 10 4 11 5 ret Err Local Refinement Search on left subtree not repeated Different abstractions for subtrees Refine right subtree only
0 LOCK=0 6 1 7 1 6 2 LOCK=0 LOCK=0 8 9 3 10 4 11 5 ret 1 1 1 Leaves Covered (Reuse work) 0 Leaves covered: Avoid repeating search when paths merge LOCK=0 Æ … COVERED !
VC Generator Program + Spec Annotations Verification Condition What is a Certificate ? • Proof Carrying Code (PCC) • Annotations: • Loop invariants, func. Precondition/Postcondition Validity of VC guarantees correctness Certificate: Annotations + Proof of VC Consumer reconstructs VC, checks proof
Annotations & VCs Annotations • For each cntrl location q, invariantI(q) Verification condition • Init µI(q0) Start set includes initial states Error location is not reached I(qe) = false For each edge q !op q’: POST(I(q),op) µI(q’) States closed under post
1 LOCK=0 2 LOCK=1 Æ new = old covered 2 LOCK=1 Æ new = old 3 LOCK=1 Æ new = old 3 LOCK=1 Æ new = old LOCK=1 Æ new=old 4 4 LOCK=0 Æ: new = old 5 1 ? LOCK=0 Æ: new = old ret 5 1 LOCK=0 Æ new=old ? Reachability Tree Invariants grow on Trees 1 LOCK=0 Ç LOCK=0 Æ: new = old LOCK=0 Æ: new = old 4 Ç LOCK=1 Æ new=old 5 LOCK=1 Æ new=old Invariants
Proving the VC • Each condition dischargeable automatically (Vampyre, CVC …) • Tree yields a small decomposition • Entire proof can be extracted from model checker’s data structures
CIL (C ! CFA) REGION STRUCTURE Vampyre (focus) Simplify (Post#) BDD Engine (Boolean ops) BLAST • Berkeley Lazy Abstraction Software verification Tool • 10K Lines of Ocaml • Analyze Linux/Windows Device Drivers LAZY ABSTRACTION
BLAST • All of C modeled except: • Function pointers • Recursive functions • “Logical” Model of memory • Pointer arithmetic imprecise • Fragile on heap dependant properties • Safety checking: • Checks if a given label is reachable in the C program • Monitor automata specified in C
Experiments Program Lines Total Preds Active Preds Total Time(sec) Prf Size (bytes) Pred. Disc. Time(sec) ide.c 18131 5 5 4.5 0.01 253 Linux Lock 3 state qpmouse.c 23539 2 2 0.5 0.01 179 aha152x.c 17736 2 2 20.93 0.03 tlan.c 16506 5 4 428.63 403.33 cdaudio.c 17798 85 45 1398 540 156787 floppy.c 17386 62 37 2086 1565 [fixed] 93 44 395 17 60129 kbflter.c 12131 54 40 64 5 Windows DDK IRP 22 state 48 35 256 165 [fixed] 37 34 10 0.38 7619 mouclass.c 17372 57 46 54 3.34 parport.c 61781 193 50 1980 519 102967
Conclusions • Lazy Abstraction • Reachability Tree yields certificate • Implemented BLAST • Finds (only) real bugs in large device drivers • … and gives proofs for correct ones ! • Future work: • Smarter abstractions • Program analysis for model reduction • Recursive functions • …
BLAST Berkeley Lazy Abstraction Software * Tool www.eecs.berkeley.edu/~tah/blast/