diff --git a/4-secctx.typ b/4-secctx.typ index eb098f2..b807ed4 100644 --- a/4-secctx.typ +++ b/4-secctx.typ @@ -2,10 +2,13 @@ #mol-chapter("Security Contexts") -Security Contexts are objects that threads attach to in-order to inherit the -permissions inside the context. The contexts store capabilities, allowing for userspace -programs to add capabilities to contexts, and kernel space to efficiently search -through them to determine whether a process has the permissions to perform a memory access. +Security Contexts are objects that threads attach to in-order to inherit access +rights, represented as capabilities, inside the context. Additionally, a thread +can attach to multiple security contexts, but can only utilize the permissions +granted by one unless they switch @twizzler. The contexts store capabilities, +allowing for userspace programs to add capabilities to contexts, and kernel +space to efficiently search through them to determine whether a process has the +permissions to perform a memory access. == Base @@ -24,16 +27,16 @@ struct SecCtxBase { ``` === Map -The map holds positions to Capabilities relevant to some target object, which -the relevant security context implementations for kernel and userspace to -parse security context objects. Implicitly, the kernel uses -this map for lookup while the user interacts with this map to indicate the insertion, removal, or modification of -a capability. The `Map` type here and for `masks` is a flat data-structure, and stores -offsets into the object where capabilities can be found for a target object. +The map contains positions of capabilities related to a target object, enabling +kernel and userspace to look for capabilities inside security contexts. +Implicitly, the kernel uses this map for lookup while the user interacts with +this map to indicate the insertion, removal, or modification of a capability. +The `Map` type here and for `masks` is a flat data-structure, and stores offsets +into the object where capabilities can be found for a target object. === Masks -Masks act as a restraint on the permissions this context can provide for some targeted object. +Masks act as a restraint on the permissions a context can provide for some target object. This allows for more expressive security policy, such as being able to quickly restrict permissions for an object, without having to remove a capability and recreating one with the dersired restricted permissions. @@ -55,24 +58,22 @@ permission to. We also plan to utilize these flags in future works, as described All enforcement happens inside the kernel, which has a seperate view into Security Contexts than userspace. The kernel keeps track of all security contexts that threads in Twizzler -attach to, instantiating a cache inside each one. Additionally, a thread can attach -to multiple security contexts, but can only utilize the permissions granted by one unless -they switch @twizzler. To manage these threads, the kernel assigns a Security Context Manager, +attach to, instantiating a cache in each one. To manage these threads, the kernel assigns a Security Context Manager, which holds onto security context references that a thread has. There exists only 1 point of enforcement for security policy if we wish to keep the kernel out of the access path; the creation of the path itself! -On page fault, the point in which a process requests the kernel to map an object in is +On page fault, the point in which a process requests the kernel to map in an object, is when we have access to the security policy we seek to enforce (the signed capabilities inside the security context), the target object, and most importantly, kernel execution! Its the only time -we can program the mmu according to the desired protections, and transfer control +we can program the MMU according to the desired protections, and transfer control of enforcement to the hardware @twizzler. Upon page fault, the kernel inspects the target object and identifies the default permissions of that object. Then the kernel checks if the currently active security context for the accessing thread has either cached or capabilities that provide -permissions. If default permissions + the active context permissions arent enough to -permit the access, the kernel then checks each of the inactive contexts to see if they +permissions. If default permissions plus the active context permissions arent enough to +permit the access and the security context isn't a jail, the kernel then checks each of the inactive contexts to see if they have any relevant permissions. If there exists such permissions, then the kernel will switch the active context of that process to the previously inactive context where the permission was found. If it fails all of these, then the kernel terminates the process, citing inadequate diff --git a/thesis.pdf b/thesis.pdf index 5bc4a50e8ab9ff7b38904518983f06487cdc1233..c6bc3f60348000424ba944120be6f840f15369d1 100644 GIT binary patch delta 8615 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 XDyb++P2(~&Fg7qZ=2BI4^>+gRXVaQd