My undergraduate thesis on a capability based security system for a data-centric operating system.
1#import "template.typ": *
2
3#mol-chapter("Security Contexts")
4
5Security Contexts are objects that threads attach to in-order to inherit the
6permissions inside the context. The contexts store capabilities, allowing for userspace
7programs to add capabilities to contexts, and kernel space to efficiently search
8through them to determine whether a process has the permissions to perform a memory access.
9
10== Base
11
12Since security contexts can be interacted with by the kernel and userspace, there needs to
13be a consistent definition that both parties can adhere to, which we define. Objects in Twizzler
14have a notion of a `Base` which defines an arbitrary block of data at the "bottom" of an object
15that is represented as a type in rust. We define the `Base` for a security context as follows:
16
17```rust
18struct SecCtxBase {
19 map: Map<ObjID, Vec<CtxMapItem>>, /// A Map from ObjIDs to possible capabilities.
20 masks: Map<ObjID, Mask>, /// A map from ObjID's to masks.
21 global_mask: Protections, /// Global mask that applies to granted prots.
22 flags: SecCtxFlags, /// Flags specific to this security context.
23}
24```
25
26=== Map
27The map holds positions to Capabilities relevant to some target object, which
28the relevant security context implementations for kernel and userspace to
29parse security context objects. Implicitly, the kernel uses
30this map for lookup while the user interacts with this map to indicate the insertion, removal, or modification of
31a capability.
32
33//TODO: talk about the map in memory, and about how its flat, might be worth discussing in the context
34// of not storing virtual address pointers.
35
36=== Masks
37Masks act as a restraint on the permissions this context can provide for some targeted object.
38This allows for more expressive security policy, such as being able to quickly restrict
39permissions for an object, without having to remove a capability and recreating one with the
40dersired restricted permissions.
41
42The global mask is quite similar to the masks mentioned above, except that it operates on
43permissions granted by the security context as a whole rather than a mask per distinct object id.
44// what now
45//
46=== Flags
47Flags is a bitmap allowing for a Security Context to have different properties. Currently, there
48is only one value, UNDETACHABLE, marking the security context as a jail of sorts, as
49once a process attaches to it, it won't be able to detach. This acts as a way to
50limit the transfer of information if a thread attaches to a sensitive object. Once a thread
51attaches to such a context, it is forced to end its execution with the objects that context grants
52permission to. We also plan to utilize these flags in future works, as described in 6.1.
53
54
55== Enforcement
56
57All enforcement happens inside the kernel, which has a seperate view into Security Contexts
58than userspace. The kernel keeps track of all security contexts that threads in Twizzler
59attach to, instantiating a cache inside each one. Additionally, a thread can attach
60to multiple security contexts, but can only utilize the permissions granted by one unless
61they switch @twizzler. To manage these threads, the kernel assigns a Security Context Manager,
62which holds onto security context references that a thread has.
63
64The enforcement of security policy in Twizzler happens on page fault when trying to access
65a new object @twizzler. Upon fault, the kernel inspects the target object and identifies the
66default permissions of that object. Then the kernel checks if the currently active
67security context for the accessing thread has either cached or capabilities that provide
68permissions. If default permissions + the active context permissions arent enough to
69permit the access, the kernel then checks each of the inactive contexts to see if they
70have any relevant permissions. If there exists such permissions, then the kernel will
71switch the active context of that process to the previously inactive context where the permission
72was found. If it fails all of these, then the kernel terminates the process, citing inadequate
73permissions.
74
75Since the security context can have a mask per object, while also having a global_mask to
76the protections it can grant, the kernel also takes this into account while determining if
77a process has the permissions for access.
78
79The original Twizzler paper @twizzler, and the following security paper
80go into more detail about the philosophy behind why enforcement works this way, such as the
81performance benefits of letting programs access objects directly without kernel involvement, etc.
82
83//TODO: may be worth summarizing a few more bits here
84// doesnt have to be super detailed or anything but its better to havea ... thing tie together
85// than and a parathere with "etc"
86//
87// eg. recovering posix semantics and why thats desirable, allowing for
88// "contained" threads, ...
89//
90// basically talk more about stuff from the original twizzler paper about why this style of enforcement
91// is good, its fine to benefit
92
93#load-bib(read("refs.bib"))