# MCS

* https://en.wikipedia.org/wiki/Bell%E2%80%93LaPadula_model
* https://en.wikipedia.org/wiki/Biba_Model
* https://xkcd.com/1200/

See also the patch for [`glblub`](https://lore.kernel.org/selinux/20190909180557.8093-1-joshua.brindle@crunchydata.com/) and [../policy/constraints/README.md](../policy/constraints/README.md)

This document explains why and how MCS in this policy works.

Every domain and object is assigned a range, consisting of a low (*confidentiality level*) and high level (*integrity level*).
The low level is always dominated by the high level (this is also an assumption made by selinux).

A domain can read an object if his *integrity level* dominates the *confidentiality level* of the target.
A domain can write to an object if his *integrity level* dominates the *integrity level* of the target.

When a domain transitions to a new domain and range the old *integrity level* must dominate the new *integrity level*.
This way a domain can **never** gain additional categories.

**NOTE:** Similiar to how a `(dir (read))` access can show files to a process even if it does not have `(file (getattr))` on said file, MCS allows a process to add files to a directory with higher integrity than it has, as long it dominates the confidenialty of the directory.
Thus the integrity level of a directory does not say that all files inside have the same (or higher) integrity level.

## Object Read

It is assumed that a domain can be trusted to handle confidential data up to his *integrity level* but not above.

```lisp
(constrain (object (read))
    (dom h1 l2)
)
```

### Strict

To ensure that a domains integrity can **never** be compromised any file read (and processed) by a domain needs to have at least the integrity of the processing domain.
This hasn't been tested and might not be very practical.

```lisp
(constrain (object (read))
    (dom h2 h1)
)
```

## Object Write

To ensure integrity of objects a domains *integrity level* needs to dominate the *integrity level* of a target object.

```lisp
(constrain (object (write))
    (dom h1 h2)
)
```

### Strict

Prevent leaking of confidential data by ensuring the *confidentiality level* of the process is dominated by the *confidentiality level* of the target object.

```lisp
(constrain (object (write))
    (dom l2 l1)
)
```

## Object Identity Change

Identity change of an object referes to both creation and a relabeling access.
Basically the same idea as for `(object (write))` applies.

```lisp
(constrain (object (identity_change))
    (dom h1 h2)
)
```

### Strict

Additionally changes to an objects range should never increase the *integrity level* and never lower the *confidentiality level*
Probably not really pratical.

```lisp
(validate (object (identity_change))
    (and
        (dom h1 h2)
        (dom l2 l1)
    )
)
```

## Domain Communication

Similiar to `(object (read))` a domain is trusted to handle the leaking of confidential information to domains with a lower *integrity level* at his own discrection.
But to prevent access to confidential information above its *integrity level* it needs to dominate the *confidentiality level* of the target domain.

```lisp
(constrain (domain (communicate))
    (dom h1 l2)
)
```

## Domain Identity Change

Identity change of a domain refers to process transitions.

To enforce integrity of new domains, they can **never** have a higher *integrity level* than the old domain.

```lisp
(constrain (domain (identity_change))
    (dom h1 h2)
)
```

### Strict

Prevent the *confidentiality level* from being lowered.

```lisp
(constrain (domain (identity_change))
    (dom l2 l1)
)
```
