Verifying Regular Behavior of C modules Sagar Chaki, Edmund Clarke, Alex Groce, CMU Somesh Jha, Wisconsin
Regular Behavior 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
Regular Behavior: LockUnlock U = (lock -> L | return -> S), L = (unlock -> U). UL lock unlock S return
C Module: PCI device driver void example() { do { KeAcquireSpinLock();//event lock nPackets = nPacketsOld; if(cond) { KeReleaseSpinLock();//event unlock nPackets++; } } while(nPackets != nPacketsOld); KeReleaseSpinLock();//event unlock }
Our Goal To show that LockUnlock simulates the PCI driver -Need to keep track of the predicate (nPackets == nPacketsOld) -Flow-insensitive analysis will fail Provide diagnostic feedback in case the simulation does not exist
POSIX pthread Spec pthread_mutex_lock() -Acquires lock and returns 0 -Increments user count on lock and returns 0 -Returns non-zero error code U U U U ret_err ret_zero lock inc_count
Glibc pthread source code int 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
C module 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
C module 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: 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:, 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} lock UL unlock S return
Example U’ L’ lock S’ return V’ ε M’ ε unlock {U} {U,L,S} lock UL unlock S return
Example U’ L’ lock S’ return V’ ε M’ ε unlock {U} {U,L,S} lock UL unlock S return
Example U’ L’ lock S’ return V’ ε M’ ε unlock {U} {U,L,S} {L} {U,L,S} lock UL unlock S return
Example U’ L’ lock S’ return V’ ε M’ ε unlock {U} {L} {U,L,S} lock UL unlock S return
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
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;
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
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
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