Constructing a Language for Security and Safe Execution 1 Sam Weber Jonathan S. Shapiro IBM T.J. Watson Research Center Distributed Systems Laboratory
[email protected] University of Pennsylvania
[email protected]
Abstract
The introduction of Web applets and servlets has sparked interest in security at the language level. Users want applets to be able to read and write local information, and also to be able to access the network. Despite this, they require assurance that the applet does not disclose sensitive information or gain access to unauthorized resources. Language-based approaches to protection are system-independent, and have the potential of allowing ner-grain control than is possible in most operating systems. Current programming language approaches to this problem are unsatisfactory. In this paper we propose a new, eciently implementable language feature { references which incorporate access control. We introduce a multi-threaded programming language in which an untrusted and unexamined piece of code can be executed with permission to read certain shared data, write to other locations, and yet it is provably impossible for it to leak information. Furthermore, this is true even though the untrusted piece of code is able to create other processes, other sharable objects, or even construct arbitrary pieces of code at run-time and execute them.
1 Introduction
operating systems are unaware of the intended semantics of the programs they execute, and therefore have to implement security on a coarse level. For instance, most operating systems cannot detect that a program has violated its type system, which is easy for programming languages to prevent. In addition, programming language approaches shelter programs from the operating system { applets can run on a variety of platforms. When attempting to design a secure programming language, a number of issues present themselves. First, given a program, when does one decide whether executing the program is allowed? A number of recent papers [Hei98, Smi98] view security as a type issue, and thus examine a program at compile-time. Other systems [Wal97, Wal98] implement run-time checks. The former can be viewed as making sure that the program cannot violate security a-priori, while the latter ensure that the program does not violate security. By incomputability arguments, there are necessarily more programs that can be executed if one does security-checks at run-time rather than at compile-time. In fact, the system of Smith and Volpano ([Smi98]) isn't Turing-complete for highsecurity data. Proposed compile-time systems generally also have assumed that the entire program is available for analysis, which provides an obstacle for language features like Scheme's eval and certain kinds of servlets, in which code is made available to the system only at run-time. Perhaps more important, commercial venders consider their source code
The introduction of Web applets and servlets has sparked interest in security at the language level. Users want applets to be able to read and write local information, and also to be able to access the network. Despite this, they require assurance that the applet does not disclose sensitive information or gain access to unauthorized resources. A typical scenario might be the following. A nancial planning applet is made available to you on the web. The applet keeps a record of what stocks you own and allows you to evaluate \what if" scenarios before investing. To save this information, the applet requires some degree of access to your disk drive. Furthermore, in order to obtain current nancial information, it must read information from the network. As a user, you wish to be assured that the applet does not send your nancial information over the network, erase your hard disk, or spread les throughout the system.2 Although security has traditionally been a concern of operating systems, implementing it in a programming language has a number of advantages. Most 1 Jonathan Shapiro was supported by DARPA under Contracts #N66001-96-C-852, #MDA972-95-1-0013, and #DABT63-95-C-0073. Additional support was provided by the AT&T Foundation, and the Hewlett-Packard and Intel Corporations. 2 A recent security aw in an existing www browser consisted of an ActiveX control leaving a le on the system which the Quicken home nance program would interpret as instructions to transfer the victim's money to a certain account [Gil79].
1
2 Syntax and Semantics
proprietary, and do not wish to make their sourcecode available. While code obfuscation techniques exist, the greater the amount of information available at compile-time, the easier it is to reverse-engineer the code. A second issue is the security model that will be supported. Carl Landwehr has written a highly recommended survey of security models that have been applied to operating systems, [Lan81]. Most programming language work has adopted models based upon military security [Bel73a, Bel74, Bel74]. In these models, a piece of information is given a classi cation level, as are \users". The security system is designed to prevent relatively untrusted users from learning more classi ed information. Unfortunately, no model is perfect: there are some problems that are more suited for one model than another. In particular, Leroy and Rouaix observe in [Ler98] that if one applied many proposed systems to existing applets, the result would be that most of these applets would be considered insecure. Leroy and Rouaix also show that in a language with safe references, reachability provides some security guarantees: an applet can only write to memory locations that it can reach via a sequence of references. This is rather a weak basis for security, however, because possession of a reference confers both the ability to read and write that location. A key observation of this paper is that \capabilities" [Den66], as used in such operating systems as EROS [Sha97a, Sha97b, Sha98] and KeyKOS [Har85], are similar in nature to references in programming languages. The essential dierence is that capabilities allow one to restrict the manner in which the holder of the capability is permitted to use that capability. We therefore propose a new programming language construct: references which carry access restrictions. In this paper we introduce a programming language, SEAL (Safe Execution [a] Language), a safe multithreaded programming language which uses references of this kind. In SEAL, an untrusted, binaryonly program can be executed with permission to read certain shared data, write to other locations, and yet it is impossible for it to leak information. This remains true even though untrusted threads are able to spawn other threads, create new shared objects, and even create arbitrary pieces of code at run-time and execute them. We then de ne correctness for our security model, which formally states the meaning of a subsystem leaking information. Finally, we sketch the proof that SEAL meets these requirements.
Unlike some previous eorts such as [Hei98], we do not allow a thread to access another thread's variables. Every thread has its own set of local variables which are unrelated to those of any other process. In SEAL, threads communicate by means of shareable objects, which are explicitly declared as such. The reason for this is partially philosophical: a language designed to be secure shouldn't make everything sharable by default. There are two distinct kinds of sharable objects: Cells and Agents. A cell is just a location: it contains a mutable value. An agent is a piece of unexecuted source code. One can think of an agent as the code for a procedure with one argument and no return value. While agents can be constructed dynamically, they are not mutable.
2.1 SEAL Values
SEAL's values include integers, booleans, the value
nil, and lists. In addition, a value can be a reference
to a cell or agent. An agent value is (AgentRef agent) where agent is the identi er for an agent. References to cells are more complicated, because cells are mutable. A reference to a cell is denoted (access CellRef cellid) where cellid is the identi er of a cell, and access is an access level: a value which states what operations this reference will allow a process to do upon the referenced cell. There are three possible access levels: RW, Ronly, and Dim, in decreasing order of power. RW allows a process to both read (dereference) the cell and to write (mutate) it. Ronly prevents write access, so that a process can dereference the value, but an assignment with it on the left-hand side will fail. The Dim access level gives only \diminished" access ability. The semantics of this is rather novel, so we will discuss it in detail. Consider a process p which has a variable x whose value is a reference to a cell c. If the reference is RW, then the process can dereference that value, via the expression !x. It also can execute a statement like x ::= 3 where ::= is the statement that assigns to a cell, after evaluating both of its sides. The result is to assign a new value to the cell c. If, instead, the reference to c was Ronly then the process would not
2
be able to execute the assignment but could do the dereference. Now, say that c contained the value (RW CellRef d), i.e. a read-write reference to another cell d. In this case p could execute the assignment
AgentId agent identi ers CellId cell identi ers ProcId process identi ers Vars variable names
8 < RW read-write access Access = : Ronly read-only Dim diminished
!x ::= 3
writing to d by going through c. In other words, making a reference read-only prevents a process from RefValue = AgentValue [ CellValue writing the target cell, but doesn't prevent it from using the reference to do a write indirectly. This is AgentValue = (AgentRef AgentId) sometimes useful (for instance, for maintaining an im- CellValue = (Access CellRef CellId) mutable list of mutable objects), but isn't powerful Value = integers [ strings [ bool [ fnilg [ enough to support our security requirements. RefValue [ Value list The purpose of the diminished quali er is to prevent a process from using the reference for either direct or indirect writing. When a diminished refer(Environment) ence is dereferenced, any references contained in the : threads existing threads resulting value are weakened, becoming diminished : cells existing cells themselves (Figure 1). So, in the above example, if : agents existing agents the reference to c was diminished then the value of !x : S( t ) execution state of thread t would be (Dim CellRef d). Since diminished access : V( t )( x ) value of variable x of thread t does not permit mutation, the assignment !x ::= 3 : C( c ) value in cell c would fail. :A(a) code of agent a Figure 2 summarizes the values of the language. Figure 2: Semantic Entities
2.2 SEAL Syntax and Informal Semantics
The syntax of SEAL is shown in Figure 3. Expressions in SEAL do not have any side-eects. Besides standard integer, string, list and boolean operations there are three operations that pertain to references: the dereference operator, readonly(), and diminish(). The dereference operator works as described above: given a cell reference, it returns the value contained in the cell, diminished if necessary. There is no operator that dereferences agent references, because program code is not a value in the language. The readonly() operator takes a RW cell reference and returns a Ronly reference to the same cell. Ronly and Dim references are returned unaltered | this operator does not increase the power of Dim references. Similarly, the diminish() function weakens all cell references to Dim references. Every thread has its own set of strictly local variables. These variables are not de ned: a variable has the value nil unless another value has been assigned to it. SEAL has the usual imperative statements: skip, if-then, while loops, and assignment to (local) variables. Assignment to cell locations is done by the
(expressions)
e ::= x variable j : : : usual int, bool, string ops j list(e1 ; : : : e ) list constructor j at(e1 ; e2 ) list accessor j !e cell ref dereference j diminish(e) make cell ref Dim j readonly(e) make cell ref Ronly n
(statements) s ::= skip j s1 ; s2 j if e then s1 else s2 end j while e do s end j x := e variable assignment j e1 ::= e2 cell assignment j e1 :call(e2 ) blocking thread start j e1 :newThread(e2 ) non-blocking thread j x := newCell() make new cell j x := compile(e) make new agent Figure 3: Syntax 3
c dim
c dim
rw
P
rw
P dim
d before
d
after
Figure 1: Eect of diminished reference cell-assignment statement, ::=. This statement evaluates both its left and right-hand sides. If the value of the left side is a RWcell reference then the assignment is performed, otherwise the statement completes without doing anything (since expressions have no side-eects). The statement x := newCell() creates a new cell, and sets the variable x to be a RWreference to it. Newly created cells contain the value nil. New agents are created by the statement x := compile(e). The expression e is evaluated, and the resulting value is translated into code. We deliberately do not specify how this translation is performed: the only requirement is that the code is a legal statement. Our security requirements hold irrespective of this translation, since we do not require a compiletime security analysis. A reasonable implementation would be that a string value would be compiled, an agent reference would copy the agent's code, and all other values would result in the code corresponding to the program \skip". There are two statements that create new threads: e1 :call(e2 ) and e1 :newThread(e2 ). Both these statements evaluate e1 and e2 . If e1 's value is an agent reference a new thread is created which executes the code of that agent. All variables of the new thread are set to the value nil except for the variable a, which is given the value of e2 . The call statement suspends the current thread until the new thread completes, while the newThread statement results in both threads executing concurrently. A call statement can be viewed as a remote procedure call which has one argument whose formal name is \a". At rst glance the fact that the call and newThread statements do not return a value may seem like a limitation. However, one can use RW cell references as if they were reference parameters, and therefore SEAL is fully expressive. For example, the equivalent to the following C-like program fragment:
... result = addThree(2); ... int addThree(int x) { return x+3; }
would be the code ... result := newCell(); addThree.call(list(result, 2)); ...
where the agent referred to by addThree has the code at(a,1) ::= at(a,2)+3;
2.3 Formal Semantics
We now describe the formal semantics of SEAL. At any point, the state of the system consists of the set of threads in existence, the set of existing cells, the set of agents, the execution state of each thread, the values of the variables in each thread, the value held by each cell, and the code of each agent. The notation for accessing constituents of the system state is shown in Figure 2. Naturally there are a few sanity conditions imposed on states of the system, such as the requirement that two threads can't be both waiting for the same thread. For expressions we de ne the function eval (e) which evaluates the expression e in state using the p
4
values of the variables of thread p. The de nition of this function is obvious for all the typical integer, string, boolean and list operations. The semantics for the operations dealing with references is shown in Figure 4. SEAL statements are insucient to fully describe the full command state of a system: threads can have nished executing their code, or could be in the process of waiting for another thread, after having executed a call statement. Therefore, we add the states \done" and \await p" in order to obtain the set of command states. This is shown in Figure 5. SEAL's transition relation is written ?! 0 , which means, informally, that in the system the thread p executed, leaving the system in state 0 . The transition relation is de ned in a method typical for that of imperative programming languages. We de ne the relation by cases on the possible command states of each process p. These cases are shown in Figure 5 { the semantics for the \;", if, skip and while statements is omitted for brevity's sake.
data := newCell(); data ::= (image data -- e.g. int list) routine.call(data); ...process transformed image from data
The image routine could, of course, output nonsensical information. However, it could not alter any other cells that other processes might be using. Informally, this is because pointers to cells can't be forged, and when the routine starts the only reference it has is to the one data cell. Creating new cells or agents won't give access to cells used by other processes, nor will creating other processes. Scenario 2. An investment company distributes a program that will calculate investment information for you, given a detailed list of your nancial transactions and a collection of end-of-day stock prices. Each transaction consists of a tuple of the form (purchase price, number, company). The company eld is a cell, because the names of companies change as the companies change hands. You wish to make sure that this program only writes to the output le. The information should not end up scattered around the network, or even elsewhere on the le system. In particular, you wish to ensure that the applet cannot maliciously alter the transaction list. A program fragment to implement a solution to this is:
p
3 Safe Execution Many of the scenarios for safe execution are concerned with the problem of con nement : ensuring that a program is able to communicate information only via authorized channels (variables). Depending on what is authorized, such channels can be either unidirectional or bidirectional. More restrictive policies that one might wish to apply include the *-property or the lattice model. Each of these policies requires con ned systems whose authorized channels allow only unidirectional communication.
output := newCell(); planner.call( list( stockinfo, diminish(transactions), output));
3.1 Informal Scenarios
where \transactions" is a reference to the cell containing the nancial records. The key point here is the transitive accessability of pointers from the transaction records (the pointers to the company names). While read-only access to the transactions would protect the amounts and quantities, it would remain possible for the program to corrupt the company information within the transaction records. This is essentially the problem of Figure 1 appearing in a new guise. The call to diminish() ensures that any transitive access beginning from the diminished transaction list cannot result in the authority to mutate a cell. Scenario 3. We revise the application of Scenario 2 to use \tick data" (a continuously updated stream) rather than close-of-day data. The stock information will now be obtained from a public wire service, and
In this section we will present a series of informal scenarios which illustrate security problems. For each of them, we'll show how to use SEAL to implement solutions, and give an informal argument as to why they work. Afterwards, we will de ne the formal correctness requirements and sketch the proof that SEAL satis es them. Scenario 1. Program p has constructed an image data structure, and also has available a routine which does a desired transformation upon such images. The programmer wants to call the routine on the particular image, but would like to make sure that any errors in the routine cannot corrupt anything other than the passed image. This scenario can be implemented in SEAL as follows: 5
eval (diminish(v)) = p
(Dim CellRef c) if v = (a CellRef c) nil else
8 Ronly CellRef c) if v = (RW CellRef c) > > < ((Ronly CellRef c) if v = (Ronly CellRef c) eval (readonly(v)) = > (Dim CellRef c) if v = (Dim CellRef c) : p
nil
else
8 v 2= CellValue < nil eval (!v) = : weaken(:C(c)) if v = (Dim CellRef c) :C(c) else p
where weaken(list(v1 ; : : : ; v )) = list(weaken(v1 ) : : : weaken(v )) weaken((a CellRef c)) = (Dim CellRef c) weaken(v) = v else n
n
Figure 4: Expression Semantics that cell, and therefore cannot modify it. As a result, the planner cannot leak any information about the transactions this user has performed or the content of their current portfolio back to the brokerage house.
the application will continually reevaluate its portfolio as prices change during the day. The wire reading program is colluding to expose the information held by the valuation program. The goal is to prevent your stock holdings from being reported to StockWatchTM or an equivalent organization. We must create a second thread to read the wire data. Since the \stockinfo" structure is now being modi ed by a third party program that might insert a channel into the tick stream, we revise the planner call as well:
3.2 Correctness Requirements
We now formally specify the correctness conditions. In any security system such conditions are usually considered to be the hardest things to get right, because a mistake means that a \correct" implementation could leak con dential information. Also, the conditions should not refer to the execution semantics of the system (for example, saying \such an action is authorized if the system may, later, perform that action"), because that reduces the statement of correctness to a tautology. Therefore, although we use SEAL's notation, the de nitions should be applicable to other systems. In English, the correctness requirement is \a con ned subsystem must not read or write any object unless it has been explicitly authorized to do so." Authorization can occur when the con ned system is rst constructed, or can be granted at run-time by an independent thread that has the authority to modify some variable that is already authorized. In order to formalize this we have to de ne the following: the contents of the con ned subsystem at any moment
output := newCell(); reader.newThread(stockinfo); planner.newThread( list(diminish(stockinfo), diminish(transactions), output));
Assume that the wire reading program is out to compromise us. In this scenario, it can do so either by producing compromised tick data or by improperly disclosing the transaction records. Compromised data can be detected by cross-checking numbers from two or more wire services. In the program shown, there exists no means by which the planner program can communicate data to the wire reader, because the reference held by the planner is diminished. Even if the wire reader inserts a read-write cell into the stockinfo stream, the planner thread will not be able to obtain RW access to 6
Command State ::= S j done j done; S j await p p 2 ProcId j await p; S Transition ?! 0 ; p 2 :threads according to the following cases on the command state of p, where 0 is assumed to be the same as except as speci cally stated: p
0 :S(p) = done 0 :V(p)(x) = eval (e) e1 ::= e2 0 :S(p) = done if eval (e1 ) = (RW CellRef c); :C(c) = eval (e2 ) e1 :call(e2 ) if eval (e1 ) = (AgentRef a); 0 :threads = :threads [ fqg; q is a new thread id 0 :S(q) = :A(a) 0 :V(q)(v) = nil; 8v 2 Vars 0 :S(p) = await q else 0 :S(p) = done e1:newThread(e2 ) 0 :S(p) = done if eval (e1 ) = (AgentRef a); 0 :threads = :threads [ fqg; q is a new thread id 0 :S(q) = :A(a) 0 :V(q)(v) = nil; 8v 2 Vars 0 x := newCell() :S(p) = done let c be a new cell identi er; 0 :cells = :cells [ fcg 0 :C(c) = nil 0 :V(p)(x) = (RW CellRef c) x := compile(e) 0 :S(p) = done let a be a new agent identi er 0 :agents = :agents [ fag 0 :A(a) = translate(eval (e)) 0 :V(p)(x) = (AgentRef a) await q; :S(q) = done 0 :S(p) = done skip, if, while and ; statements all act as expected
x := e
p
p
p
p
p
p
where translate() maps values to statements in an unspeci ed fashion. Figure 5: Statement Semantics
7
for each action by a thread outside the con ned
As we've seen before, these sets are allowed to insubsystem, what, if any, access is authorized by crease during an execution, but only by a thread outthat action. side the con nement barrier explicitly granting authority over the additional objects through an already In the following, we'll consider a system execution authorized reference (by writing to a cell that the con0 : : : , where a con ned thread is started in 0 ?! ned subsystem is allowed to fully read). state 0 . For convenience, we'll use t to refer to the All that we have to do in order to formally de ne transition ?1 ?! . The thread that acted in t the sets writeAuth , etc is to state what authorities is p . are granted by giving a particular value to a con ned subsystem. Intuitively this is easy: just obtain the De nition. If t is a transition, then de ne read(t) set of references in the value, dereference all the cell to be the cells and agents that were read by the thread refs, and repeat. Formally, that acted in the transition, written(t) be the set of cells that were written, and newObjects(t) be the set De nition. Write authority over a object x in state is granted by a value v if there is a sequence of agents and cells that were created. r0 ; r1 ; : : : r such that Say that a thread is started in state 0 which is in- r = (RW CellRef x), tended to be con ned in some fashion. As it executes, it is able to create new cells, agents and threads. All r0 is a reference that occurs in the value v, and of these objects should themselves be considered to 8i < k; r is an undiminished reference to a cell be con ned: a thread should not be able to escape a whose value contains r +1 . con nement barrier by simply forking a new thread. Therefore, at each state in an execution, we have The de nitions for granting full read and dimina set con ned ProcId [ AgentId [ CellId which is ished read authority are similar. the objects that are considered to be con ned in that As a sanity check, we have the following lemma: system state. Lemma 1. If write authority over an object x in Given the value of con ned0 , the set of con ned state is granted by a value v then there exists a objects initially, we de ne con ned as in Figure 6. closed expression context e[] such that for any thread Essentially, a thread outside the con nement bound- p, ary doesn't increase its contents. On the other hand, eval (e[v]) = (RW CellRef x) every object created by a con ned thread is itself con ned. In other words, a thread is able to compute exactly A con ned subsystem has certain rights to perform the set of cells which it is granting write access to. operations on outside objects. At any moment, we We can now formally de ne writeAuth , can consider an uncon ned object to be in one of fullreadAuth and dimreadAuth . The de nition of four categories: writeAuth is in Figure 6, the other de nitions are similar. con ned objects can modify it, Notice that the de nition of writeAuth doesn't take into account the actions of any con ned thread. con ned objects can read it, fully accessing its This is because we do not examine the code of the contents, threads, and so we have to assume the worst possible con ned objects can only read it diminished, and behaviour of any con ned code. A thread might erase so can't object write permission via the object, all of its references to a particular cell, and thus thereor after be unable to access it { this doesn't change the fact that it had been authorized to access that cell. con ned objects can access it in any fashion. We can now formally de ne our correctness requirement. we state that if a con ned thread For each state we de ne the sets writeAuth , reads orInformally, writes an then it must have the apfullreadAuth and dimreadAuth , which are the ob- propriate permissionobject, at that moment. jects that the con ned subsystem is allowed to, respectively, write, read completely, or read in a Requirement (Con nement requirement). For diminished sense. We have that writeAuth all transitions t , if p 2 con ned ?1 , then fullreadAuth dimreadAuth because a thread is read(t ) dimreadAuth ?1 [ con ned ?1 perfectly free to downgrade references, such as conwritten(t ) writeAuth ?1 [ con ned ?1 verting a RWreference to a Ronlyreference. p
n
pi
t
i
i
i
i
i
k
k
i
i
i
i
i
p
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
8
i
i
i
i
De nition. con nedi =
con nedi?1 [ newObjects(ti ) if pi 2 con nedi?1 con nedi?1 else
De nition. If a con ned subsystem was started via a call or newThread statement with argument v, then writeAuth0 = fxjWrite authority over x is granted by vg De nition. For i > 0, 8 p 2 con ned ?1 < writeAuth ?1 written(t ) \ fullreadAuth ?1 = ; writeAuth = : writeAuth ?1 writeAuth ?1 [ fxj write perm to x grantedg else i
i
i
i
i
i
i
i
Figure 6: De nitions of con ned and writeAuth i
4 SEAL Correctness
i
5 Conclusion
In this section we sketch the proof that con ned subprocesses in SEAL actually remain con ned. The main lemma we show is an extension of lemma 1. Essentially, we show that we can compute fxjx 2 RefValue; s.t. 9 expression e; x = eval (e)g by considering only the references reachable from the values of the variables of p. Call this set reachable . We rst show that the reachable set captures all objects that a thread can use:
In this paper we have introduced a new language feature: references which embed access restrictions. In particular, the diminished reference prevents a thread from obtaining the ability to do writes either directly or indirectly using the reference. We have designed and formally speci ed a language, SEAL, in which one can execute routines in a con ned fashion, so that they are unable to leak information except as explicitly authorized. SEAL is a powerful language, in which it is possible for even Lemma 2. If ?! 0, then any objects read or writ- con ned threads to create new threads, compile arbiten to in that transition have appropriate references trary strings into executable code, create new shareable objects and do interprocess communication. To in reachable . our knowledge all other languages which have been The next step is to show that con ned subsystems proven to be secure are weaker than SEAL. can only decrease their outside references. We have formally de ned correctness requirements for a system to implement con nement. We feel that Lemma 3. 3 these requirements could be adapted for use in other systems. If ?! +1 , and p 2 con ned , then Finally, we have proven that SEAL's con nement mechanism meets its correctness requirements. reachable ? con ned Our particular thanks to Bard Bloom of IBM, for reachable +1 ? con ned +1 his helpful comments. p
p
p
p
i
pi
i
p
i
i
i
i
p
i
i
Finally, we show that if a thread writes a value into a cell that another thread can read, then the second thread's reachable set is at most increased by the references implied by which cells were granted [Bel73a] D. E. Bell. \Secure Computer Systems: Mathematical Foundations." ESD-TR-73write/full read/diminished read access. This suces 278, vol 1, ESD/AFSD, Hanscom AFB, to prove correctness. Bedford, Mass., April 1974 (MTR 2547, 3 The statement of this lemma has been slightly simpli ed vol. 1, MITRE Corp., Bedford, Mass).
References
for readability's sake: a thread can take a RW reference and convert it to a Ronly reference, which adds a new element to the reachable set. However, this new reference is strictly [Bel73b] D. E. Bell. \Secure Computer Systems: weaker than the old one, so the intuitive meaning is preserved. A Mathematical Model." ESD-TR-73-278,
9
[Bel74]
[Bis79]
[Den66]
[Gil79] [Har85] [Hei98]
[Jon76]
[Lan81]
[Ler98]
[Sha97a]
vol 2, ESD/AFSD, Hanscom AFB, Bedford, Mass., April 1974 (MTR 2547, vol. 2, MITRE Corp., Bedford, Mass). D. E. Bell. \Secure Computer Systems: A Re nement of the Mathematical Model." ESD-TR-73-278, vol 3, ESD/AFSD, Hanscom AFB, Bedford, Mass., April 1974 (MTR 2547, vol. 3, MITRE Corp., Bedford, Mass). Matt Bishop. \The Transfer of Information and Authority in a Protection System." Proceedings of the 7th ACM Symposium on Operating Systems Principles, published as Operating System Review, Vol 13, No 4, Dec 179, pp. 45-54. J. B. Dennis and E. C. Van Horn. \Programming Semantics for Multiprogrammed Computations" in Communications of the ACM, vol. 9, pp. 143{154, March 1966. \Crackers Shue Cash With Quicken, ActiveX" Wired, February, 1997 Norman Hardy. \The KeyKOS Architecture" Operating Systems Review. Oct. 1985, pp 8-25. Nevin Heintze and Jon G. Riecke. \The SLam Calculus: Programming with Security and Integrity" Proc. 25th Symposium Principles of Programming Languages, January 19-21, 1998 San Diego, California. A K. Jones, R. J. Lipton, and L. Snyder. \A Linear Time Algorithm for Deciding Security." Proc. 17th Symposium on Foundations of Computer Science, Houston, Texas, 1976 pp. 33-41 Carl E. Landwehr \Formal Models for Computer Security." ACM Computing Surveys, Vol. 13, No. 3, September 1981, pp. 247-278. Xavier Leroy and Francois Rouaix \Security properties of typed applets" Proc. 25th Symposium Principles of Programming Languages, January 19-21, 1998 San Diego, California. Jonathan S. Shapiro. EROS: A Capability System. Department of Computer and Information Science Technical Report
[Sha97b]
[Sha98]
[Smi98]
[Wal97]
[Wal98]
10
MS-CIS-97-04, University of Pennsylvania, 1997. J. S. Shapiro, S. Weber, Verifying Operating System Security Department of Computer and Information Science Technical Report MS-CIS-97-26, University of Pennsylvania, 1997. J. S. Shapiro, S. Weber. A Family of Securable Protection Systems. Department of Computer and Information Science Technical Report MS-CIS-98-18, University of Pennsylvania, 1998. Georey Smith and Dennis Volpano. \Secure Information Flow in a Multi-threaded Imperative Language" Proc. 25th Symposium Principles of Programming Languages, January 19-21, 1998 San Diego, California. Dan S. Wallach, Dirk Balfanz, Drew Dean, and Edward W. Felten. \Extensible Security Architectures for Java." Proceedings of the 16th ACM Symposium on Operating Systems Principles, October 5-8, 1997. Saint-Malo, France. Dan S. Wallach, Dirk Balfanz, Drew Dean, and Edward W. Felten. \Understanding Java Stack Introspection." Proceedings of the 1997 IEEE Symposium on Security and Privacy, Oakland, California, May 1998.