Title: The SLAM Project: Debugging System Software via Static Analysis
1The SLAM ProjectDebugging System Software via
Static Analysis
- Thomas Ball
- Sriram K. Rajamani
- Microsoft Research
- http//research.microsoft.com/slam/
2Thanks To
- Sagar Chaki (CMU)
- Satyaki Das (Stanford)
- Rupak Majumdar (UC Berkeley)
- Todd Millstein (U. Washington)
- Robby (KSU)
- Westley Weimer (UC Berkeley)
- Andreas Podelski (MPI)
- Stefan Schwoon (U. Edinburgh)
- Software Productivity Tools Research group at MSR
3SLAM Agenda
- Overview
- Demo
- Termination (of SLAM)
- Termination (of talk)
4Specifying and Checking Properties of Programs
- Many (mature) techniques
- automated deduction
- program analysis
- type checking
- model checking
- Many projects
- Bandera, ESC-Java, FeaVer, JPF, LClint, OSQ,
PolyScope, PREfix, rccjava, TVLA, Verisoft,
Vault, xgcc,
- Goals
- defect detection
- partial validation
- Properties
- memory safety
- temporal safety
- security
-
5Programming
Testing
Code
6Windows Device Drivers
- Kernel presents a very complex interface to
driver - stack of drivers
- NT kernel multi-threaded
- IRP completion, IRQL, plug-n-play, power
management, - Correct API usage described by finite state
protocols - Automatically check that clients respect these
protocols
7start NP
CallDriver
SKIP2
SKIP1
return child status
Skip
IPC
CallDriver
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
IPC
CallDriver
synch
MPR3
NP
CallDriver
return Pending
prop completion
PPC
not pending returned
MPR completion
Complete request
CallDriver
MPR1
MPR2
DC
no prop completion
CallDriver
N/A
8The SLAM Thesis
- We can soundly and precisely check a program
without annotations against API rules by - creating a program abstraction
- exploring the abstractions state space
- refining the abstraction
- We can scale such an approach to many 100kloc via
- modular analysis
- model checking
9SLAM
- Input
- API usage rules
- client C source code as is
- Analysis
- create, explore and refine boolean program
abstractions - Output
- Error traces (minimize noise)
- Verification (soundness)
10Usage Rule for Locking
State Machine
U
L
Unlocked
Locked
Error
L
U
11 Example
do //get the write lock KeAcquireSpinLock(
devExt-gtwriteListLock) nPacketsOld
nPackets request devExt-gtWLHeadVa if
(request) KeReleaseSpinLock(devExt-gtwriteListL
ock) ... nPackets while (nPackets !
nPacketsOld) KeReleaseSpinLock(devExt-gtwriteList
Lock)
Loop Invariant nPackets nPacketsOld IFF lock
is held
12The SLAM Process
predicates
boolean program
c2bp
prog. P
prog. P
slic
predicates
bebop
SLIC rules
newton
path p
13Instrumented Code
do //get the write lock SLIC_KeAcquireSpin
Lock_call() KeAcquireSpinLock(devExt-gtwriteList
Lock) nPacketsOld nPackets request
devExt-gtWLHeadVa if (request) SLIC_KeReleas
eSpinLock_call() KeReleaseSpinLock(devExt-gtwri
teListLock) ... nPackets while
(nPackets ! nPacketsOld) SLIC_KeReleaseSpinLock_
call() KeReleaseSpinLock(devExt-gtwriteListLock)
14Predicate Abstraction of C (c2bp)
- Input a C program P and set of predicates E
- predicate pure C boolean expression
- Output a boolean program bp(P,E) that is
- a sound abstraction of P
- a precise (boolean) abstraction of P
- Results
- separate compilation (predicate abstraction) in
presence of procedures and pointers
15Skeletal Boolean Program
Predicates (locked0) (locked1)
- do
- //get the write lock
- SLIC_KeAcquireSpinLock_call()
-
- if () then
-
- SLIC_KeReleaseSpinLock_call()
-
- fi
- while ()
- SLIC_KeReleaseSpinLock_call()
16Reachability in Boolean Programs (bebop)
- Symbolic interprocedural data flow analysis
- Based on CFL-reachability Reps-Horwitz-Sagiv 95
- Explicit representation of CFG
- Implicit representation of reachable states via
BDDs - Worst-case complexity is O( P (GL)3 )
- P program size
- G number of global states in state machine
- L max. number of local states over all
procedures
17Shortest Error Path (Acquire 2x)
Predicates (locked0) (locked1)
- do
- //get the write lock
- SLIC_KeAcquireSpinLock_call()
-
- if () then
-
- SLIC_KeReleaseSpinLock_call()
-
- fi
- while ()
- SLIC_KeReleaseSpinLock_call()
18Counterexample-driven Refinement (newton)
- Symbolically execute path in C program
- Check for path infeasibility at each conditional
- Simplify theorem prover
- If path is infeasible, generate new predicates to
rule out infeasible path - heuristics to generate weak explanation
19Error Path in C code
do //get the write lock KeAcquireSpinLock(
devExt-gtwriteListLock) nPacketsOld
nPackets request devExt-gtWLHeadVa if
(request) KeReleaseSpinLock(devExt-gtwriteListL
ock) ... nPackets while (nPackets !
nPacketsOld) KeReleaseSpinLock(devExt-gtwriteList
Lock)
20Newton Path Simulation
Store
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
21Newton
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
22Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
23Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
24Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
- ? -gtWLHeadVa ? (3)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
25Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
- ? -gtWLHeadVa ? (3)
- request ? (3,4)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions
26Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
- ? -gtWLHeadVa ? (3)
- request ? (3,4)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions ! ?
(5)
27Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
- ? -gtWLHeadVa ? (3)
- request ? (3,4)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions ! ?
(5) ? ! ? (1,2)
28Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
- devExt ?
- ? -gtWLHeadVa ? (3)
- request ? (3,4)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions ? ! ? (1,2)
29Newton
- Store
- nPacketsOld ?
- nPackets ? (1)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Conditions ? ! ? (1,2)
30Newton
Predicates (nPacketsOld ?) (nPackets
? ) (? ! ?)
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
31Newton
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Predicates (nPacketsOld ! nPackets)
32Newton
nPackets nPacketsOld request
devExt-gtWLHeadVa assume(!request) assume(nPack
ets ! nPacketsOld)
Predicates (nPacketsOld nPackets)
33Refined Boolean Program
Boolean variable b represents the condition
(nPacketsOldnPackets)
- do
- //get the write lock
- SLIC_KeAcquireSpinLock_call()
- b true // npacketsOld npackets
-
- if () then
- SLIC_KeReleaseSpinLock_call()
-
-
- b b ? false // npackets
- fi
- while ( !b ) // (nPackets ! nPacketsOld)
- SLIC_KeReleaseSpinLock_call()
34Results on Drivers (so far)
- Handful of drivers analyzed so far
- 2k-30k of C code each
- Each driver has yielded bugs
- SLAM process has always terminated
- minutes to ½ hour
- Process optimizations have huge effects
35Demo
- Lock example
- validation
- Lock example with bug
- error trace
- SLAMs first bug
- floppy device driver
36Termination of SLAM
- Cousot-Cousot, PLILP92
- widening abstract interpretation with infinite
lattices (WAIL) is more powerful than a (single)
finite abstraction - Ball-Podelski-Rajamani, TACAS02
- finite abstractions plus iterative refinement
(FAIR) is more powerful than WAIL
37Termination and Widening
- Widening is used to achieve termination by
enlarging the set of states (to reach a fixpoint) - 5 ? x ? 10 widened to 5 ? x
- Of course, widening may lose precision
- Every fixpoint algorithm that loses precision (in
order to terminate) uses widening (implicitly)
38Fixpoint
X init while X ? S do X X ? F(X)
if X ? X then break X
X od return X ? S
39Search Space of Widenings
40Finite Abstraction Iterative Refinement
- If WAIL succeeds in N iterations then FAIR will
succeed in N iterations - But, FAIR can succeed earlier, due to use of
interior (abstract) fixpoint
X init while true do P
atoms(X) X lfp(FP, init) if X
? S then break X X ? F(X) od return X
? S
41Search Space
WAILoracle
FAIR
42Searching for Solutions
- Once upon a time, only a human could play a great
game of chess - but then smart brute force won the day (Deep
Blue vs. Kasparov) - Once upon a time, only a human could design a
great abstraction
43Termination of Talk
- SLAM automatically discovers inductive invariants
via - predicate abstraction of C programs
- model checking of boolean programs
- counterexample-driven refinement
- Implemented and starting to yield results on NT
device drivers
44SLAMming on the shoulders of
- Model checking
- predicate abstraction
- counterexample-driven refinement
- BDDs and symbolic model checking
- Program analysis
- abstract interpretation
- points-to analysis
- dataflow via CFL-reachability
- Automated deduction
- weakest preconditions
- theorem proving
- Software
- AST toolkit
- Dass Golf
- CU and CMU BDD
- Simplify, Vampyre
- OCAML
45SLAM Future Work
- More impact
- Static Driver Verifier (internal, external)
- More features
- Heap abstractions
- Concurrency
- More languages
- C and CIL
- More users
- 2002 public release of SLAM toolkit
46Predictions
- The holy grail of full program verification has
been abandoned - New checking tools will emerge and be widely used
- Tools will
- exploit ideas from various analysis disciplines
- alleviate the chicken-and-egg problem of
specifications
47Challenges / SLAM Reading List
- Specifications
- Mining specifications
- Abstractions
- Predicate abstraction for software verification
- Annotations
- Types as models model checking MP programs
- Role analysis
- Soundness
- Ccured type-safe retrofitting of legacy code
- Scaling
- Lazy abstraction
48The End