Separating Access Control Policy, Enforcement, and Functionality in Extensible Systems Robert Grimm and Brian N. Bershad Summary: This paper presents an access control system for the SPIN extensible operating system. I'll begin this summary with a short explanation of SPIN and extensible operating systems, since they're quite different from conventional OS's. In a conventional OS such as Linux, the system is based on a static kernel that implements a fixed set of services that are provided to other kernel components and userspace applications. The kernel can only be extended by inserting modules which support additional hardware or filesystems, etc. You cannot introduce an entirely new subsystem or system interface using a module. In fact, system call numbers are hardcoded into an architecture-dependent file, illustrating how fixed the system services actually are. In SPIN it is possible to introduce entirely new subsystems and interfaces into the running kernel. Additionally, these interfaces are accessed directly by other kernel components using standard procedure calls, rather than microkernel IPC calls as is the case in other microkernels such as L4 and Mach. Thus, controlling access to these interfaces presents some interesting challenges. SPIN considers itself to be a capability-based system, as it is implemented in a type-safe language, Modula-3, and uses compiler-checked pointers to reference kernel objects. An interesting feature of SPIN is that applications commonly run entirely in kernel-space, using the type-safe language to provide assurances of safety. The most popular access control mechanism for Linux is NSA SELinux, so I'll compare the SPIN access controls to SELinux. The SELinux developers inserted hook function calls surrounding each important service in the Linux kernel. Whenever a new subsystem is introduced into the kernel, they must create new hooks to protect all of the important functions provided by the new subsystem. This summer I was responsible for implementing the hooks for the kernel access key retention subsystem in Linux. It's difficult to extend these hooks, because you, as the security specialist, must have a deep understanding of how the new subsystem operates and what its vulnerabilities are. In SPIN's access control system, all procedural interfaces can be regulated by an arbitrary policy. A security policy manager converts the policy into a set of security IDs which identify the privileges associated with subjects (threads), and to distinguish classes of objects. It also produces rights which are used to determine what operations each subject identified by some SID can perform on each object some other (or the same) SID. The "hooks" are automatically generated by performing binary interposition in the procedure jump tables, and can be optimized out if they are not necessary. Since the protections are so heavily based on function interfaces, objects must use careful encapsulation to prevent direct access to their data members. This also prevents checks from being performed within functions, so functions should be highly subdivided to provide adequate resolution. Furthermore, the SIDs of the arguments used by functions can be restricted, but the values of those arguments cannot, which causes problems for ioctl-style functions. The SPIN access control system recognizes three main operations: protection domain transfers, access checks between subjects and objects, and auditing operations. Everything in the system that is controlled by access checks must have a SID. Threads are the objects that represent users, and are assigned a default SID associated with the user when they authenticate themselves. When the thread passes through an extension's protection domain, the thread's SID is updated to one determined by a special transition function that takes the SID of the user and the SID of extension. Extension linkage is controlled by two special permissions: Extend and Execute, and the SID associated with each extension's protection domain is determined by a digital signature on the extension. The signature also serves to certify the origin of each extension. Extensions can include policy fragments of their own that may affect any aspect of the access control system. Extensions may also override the default SID assigned to new objects by the type transition function. Pros: - Hooks automatically generated (Access control enforcement separated from functionality) - Supports arbitrary policies (Security policy management separated from access control enforcement) - Policies may be provided by trusted extensions as well as by administrators. - Access control system is transparent to applications except in the presence of security violations. Cons: - Checks restricted to function boundaries - Requires a trusted compiler. - No figures on memory overhead - Does not address how to determine whether an extension is trusted. - Certificate repository? - Too many exaggerated claims Questions: - Intelligent work must be done to determine what important functionalities must be protected by an access control system - This system extracts that information from the policy - SELinux requires two steps: function hook definition and policy definition - Is it good to have a web server in the SPIN kernel? - Better performance - Similar to sendfile system call in Linux kernel - Is it possible to override the security policy manager dynamically - Unanswered bootstrap issues, can system integrity be compromised before access control system is activated? - Need good management practices, make sure access control system is activated as early as possible. - Highlights problems with arbitrary extensions: - Need good binary type-checking to ensure that no extension will break the system - Details of the extension trust management system used by the system are omitted. This is a critical part of the system, because extensions execute in kernel-space and can undermine the entire system. What sort of system would be reasonable for this application? - Administrator defines a maximal set of software certification authorities trusted to issue certificates for extensions. - Individual users can further restrict that set, but cannot expand it. - Individual extensions can further restrict that set, but cannot expand it. - Trusted, non-maskable interface within system should be available to verify the set of extensions actually running on the system. - No real good solution to this problem yet - Extensions can override the default SID assigned by the object creation mapping (pp.47, pg.2). If left unregulated, this could provide a way for applications to create arbitrarily-labeled objects. I think that a "create" permission should be present in the system that restricts the set of SIDs that can be created by each protection domain. What do you think? - Why couldn't they permit function value restriction, too? - Where else does this sort of access control scheme appear? How is it related to the .NET CAS (Code Access Security) security model? - Subject's privileges determined by code identity, not user identity (just like protection domains) - Evidence: information about assembly, like digital signature - URL, site, zone, digital signature, hash of software - Permissions: object's conferring privilege, like capabilities - Security Policy: assignment of permissions to module, based on evidence - Enterprise, machine, user - Assemblies and hosts both provide permission requirements as conditions for execution - Java may have been influenced by this system, particularly since it was explicitly discussed in the paper - SPIN itself depends critically upon a trusted compiler that produces type-safe code. However, there is currently no way to know what compiler generated the extensions that SPIN allows applications to dynamically insert into the system. They mention proof-carrying-code and typed assembly language as possible solutions to this problem, but those are still not practical for real usage. Can you foresee any solutions to this problem? - If it is possible to generate a code analyzer that could inspect the binary extensions for type safety, that would be ideal. Otherwise, it might be possible to distribute the source code for extensions and have the application use a trusted compiler to generate the binary extension. - Java and .NET have type safety verifiers - How does this compare with SELinux and other more conventional access control frameworks in terms of ease of administration? How will the administrator be able to comprehend the security properties of the system when the policies could come from so many different sources? - Could introduce logically conflicting permissions - Administrator can't reduce extension policies to perform a lockdown - Worst of both worlds: - Extension authors could introduce holes in system - Administrator has poor understanding of subsystems - On a related note, what ramifications would this have for formal policy analysis systems? Isn't there something to be said for system tranquility? What is the proper tradeoff between that and extensibility? - Not actually discussed, but still potentially interesting. 10 weak accepts 5 weak rejects