software verification via refinement checking sagar chaki, edmund clarke, alex groce, cmu somesh...
Post on 18-Dec-2015
223 views
TRANSCRIPT
Software Verification via Refinement Checking
Sagar Chaki, Edmund Clarke, Alex Groce, CMU
Somesh Jha, Wisconsin
Motivation• Refinement mappings exist between real
code and specifications
• Potentially cheaper than model checking- Simulation vs. Trace containment
• Refinement mappings are like proofs
Specifications• Expressed as Finite Labeled Transition
Systems (FLTS)- Locking protocols
• We use the FSP syntax to describe FLTSs- Concurrency: State Models and Java Programs –
Jeff Magee, Jeff Kramer - Wiley
Specification: LockUnlock• U = (lock -> L | return -> S),
L = (unlock -> U).
U L
lock
unlock
S
return
Implementation: Device drivervoid example() {
do {
KeAcquireSpinLock(); //event lock
nPackets = nPacketsOld;
if(cond) {
KeReleaseSpinLock(); //event unlock
nPackets++;
}
} while(nPackets != nPacketsOld);
KeReleaseSpinLock(); //event unlock
}
Our Goal• To show that Driver refines LockUnlock
- Need to keep track of the predicate (nPackets == nPacketsOld)
- Data-insensitive analysis will fail
• Provide diagnostic feedback in case the simulation does not exist
Specification: POSIX pthread• pthread_mutex_lock()
- Acquires lock and returns 0- Increments user count on lock and returns 0- Returns non-zero error code
S0
S1
S3
S2
ret_err
ret_zerolock
inc_count
Implementation: Glibc pthreadint pthread_mutex_lock() {
case PTHREAD_MUTEX_RECURSIVE_NP:
self = thread_self();
if (mutex->__m_owner == self) {
mutex->__m_count++; // inc_count
return 0; // ret_zero
}
pthread_lock(&mutex->__m_lock, self); // lock
mutex->__m_owner = self;
mutex->__m_count = 0;
return 0; } // ret_zero
Implementation• Collection of C procedure definitions
- The pthread library
• Designated main procedure- The pthread_mutex_lock function- We are interested in behavior observed during an
invocation of main
Implementation• For each procedure called, one of two things
must be available
- Definition of procedure
- Information about behavior observed during invocation of procedure
Verification• Check that every possible behavior of main is
also a behavior of the FLTS- Trace-containment
• In practice it is sufficient to check for a stronger condition viz. simulation- FLTS ≥ main
FLTS: Definition• Fix an alphabet: Σ
- Assume Σ contains special symbol ε
• Three-tuple: <Q,I,δ>- Q: finite set of states- I: initial state- δ: transition relation over Q X Σ X Q
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
Simulation• FLTSs: <Q1,I1,δ1>,<Q2,I2,δ2>• Relation ≥ Q1 X Q2 is simulation if
(1) Init: For all t Є I2 exists s Є I1 s.t. s ≥ t
(2) Step: s ≥ t and (t,a,t’) Є δ2 => exists s’ s.t. (s,a,s’) Є δ1 and s’ ≥ t’
(3) Stutter: s ≥ t and (t,ε,t’) Є δ2 => s ≥ t’ OR exists s’ s.t. (s,ε,s’) Є δ1 and s’ ≥ t’
Overall method• Step 1: Compute relation R that satisfies
conditions 2 and 3
• Step 2: Check that R satisfies condition 1 as well
Step 1• Start with R = Q1 X Q2
• Iteratively refine R using condition 2 and 3 till a fixed point is reached- If (s,t) Є R and if (t,a,t’) Є δ2 then remove (s,t) if
there does not exist s’ s.t. (s,a,s’) Є δ1 and (s’,t’) Є R
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
{U,L,S}
{U,L,S}
{U,L,S}
{U,L,S}
{U,L,S}
lockU L
unlock
Sreturn
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
{U}
{U,L,S}
{U,L,S}
{U,L,S}
{U,L,S}
lockU L
unlock
Sreturn
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
{U}
{U}
{U,L,S}
{U,L,S}
{U,L,S}
lockU L
unlock
Sreturn
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
{U}
{U}
{U,L,S}
{L}
{U,L,S}
lockU L
unlock
Sreturn
Example
U’ L’
lock
S’
return
V’ε
M’ε
unlock
{U}
{U}
{L}
{L}
{U,L,S}
lockU L
unlock
Sreturn
FLTS from C module• Based on a set of predicates
• Each state of the FLTS consists of a control location of the C module and a valuation to the predicates- Non-context-sensitive
• Weakest preconditions and theorem proving are used to compute the transitions on-the-fly
Examplevoid example() {
do {
KeAcquireSpinLock();
nPackets = nPacketsOld;
if(cond) {
KeReleaseSpinLock();
nPackets++;
}
} while(nPackets != nPacketsOld);
KeReleaseSpinLock();
}
Θ: nPackets == nPacketsOld
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ’
Θ
Θ
Θ
Θ
Θ
Θ
Θ
Θ
Θ
Θ
Θ
Loc Loc
Unl Unl
Unl Unl
Ret Ret
Challenges• Extract event information from C code• Provide diagnostic feedback in case
simulation is not found• Pointers and dynamic memory allocation• Introduce context-sensitivity• Introduce concurrency
Predicates and Property• Need to specify predicates to be used
- predicate (nPackets == nPacketsOld);
• Need to specify the simulation relation to be checked- property U simulates example;
Additional Info• Specify that call to KeAcquireSpinLock()
represents a locking action- action call KeAcquireSpinLock = lock;
• Similarly for KeReleaseSpinLock()- action call KeReleaseSpinLock = unlock;
Using Static Analysis• Mostly for alias information
- Predicate : (x == 4)- Assignment : *y = 5;- WP: ((y == &x)&&(5 == 4)) || ((y != &x)&&(x==4))- Static analysis could tell us whether (y == &x)
before this assignment statement
- x = (*y)(100);- What procedures could y potentially point to
Java• Java source
- Object-oriented-ness
• Java bytecode- Stack based- Need to finitise the state, perhaps by imposing a
upper bound on the stack size
Refinements as Proofs• Class loader obtains bytecode with the spec,
refinement relation and set of predicates
• Checks that the refinement really is valid using the predicates
• Loads class only if the check passes
Refinements as Proofs• Tradeoff between bandwidth and computation
- Supply just the predicates and let the loader compute the refinement relation
- Supply the refinement so that loader just has to check its validity
• Can we do this for the Linux process loader- Doubtful
Related Work• Based on predicate abstraction
- Graf & Saidi, Dill et. al.• Do not work with C
- SLAM, Bandera
• Specify desired behavior as patterns, or unwanted behavior as monitors- Engler et. al., SLAM, Bandera
Major Differences• Unlike Engler et. al.
- Flow-sensitive, based on predicates- Check arbitrary regular behavior
• Unlike SLAM- On-the-fly: no boolean programs- Not context-sensitive
• Unlike Bandera- Work with C- Check arbitrary regular behavior