The SLAM Project: Debugging System Software via Static Analysis Thomas Ball

advertisement
The SLAM Project:
Debugging System
Software via Static Analysis
Thomas Ball
Sriram K. Rajamani
Microsoft Research
http://research.microsoft.com/slam/
1
2
Thanks 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

3
SLAM Agenda

Overview

Demo

Termination (of SLAM)

Termination (of talk)
4
Specifying and Checking
Properties of Programs

Goals

 defect
detection
 partial validation

Many (mature) techniques
automated
deduction
program analysis
type checking
model checking
Properties
 memory
safety
 temporal safety
 security
…

Many projects
Bandera,
ESC-Java, FeaVer,
JPF, LClint, OSQ, PolyScope,
PREfix, rccjava, TVLA, Verisoft,
Vault, xgcc, …
5
API
Usage Rules
Programming
Testing
Code
6
Windows 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
7
start NP
CallDriver
SKIP1
SKIP2
return
child status
Skip
CallDriver
MPR3
NP
MPR2
IPC
synch
CallDriver
MPR
completion
prop
completion
CallDriver
PPC
Complete
request
MPR1
DC
no prop
completion
IRP accessible
synch
CallDriver
N/A
start P
Mark Pending
return
not Pend
N/A
CallDriver
SKIP2
SKIP1
Skip
CallDriver
MPR3
synch
NP
MPR2
CallDriver
MPR
completion
prop
completion
IPC
CallDriver
return
Pending
PPC
Complete
request
MPR1
DC
no prop
completion
CallDriver
N/A
8
The SLAM Thesis

We can soundly and precisely check a program
without annotations against API rules by




creating a program abstraction
exploring the abstraction’s state space
refining the abstraction
We can scale such an approach to many 100kloc
via


modular analysis
model checking
9
SLAM

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)
10
Usage Rule for Locking
SLIC
State Machine
state {
int locked = 0;
}
U
Unlocked
L
Locked
U
L
Error
KeAcquireSpinLock.call {
if (locked==1) abort;
else locked = 1;
}
KeReleaseSpinLock.call {
if (locked==0) abort;
else locked = 0;
}
11
Example
do {
//get the write lock
KeAcquireSpinLock(&devExt->writeListLock);
nPacketsOld = nPackets;
request = devExt->WLHeadVa;
if (request){
KeReleaseSpinLock(&devExt->writeListLock);
...
nPackets++;
}
} while (nPackets != nPacketsOld);
KeReleaseSpinLock(&devExt->writeListLock);
Loop Invariant: nPackets = nPacketsOld IFF lock is held
12
The SLAM Process
predicates
c2bp
prog. P
slic
prog. P’
predicates
boolean program
bebop
SLIC rules
newton
path p
13
Instrumented Code
do {
//get the write lock
SLIC_KeAcquireSpinLock_call();
KeAcquireSpinLock(&devExt->writeListLock);
nPacketsOld = nPackets;
request = devExt->WLHeadVa;
if (request){
SLIC_KeReleaseSpinLock_call();
KeReleaseSpinLock(&devExt->writeListLock);
...
nPackets++;
}
} while (nPackets != nPacketsOld);
SLIC_KeReleaseSpinLock_call();
KeReleaseSpinLock(&devExt->writeListLock);
14
Predicate Abstraction of C
(c2bp)

Input: a C program P and set of predicates E
 predicate

Output: a boolean program bp(P,E) that is
a
a

= pure C boolean expression
sound abstraction of P
precise (boolean) abstraction of P
Results
 separate
compilation (predicate abstraction) in
presence of procedures and pointers
15
Skeletal Boolean Program
do
Predicates:
//get the write lock
SLIC_KeAcquireSpinLock_call();
(locked==0)
(locked==1)
if (*) then
SLIC_KeReleaseSpinLock_call();
fi
while (*);
SLIC_KeReleaseSpinLock_call();
16
Reachability 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
17
Shortest Error Path (Acquire 2x)
Predicates:
do
//get the write lock
SLIC_KeAcquireSpinLock_call();
(locked==0)
(locked==1)
if (*) then
SLIC_KeReleaseSpinLock_call();
fi
while (*);
SLIC_KeReleaseSpinLock_call();
18
Counterexample-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
19
Error Path in C code
do {
//get the write lock
KeAcquireSpinLock(&devExt->writeListLock);
nPacketsOld = nPackets;
request = devExt->WLHeadVa;
if (request){
KeReleaseSpinLock(&devExt->writeListLock);
...
nPackets++;
}
} while (nPackets != nPacketsOld);
KeReleaseSpinLock(&devExt->writeListLock);
20
Newton: Path Simulation
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
Conditions:
21
Newton
Store:
nPackets = nPacketsOld;
(1) nPacketsOld:

request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
Conditions:
22
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
(1) nPacketsOld:

(2) nPackets:
 (1)
assume(!request);
assume(nPackets != nPacketsOld);
Conditions:
23
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

assume(!request);
assume(nPackets != nPacketsOld);
Conditions:
24
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

(4)  ->WLHeadVa:  (3)
assume(nPackets != nPacketsOld);
Conditions:
25
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

(4)  ->WLHeadVa:  (3)
(5) request:
 (3,4)
Conditions:
26
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

(4)  ->WLHeadVa:  (3)
(5) request:
 (3,4)
Conditions:
!

(5)
27
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

(4)  ->WLHeadVa:  (3)
(5) request:
 (3,4)
Conditions:
!

 != 
(5)
(1,2)
28
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
assume(!request);
assume(nPackets != nPacketsOld);
(1) nPacketsOld:

(2) nPackets:
 (1)
(3) devExt:

(4)  ->WLHeadVa:  (3)
(5) request:
 (3,4)
Conditions:
 != 
(1,2)
29
Newton
Store:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
(1) nPacketsOld:

(2) nPackets:
 (1)
assume(!request);
assume(nPackets != nPacketsOld);
Conditions:
 != 
(1,2)
30
Newton
Predicates:
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
(nPacketsOld ==
(nPackets ==
)
 )
( != )
assume(!request);
assume(nPackets != nPacketsOld);
31
Newton
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
Predicates:
(nPacketsOld != nPackets)
assume(!request);
assume(nPackets != nPacketsOld);
32
Newton
nPackets = nPacketsOld;
request = devExt->WLHeadVa;
Predicates:
(nPacketsOld == nPackets)
assume(!request);
assume(nPackets != nPacketsOld);
33
Refined Boolean Program
Boolean variable b represents the condition
(nPacketsOld==nPackets)
do
//get the write lock
SLIC_KeAcquireSpinLock_call();
b := true;
// npacketsOld = npackets;
!b
b
b
if (*) then
SLIC_KeReleaseSpinLock_call();
b
b
b
!b
b := b ? false : *; // npackets++;
fi
while ( !b ); // (nPackets != nPacketsOld);
SLIC_KeReleaseSpinLock_call();
34
Results 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
35
Demo

Lock example
 validation

Lock example with bug
 error

trace
SLAM’s first bug
 floppy
device driver
36
Termination of SLAM

[Cousot-Cousot, PLILP’92]
 widening
+ abstract interpretation with infinite lattices
(WAIL) is more powerful than a (single) finite abstraction

[Ball-Podelski-Rajamani, TACAS’02]
 finite
abstractions plus iterative refinement (FAIR) is more
powerful than WAIL
37
Termination 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)
38
Fixpoint
X := init;
while X  S do
X’ := X  F(X)
if X’  X then break
X := X’
od
return X  S
Fixpoint + Widening
(WAIL)
X := init;
while X  S do
X’ := X  F(X)
if X’  X then break
i := oracle’s guess
X := W(i, X’)
od
return X  S
39
Search Space of Widenings
F
F
F
F
F
F
F
F
W
W
W
F
F
W
F
W
F
40
Finite Abstraction + Iterative Refinement
X := init;
while true do
P := atoms(X);
X# := lfp(F#P, init)
if X#  S then break
X := X  F(X)
od
return X#  S

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
41
Search Space
F
F
F
F
F
F
W
F
F
W
F
W
F
F
F
F
W
F
F
W
F
WAIL+oracle
F
FAIR
42
Searching 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…
43
Termination 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
44
SLAMming 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 CFLreachability
Automated deduction
 weakest
 theorem

preconditions
proving
Software
 AST toolkit
 Das’s Golf
 CU and CMU BDD
 Simplify, Vampyre
 OCAML
45
SLAM 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
46
Predictions

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
47
Challenges / SLAM Reading List

Specifications
 Mining

specifications
Abstractions
 Predicate

abstraction for software verification
Annotations
 Types as models:
 Role analysis

Soundness
 Ccured:

model checking MP programs
type-safe retrofitting of legacy code
Scaling
 Lazy
abstraction
48
The End
49
Download