Modeling and Verification of Mobile Systems - CiteSeerX

11 downloads 35475 Views 285KB Size Report
trative domains, hosts, physical locations, etc.); ... the agent's goal is to find the best airfare for a flight with .... the threads dynamically loaded from a remote host.
Modeling and Verification of Mobile Systems Chiara Braghin

Natasha Sharygina

University of Lugano Lugano, Switzerland

Univ. of Lugano and Carnegie Mellon University Lugano, Switzerland and Pittsburgh, PA, USA

[email protected]

[email protected], [email protected]

ABSTRACT This paper describes an approach for modeling and verification of mobile systems. Mobile systems are multi-threaded programs that are characterized by 1) the explicit notion of locations (e.g., sites where they run), 2) the ability to create and execute (possibly infinite) threads at multiple locations (e.g., sites), and 3) the capability to withstand network failures. We give formal semantics to mobile systems as Labeled Kripke Structures (LKSs), which encapsulate the notion of location and unbounded thread creation. This notation allows for the modeling of both data and communication structures of the multi-threaded systems and, thus, outperforms the traditional process algebra approach which captures only the communication behavior. We show how mobile programs can be exhaustively analyzed by using model checking techniques. The LSKs are readily usable from within the SATABS toolset. SATABS implements the SAT-based counterexample-guided abstraction refinement framework (CEGAR for short) for ANSI-C programs, and supports verification of multi-threaded programs with unbounded thread creation. We are currently developing a front-end to SATABS that allows for languages with explicit location features, such as mobile agents. To the best of our knowledge, this is the first approach that allows modeling and verification of the full spectrum of mobile systems properties.

1.

INTRODUCTION

Programming a concurrent application is difficult: deadlocks and race conditions are well-known problems in multithreaded applications on a single machine. Programming a concurrent application running on a distributed network, where threads may be executed both at the same site or at different sites, is even more difficult, as we must deal with additional problems such as partial failure of one or more sites. In recent years, large-scale computer networks have become an essential aspect of our daily computing environ-

ment. Programming a concurrent application running on a network that includes mobile hosts or mobile software is even more difficult. Programming over a wide area network such as the Internet distribution, not only introduces new issues to the field of multi-threaded programming and analysis, but also breaks many postulates commonly assumed in concurrent systems. For example, during execution of a mobile program a given thread may stop executing at a site, and continue executing at another site. That is, threads may jump from site to site while retaining their conceptual identity. The following issues distinguish mobile systems from a more general case of multi-threaded programs: - threads may run in different locations (e.g, administrative domains, hosts, physical locations, etc.); - communication among threads takes into account their geographical distribution: there exists distinction among local and global communication due to bandwidth fluctuations, node failures, etc. - threads migration also takes into account the geographical distribution of threads (e.g., there exist rules that constrain the migration only to the directly linked net locations). An example of a shopping agent (see Figure 1) demonstrates the issues specific to mobile programs. In the common jargon, an agent is a thread that, created in one execution environment, can migrate to another execution environment in the network, where it resumes its execution. In our example, the agent’s goal is to find the best airfare for a flight with a particular route. The agent is given various requirements, such as departure and destination, time restrictions, etc., and sent out to find the cheapest ticket before committing to a particular purchase. The agent will roam the network, visit some airline Web-sites and query their databases before reporting back to the user who made the request. If necessary, it waits for the price to fall to a client-specified level, and returns when either the price reaches that level or a client-specific period of time has elapsed. Analysis of mobile programs is an active research area. The most common approach to address the issues specific to mobile programs is the process algebra-based approach. Process algebra is an algebraic framework built from a reduced

We show how mobile systems can be exhaustively analyzed by model checking. Our models are readily usable from within the SATABS model checker [11]. SATABS implements the SAT-based counterexample-guided abstraction refinement framework (CEGAR for short) for ANSI-C programs and supports verification of multi-threaded programs with unbounded thread creation. In summary, our approach has several advantageous features: • it explicitly models thread location, location distribution and thread moving operations that are essential elements of mobile programs; Figure 1: A shopping agent. Here, `0 to `4 are locations representing sites, and T1 to T6 threads.

• it handles unbounded thread creation; • it preserves both data and communication of mobile systems;

number of operators, yet expressive enough to model a wide range of computational systems and data structures. Process algebras has proved to be valuable mathematical tools to reason about the behavior of concurrent and communicating systems (e.g., CSP [32] and π calculus [28]). Various location-aware calculi, with an explicit notion of location, have arisen in the literature to directly model phenomena such as the distribution of processes within different localities, their migrations, or their failures [5, 23, 17, 21]. The most famous one is the Mobile Ambient calculus [4, 5] (MA for short): this tiny but extremely expressive specification language provides a very simple framework that encompasses mobile agents, the domains where agents interact and the mobility of the agents themselves. The disadvantages of process algebra-based approaches, however, is that they model only limited details of the systems (e.g., they are restricted only to communication structures and do not preserve any data information). This restricts the set of properties that can be analyzed only to a set of the control-specific properties. Additionally, process-algebraic techniques usually deal with coarse over-approximations during the analysis of mobile systems. Over-approximations are useful to reduce the analysis complexity and guarantee that, if no errors are found in the abstract system, then no errors are present in the actual system. However, if errors are found, the verification techniques developed for process algebra fail to guarantee that they are real. To do so, other analysis techniques (for example, model checking) simulate the errors on the actual system and, if the errors are found to be spurious, the approximated programs are refined. To best of our knowledge, there are no abstraction-refinement techniques that would support the process algebraic analysis techniques. This paper describes an original approach for modeling and verification of mobile systems. We give formal semantics to mobile systems as Labeled Kripke Structures (LKSs) which encapsulate the notion of location and unbounded thread creation that are typical to mobile systems. We define semantics of mobile programs where thread locations are hierarchically structured, where threads are always confined to locations and where threads may move within Internet. The LKS notation allows modeling both data and communication structures of the multi-threaded systems and, thus, outperforms the traditional process algebra approach that captures only the communication behavior.

• it enables exhaustive analysis of mobile programs using abstraction-refinement-based model checking techniques. We are currently developing a front-end to SATABS that allows for languages with explicit location features such as mobile agents. The rest of the paper is organized as follows. Section 2 gives some preliminary information. Here, we distinguish between the generic multi-threaded programs and mobile systemsspecific multi-threaded programs (also called location-aware multi-threaded systems). Section 3 defines formal semantics of mobile systems. Section 4 gives examples how verification properties of mobile systems can be defined. Section 5 maps the modeling techniques to the SATABS-based model checking approach, and Section 7 concludes the paper with the summary of the contributions.

2.

PRELIMINARIES

