Home arrow Confinement of Objects
Confinement of Objects Print E-mail

One of the most difficult practical problems to solve in both conventional and capability based systems is the confinement problem. This problem can be stated in a general way as: how can a user or a software module with legitimate access to information be prevented from passing that information to unauthorised third parties. The possibility that a user has memorised such information in his head is ignored in this context, as that is no longer a technical problem. In a capability based system such as SPEEDOS there remain in principle two possibilities, that the information itself is passed on or that a capability for it is passed on. Here we describe how SPEEDOS can be used to ensure that the information itself not passed to unauthorised third parties. In a separate note we describe how capabilities can be confined.

We widen the issue to cover not only information confidentiality (i.e. leakage of information), but also information integrity and availability, i.e. how can a user prevent information from being modified or destroyed. These are related issues, which can play a similarly important role in ensuring the security of systems.

We assume that

  • the information to be protected is persistent information held in the file data of a module;
  • all modules conform to the uniform module structure supported in SPEEDOS and Monads; and
  • attribute modules (including bracket routines) cannot access the persistent data of an attributed module.

We also initially assume that we are working in an environment in which information is stored in logical segments (e.g. holding parameters, persistent file information) which can be individually accessed via a protected addressing mechanism such as the orthogonal paging and segmentation scheme allows. We later consider how an implementation can be tailored to situations where such a mechanism is not available.

Basic Confinement Mechanisms for Preventing Information Leakage

We begin by considering how information might potentially be "illegally" released to other users. The following possibilities exist for passing information between the modules executing within a single process.

The information might be returned to a caller via return parameters. This can be prevented if a mechanism exists to confine a suspect module in such a way that it cannot return information in the return parameter segment(s). Assuming that parameter segments can be separately identified, then the solution to our problem is to set the access rights for the corresponding segments to "read only" in the called module. We call the unconfined state permit_enq, because in this state enquiries, in the L1 sense, are permitted (i.e. a module can return information about its internal state). If we have a mechanism which can turn off this state, then a module cannot pass back information to its caller.

The information might be passed to another module via input parameters. The apparent analogy for this case would be to prevent a module from passing parameters to another module, but to do this via the access rights of parameter segments makes no sense. If a module cannot receive input parameters, then it will rarely be a useful module. A more sensible alternative is to prevent a module from making calls at all to another module. As inter-module calls are handled via the Kernel this is easily implementable if we introduce an unconfined state permit_calls, which can be turned off as appropriate.

So far we have considered leakage of information passed between modules within a single process. A further form of leakage can arise if information can be passed between processes. In fact the SPEEDOS-Monads persistent process model only allows information to be passed between processes via persistent data. There are potentially two ways to prevent this.

Suspect modules active in a process can be restricted to calling modules which have no persistent data segments. This can be formulated as an unconfined state permit_file, which can be turned off. An implementation in the Kernel is straightforward: on an inter-module call the Kernel checks that a called module has no persistent data segments, i.e. it operates as a program or a normal subroutine library.

Notice however that the same effect can be achieved by allowing inter-module calls to modules with persistent data, provided that this information cannot be changed in the active process. We introduce a further nconfined state permit_op, which when turned off prevents write accesses to persistent data segments. This can be implemented in the Kernel provided that persistent data segments can be separately identified and can be subjected to separate access rights.

Confinement by turning off the state permit_op can be more flexible than by turning off the state permit_file as this for example allows a subroutine library to be called which uses look-up tables held in persistent data (e.g. a tax table or a table of logarithms).

Notice that the use of permit_op and permit_file can in appropriate cases serve as a more flexible form of confinement than permit_calls, when a module active in a process needs to call a subroutine library but needs to be confined to prevent information leakage.

Notice also that the turning off of permit_op can serve to secure the integrity of persistent data, because it ensures that persistent data cannot be modified.

Propagation of Confinements

