1 / 65

Microsoft’s Slam Project

Microsoft’s Slam Project. Alon Flaisher December 2002. Opening. Static analysis of programs Microsoft’s Slam project Usage – verification of device drivers. Reviewed Papers. All papers by Ball and Rajamani: The Slam Project: Debugging System Software via Static Analysis.

dfuentes
Download Presentation

Microsoft’s Slam Project

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. Microsoft’s Slam Project Alon Flaisher December 2002

  2. Opening • Static analysis of programs • Microsoft’s Slam project • Usage – verification of device drivers A.F.

  3. Reviewed Papers All papers by Ball and Rajamani: • The Slam Project: Debugging System Software via Static Analysis. • Slic : a Specification Language for Interface Checking. • Checking Temporal Properties of Software with Boolean Programs. • Automatically Validating Temporal Safety Properties of Interfaces. • Bebop: A Symbolic Model Checker for Boolean Programs. A.F.

  4. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  5. Introduction to Slam • The goal of the Slam project is to check whether or not a program obeys “API usage rules“ that specify what it means to be a good client of an API. • The Slam toolkit statically analyzes a C program to determine whether or not it violates given usage rules. A.F.

  6. Introduction – Cont. • The SLAM toolkit provides a fully automatic way of checking temporal safety properties of system software. • Violations are reported by the SLAM toolkit as paths over the program P. It never reports spurious error paths. • Instead, it detects spurious error paths and uses them to automatically refine the abstraction. • Since property checking is undecidable, the SLAM refinement algorithm may not converge. A.F.

  7. Boolean Abstraction • Slam models abstractions of C programs using Boolean programs. • Boolean programs are C programs in which all variables have Boolean type. • Each Boolean variable in a Boolean program has an interpretation as a predicate over the infinite state space of the C program. A.F.

  8. Refinement • Such abstraction often cause spurious counter examples. • Slam’s refinement algorithm finds Boolean program abstractions that are precise enough to validate properties. A.F.

  9. Unique Aspects of Slam • Does not require the programmer to annotate the source program. • Minimizes noise (false error messages) through counterexample-driven refinement. • Slam exploits and extends results from program analysis, model checking and automated deduction. A.F.

  10. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  11. Specification • Slam project checks temporal safety properties of sequential C programs. • Roughly stated, temporal safety properties are those properties whose violation is witnessed by a finite execution trace. • Slic – Specification Language for Interface Checking. A.F.

  12. Slic Specification Language • A low-level specification language designed to specify the temporal safety properties of APIs implemented in the C programming language. • Allows the definition of a safety automaton that monitors the execution behavior of a program at the level of function calls and returns. • Given a program P and a Slic specification S, a preprocessor creates an instrumented program P’ such that a unique label ERROR is reachable in P’ iff P does not satisfy S. A.F.

  13. Slic Design • Out-of-line specification (because legacy code is checked) • C like syntax • A Slic specification consists of two basic parts: • A state structure definition • A list of transfer functions A.F.

  14. enum { Unlocked=0, Locked=1 } state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return() { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; } Compilation to C Slic Spec for Spin Locks and its Compilation into C state { enum { Unlocked=0, Locked=1 } state = Unlocked; } KeAcquireSpinLock.return { if (state == Locked) abort; else state = Locked; } KeReleaseSpinLock.return { if (state == Unlocked) abort; else state = Unlocked; } A.F. Example P'

  15. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on Newton and Bebop • Summary and related work A.F.

  16. Implementation Three basic tools comprise the Slam toolkit: • C2BP (predicate abstractor for C) • Bebop (model checker for Boolean programs) • Newton (predicate discoverer) A.F.

  17. Implementation – C2BP • C2BP is a tool that transforms a C program P into a Boolean program BP(P, E) with respect to a set of predicates E. • C2BP translates each procedure of the C program separately, enabling it to scale to large programs. A.F.

  18. Implementation – Bebop • Bebop is a tool for performing reachability analysis of Boolean programs. • It combines interprocedural data flow analysis with BDDs (to efficiently represent the reachable states. A.F.

  19. Implementation - Newton • Newton is a tool that discovers additional predicates to refine the Boolean program, by analyzing the feasibility of paths in the C program. • It takes a C program and a potential error path as input. It then determines if the path is feasible. • If “Yes”, the error path is reported. • if “No”, it identifies a small set of predicates that explain why the path is infeasible. A.F.

  20. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  21. Slam Process • The basic design of the Slam process is to iterate the creation, analysis and refinement of program abstractions, until: • a feasible execution path in P to ERROR is found, or • ERROR is shown not to be reachable, or • we run out of resources. A.F.

  22. Boolean Program Abstraction • The Slam process creates a sound Boolean program abstractionB’ of the C program P’. • Boolean programs have all the control flow constructs of C programs, but contain only Boolean variables. • Each boolean variable in B’ conservatively tracks the state of a predicate (Boolean expression) in the C program. A.F.

  23. Boolean Program Abstraction Cont. • If a reachability analysis of B’ determines that the label ERROR is not reachable in B’ then it is not reachable in P’. • It is possible that B’ may be too coarse an abstraction of P’ (that is, ERROR is reachable in B’ via a path p but ERROR is not reachable in P’ via p). • Counterexample-driven refinement is applied to create a more precise boolean program. A.F.

  24. Refinement Algorithm • In the first iteration (i = 0), we start with a set of predicates E0 that are present in the conditionals of the Slic specification. • Let Eibe some set of predicates over the state of P’. Then iteration i of SLAM is carried out using the following steps: A.F.

  25. Refinement Algorithm Cont. 1. Apply C2BP to construct the boolean program BP(P’;Ei). 2. Apply Bebop to check if there is a path  in BP(P’;Ei) that reaches the ERROR label. If ERROR is not reachable, then the property is valid in P, and the algorithm terminates. A.F.

  26. Refinement Algorithm Cont. 3. If there is such a path p, then we use Newton to check if p is feasible in P. There are two outcomes: • “yes": the property has been invalidated in P, and the algorithm terminates with an error path . • “no": Newton finds a set of predicates Fi that explain the infeasibility of path in P. 4. Let Ei +1:= Ei Fi , and i := i + 1, and proceed to the next iteration. A.F.

  27. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  28. PCI Device Driver Example • We present a snippet of (simplified) C code from a PCI device driver that processes interrupt request packets (IRPs). • Of interest here are the calls the code makes to acquire and release spin locks (KeAcquireSpinLock and KeReleaseSpinLock). A.F.

  29. void example() { do { KeAcquireSpinLock(); A: KeAcquireSpinLock_return(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status){ devExt->WLHV = req->Next; KeReleaseSpinLock(); B: KeReleaseSpinLock_return(); irp = req->irp; if(req->status > 0){ irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); C: KeReleaseSpinLock_return(); } Slic Tool P’ void example() { do { KeAcquireSpinLock(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status) { devExt->WLHV = req->Next; KeReleaseSpinLock(); irp = req->irp; if(req->status > 0){ irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); } P

  30. Slic Spec Compiled by C2BP into a Boolean Program enum { Unlocked=0, Locked=1 } state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return() { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; } A.F.

  31. Slic Spec Compiled by C2BP into a Boolean Program decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end The set of initial global predicates E0 The statement c=locked in the C code affects both predicates A.F. Return

  32. C2BP E0 P’’=BP(P’;E0) P’ BP(P’;E0) abstracts P’ Abstracting the Instrumented C Program A.F.

  33. void example() { do { KeAcquireSpinLock(); A: KeAcquireSpinLock_return(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status){ devExt->WLHV = req->Next; KeReleaseSpinLock(); B: KeReleaseSpinLock_return(); irp = req->irp; if(req->status > 0){ irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); C: KeReleaseSpinLock_return(); } P’ P’’ void example() begin do skip; A: KeAcquireSpinLock_return(); skip; skip; if (*) then skip; skip; B: KeReleaseSpinLock_return(); skip; if (*) then skip; skip; else skip; skip; fi skip; skip; skip; fi while (*); skip; C: KeReleaseSpinLock_return(); end

  34. void example() { do { KeAcquireSpinLock(); A: KeAcquireSpinLock_return(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status){ devExt->WLHV = req->Next; KeReleaseSpinLock(); B: KeReleaseSpinLock_return(); irp = req->irp; if(req->status > 0){ irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); C: KeReleaseSpinLock_return(); } P’ P’’ The condition in the C program cannot be abstracted precisely using the predicates in E0 void example() begin do skip; A: KeAcquireSpinLock_return(); skip; skip; if (*) then skip; skip; B: KeReleaseSpinLock_return(); skip; if (*) then skip; skip; else skip; skip; fi skip; skip; skip; fi while (*); skip; C: KeReleaseSpinLock_return(); end P’’actually consists of this piece of code, plus the Slic spec translation

  35. Model Checking P’’ decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end void example() begin do … A: KeAcquireSpinLock_return(); … if (*) then … B: KeReleaseSpinLock_return(); … if (*) then … else … fi … fi while (*); C: KeReleaseSpinLock_return(); end A.F.

  36. Model Checking P’’ decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end void example() begin do … A: KeAcquireSpinLock_return(); … if (*) then … B: KeReleaseSpinLock_return(); … if (*) then … else … fi … fi while (*); C: KeReleaseSpinLock_return(); end A.F.

  37. Model Checking P’’ decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end void example() begin do … A: KeAcquireSpinLock_return(); … if (*) then … B: KeReleaseSpinLock_return(); … if (*) then … else … fi … fi while (*); C: KeReleaseSpinLock_return(); end A.F.

  38. Model Checking P’’ decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end void example() begin do … A: KeAcquireSpinLock_return(); … if (*) then … B: KeReleaseSpinLock_return(); … if (*) then … else … fi … fi while (*); C: KeReleaseSpinLock_return(); end A.F.

  39. Model Checking P’’ decl {state==Locked}, {state==Unlocked}; void slic_abort() begin ERROR: skip; end void KeAcquireSpinLock_return() begin if ({state==Locked}) slic_abort(); else {state==Locked},{state==Unlocked} := T,F; end void KeReleaseSpinLock_return() begin if ({state == Unlocked}) slic_abort(); else {state==Locked},{state==Unlocked} := F,T; end void example() begin do … A: KeAcquireSpinLock_return(); … if (*) then … B: KeReleaseSpinLock_return(); … if (*) then … else … fi … fi while (*); C: KeReleaseSpinLock_return(); end A.F.

  40. Newton Detects Feasibility void example() { do { KeAcquireSpinLock(); A: KeAcquireSpinLock_return(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status){ … } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); C: KeReleaseSpinLock_return(); } • Is the path found by Bebop [A, A, ERROR] feasible in the program P? • Newton detects that the path is infeasible in P. A.F.

  41. New Set of Predicates – E1 • In the second iteration of the process, the predicate (nPackets = nPacketsOld) is added to the set of predicates E0 to result in a new set of predicates E1. • BP(P’’,E1) has one additional boolean variable (b) to represent the predicate. • The assignment statement nPackets = nPacketsOld; makes this condition true. A.F.

  42. void example() { do { KeAcquireSpinLock(); A: KeAcquireSpinLock_return(); nPacketsOld = nPackets; req = devExt->WLHV; if(req && req->status){ devExt->WLHV = req->Next; KeReleaseSpinLock(); B: KeReleaseSpinLock_return(); irp = req->irp; if(req->status > 0){ irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while(nPackets!=nPacketsOld); KeReleaseSpinLock(); C: KeReleaseSpinLock_return(); } void example() begin do skip; A: KeAcquireSpinLock_return(); b := T; skip; if (*) then skip; skip; B: KeReleaseSpinLock_return(); skip; if (*) then skip; skip; else skip; skip; fi skip; skip; b := choose(F,b); fi while (!b); skip; C: KeReleaseSpinLock_return(); end P’ P’’ P’’’ void example() begin do skip; A: KeAcquireSpinLock_return(); skip; skip; if (*) then skip; skip; B: KeReleaseSpinLock_return(); skip; if (*) then skip; skip; else skip; skip; fi skip; skip; skip; fi while (*); skip; C: KeReleaseSpinLock_return(); end

  43. The Choose Function • Using a theorem prover, C2BP determines that if the predicate is true before the statement nPackets++, then it is false afterwards. • This is captured by the assignment statement in the boolean program b := choose(F,b). A.F.

  44. Example Results • Applying Bebop to the new boolean program shows that the label ERROR is not reachable. • In performing its fixpoint computation, Bebop discovers that the following loop invariant holds at the end of the do-while loop:(state = Locked  nPackets = nPacketsOld) (state = Unlocked  nPackets  nPacketsOld) A.F.

  45. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  46. Restrictions • The C program obeys a logical memory model in which the expressions *p and *(p+i) refer to the same object. • Slam process is expected to work well for programs whose behavior is governed by an underlying finite state protocol. A.F.

  47. Outline • Introduction to the Slam toolkit • Slic specification language • Design – the Slam process • Implementation – C2BP, Bebop and Newton tools • Example • Restrictions • More on C2BP, Bebop and Newton • Summary and related work A.F.

  48. More on C2BP

  49. More on C2BP – Pointers • C2BP tool uses alias analysis to determine whether or not an assignment statement through a pointer dereference can affect a predicate. • This increases the precision of the C2BP. Without alias analysis, conservative assumptions which lead to invalidating many predicates would be made. • In the PCI example, the points-to (alias) analysis shows that no variable in the C program can alias the address of the global state variable. A.F.

  50. C2BP – Procedure Calls • Since boolean programs support procedure calls, C2BP is able to abstract procedures modularly. • After a call, the caller must conservatively update local state that may have been modified by the callee. • C2BP provides a sound and precise approach to abstracting procedure calls that takes such side-effects into account. A.F.

More Related