1 / 35

Temporal-Safety Proofs for Systems Code

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

abril
Download Presentation

Temporal-Safety Proofs for Systems Code

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Temporal-Safety Proofs for Systems Code Thomas A. Henzinger Ranjit Jhala Rupak Majumdar George Necula Westley Weimer Grégoire Sutre UC Berkeley

  2. 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

  3. 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

  4. Verification

  5. 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,...]

  6. Init ERROR STATES Model Checking & Abstraction • Partition the state space • Existentially lift transition relation

  7. Model Checking & Abstraction • Problem: Abstraction too coarse • Solution: Refine abstraction Init ERROR STATES

  8. Model Checking & Abstraction • Problem: Abstraction too coarse • Solution: Refine abstraction Init ERROR STATES

  9. 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

  10. Refine Only Where Required • Why be precise everywhere ? • Don’t refine error-free regions Init ERROR STATES ERROR FREE

  11. 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

  12. 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

  13. 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 ?

  14. 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; }

  15. 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 ?

  16. 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

  17. 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

  18. 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()

  19. 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

  20. 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

  21. 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

  22. 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

  23. 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; }

  24. 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

  25. 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 !

  26. Certification

  27. 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

  28. 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

  29. 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

  30. 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

  31. 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

  32. 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

  33. 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

  34. 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 • …

  35. BLAST Berkeley Lazy Abstraction Software * Tool www.eecs.berkeley.edu/~tah/blast/

More Related