If a module calls another module in a confined state, e.g. by turning off permit_file, then the question arises whether this can call further modules ­ and in that case what confinements apply. Clearly some form of confinement may be needed with respect to further calls, but this may not always be the same form of confinement as applies to the original module. For example if a file editor is implemented as a semantic operation of a file type, the owner of a file might wish to allow the editor to modify the file but at the same time he may wish to confine the editor so that it cannot pass information from the file to other modules. Hence it is necessary to distinguish between the confinements placed on a called module and thos placed on modules which this calls. It suffices to distinguish between primary and secondary confinements. The primary confinements apply to the immediately called module, secondary confinements are then applied to the module(s) which it calls and are propagated to all further calls made by such modules.

Calls to Modules Passed as Parameters

Modules can be passed as parameters to other modules in the form of module capabilities. Do the same confinement restrictions apply to these as to other calls made by the receiving module? The answer may vary depending on the situation. For example the owner O of a file may provide another user U with access to it, but O may not trust U to provide arbitrary parameters when he calls it, as these could be used to store information from his file into another file owned by U, which could then be accessed later by U. On the other hand when O calls his own file module, he possibly trusts the capability which he passes as a parameter. We shall see that this distinction is particualry useful in solving various confinement problems.

To implement it we introduce a further state permit_param_calls, which when unset does not allow capabilities passed as parameters to be used in calls, whereas the state permit_calls described above refers to calls using capabilities which were not passed as parameters. Then two sets of secondary confinements are needed, to distinguish between confinements for calls on modules passed as parameters and those not.

The confinement permissions associated with a module are illustrated in the following diagram.

Confinement Bits Illustration

Overview of the Confinement Access Rights

There are five basic kinds of confinement rights. permit_file determines whether a modile may have file data. If this is set then permit_op determines whether the file data may be modified. permit_enq is independent of permit_file and determines whether a module may pass back parameters to the caller. permit_calls determines if a module can make calls to other modules.

If this is set in the primary confinements (parameter section) it determines whether the primary module can call modules for which it received the capability used for the inter-module call and (non-parameter section) whether it can call other modules for which it did not receive a capability as a parameter. If the appropriate permit_calls is set then permit_unconfined determines whether these calls are to be confined as defined in the secondary rights. In addition both sets of secondary rights include a further right to determine whether secondary modules can themselves call further modules. If so the confinement is imposed as for the secondary module.

Kernel Implementation of the Basic Confinement Mechanisms

For each module active in a process there is a Process Security Word (PSecW), which consists of a bit list containing permissions (if the corresponding bit = 1) which can be turned off (the corresponding bit = 0) individually. There is a separate bit for each of the permissions (confinement rights) described above.

When an inter-module call occurs PSecW is examined to determine whether the call may take place. If so the current value of PSecW is stored with the linkage (and restored later on exit from the called module.

A new value for PSecW is constructed on the basis of the secondary values in PSecW of the caller, further restricted by any additional confinements which are placed on the called module. These may come from two sources: from the module capability which is used to make the call and from bracket routines which invoke Kernel instructions to make further restrictions.

Confinement Controls in Module Capabilities

Module capabilities in SPEEDOS differ from those in Monads primarily through containing not only semantic and other access rights but also the confinement permissions defined above. In the initial capability for a module (the "owner capability") all the confinement permissions are valid (i.e. there are no confinement restrictions). When a user makes a copy of a capability (intended to be passed to another user) he can reduce (but not increase) both the semantic access rights and the confinement permissions. The confinements thereby defined are "anded" with the other confinement permissions associated with the module to be called (e.g. the secondary confinements of the calling module) in constructing the PSecW for the module.

Confinement Controls in Bracket Routines

When a bracket routine is executing it can invoke Kernel instructions to reduce the confinement permissions associated with the module which it is bracketing (the target module). The effect is to reduce the corresponding permissions in the PSecW for the attributed module - but not for the bracket routine itself nor for the bracket routines of other attributes associated with the target module.

Further Information

Here we have described the basic mechanisms available for confining objects. Elsewhere some standard examples of the use of these mechanisms to solve a variety of confinement problems in the SPEEDOS environment are described. In addition there is a further note on rule based confinement.

Two related issues associated with confinement in the SPEEDOS environment are discussed in more detail elsewhere: the confinement of capabilities and the confinement of environmental information.

 
< Prev   Next >
© 2008 Homepage of Prof. Dr. J.L.Keedy