This section first (Section 2.1) discusses the subtle differences between general multi-threaded programs and mobile systems. It also outlines how the features specific to mobile systems are supported by programming languages. Then, (Section 2.2) it defines syntax of both general multi-threaded programs and mobile programs (which we call location-aware multi-threaded programs). Finally, (Section 2.3), it provides some background definitions of Labeled Kripke structures which we use in the later section to define semantics of mobile programs.

2.1

Programming Languages for Mobile Code

In the last decade, the Web has rapidly evolved into a global computing platform, which main characteristic is the geographical distribution. Currently, the state of the practice is that general purpose programming languages (e.g., ANSIC, C++, Java, etc.) are used to implement mobile systems. Additionally, a number of new generation programming languages viewing the network and its resources as a global computational environment have been proposed. They are characterized by the capability to provide some sort of code mobility, and to allow distributed multi-threading, i.e., threads running concurrently in different locations. This new programming paradigm demonstrates features that make

mobile programs different, and more complex, from the standard notion of multi-threaded computing. These features are essential and we believe that they should be explicitly modeled and verified. In this section, we first list the key characteristics of mobile systems. They are defined in general terms disregarding any particular implementation language. In particular, we show that the core features are thread location and location net. Then, we demonstrate how two programming languages implement these features: Java, the most commonly used language to implement mobile systems, and Telescript, one of the pioneering languages that introduced the notion of thread mobility. Key features of mobile programs. The key characteristics of mobile programs are: - an explicit notion of location (e.g., physical locations (hosts), administrative domains where threads run, etc.); - locations are structured to capture the distributed environment of the Web (e.g., an application running on several sites); - the capability for a thread to migrate; - the distinction between local and global thread communication to depict communication within a single administrative domain or among different domains. As a first example demonstrating these features, we consider the Telescript language [35]. Telescript [35] is a rich, object-oriented language conceived for the development of large distributed applications, oriented in particular to the electronic market. It is an agent-based language that explicitly deals with locality and mobility: there are two kinds of entities, agents, i.e., threads that can move, and places, i.e., physical locations that offer services and can contain other agents or places. A thread running on an interpreter (called engine in the Telescript jargon) is able to migrate autonomously to another engine run by a different machine by executing a go instruction. This operation causes the engine to suspend the thread, serialize it together with its state, and transmit it to the destination engine specified as argument. There, the thread will be unserialized, and its execution will be resumed from the instruction following the go. If a trip cannot be made, the go instruction fails and the thread throws an exception. Migration is transparent by default, i.e., only the final destination is given by the agent, but the go method allows the agent to request explicitly the route to follow. Agents do not communicate remotely with other agents; rather, they move to some location and communicate locally when they get there by executing a meet instruction. Java [27] is another example. It is a portable, generalpurpose, object-oriented language which deals with distribution and mobility by means of three different mechanisms: applets, dynamic class loading, and aglets. Applets transmit program sources in a platform-independent preprocessed form (i.e., the Java byte code), rather than using threads.

The class loader performs the loading and linking of the different classes that compose a Java application at run-time. By default it loads the classes from the local host file system, but, instead of having a fixed policy for resolving class names at run-time, Java provides the capability to program where the code corresponding to an unresolved class name may be retrieved, allowing classes to be loaded from the network. However, this kind of mobility is not under the control of the threads dynamically loaded from a remote host. Aglet software development kit (ASDK) [16] was originally developed by the IBM Tokyo research laboratory, and is now hosted at SourceForge.net as an open source project. An aglet is a mobile agent written in Java and named after the base class in the Aglets library. The Aglet class defines the default properties and methods for a thread to control its mobility and life-cycle. In particular, during its execution, by calling the dispatch method, an aglet can dispatch itself from an execution context to others either in the same Java virtual machine or on remote hosts. Moreover, aglets may communicate both by local and remote message passing. As an implementation example demonstrating the features of mobile programs, consider the Telescript implementation of the shopping agent example [35]. Example 2.1. The shopping agent scenario depicted in Figure 1 consists of different locations representing a user personal computer and the servers hosting the various airline Web-sites. The shopping agent is a thread that migrates from his home location (i.e., the personal computer) to the airline locations to collect informations on their flights. In the Telescript programming language, migrating threads are called agents, whereas locations are called places. Moreover, user-defined classes for agents and places are subclasses of the predefined Place and Agent classes. In our example, the shopping thread correspond to a Telescript agent, and two place classes must be defined: one for the airline locations (in the example they all offer the same services), and one for the home location of the thread. In the following, we give the definition of the three classes, omitting the details which are out of the scope of the paper. The Airline Location class is defined as follows: Airline_Location: class (Place) = ( public flightSearch: op (src, dest, date: String) List = { /* body */ } property flightCatalog: Dictionary[String, Entry]; ) Note that within a class definition the three keywords public, private and property distinguish among public and private methods, and local or global variables, respectively. In addition, List and Dictionary are predefined types with the usual meaning. The meaning of the code is rather intuitive: a Airline Location offers a method to look for flights, given the desired source, destination and date of the trip. The method searches within the flightCatalog and returns a, possibly empty, list of flights available. Each location `1 to

`n from Figure 1 will be an object of this class, while `0 will be an instantiation of the following class:

T

Instr

| ::=

Expr

| | | | | | ::=

Home_Location: class (Place) = ( private orderFlight: op (src, dest, date: String) = { Shopping_Agent (src, dest, date: String); /* check returned list of flights */ } ) This class has only one private method that creates an agent which goes to search in the Web for a cheap flight. The places where to migrate must be given in the omitted body code.

Shopping_Agent: class (Agent) = ( public showReport: op () = { ... }; private goShopping: op () = { ... }; checkPrice: op () = { ... }; goHome: op () = { ... }; property homeAddress, clientName: String; desiredPrice, actualPrice: Integer; source, destination, date: String; ) The goShopping and goHome methods are based on the predefined method go. The goShopping method contains the list of Airline locations to visit and possibly some of the route details specified by the user (e.g., the period of time to do the research, the price range, etc.). 

In the next section, we formalize in a language-independent way the features of mobile systems highlighted here .

2.2

Threads vs Location-aware Threads

This section first defines the syntax of generic multi-threaded programs. To this aim, we use a C-like programming language (which we believe is one of the most popular generalpurpose languages) augmented with a threads package. Then, it defines the syntax of mobile programs by extending the generic definition with the notions of location and moving actions.

2.2.1

Multi-threaded Programs

The syntax of a multi-threaded program is defined using a finite set of variables (either local to a thread or shared among threads), a finite set of constants, and a finite set of names, representing constructs for thread synchronization, such as post and wait of Fortran, Ada rendezvous constructs, or the Java wait and notify constructs. It is specified by the following grammar (here, x ranges over variables, c over constants, and m over the names of synchronization constructs):

::=

| | | |

T1 | T2 Instr Instr1 ; Instr2 x := e if (Expr != 0) Instr while (Expr != 0) Instr skip m fork c Expr1 Expr1 Expr1 Expr1

+ * /

Expr2 Expr2 Expr2 Expr2

threads parallel comp. sequential exec. instructions sequential exec. assignment condition loop skip sync. call thread creation expressions constant sum difference product division

The meaning of the constructs for expressions and instructions is rather intuitive: an expression can be either a constant or an arithmetic operation (i.e., sum, difference, product and division). The instruction set mainly consists of the standard instructions for imperative languages: a sequential composition operator (;), the assignment instruction, the control flow instructions if and while, and the skip statement. The instructions specific to the threads package are the fork instruction, which spawns a new thread that is an exact copy of the thread executing the fork instruction, and the call to a synchronization method m. A composition T1 | T2 describes two threads T1 and T2 running in parallel. Concurrent threads may proceed independently or they may interact in two ways:

- by means of shared variables;

- a ` la CSP [32], on a set of shared actions, in our case the synchronization method m.

