Software Verification via Refinement Checking Sagar Chaki, Edmund Clarke, Alex Groce, CMU Somesh Jha, Wisconsin.

Post on 18-Dec-2015

221 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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

top related