lio- Labeled IO Information Flow Control Library

Safe HaskellUnsafe




This module exports symbols that must be accessible only to trusted code. By convention, the names of such symbols always end "...TCB" (short for "trusted computing base"). In many cases, a type is safe to export while its constructor is not. Hence, only the constructor ends "TCB", while the type is re-exported to safe code (without constructors) from LIO.Core.

Security rests on the fact that untrusted code must be compiled with -XSafe. Because this module is flagged unsafe, it cannot be imported from safe modules.


LIO monad

data LIOState l Source

Internal state of an LIO computation.




lioLabel :: !l

Current label.

lioClearance :: !l

Current clearance.


Eq l => Eq (LIOState l) 
Read l => Read (LIOState l) 
Show l => Show (LIOState l) 

newtype LIO l a Source

The LIO monad is a wrapper around IO that keeps track of a current label and current clearance. Safe code cannot execute arbitrary IO actions from the LIO monad. However, trusted runtime functions can use ioTCB to perform IO actions (which they should only do after appropriately checking labels).


LIOTCB (IORef (LIOState l) -> IO a) 


Typeable2 LIO 
Label l => MonadLIO l (LIO l) 
GuardIO l (IO r) (LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> a10 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> a10 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> a5 -> IO r) (a1 -> a2 -> a3 -> a4 -> a5 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> a4 -> IO r) (a1 -> a2 -> a3 -> a4 -> LIO l r) 
GuardIO l (a1 -> a2 -> a3 -> IO r) (a1 -> a2 -> a3 -> LIO l r) 
GuardIO l (a1 -> a2 -> IO r) (a1 -> a2 -> LIO l r) 
GuardIO l (a1 -> IO r) (a1 -> LIO l r) 
Monad (LIO l) 
Functor (LIO l) 
Applicative (LIO l) 

Accessing internal state

getLIOStateTCB :: LIO l (LIOState l)Source

Get internal state. This function is not actually unsafe, but to avoid future security bugs we leave all direct access to the internal state to trusted code.

putLIOStateTCB :: LIOState l -> LIO l ()Source

Set internal state.

modifyLIOStateTCB :: (LIOState l -> LIOState l) -> LIO l ()Source

Update the internal state given some function.

Executing IO actions

ioTCB :: IO a -> LIO l aSource

Lifts an IO computation into the LIO monad. This function is dangerous and should only be called after appropriate checks ensure the IO computation will not violate IFC policy.

Privileged constructors

newtype Priv a Source

A newtype wrapper that can be used by trusted code to transform a powerless description of privileges into actual privileges. The constructor, PrivTCB, is dangerous as it allows creation of arbitrary privileges. Hence it is only exported by the unsafe module LIO.TCB. A safe way to create arbitrary privileges is to call privInit (see LIO.Run) from the IO monad before running your LIO computation.


PrivTCB a 


Typeable1 Priv 
PrivDesc l p => PrivDesc l (Priv p) 
Eq a => Eq (Priv a) 
Show a => Show (Priv a) 
Monoid p => Monoid (Priv p) 
SpeaksFor p => SpeaksFor (Priv p) 
ToCNF (Priv CNF) 

data Labeled l t Source

Labeled l a is a value that associates a label of type l with a pure value of type a. Labeled values allow users to label data with a label other than the current label. Note that Labeled is an instance of LabelOf, which means that only the contents of a labeled value (the type t) is kept secret, not the label. Of course, if you have a Labeled within a Labeled, then the label on the inner value will be protected by the outer label.


LabeledTCB !l t 


Typeable2 Labeled 
LabelOf Labeled 
(Show l, Show a) => ShowTCB (Labeled l a)

Trusted Show instance.

class LabelOf t whereSource

Generic class used to get the type of labeled objects. For, instance, if you wish to associate a label with a pure value (as in LIO.Labeled), you may create a data type:

 data LVal l a = LValTCB l a

Then, you may wish to allow untrusted code to read the label of any LVals but not necessarily the actual value. To do so, simply provide an instance for LabelOf:

 instance LabelOf LVal where
   labelOf (LValTCB l a) = l


labelOf :: t l a -> lSource

Get the label of a labeled value or object. Note the label must be the second to last type constructor argument.

Uncatchable exception type

data UncatchableTCB Source

An uncatchable exception hierarchy is used to terminate an untrusted thread. Wrap the uncatchable exception in UncatchableTCB before throwing it to the thread. runLIO will subsequently unwrap the UncatchableTCB constructor.

Note this can be circumvented by mapException, which should be made unsafe. In the interim, auditing untrusted code for this is necessary.


forall e . Exception e => UncatchableTCB e 

makeCatchable :: SomeException -> SomeExceptionSource

Simple utility function that strips UncatchableTCB from around an exception.

Trusted Show

class ShowTCB a whereSource

It would be a security issue to make certain objects members of the Show class. Nonetheless it is useful to be able to examine such objects when debugging. The showTCB method can be used to examine such objects.


showTCB :: a -> StringSource


(Show l, Show a) => ShowTCB (Labeled l a)

Trusted Show instance.

(Label l, Show t) => ShowTCB (LObj l t) 


data LabeledResult l a Source

A LabeledResult encapsulates a future result from a computation spawned by lFork or lForkP. See LIO.Concurrent for a description of the concurrency abstractions of LIO.




lresThreadIdTCB :: !ThreadId

Thread executing the computation

lresLabelTCB :: !l

Label of the tresult

lresBlockTCB :: !(MVar ())

This MVar is empty until such point as lresStatusTCB is no longer LResEmpty. Hence, calling readMVar on this field allows one to wait for the thread to terminate.

lresStatusTCB :: !(IORef (LResStatus l a))

Result (when it is ready), or the label at which the thread terminated, if that label could not flow to lresLabelTCB.

data LResStatus l a Source

Status of a LabeledResult.


(Show l, Show a) => Show (LResStatus l a)