430 likes | 564 Views
CS 290C: Formal Models for Web Software Lecture 4: Model Checking Navigation Models with Spin Instructor: Tevfik Bultan. Model Checking Navigation. We discussed modeling navigation using state machines. Once we have a navigation model, we would like to analyze it.
E N D
CS 290C: Formal Models for Web Software Lecture 4: Model Checking Navigation Models with SpinInstructor: Tevfik Bultan
Model Checking Navigation • We discussed modeling navigation using state machines. • Once we have a navigation model, we would like to analyze it. • We can use model existing model checking tools if we can write our state machine model in the input language of a model checker • There are model checkers (such as Spin) that can be used to specify and verify finite state machine specifications.
Model checking navigation in existing applications • The following paper uses model checking to analyze navigation: • “Automatic Extraction and Verification of Page Transitions in a Web Application”, Atsuto Kubo, Hironori Washizaki, Yoshiaki Fukazawa, APSEC 2007 • They focus on the Struts framework, I will discuss this paper in the next several slides
Model checking navigation • Model checking navigation can be done in two ways • We can first construct the navigation model, verify it, and then while implementing the application we can enforce the navigation model (forward engineering) • If we can enforce the navigation model precisely, then verification results hold for the final application • We can try to extract the navigation model from an existing application by analyzing the application, and then verify the properties of the extracted model (reverse engineering) • If the automatically extracted model is precise, then the verification results hold for the application
Model checking navigation • Web application typically have some navigation constraints that they wish to enforce. • For example • Transition to a particular page must be via a specific other page. For example, a page displaying the contents of the shopping cart must be displayed before proceeding to the checkout • From any position in the application the users should be able to go back to the home page • We would like to check these types of constraints on the navigation model
Web application model in Struts • The application model in Struts framework uses a set of pages and a set of transitions between pages • The pages are separated from the processing • Page generation is handled with JSP • Processing is handled by action servlets • JSP and servlets can be developed independently and the associations between them are made using a configuration file • The processing of the user requests is as follows; • The user sends form data as a request to the server • The server handles the request with and action servlet that makes calls to the business logic • The action servlet returns the processing results using a JSP
Navigation behavior in web applications • http is a stateless protocol • The state information for http sessions is held using • session cookies • or as part of the URI • However, clients can modify this content • so the server cannot control what will be the next request that will be sent by the client
Navigation behavior in web applications • In extracting a navigation model, we must decide what type of page transitions we are trying to model • In the most general case, we can assume that the user can transition from any page to any other page • Or we can allow transitions that only correspond to the links on the pages plus the backward or forward button of the browser • Or we can allow transitions that only corresponds to the links on the pages without using any navigation capability of the browser
Extracting navigation model for Struts • Kubo et al. extract a navigation model from Struts applications by focusing only only links provided by the application • They analyze • the Struts config file, and • the JSP template files to extract this information • Their analysis is limited, they do not perform any analysis on the Java code and may ignore transitions among pages that are allowed by the application • After extracting the state machine model they also simplify it and eliminate or merge transitions which they find uninteresting fro the verification perspective
Modeling user • After extracting the navigation state machine, they also generate a state machine that represents the user • The user can submit arbitrary requests to the web application • so the state machine his state machine modeling the user randomly generates requests in a loop and sends it to the web application
Generating the Promela model • Then, they generate a Promela model from the navigation state machine • They use an enumerated variable to represent the states of the navigation state machine • They generate a communication channel to represent the communication between the user process and the navigation state machine • They create one user process and one web application process and run them concurrently
Verifying the navigation model • They write navigation properties in LTL • Use the Spin model checker to check the properties on the Promela specification • Spin model checker outputs error traces for the properties that are violated
SPIN [Holzmann 91, TSE 97] • Explicit state model checker • Finite state • Temporal logic: LTL • Input language: PROMELA • Asynchronous processes • Shared variables • Message passing through (bounded) communication channels • Variables: boolean, char, integer (bounded), arrays (fixed size) • Structured data types
LTL Model Checking • Each LTL property can be converted to some type of automaton • Generate the property automaton from the negated LTL property • Generate the product of the property automaton and the transition system • Show that there is no accepting (infinite) path in the product automaton (check language emptiness) • i.e., show that the intersection of the paths generated by the transition system and the paths accepted by the (negated) property automaton is empty • If there is an accepting path, it corresponds to a counterexample behavior that demonstrates the bug
SPIN Verification in SPIN • Uses the LTL model checking approach • Constructs the product automaton on-the-fly • It is possible to find an accepting path (i.e. a counter-example) without constructing the whole state space • Uses a nested depth-first search algorithm to look for an accepting path (which is must end in a cycle since we are looking for infinite paths) • Uses various heuristics to improve the efficiency of the nested depth first search: • partial order reduction • state compression
Promela (PROcess MOdeling LAnguage) • Basic data types and ranges • bit (or bool) 0..1 • byte 0..255 • short -215-1 .. 215-1 • int -231-1 .. 231-1 bool flag; /* declares a boolean array */ int state; /* declares an integer variable called state */ • Array variables byte myarray[N] /* decleras an array of size N */
Processes • You can define processes using proctype proctype A() { byte state; /* local variable */ state = 3 } ; used as a separator not terminator, so no ; after the last statement
Processes • you can also use -> instead of ; byte state = 2; proctype A() { (state==1) -> state=3 } proctype B() { state = state – 1 }
Process Instantiation • You use an init block to identify initial states of the system init { skip } • You can use the init block to instantiate processes init { run A(); run B() } • run is used to start executing a process and can also pass arguments (basic data types) to a process
Atomic sequences • A sequence of statements can be executed atomically using the atomic construct atomic { (state==1) -> state=state+1}
Message passing • Channels can be used to model transfer of data from one process to another • Channels are basically FIFO message queues • Channels can store tuples of values at each location in the message queue chan qname = [16] of { int } • A channel that stores integer values chan qname = [16] of {int, int, bool} • A channel that stores tuples that consist of two integers and one boolean value
Message passing • Send operations: qname!expr sends the value of the expression expr to the channel named qname • Receive operations: qname?msg retrieves the message from the head of the channel qname and stores it in the variable msg
Rendez-Vous Communication • If the channel size is set to 0 then, the communication corresponds to synchronous communication • Sender and receiver must execute matching send and receive actions at the same time • If the sender (the receiver) reaches the send (the receive) operation before the receiver (the sender) reaches the receive (the send) operation, it has to wait chan port = [0] of {byte}
Control flow: case selection if ::(a!=b) -> option1 ::(a==b) -> option2 fi If more than one guard is executable, then one option is chosen nondeterministically
Control flow: repetition (loops) do :: count = count+1 :: count= count-1 :: (count==0) -> break od Only one option is selected for execution at a time. After that option is executed then the process is repeated
Enumerated variables • You can define enumerated variables using mtype mtype = {ack, nak, err, next, accept} chan q = [4] of {mtype, mtype, bit, short}
Example Mutual Exclusion Protocol Two concurrently executing processes are trying to enter a critical section without violating mutual exclusion Process 1: while (true) { out: a := true; turn := true; wait: await (b = false or turn = false); cs: a := false; } || Process 2: while (true) { out: b := true; turn := false; wait: await (a = false or turn); cs: b := false; }
Example Mutual Exclusion Protocol in Promela #define cs1 process1@cs #define cs2 process2@cs #define wait1 process1@wait #define wait2 process2@wait #define true 1 #define false 0 bool a; bool b; bool turn; proctype process1() { out: a = true; turn = true; wait: (b == false || turn == false); cs: a = false; goto out; } proctype process2() { out: b = true; turn = false; wait: (a == false || turn == true); cs: b = false; goto out; } init { run process1(); run process2() }
Property automaton generation • Input formula • “[]” means G • “<>” means F • “spin –f” option • generates a Buchi automaton for the input LTL formula % spin -f "! [] (! (cs1 && cs2))“ never { /* ! [] (! (cs1 && cs2)) */ T0_init: if :: ((cs1) && (cs2)) -> goto accept_all :: (1) -> goto T0_init fi; accept_all: skip } % spin -f "!([](wait1 -> <>(cs1)))“ never { /* !([](wait1 -> <>(cs1))) */ T0_init: if :: (! ((cs1)) && (wait1)) -> goto accept_S4 :: (1) -> goto T0_init fi; accept_S4: if :: (! ((cs1))) -> goto accept_S4 fi; } Concatanate the generated never claims to the end of the specification file
SPIN • “spin –a mutex.pml” generates a C program “pan.c” from the specification file • You need to use the “-a” flag to verify temporal logic formulas • The generated pan.c is a C program that implements the on-the-fly nested-depth first search algorithm • You compile “pan.c” and run it to the model checking • Spin generates a counter-example trace if it finds out that a property is violated • You can view the counter-example trace using “spin –t –p mutex.pml”
%mutex -a warning: for p.o. reduction to be valid the never claim must be stutter-invariant (never claims generated from LTL formulae are stutter-invariant) (Spin Version 4.2.6 -- 27 October 2005) + Partial Order Reduction Full statespace search for: never claim + assertion violations + (if within scope of claim) acceptance cycles + (fairness disabled) invalid end states - (disabled by never claim) State-vector 28 byte, depth reached 33, errors: 0 22 states, stored 15 states, matched 37 transitions (= stored+matched) 0 atomic steps hash conflicts: 0 (resolved) 2.622 memory usage (Mbyte) unreached in proctype process1 line 18, state 6, "-end-" (1 of 6 states) unreached in proctype process2 line 27, state 6, "-end-" (1 of 6 states) unreached in proctype :init: (0 of 3 states)
Modeling state machines with spin • To model a basic (flat) state machine with Spin we can do the following • Declare the states of the state machine as an mtype • Declare a variable called state that will store the current state of the state machine • Use the init block to initialize the state variable to an initial state of the state machine • Model the transitions of the state machine as a switch cases in a loop do ::(state==s1) -> state=s2 :: ... /* one choice for each transition */ ... od
An example #define state1 state==s1 #define state2 state==s2 #define state3 state==s3 #define state4 state==s4 #define p (state==s1 || state==s4) mtype = {s1, s2, s3, s4}; mtype state; proctype fsm() { do :: state==s1 -> state=s2; :: state==s2 -> state=s3; :: state==s3 -> state=s1; :: state==s3 -> state=s4; :: state==s4 -> state=s3 od } init { state = s3; run fsm() } A simple state machine and the corresponding Promela model (saved it in a file fsm.pml) p p s1 s2 s3 s4
An example • We can check properties such as the following LTL formulas (<> is F and [] is G): <> p (this property holds on our example) [] p (this property does not hold on our example) [] !p (this property does not hold our example either) []<> p (this property holds on our examle)
An example • To check propety <>p we create a never claim for its negation: % spin -f “! <> p” never { /* ! <> p */ accept_init: T0_init: if :: (! ((p))) -> goto T0_init fi; }
An example • Concatenate the never claim to fsm.pml and then do the following: % spin -a fsm.pml % gcc pan.c -o fsm % ./fsm • We get the output in the next page
Verification output $ ./fsm warning: never claim + accept labels requires -a flag to fully verify hint: this search is more efficient if pan.c is compiled -DSAFETY warning: for p.o. reduction to be valid the never claim must be stutter-invariant (never claims generated from LTL formulae are stutter-invariant) (Spin Version 4.2.6 -- 27 October 2005) + Partial Order Reduction Full statespace search for: never claim + assertion violations + (if within scope of claim) acceptance cycles - (not selected) invalid end states - (disabled by never claim) State-vector 24 byte, depth reached 8, errors: 0 7 states, stored 0 states, matched 7 transitions (= stored+matched) 0 atomic steps hash conflicts: 0 (resolved) 2.622 memory usage (Mbyte) unreached in proctype fsm line 11, state 2, "state = s2" line 12, state 4, "state = s3" line 15, state 10, "state = s3" line 17, state 14, "-end-" (4 of 14 states) unreached in proctype :init: (0 of 3 states) Means that the property holds
An example • Now let’s check the following property [] !p we create a never claim for its negation: % spin -f “! [] ! p” never { /* ! [] ! p */ T0_init: if :: ((p)) -> goto accept_all :: (1) -> goto T0_init fi; accept_all: skip }
An example % ./fsm warning: never claim + accept labels requires -a flag to fully verify hint: this search is more efficient if pan.c is compiled -DSAFETY warning: for p.o. reduction to be valid the never claim must be stutter-invariant (never claims generated from LTL formulae are stutter-invariant) pan: claim violated! (at depth 11) pan: wrote fsm.spin.trail (Spin Version 4.2.6 -- 27 October 2005) Warning: Search not completed + Partial Order Reduction Full statespace search for: never claim + assertion violations + (if within scope of claim) acceptance cycles - (not selected) invalid end states - (disabled by never claim) State-vector 24 byte, depth reached 11, errors: 1 6 states, stored 0 states, matched 6 transitions (= stored+matched) 0 atomic steps hash conflicts: 0 (resolved) 2.622 memory usage (Mbyte) Means that the property is violated
An example • Then we can generate the counter-example trace using “spin –t –p fsm.pml” This is referring to the state of the whole specification This is the variable we declared % spin -t -p fsm.pml Starting :init: with pid 0 Starting :never: with pid 1 Never claim moves to line 32 [(1)] 2: proc 0 (:init:) line 19 "fsm.pml" (state 1) [state = s3] Starting fsm with pid 2 4: proc 0 (:init:) line 20 "fsm.pml" (state 2) [(run fsm())] 6: proc 1 (fsm) line 13 "fsm.pml" (state 5) [((state==s3))] 8: proc 1 (fsm) line 13 "fsm.pml" (state 6) [state = s1] Never claim moves to line 31 [(((state==s1)||(state==s4)))] 10: proc 1 (fsm) line 11 "fsm.pml" (state 1) [((state==s1))] Never claim moves to line 35 [(1)] spin: trail ends after 11 steps #processes: 2 state = s1 11: proc 1 (fsm) line 11 "fsm.pml" (state 2) 11: proc 0 (:init:) line 21 "fsm.pml" (state 3) <valid end state> 11: proc - (:never:) line 36 "fsm.pml" (state 8) <valid end state> 2 processes created
How to model statecharts in spin • Statecharts can be converted to flat-state machines • So we can do the following: • Flatten the statecharts specification, which generates at regular state machine • Use the approach decribed in the previous slides • However this approach will result in a very large and ugly state machine
How to model statecharts in spin • Instead of flattening the statecharts, we can keep the hierarchy • Declare an mtype that lists the sub-states of all OR-states in the statecharts specification • Create one state variable of type mtype for each OR-state in the statecharts specification • Use the same type of modeling we used for basic state machines where there is one loop and there is a switch statement in the loop with multiple selections • However, this time each selection can correspond to multiple transitions • In case of AND-states we have to do the transitions together for each sub-state
How to model statecharts in spin • We can model the events using boolean variables • At each iteration of the loop select one event variable and set it to true • At the end of each transition set the event variable to false