A multi-threaded program consists of multiple threads running in parallel.

2.2.2

Location-aware Multi-threaded Programs

The standard definition of multi-threaded programs is not expressive enough to describe mobile systems, so this section introduces an explicit notion of location. In addition to the set of variables, constants, and synchronization construct names, we assume a set of location names Loc. The syntax of a location-aware multi-threaded program can be derived by extending the generic multi-threaded program, and is specified by the following grammar (we omit the unnecessary repetitions, and we let `, `1 , `2 , . . . range over Loc.):

LT

T

Instr M Instr

::= | | ::= | | ::= | ::= | |

`[[ T ] LT1 k LT2 T1 | T2 Instr ··· M Instr go in(`) go out(`)

location-aware threads single thread parallel composition threads parallel composition sequential execution instructions moving instructions moving actions move in move out

Each location-aware thread is uniquely identified by a location. A location-aware thread is written `[[ T ] , with ` being the location name of thread T . Moreover, more than one thread may be identified by the same location, that is `[[ T1 | T2 ] (examples will be shown later). A location-aware multi-threaded program consists of the parallel composition of multiple location-aware threads. A location can thus be seen as a bounded place, where multi-threaded computation happens. Conceptually, thread locations represent the geographical distribution of the Web. To capture this fact we use a special structure called location net that encapsulates the hierarchical nesting of the Web. We define the location net as a tree, whose nodes are labeled by unique location names, and the root labeled by the special location name env, which represents the external environment of the system under analysis. A tree t` is identified with the set of its paths, i.e., t` will be a finite, possibly empty, subset of Loc∗ .

Example 2.2. For example, the set of locations of the mobile system of Figure 1 is Loc = {env, `0 , `1 , `2 , `3 , `4 }. Some of the locations are nested, and the location net corresponds to the following tree.

explicit notion of location and the existence of moving actions effect the interaction among concurrent threads as follows (the formal definition will be given in Section 3): - There are two types of composition: the parallel composition among location-aware threads identified by the same location (i.e., `[[ T1 | T2 ] ), and the parallel composition among location-aware threads identified by different locations (i.e., `1 [ T1 ] k `2 [ T2 ] ) - see the example below. - The execution of moving actions changes the location net, i.e., mobility can be described by updates of the location net. - The execution of moving actions is constrained by the structure of the location net, i.e., moving actions can be performed only if the thread location and the target location are father-child or siblings. Example 2.3. For example, the shopping agent program in Figure 1 with the set Loc and the location net as defined in Example 2.2, can be formalized as a location-aware multithreaded program as follows: `0 [ T1 | T2 ] k `1 [ T3 ] k `2 [ T4 ] k `3 [ T5 ] k `4 [ T6 ] Threads T1 and T2 may represent a mail server and a browser, respectively, while T3 may be defined as T3 = go out(`0 ); go in(`2 ); T30 In this program, threads T1 and T2 are running in parallel locally since `0 [ T1 | T2 ] . On the contrary, T3 and T4 are running remotely since `1 [ T3 ] k `2 [ T4 ] . Let us now suppose that thread `1 [ T3 ] executes the first instruction, then `1 [ go out(`0 ); go in(`2 ); T30 ] 6→ env[[ go in(`2 ); T30 ] as a reader could expect, but `1 [ go out(`0 ); go in(`2 ); T30 ] → `1 [ go in(`2 ); T30 ] and the location net is updated as depicted in the following instr picture (where it is informally written −−−−→ to mean that the thread executes instruction instr).

The tree can be also identified by the set of its paths, i.e., t` = {env.`0 .`1 , env.`2 , env.`3 , env.`4 }. In the rest of the paper, when referring to nodes of the location net, we borrow some standard vocabulary to define the relationship among tree nodes, such as a father, a child and a sibling. For instance, in our example, `2 and `3 are siblings, whereas `0 is the father of `1 (and, obviously, `1 is the child of `0 ). 

The location net represents the topology of thread locations. In fact, it implicitly represents the distribution of threads. Location-aware threads are capable to perform moving actions to support the distribution. In our notation, these actions are the moving instructions, go in and go out. The

In this case, the moving instruction go out(`0 ); can be executed since location `0 and location `1 are father and child, i.e., location `1 is nested inside `0 , thus a location-aware thread identified by location `1 can go out of location `0 . 

In the current state of the project, we support only local communication (i.e., only threads identified by the same location, such as `0 [ T1 | T2 ] , can synchronize by means of shared actions).

Example 2.4. Consider the location-aware program defined in Example 2.3. In that program, threads T1 and T2 can communicate since they are identified by the same location (i.e., `0 ). On the contrary, threads T2 and T3 cannot communicate since they are identified by different locations (i.e., `0 and `1 , respectively). 

- Si is a (possibly infinite) set of states; - Initi ∈ Si is the initial state; - APi is the set of atomic propositions; - Li : S → 2AP is a state-labeling function; - Σi is a finite set (alphabet) of actions;

2.3

A Labeled Kripke Structure

A Labeled Kripke structure [7] (LKS for short) is a 6-tuple (S, Int, AP, L, Σ, R) where: (i) S a finite non-empty set of states; (ii) Init ∈ S is the initial state; (iii) AP is a finite set of atomic state propositions; (iv) L : S → 2AP is a statelabeling function; (v) Σ a finite set (alphabet) of actions; and (vi) R ⊆ S × Σ × S is a labeled transition relation.

- Ri ⊆ Si ×Σi ×Si ∪{Si ×Si } is a total labeled transition a relation. We write s −−→ i s0 to mean (s, a, s0 ) ∈ Ri , with a ∈ Σi . Note that, since we allow thread creation, fork s0 can be defined as a pair of states s.t. s −−−−−→ i (s0 , s), 0 where s is the next state of s, and s = Initi is an initial state of the newly created thread.

a

We will often write s −−→ s0 to mean (s, a, s0 ) ∈ R, with a a ∈ Σ. Thus, s −−→ s0 will express the fact that the system when in state s can perform an action a and consequently change its state to s0 . Notice that both states and transitions are labeled: the former with sets of atomic propositions (expressing data), and the latter with an action (expressing communication). A path π = hs1 , a1 , s2 , a2 , . . .i of a LKS is an alternating (possibly infinite) sequence of states and events such that s1 = Init and, for each j ≥ 1, sj ∈ S, aj ∈ Σ, and aj sj −−→ sj+1 . A path represents a single run (one possible computational path) of a LKS. The language of an LKS M , denoted L(M ), consists of the set of maximal paths of M whose first state is the initial state Init. Let M = (S, Int, AP, L, Σ, R) and A = (SA , IntA , APA , LA , ΣA , RA ) be two Labeled Kripke structures. We say that A is an abstraction of M , written M v A, iff: - APA ⊆ AP , - ΣA = Σ, - For every path π = hs1 , a1 , . . .i ∈ L(M ) there exists a path π 0 = hs01 , a01 , . . .i ∈ L(A) such that, for each i ≥ 1, a0j = aj and LA (s0j ) = L(sj ) ∩ APA . In other words, A is an abstraction of M if the ’propositional’ language accepted by A contains the ’propositional’ language of M , when restricted to the atomic propositions of A. Two-way abstraction defines an equivalence relation ∼ on LKSs: M ∼ M 0 iff M v M 0 and M 0 v M .

3.

THE COMPUTATIONAL MODEL

This section formalizes the semantics of mobile programs as they defined in Section 2.2. In Section 3.1, we describe the semantics of a single thread, whereas in Section 3.2 we give the formal definition of a location-aware multi-threaded systems.

3.1

A Location-aware Thread

Definition 3.1 (Location-aware Thread). Let 1 ≤ i ≤ n be an integer value identifying a thread. Then the thread is defined as an LKS Ti = (Si , Initi , APi , Li , Σi , Ri ) such that:

The set of states Si of a location-aware thread Ti is defined as a tuple (Vl , Vg , pc, ϕ, η), where Vl is the set of local variables, Vg is the set of global variables, pc is the program counter, ϕ : Loc → Loc is a partial order function denoting the location net (where Loc is the set of location names as defined in Section 2.2.2), and η : N → Loc is a partial function denoting the thread location. More specifically, ϕ describes the location net at a given state by recording the father-child relationship among all nodes of the net (⊥ in the case of env), whereas η(i) returns the location name of thread Ti . Example 3.2. Consider the location-aware program of the shopping agent defined in Example 2.3. Its location net corresponds to the following composition (both local and global) of the system threads: `0 [ T1 | T2 ] k `1 [ T3 ] k `2 [ T4 ] k `3 [ T5 ] k `4 [ T6 ] The location net function is defined as ϕ(`0 ) = env, ϕ(`1 ) = `0 , ϕ(`2 ) = env, ϕ(`3 ) = env, ϕ(`4 ) = env, and the thread location function is defined as η(`0 ) = env, η(1) = `0 , η(2) = `0 , η(3) = `1 , η(4) = env, η(5) = `3 , η(6) = `4 . 

The transition relation Ri is labeled by the actions of which there are four types: moving, synchronization, thread creation, and τ actions, which are contained in the mutually disjoint sets ΣM , ΣS , ΣT , Στ , respectively. We write Σ for the set of all actions, with Σ = {(go in(l), go out(l)), m, fork, τ }. τ represents a generic action such as an assignment, a function call, etc. Table 1 gives the inference rules for moving actions (go in(l), go out(l), thread creation action, fork, and the synchronization action m. For the other rules corresponding to the generic operations the reader is referred to [15]. Table 1 defines the inference rules for the labeled transition relation. It uses the following notation. A single state belonging to Si is denoted by si , i.e., with a superscript and variable i we indicate the thread number of individual states. When needed, we also use a subscript (and variable j) to indicate the index of an element of a particular path. For example, si1 is the initial state of thread Ti . Given a state si ∈ Si of thread Ti , si .Vl , si .Vg , si .pc, si .ϕ and si .η are the values of local variables Vl , of global variables Vg , of program counter pc, of ϕ and of η, respectively. Moreover,

(Fork-action) Instr(s.pc) = fork fork

s −−−→

i

(s0 , s) [s0 .pc = s.pc + 1; s = Initi ]

(in-action) Instr(s.pc) = go in(`) ∧ (∃`1 s.t.: `1 := s.η(i) ∧ s.ϕ(`1 ) = s.ϕ(`)) go in(l)

s −−−−−−→

i

s0 [s0 .pc = s.pc + 1; s.ϕ ∪ {` 7→ `1 }]

(out-action) Instr(s.pc) = go out(`) ∧ (∃`1 s.t.: `1 := s.η(i) ∧ s.ϕ(`1 ) = `) go out(l)

s −−−−−−→

i

s0 [s0 .pc = s.pc + 1; s.ϕ ∪ {`1 7→ s.ϕ(`), ` 7→ `1 }] (Sync-action) Instr(s.pc) = m m

s −−→

i

s0 [s0 .pc = s.pc + 1]

Table 1: Inference rules for the labeled transition relation Ri for thread Ti . (Sync-action) 01

a

1 a ∈ ΣC −→ 1 ∧s −

1

s

02

a

2 ∧ a ∈ ΣC −→ 2 ∧s − a

01

s

2

∧ s1 .η(1) = s2 .η(2)

02

(s1 , s2 ) −−→ (s , s ) (L-Par)

(R-Par) 01

a

−→ a ∈ ΣM 1 ∧s − 1

02

a

2 a ∈ ΣM −→ 2 ∧s −

s

01

a

(s1 , s2 ) −−→

1

s

02

a

(s1 , s2 ) −−→

(s , s2 )

2

2

(s1 , s )

Table 2: The labeled transition relation for the parallel composition of two threads. Instr(si .pc) denotes the instruction pointed by pc in thread Ti at state si . The premises of the rules presented in Table 1 represent guarded conditions for the execution of the actions. All rules check the value of Instr(s.pc) that determines the instruction to be executed by the running thread. Then, depending on the type of the action, they check further guarding conditions. In the consequences of the inference rules, we describe within square brackets the updates of the thread state caused by the execution of an action. We use the standard notation ϕ ∪ {`1 7→ `2 } (with `1 , `2 ∈ Loc) to indicate the update to function ϕ, i.e., the updates to the location net. In the case of a ”fork” action, thread Ti spawns a new thread that is an exact copy of itself. As a consequence, the program counter of Ti is updated, and a new thread is created with an initial state s. The initial state is a copy of the initial state of Ti . In the case of a ”go in(l)” action, if ` is a sibling location to thread Ti location (i.e., s.ϕ(s.η(i)) = s.ϕ(`)), then the thread makes a transition and changes the state accordingly: the program counter pc is incremented, and the location net is updated (` is now the father location of Ti location). If ` is not a sibling location, then the action is not performed because the guard does not hold.

In the case of a ”go out(l)” action, if ` is the father location of thread Ti location (i.e., s.ϕ(s.η(i)) = `), then the thread makes a transition and changes the state accordingly: again, the program counter pc is incremented, and the location net is updated. If ` is not a parent location, then the action is not performed. Note that the subtle features of mobile programs (namely, location, location net and unbounded thread creation) are modeled explicitly.

3.2

A Location-aware Multi-threaded System

Let T1 , · · · , Tn be a set of threads initially present in the mobile program P, then P = T1 k · · · k Tn . The parallel composition operation is defined as follows1 .

Definition 3.3 (Location-aware Program). Let thread T1 = (S1 , Init1 , AP1 , L1 , Σ1 , R1 ) and thread T2 = (S2 , Init2 , AP2 , L2 , Σ2 , R2 ) be two Labeled Kripke structures. Then their composition is defined as follows: T1 k T2 = (S1 × S2 , Init1 × Init2 , AP, L, Σ1 ∪ Σ2 , R) with the labeled transition relation defined in Table 2. 1 See case 1 of Theorem 4.6 for the properties of parallel composition.

In other words, threads proceed independently on local actions and synchronize on shared actions (m ∈ ΣM ), or on shared data (by definition of Si , S1 ∩ S2 6= ∅). In this project, we allow only local communication: threads T1 and T2 can synchronize only if they are identified by the same location, i.e., s1 .η(1) = s2 .η(2). However, it is straightforward to add more complex communication mechanisms, distinguishing among input and output communication, or sending variables along channels, as in the π calculus [28]. Additionally, one also could model communication among threads identified by father-child locations, ` a la Boxed Ambient [2], by adjusting the constraints of the synchronization rule.

4.

SPECIFYING PROPERTIES OF MOBILE PROGRAMS

This section demonstrates how properties of mobile systems can be specified. To this aim, we define: 1) a location projection function, 2) a moving projection function, and 3) a thread projection function. First, we define a path of a mobile thread. The definition reflects a possibility of unbounded thread creation during the execution of the fork instruction. Definition 4.1 (Path). A path π = h(s11 , s21 , . . . , sn 1 ), a1 , (s12 , s22 , . . . , sm 1 ), a2 , . . .i of a single thread is an alternating (possible infinite) sequence of tuples of states and events such that: (i) m, n ∈ N and, ∀i, j ≥ 1, si1 = Initi , sij ∈ Si , and aj ∈ ∪i Σi ;

Then, a possible path π formalizing the semantics of the thread is: hs11 , go in(l), s12 , m, s13 , go out(l), s14 , fork, (s15 , s21 ), fork, (s16 , s22 , s21 )i.



The path definition can be extended in a straightforward manner to deal with multiple threads. Given a path of a concurrent system T1 k · · · k Tn , one can construct projections by restricting the path to some of the actions in the alphabets of the threads, or to the states satisfying some conditions. In particular, the explicit notion of location leads nicely to the definition of location-based projections, which allows efficient verification of locationspecific properties. In the following definitions, we will assume only paths of finite length, as they are computed by the symbolic fixpoint algorithm to handle verification of systems with an unbounded number of threads (see the next section for further details). The following notation is used further: we write hi for the empty path, and we use the dot notation to denote the concatenation of sequences. The concatenation of sequences will be used in the inductive definitions of projections to concatenate subsequences of paths. For example, given π as defined above, it could be represented as the concatenation of two sequences hs11 , in l, s12 , m, s13 , out l, s14 , fork, (s15 i.hs21 ), fork, 1 2 2 (s6 , s2 , s1 )i. Notice that . is the concatenation operator for sequences of characters, thus it is not affected by the presence of mismatched parentheses.

aj

(ii) either sij −−−→ sij+1 or sij = sij+1 for 1 ≤ i ≤ n; (iii) if aj = fork: – then m = n + 1 and – else m = n.

sm 1

=

sk1

with

skj

aj

−−−→

skj+1

A path includes tuples of states, rather than individual states. The reason for that is that when a fork operation is executed, the state of the newly created thread must be recorded. Our notation indicates each state by two indices, i and j, one to indicate the thread number, the other one to indicate the path length, respectively. The size of the tuple of states (i.e., the number of the currently existing threads) increases only if a fork is executed, otherwise it remains unchanged (case (iii)). In case of a fork, index k identifies the thread that performed the action. Thus, the state of the newly created thread is a copy of the initial state of thread Tk . Moreover, depending on the type of action (i.e., shared or local) one or more threads will change state, whereas the others do not change (case (ii)). To demonstrate this notation, consider the following example. Example 4.2. Consider the following location-aware thread: go in(`); m; go out(`);fork; fork;

Definition 4.3 (Location Projection, π ↓ `). Let P be T1 k · · · k Tn and ` ∈ Loc be a location. The projection function P roj` : L(P)∗ → L(P)∗ is defined inductively as follows (we write π ↓ ` to mean P roj` (π)): 1. hi ↓ ` = hi 2. If si .η(i) = ` then (hsi i.π) ↓ ` = hsi i.(π ↓ `) 3. If si .η(i) 6= ` then (hsi i.π) ↓ ` = π ↓ ` 4. If a ∈ Σi , with i s.t. si .η(i) = `, then (hai.π) ↓ ` = hai.(π ↓ `) 5. If a 6∈ Σi , with i s.t. si .η(i) 6= `, then (ha, (s1 , s2 , . . . , sn )i.π) ↓ ` = π ↓ `

This projection traces the threads execution for a particular location. The following information is collected: (i) states of threads whose location is ` (i.e., threads Ti such that si .η(i) = `), and (ii) actions that are performed by the threads whose location is ` (i.e., actions a such that a ∈ Σi , with `[[ Ti ] ). Here, the concatenation is done on each state element of the path, since each single state is examined to satisfy condition (i) (see rules 2-3). On the contrary, once an action does not satisfy condition (ii), the next tuple is

erased (see rule 4). It is straightforward to extend this definition to collect information on all location-aware threads that perform a go in(`) or a go out(`) actions; this property is essential when verifying security issues of mobile systems.

1. Parallel composition is (well defined and) associative and commutative up to ∼-equivalence. 2. Let T1 , . . . , Tn be LKSs, and let A1 , . . . , An be the respective abstractions of the Ti : for each i, Ti v Ai . Then, T1 k · · · k Tn v A1 k · · · k An .

Definition 4.4 (Moving Projection, π ↓M i). Let P be T1 k · · · k Tn . For 1 ≤ i ≤ n, the projection function P rojiM : L(P)∗ → L(P)∗ is defined inductively as follows (we write π ↓ i to mean P roji (π)):

3. Let T1 , . . . , Tn be LKSs with alphabets Σ1 , . . . , Σn , and let π be a path of T1 k · · · k Tn . Then, π ∈ L(T1 k · · · k Tn ) iff, for each i, there exists πi0 ∈ L(Ti ) such that π ↓ i is a prefix of πi0 .

1. hi ↓M i = hi i 2. ( h(s11 , s21 , . . . , sn 1 )i.π ) ↓M i = hs1 i.(π ↓M i) 1 2 n i 3. If a ∈ ΣM i then (haj , (sj , sj , . . . , sj )i.π) ↓M i = haj , sj i. (π ↓M i)

Sketch of the Proof. The correctness of the theorem follows directly from the definitions 4.1 and 4.5, and from the properties of set union. For the full proof we refer the reader to [32].

1 2 n 4. If a 6∈ ΣM i then (haj , (sj , sj , . . . , sj )i.π) ↓M i = π ↓M i

Here ΣM = { go in(l), go out(l) }. This allows keeping track of all the moving actions executed by thread Ti . Therefore, our framework is able to track the route followed by each thread. Many other location-specific properties can be specified, e.g., which thread interacts with the other threads, in what order and under which conditions, etc. This ability is of paramount importance since mobility requires more than the traditional notion of authorization to run and to access information in certain domains: it involves the authorization to enter or exit certain domains. Thus we can exploit our verification framework for security analysis. Definition 4.5 (Thread Projection, π ↓ i). Let P be T1 k · · · k Tn . For 1 ≤ i ≤ n, the projection function P roji : L(P)∗ → L(P)∗ is defined inductively as follows (we write π ↓ i to mean P roji (π)): 1. hi ↓ i = hi i 2. ( h(s11 , s21 , . . . , sn 1 )i.π ) ↓M i = hs1 i.(π ↓M i) i 3. If a ∈ Σi then (haj , (s1j , s2j , . . . , sn j )i.π) ↓ i = haj , sj i. (π ↓ i).

4. If a 6∈ Σi then (haj , (s1j , s2j , . . . , sn j )i.π) ↓ i = π ↓ i. Intuitively, the projection π ↓ i of π = h(s11 , s21 , .., sn 1 ), a1 , . . .i on Ti consists of the (possibly infinite) subsequence hsi1 , a1 , . . .i obtained by removing all pairs haj , (s1j , s2j , . . . , sn j )i for which aj 6∈ Σi and by removing all states stj where 1 ≤ t ≤ n and t 6= i (i.e., those states that do not belong to Ti ). As a consequence of Definition 4.5, the following theorem extends similar standard results obtained for CSP, and enable efficient compositional analysis of multi-threaded programs: abstraction, counter-example validation, and refinement can all be done one thread at a time. Theorem 4.6 (Soundness). Let π be a path, and k be defined as in Table 2, then:

The theorem states that parallel composition preserves the abstraction relation, and that it is possible to check whether a path belongs to the language of a mobile program by projecting and examining the path on each individual thread separately.

5.

VERIFICATION OF LOCATION-AWARE MULTI-THREADED SYSTEMS

As shown in the previous section, the explicit notion of location of multi-threaded systems enables the specification and analysis of location-specific properties. In this project, we employ a model checking-based approach for exhaustive analysis of such properties. Model checking is a formal verification technique for detecting behavioral anomalies in system descriptions [10]. Applying model checking to the analysis of multi-threaded systems is complicated by several factors, ranging from the perennial scalability problems to thread creation that is potentially unbounded and that thus leads to infinite state space. A number of successful approaches (such as abstraction, compositional reasoning, symmetry reduction, partial order reduction, etc.) has been developed to avoid the state space explosion and to enable the verification of realistic programs. One principal method in state space reduction is abstraction. Abstraction techniques reduce the state space by mapping the set of states of the actual, concrete system to an abstract, and smaller, set of states in a way that preserves the relevant behaviors of the system. Predicate abstraction is one of the most popular and widely applied methods for systematic state-space reduction of programs. It abstracts data by only keeping track of certain predicates on the data. Each predicate is represented by a Boolean variable in the abstract program, while the original data variables are eliminated. The resulting Boolean program is an over-approximation of the original program. One starts with a coarse abstraction, and if it is found that an error-trace reported by the model checker is not realistic, the error trace is used to refine the abstract program, and the process proceeds until no spurious error traces can be found. The actual steps of the loop follow the abstractverify-refine paradigm [26].

Our technique for verification of location-aware multi-threaded programs uses a model checking toolset, SATABS [11]. SATABS implements the abstraction refinement loop by computing and refining abstract programs using SAT-based symbolic model checking. SATABS employs a model checker for Boolean programs, Boppo[15] that handles unbounded thread creation. The development of static analysis tools is difficult for multithreaded programs with unbounded number of threads due to the fact that reachibility for such programs is undecidable [30]. It is an active research area, however, and over the last several years a number of research groups have developed techniques to handle unbounded thread creation. The underlying idea is to ‘fix‘ the behavior of a single thread and project it to the global state space of the system. It has been shown [13, 20, 14] that for symmetric systems the projection can handle the unbounded set of threads since the environment of the projected thread is a transition relation over its global behavior. As defined earlier, mobile programs can generate an unbounded number of threads. In particular, the execution of the fork operation results in generating a possibly infinite state space of the reproduced threads. In this project we handle the unbounded thread creation of location-aware systems using the technique implemented in Boppo. Boppo computes an over-approximation of the reachable state space of the analyzed program [14]. This technique uses the abstractionrefinement framework for both 1) ensure the soundness of the algorithm and 2) manage the complexity of the verification procedures. In Boppo’s approach, the thread states of the state space are the projections of the entire state state to that of a single thread. The over-approximated set of states is computed by a symbolic fix-point algorithm that abstracts away the thread number from the computed states. Since the variables are Boolean (they are abstracted using the predicate abstraction approach) and the program counter is finite, this results in a finite abstraction that is then can be model checked using the conventional verification techniques. The over-approximation conserves safety properties, thus, if the property is proved on the abstract model, it can be concluded that the property holds on the original program. If the property is found to be violated in the abstraction, a simulation step is performed to determine if the counterexample is spurious. If so, the abstraction is refined. The details of Boppo’s symbolic fix-point algorithm for handling the unbounded thread creation are outside of the scope of this paper and can be found in [14]. We are currently implementing the front-end to Boppo for parsing programs with syntactic features of locations. We are currently working with benchmarks that have a C-based action language such as Telescript. The implementation is straightforward since SATABS’s front-end already supports the full syntax of ANSI-C programs.

6.

RELATED WORK

Modeling of Multi-threaded Systems. Many calculi have been proposed to deal with mobility. The π calculus [28] is often referred to as mobile because it features the ability to dynamically create and exchange channel names. While it is a de facto standard for modeling concurrent systems, the mobility it supports encompasses only part of all the abstractions meaningful in a distributed system. In fact, it does not directly and explicitly model phenomena such as the distribution of processes within different localities, their migrations, or their failures. Moreover, mobility is not expressed in a sufficient explicit manner since it basically allows processes only to change their interconnection structures, even if dynamically. Indeed, name mobility is often referred to as a model of labile processes or as link mobility, characterized by a dynamic interaction structure, and distinguished from calculi of mobile processes which exhibit explicit movement. Seal [34] is one of the many variants spawned by π calculus. The principal ingredient added, the seal, is the generalization of the notions of agents and locations. Hierarchical locations are added to the syntax, and locations influence the possible interaction among processes. As in the π calculus, interaction takes place over named channel. Communication is restrained to take place inside a location, or to spread over two locations that are in parent-child relationship. Locations are also the unit of movement, abstracting both the notions of site and agent: a location, together with its contents, can be sent over a channel, mimicking mobility of active computations. Djoin [21] extends the π calculus with location, migration, remote communication and failure. The calculus allows one to express mobile agents roaming on the net, however, differently from the Mobile Ambient calculus, the details of message routing are hidden. The Mobile Ambient calculus [5] specification language provides a very framework that encompasses mobile agents, the domains where agents interact and the mobility of the agents themselves. An ambient is a generalization of both agent and place notions. Like an agent, an ambient can move across places (also represented by ambients) where it can interact with other agents. Like a place, an ambient supports local undirected communication, and can receive messages (also represented by ambients) from other places [6]. All these models have in common the fact that they describe concurrency and mobility at a simple and abstract level: 1) using only few basic primitives, 2) with no explicit storage (i.e., no notion of variables), and 3) no explicit representation of values. These features, although useful, limit the spectrum of properties which can be verified. Verification of Multi-threaded Systems. Formal verification of multi-threaded programs is an area of active research; see [31] for an excellent survey. Pushdown automata have been used as tools for analyzing

sequential programs with (recursive) procedures [3]. The expressive power of pushdown systems is equivalent to that of sequential programs with (possibly recursive) procedures where all variables have a finite data type. sc Moped [19] and Bepop [1], for example, are BDD-based symbolic model checkers for this class of language. There has also been work on pushdown automata with multiple stacks, e.g., see [8]. As reachibility is undecidable in this case, the existing implementations are not fully automated. The class of programs considered in this paper can be viewed as an instance of a parameterized system, i.e., a system with a number of identical processes (threads in our case). Many approaches to this problem have been developed over the years, including the use of symbolic automata-based techniques, network invariants, predicate abstraction or system symmetry (see an excellent overview in [12]). Methods that are most closely related to our work are based on abstraction (for example, an extension of Murφ uses abstraction for replicated identical components [25]). In contrast to our approach, many of these methods are only partially automated, requiring at least some human ingenuity to construct a process invariant or a closure process (for example, the TLPVS tool [29] is based on manual theorem proving). Henzinger et al. use predicate abstraction in order to construct environment models from threads [24]. When combined with a counter abstraction, an unbounded number of threads can be supported. Flanagan and Qadeer propose to use the idea of thread-states in order to obtain environment models for l oosely-coupled multi-threaded programs [20]. In contrast to their algorithm, the model checking approach we use addresses the spurious behavior introduced by this overapproximation by (safely) restricting the thread-states that are passed, and by an automatic refinement procedure. A number of tools for analysis of multi-threaded Java programs is available. While some of the tools compute abstract models automatically, most are restricted to explicit state space exploration. Representative examples of model checkers for Java are [33] and JPF [22]. Yahav reports an implementation of a Model Checker for Java with an unbounded number of threads using three-valued logic [36]. Similarly to the approach we use our, an over-approximation is computed. There exists a number of efforts to model check process algebra-based techniques. For example, [18] and [9] proposes techniques for model checking Mobile Ambients. Since they use the ambient calculus as modeling language, they do not consider data. Moreover, they do not use any abstractionrefinement technique.

7.

CONCLUSION AND FUTURE WORK

In this paper, we introduce a general framework for the modeling and verification of multi-threaded programs in a mobile and distributed environment. The system semantics is given in terms of Labeled Kripke structures, which incapsulate the essential features of mobile programs: namely, location and unbounded thread creation. The explicit modeling of these features enables the specification of the mobile system properties which otherwise are impossible or difficult to define. The verification is based on model checking

exploiting abstraction-refinement techniques, that not only allow handling unbounded state space but also deals effectively with large systems. To the best of our knowledge, this is the first approach that allows modeling and verification of the full spectrum of mobile systems properties. As a matter of fact, our analysis is more precise than the static analysis techniques applied to the ambient calculus, one of the most popular approaches used for modeling and analysis of mobile systems. Our approach is flow-sensitive, it models both data and control structures and deals with unbounded thread creation. Distributed applications rely on network communications which are not only potential victims of computer viruses, but they can also be tampered and eavesdropped in many ways, thus becoming vulnerable and insecure. In general, mobile code and communication may need to cross administrative domains and firewalls, and untrusted sites as well. We believe that our verification framework with the explicit notion of location and location net can be very useful for the verification of security properties.

8.

REFERENCES

[1] T. Ball and S. K. Rajamani. Bebop: A symbolic model checker for Boolean programs. In SPIN 00: SPIN Workshop, LNCS 1885, pages 113–130. Springer-Verlag, 2000. [2] M. Bugliesi, G. Castagna, and S. Crafa. Boxed Ambients. In Proc. of 4th Int. Conference on Theoretical, Aspects of Computer Science (TACS’01), number 2215 in Lecture Notes in Computer Science, pages 38–63. Springer–Verlag, Berlin, 2001. [3] O. Burkart and B. Steffen. Composition, decomposition and model checking of pushdown processes. Nordic Journal of Computing, 2:89 – 125, 1995. [4] L. Cardelli. Wide Area Computation. In J. Wiedermann, P. van Emde Boas, and M. Nielsen, editors, Proc. of 26th Int. Colloquium in Automata, Languages and Programming (ICALP’99), volume 1644 of Lecture Notes in Computer Science, pages 10–24. Springer–Verlag, Berlin, 1999. Invited Paper. [5] L. Cardelli and A. D. Gordon. Mobile Ambients. In M. Nivat, editor, Proc. of Int. Conf. on Foundations of Software Science and Computation Structures (FoSSaCS’98), volume 1378 of Lecture Notes in Computer Science, pages 140–155. Springer–Verlag, Berlin, Mar. 1998. [6] L. Cardelli and A. D. Gordon. Mobile Ambients. Theoretical Computer Science, 240(1):177–213, 2000. [7] S. Chaki, E. Clarke, J. Ouaknine, N. Sharygina, and N. Sinha. State/Event-Based Software Model Checking. In IFM 2004, pages 128–147, 2004. [8] S. Chaki, E. M. Clarke, N. Kidd, T. W. Reps, and T. Touili. Verifying concurrent message-passing c programs with recursive calls. In H. Hermanns and J. Palsberg, editors, Proceedings of the 12th International Conference on Tools and Algorithms for the Construction and Analysis of Systems (TACAS), volume 3920 of Lecture Notes in Computer Science, pages 334–349. Springer, 2006.

[9] W. Charatonik, S. Dal Zilio, A. D. Gordon, S. Mukhopadhyay, and J.-M. Talbot. Finite-control mobile ambients. In Proc. of European Symposium on Programming (ESOP02), number 2305 in Lecture Notes in Computer Science, pages 295–313. Springer–Verlag, Berlin, 2002. [10] E. Clarke, O. Grumberg, and D. Peled. Model Checking. MIT Press, December 1999. [11] E. Clarke, D. Kroening, N. Sharygina, and K. Yorav. SATABS: SAT-based predicate abstraction for ANSI-C. In Tools and Algorithms for the Construction and Analysis of Systems (TACAS 2005), volume 3440 of Lecture Notes in Computer Science, pages 570–574. Springer Verlag, 2005. [12] E. Clarke, M. Talupur, T. Touili, and H. Veith. Verification by network decomposition. In CONCUR 04, pages 276–291. Springer-Verlag, 2004. [13] J. M. Cobleigh, D. Giannakopoulou, and C. S. Pasareanu. Learning assumptions for compositional verification. In TACAS, volume 2619. Springer-Verlag, 2003. [14] B. Cook, D. Kroening, and N. Sharygina. Over-Approximating Boolean Programs with Unbounded Thread Creation. submitted for review. [15] B. Cook, D. Kroening, and N. Sharygina. Symbolic model checking for asynchronous boolean programs. In Proceedings of SPIN, pages 75–90. Springer Verlag, 2005. [16] I. Corporation. Aglet software development kit, 1999. [17] R. De Nicola, G. Ferrari, and R. Pugliese. Klaim: a Kernel Language for Agents Interaction and Mobility. IEEE Transactions on Software Engineering, 24(5):315–330, 1998. [18] D. Distefano. A parametric model for the analysis of mobile ambients. In 3rd Asian Symposium on Programming Languages and Systems (APLAS 2005). Tsukuba, Japan. LNCS 3780, pp. 401-417, Springer 2005, pages 305–326. Kluwer Academic Publishers, 2000. [19] J. Esparza and S. Schwoon. A BDD-based model checker for recursive programs. In CAV, LNCS 2102, pages 324–336. Springer-Verlag, 2001. [20] C. Flanagan and S. Qadeer. Thread-modular model checking. In Proceedings of the 10th International Workshop on Model Checking Software (SPIN), volume 2648 of Lecture Notes in Computer Science, pages 213–224. Springer, 2003. [21] C. Fournet, G. Gonthier, J.-J. L´evy, L. Maranget, and D. R´emy. A Calculus of Mobile Agents. In Proc. of the 7th Int. Conf. on Concurrency Theory (CONCUR’96), pages 406–421. Springer–Verlag, Berlin, 1996. [22] K. Havelund and T. Pressburger. Model checking Java programs using Java PathFinder. International Journal on Software Tools for Technology Transfer, 2(4), 2000.

[23] M. Hennessy and J. Riely. Resource Access Control in Systems of Mobile Agents. In Proc. of 3rd Int. Workshop on High-Level Concurrent Languages (HLCL ’98), Electronic Notes on Theoretical Computer Science, pages 3–17. Elsevier Science Inc., New York, 1998. [24] T. A. Henzinger, R. Jhala, and R. Majumdar. Race checking by context inference. In W. Pugh and C. Chambers, editors, Proceedings of the ACM SIGPLAN 2004 Conference on Programming Language Design and Implementation (PLDI), pages 1–13. ACM, 2004. [25] C. Ip and D. Dill. Verifying systems with replicated components in murφ. In Proceedings of CAV, volume 1102, pages 147–158. Springer Verlag, 1996. [26] R. Kurshan. Computer-Aided Verification of Coordinating Processes. Princeton University Press, Princeton, 1995. [27] S. Microsystems. The java language specification, 1995. [28] R. Milner, J. Parrow, and D. Walker. A Calculus of Mobile Processes, I and II. Information and Computation, 100(1):1–40,41–77, Sept. 1992. [29] A. Pnueli and T. Arons. TLPVS: A PVS-based LTL verification system. In Verification–Theory and Practice: Proceedings of an International Symposium in Honor of Zohar Manna’s 64th Birthday, Lect. Notes in Comp. Sci., pages 84–98. Springer-Verlag, 2003. [30] G. Ramalingam. Context-sensitive synchronization-sensitive analysis is undecidable. ACM Transactions on Programming Languages and Systems, 22(2):416–430, March 2000. [31] M. Rinard. Analysis of multithreaded programs. Lecture Notes in Computer Science, 2126, 2001. [32] A. W. Roscoe. The Theory and Practice of Concurrency. Prentice-Hall, 1998. [33] S. Stoller. Model-checking multi-threaded distributed Java programs. In SPIN 00: International SPIN Workshop on SPIN Model Checking and Software Verification. Springer-Verlag, 2000. [34] J. Vitek and G. Castagna. Seal: A Framework for Secure Mobile Computations. In H. Bal, B. Belkhouche, and L. Cardelli, editors, Internet Programming Languages, number 1686 in Lecture Notes in Computer Science, pages 47–77. Springer–Verlag, Berlin, 1999. [35] J. White. Telescript technology: The foundation of the electronic marketplace. Technical report, General Magic Inc., 1994. [36] E. Yahav. Verifying safety properties of concurrent java programs using 3-valued logic. In POPL, pages 27–40, 2001.