1.4k likes | 1.77k Views
Scalable Software Verification with BLAST Rupak Majumdar U.C. Los Angeles Mars, July 4, 1997 Lost contact due to real-time priority inversion bug Mars, December 3, 1999 Crashed due to uninitialized variable Jul 19, 2001 Code Red: Buffer overrun Estimated cost $2.6 billion
E N D
Scalable Software Verification with BLAST Rupak Majumdar U.C. Los Angeles
Mars, July 4, 1997 Lost contact due to real-time priority inversion bug Mars, December 3, 1999 Crashed due to uninitialized variable
Jul 19, 2001 Code Red: Buffer overrun Estimated cost $2.6 billion
Conclusion Code is buggy! So what’s new? • Reliability is an important issue now! • More computers are used in embedded, safety critical applications • Cost of failure or fixing bug is high • Computers are faster, so reliability is more important in many applications than speed
Something Reliable Uptime: 67 years
Why don’t Bridges Crash ? Abstraction Bridges Programs Building Blocks Logic Mechanics • Relevant facts* • Model • Analysis Mass, Tensile Strength Free Body Diagram Solve Equations ? ? ? * w.r.t. property of interest
Primary Goal Yes BLAST Safe Search CProgram Relevant facts Model Analysis [POPL 02] Refine No Property Property [POPL 04] Trace Lazy Abstraction: Abstract what is needed, nothing more, nothing less
Properties • Goals • defect detection • partial validation • Properties • memory safety • temporal safety • security • … Example Properties: • “Do not lock a spin_lock that has already been locked” • “Do not call system() with root privilege” • “If the IO request is delegated to a lower level driver, return the error status of the lower driver” • “no buffer is accessed beyond its length”
lock unlock unlock lock Property 1: Double Locking “An attempt to re-acquire an acquired lock or release a released lock will cause a deadlock.” Calls to lock and unlock must alternate.
Property 2: Drop Root Privilege [Chen-Dean-Wagner ’02] “User applications must not run with root privilege” When execv is called, must have suid 0
start NP CallDriver SKIP1 SKIP2 return child status Skip CallDriver IPC synch MPR3 NP CallDriver prop completion PPC not pending returned MPR completion Complete request CallDriver MPR1 MPR2 DC return not Pend no prop completion synch CallDriver N/A N/A IRP accessible CallDriver start P SKIP2 Mark Pending SKIP1 Skip CallDriver IPC synch MPR3 NP CallDriver prop completion return Pending PPC not pending returned MPR completion Complete request CallDriver MPR1 MPR2 DC no prop completion CallDriver N/A Property 3 : IRP Handler [Fahndrich]
A data race on x is a state where: Two threads can access x One of the accesses is a write There should be no races on shared variables Property 4: Data Races x:= x+1 x:= x-5 x
Our Goal Specifying and Checking Properties of Programs • Goals • defect detection • partial validation • Properties • memory safety • temporal safety • security • … Many techniques • Testing and code auditing • Automated analysis of software • Program analysis • Symbolic model checking • Theorem proving
Plan • C.G. Abstraction-Refinement • Lazy Abstraction • Sequential Programs • Multithreaded Programs • Demo
The Safety Verification Problem Error Initial Program State Space Q:From Initial states is an Error state Reachable ? Idea 1: Symbolic Analysis (strongest postconditions) Problem: Symbolic Iteration does not terminate
Idea 2: Predicate Abstraction Error Initial • [Graf-Saidi 97] Abstraction Program State Space • Abstraction: Predicates on program state • Signs: x > 0 • Aliasing: &x &y • States satisfying the same preds are equivalent • Merged into single abstract state
Example: Predicate Abstraction For the red region above, the predicate abstraction is the set of “boxes” that cover the red region • Use a decision procedure to compute this blue region For each small box , ask the theorem prover if Æ is satisfiable
Idea 2: Predicate Abstraction Abstract • Search finite state space symbolically • Conservative • Abstraction safe ) System safe • Too coarse )spurious counterexample
Idea 3: Counterexample Analysis Abstract Counterexamples: Analyze counterexamples to check feasibility 1. Feasible )BUG 2. Infeasible ) What predicates distinguish states across cut? 3. Build refined abstraction
Idea 3: Counterex.-Guided Refinement Abstract Refine • [Kurshan et al. 93] • [Clarke et al. 00] • [Ball-Rajamani 01] • Add predicates to rule out spurious trace • Repeat reachability • Till safe or real trace is found
Idea 3: Counterex.-Guided Refinement Abstract safe Refine • [Kurshan et al. 93] • [Clarke et al. 00] • [Ball-Rajamani 01] • Add predicates to rule out spurious trace • Repeat reachability • Till safe or real trace is found
Plan 1. C.G. Abstraction-Refinement 2. Lazy Abstraction • Sequential Programs • Multithreaded Programs 3. Future Work
Scaling Sequential Verification Yes Safe Abstract lazily CProgram Refine No Property Trace
Problem: Abstraction is Expensive Reachable Problem #abstract states = 2#predicates Exponential Thm. Prover queries Observe Fraction of state space reachable #Preds ~ 100’s, #States ~ 2100 , #Reach ~ 1000’s
Solution1: Only Abstract Reachable States Solution Build abstraction on-the-fly, during search Problem #abstract states = 2#predicates Exponential Thm. Prover queries
Solution1: Only Abstract Reachable States Solution Build abstraction on-the-fly, during search Problem #abstract states = 2#predicates Exponential Thm. Prover queries
Solution1: Only Abstract Reachable States Solution Build abstraction on-the-fly, during search Problem #abstract states = 2#predicates Exponential Thm. Prover queries
Solution1: Only Abstract Reachable States Safe Solution Build abstraction on-the-fly, during search Problem #abstract states = 2#predicates Exponential Thm. Prover queries
Solution2: Don’t Refine Error-Free Regions Error Free Solution Don’t refine error-free regions Problem #abstract states = 2#predicates Exponential Thm. Prover queries
Key Idea: Reachability Tree Initial Unroll Abstraction 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 Find min infeasible suffix - Learn new predicates - Rebuild subtree with new preds. 5 4 3
Key Idea: Reachability Tree Initial Unroll Abstraction 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 6 Find min infeasible suffix - Learn new predicates - Rebuild subtree with new preds. 4 7 5 3 3 Error Free
Key Idea: Reachability Tree Initial Unroll 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 6 Find min spurious suffix - Learn new predicates - Rebuild subtree with new preds. 4 7 8 5 8 3 1 1 3 Error Free S1: Only Abstract Reachable States S2: Don’t refine error-free regions SAFE
Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 1 Reachability Tree Predicates:LOCK
Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 2 LOCK 3 LOCK 4 : LOCK 5 : LOCK 5 unlock() 4 : LOCK 1 2 3 Reachability Tree Predicates:LOCK
Analyze Counterexample Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK lock() old = new q=q->next 2 LOCK [q!=NULL] 3 LOCK q->data = new unlock() new++ 4 : LOCK [new==old] 5 : LOCK 5 unlock() 4 : LOCK 1 2 3 Reachability Tree Predicates:LOCK
Analyze Counterexample Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK old = new 2 LOCK 3 LOCK new++ 4 : LOCK [new==old] 5 : LOCK 5 Inconsistent 4 : LOCK new == old 1 2 3 Reachability Tree Predicates:LOCK
Repeat Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 1 Reachability Tree Predicates:LOCK, new==old
Repeat Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 2 LOCK , new==old 3 LOCK , new==old 4 : LOCK , : new = old [new==old] 4 1 2 3 Reachability Tree Predicates:LOCK, new==old
Repeat Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 2 LOCK , new==old 3 LOCK , new==old 4 : LOCK , : new = old [new!=old] 1 : LOCK, : new == old 4 4 1 2 3 Reachability Tree Predicates:LOCK, new==old
Repeat Build-and-Search Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); } 1 : LOCK 2 LOCK , new==old SAFE 3 LOCK , new==old 4 4 LOCK , new=old : LOCK , : new = old 1 5 5 : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Reachability Tree Predicates:LOCK, new==old
Scaling Sequential Verification Yes Safe Abstract lazily CProgram Refine No Property Trace Problem:Abstraction is Expensive Solution:1.Abstract reachable states, 2. Avoid refining error-free regions Key Idea: Reachability Tree
Property3: IRP Handler Win NT DDK Results * Pre-processed
#Predicates grows with program size while(1){ 1: if (p1) lock() ; if (p1) unlock() ; … 2: if (p2) lock() ; if (p2) unlock() ; … n: if (pn) lock() ; if (pn) unlock() ; } T F T Tracking lock not enough Problem: p1,…,pn needed for verification Exponential reachable abstract states
#Predicates grows with program size while(1){ 1: if (p1) lock() ; if (p1) unlock() ; … 2: if (p2) lock() ; if (p2) unlock() ; … n: if (pn) lock() ; if (pn) unlock() ; } : LOCK LOCK, p1 : LOCK, : p1 : LOCK, : p1 : LOCK, p1 : LOCK p1p2 p1: p2 : p1 p2 : p1: p2 2nAbstract States Problem: p1,…,pn needed for verification Exponential reachable abstract states
LOCK, p2 : LOCK, : p2 #Predicates grows with program size while(1){ 1: if (p1) lock() ; if (p1) unlock() ; … 2: if (p2) lock() ; if (p2) unlock() ; … n: if (pn) lock() ; if (pn) unlock() ; } : LOCK p1 LOCK, p1 : LOCK, : p1 : LOCK, : p1 : LOCK : LOCK, p1 : LOCK : LOCK p2 : LOCK, : p2 : LOCK, p2 : LOCK pn 2.n Abstract States Observe: Predicates are useful locally
#Predicates grows with program size while(1){ 1: if (p1) lock() ; if (p1) unlock() ; … 2: if (p2) lock() ; if (p2) unlock() ; … n: if (pn) lock() ; if (pn) unlock() ; } p1 p2 Preds. used globally Ex: 2n states Preds. Used locally Ex: 2.n states pn Solution: Use predicates only where needed Refinement: from (spurious) Counterexamples Q1.Find predicates Q2.Find where predicates are needed
Scaling Sequential Verification Yes Safe Abstract lazily CProgram Refine locally No Property Trace Problem:#Preds grows w/ Program Size Solution: Localize pred. use, find where preds. needed Refine Trace Feas Formula Proof of Unsat Ctrex. Trace Pred. Map PC Preds. Thm Pvr Interpolate
Counterexample Traces 1: x = ctr; 2: ctr = ctr + 1; 3: y = ctr; 4: if (x = i-1){ 5: if (y != i){ ERROR: } } 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y i) y = x +1
Trace Feasibility Formulas 1: x = ctr 2: ctr = ctr+1 3: y = ctr 4: assume(x=i-1) 5: assume(yi) 1: x1 = ctr0 2: ctr1 = ctr0+1 3: y1 = ctr1 4: assume(x1=i0-1) 5: assume(y1i0) x1 = ctr0 Æctr1 = ctr0 + 1 Æy1 = ctr1 Æ x1 = i0- 1 Æy1i0 Trace Trace Feasibility Formula SSA Trace