4.3 Apple’s Mac OS X and iOS
4.3.2 Adapting the MAC Framework to Mac OS X
The design of the MAC Framework reflects a detailed analysis of the FreeBSD kernel; the resulting system is tightly integrated with low-level kernel memory management and synchronisation, as well as high-level services such as the file system, IPC facilities, and network stack. A reference monitor must be aware of and able to integrate with all security-critical services in the kernel – especially, it must be able to label and control access to all system objects relevant to policies such as MLS and Biba. While our adaptation of the framework to Mac OS X was able to rely heavily on Apple’s reuse of FreeBSD kernel components, the framework also required fundamental changes to reflect differences in low-level and high-level kernel features between FreeBSD and XNU. The project was performed in several stages:
1. An initial port of the framework where obvious mappings existed between the two systems, protecting BSD objects from BSD system call accesses.
2. Feature enhancements to the framework to support specific Mac OS X porting goals relating to policy expression and protection.
3. Expanded analysis to cover new services found only in Mac OS X – especially, Mach objects such as tasks and ports.
In the next few sections, I consider a few of the more interesting research problems discovered during the SEDarwin project.
9I was principal investigator for this project both at McAfee Research and following our acquisition
by SPARTA ISSO. Although I left SPARTA in 2005 to begin my PhD, I continued my collaboration with SPARTA and Apple, engaging with Apple developers adapting the framework for use in their products.
Phase 1: XNU BSD kernel components
In this phase, a number of obstacles were encountered reflecting semantic differences between the two operating systems. For example, the HFS+ file system is structured around the idea of a disk catalogue, in which the directory namespace is a first-class object, unlike UFS in which directories are simply a form of file supporting special operations. One implication of this difference is that Mac OS X includes several system calls that operate on the catalogue rather than on individual files, such asgetattrlist
which performs bulk retrieval of both directory listings and file attributes. HFS+’s implementation of the underlying vnode operation, vnop readdirattr, did not instan- tiate a vnode for each entry in order to query these attributes – a problem for the MAC Framework that assumes file system access control is performed with respect to
vnodes, which are labelled kernel objects. In the initial port, we disabled this optimi- sation, forcing avnodeto be allocated, a change later adopted in Mac OS X for similar reasons.
There also proved to be significant differences in the basic construction of the XNU kernel: FreeBSD relies heavily on the linker set facility described in the previous chap- ter. Mac OS X lacks the SYSINIT facility, requiring manual insertion of the MAC Framework and its policies into the boot process, as well as explicit registration of policies during module init and destroy routines.
Phase 2: MAC Framework enhancements
During development of the SEDarwin prototype, the MAC Framework was enhanced in several ways to address functional differences from FreeBSD, but also to explore feature improvements in the framework itself:
• The XNU kernel’s BSD subsystem included features such as POSIX semaphores and shared memory that would arrive only later in FreeBSD. In general, these features fit naturally into the existing MAC Framework model; this code would later be backported as the FreeBSD kernel grew similar features.
• The Mac OS X port of the MAC Framework supports labelling of file descriptors as well as access control on file descriptor operations (such aslseek). This feature was introduced during SEBSD development, but never merged back into the base FreeBSD tree; as it was required for SEDarwin, it was subsequently included in Mac OS X.
• A further enhancement added to the Mac OS X version of the MAC Framework is explicit kernel “login contexts,” an abstraction allowing labelling of an entire login session. This feature was added in order to support the notion of a more complex security context associated with the session, which would augment the security labelling of a particular process – for example, for use in a Compart- mented Mode Workstation policy environment [16]. This feature is, as far as I
am aware, unexercised in both the SEDarwin TE policy and all policies shipped by Apple.
• One known problem with the design of the MAC Framework in FreeBSD is that while the policy-agnostic APIs allow userspace tools to query labels for policies without specific knowledge of their semantics, the query system calls require that the userspace tool be aware of the label element names (such as “biba”). In Free- BSD, defaults are configured using /etc/mac.conf; in the SEDarwin prototype, the MAC Framework was extended to allow policies to declare lists of element names that they accept. Userspace is able to query that list, in order to provide a useful default set of label elements to query.
• Mac OS X has a much more formal notion of kernel programming interface (KPI) for third-party developers; in order to conform to this design, and allow greater flexibility to change policy memory allocation models, the MAC Framework in SEDarwin provides explicit memory allocation and free interfaces that the frame- work translates into Mach memory allocation calls.
• As part of maturing the MAC Framework on Mac OS X, many entry point names were “normalised”, or given a more consistent format. This change was later largely propagated back to FreeBSD 8.0, leading to a significant change in KPI. In general, the new names better reflect the object-method paradigm, and make it easier to predict the name of an entry point.
• The MAC Framework on XNU can control configuration of the audit subsystem, but also submit its own audit records. Control of audit was later merged to the FreeBSD version of the MAC Framework, but not the ability to submit audit records.
Phase 3: Mach tasks, ports, and services in XNU
In the third phase, coverage was expanded to include Mach objects – especially, Mach tasks and Mach ports (IPC channels). A technical issue that quickly arose in adding labelling and access control entry points for Mach objects was the order of the XNU boot. The module linker is initialised only after a number of Mach objects, including early Mach tasks and ports, have been created. As a result, policies registered “early” would still miss the creation of these early Mach objects, missing the opportunity to label them from inception. In the SEDarwin port, the creation of early Mach objects is “journalled” and then entry points for those objects are replayed once early modules have been loaded, allowing early boot objects to be labelled in order, restoring the universal labelling and mediation invariants of policies such as MLS and Biba.
As with processes in FreeBSD, Mach tasks represent the “subject” in operations on the system, invoking operations (via threads) on services. An XNU process is con- structed, then, of two parts: an underlying Mach task which provides the scheduling
and virtual memory properties, and a BSD process layered above it that carries UNIX properties such as credentials, file descriptors, signal state, etc. This separation presents a fundamental philosophical problem: policies such as MLS and Biba require a unified view of interactions between subjects and objects in the system, labelling both and en- forcing protections between them regardless of their “layer” in an abstraction hierarchy. Is the MAC Framework a service of the Mach layer, or the BSD layer?
Our conclusion was that, while useful in some ways, the abstraction boundary be- tween Mach and BSD was fundamentally artificial as system subjects can directly ad- dress both layers: the MAC Framework must likewise serve both layers, and be aware of data types and semantics for both layers. In the SEDarwin port, this conflict is resolved for subjects by maintaining security labels on both the BSD process and the Mach task, but with the BSD label considered the authoritative copy; label changes are propagated to the task label when required. BSD-level operations can then be au- thorised against the credential label, and Mach operations are authorised against the task label, maintaining the code abstraction while satisfying the needs of policies such as Type Enforcement.
Mach ports are another case in which the microkernel origins of Mach come into conflict with the design premises of the MAC Framework. Mach ports are one-way IPC channels effectively treated as object capabilities in Mach, and unlike semantically rich IPC channels in BSD, which rely on kernel-managed namespaces such as the file system, Mach ports rely solely on userspace provision of global namespaces, typically managed by launchd, which provides port lookup services for applications (including the desktop IPC namespace).
Taking a leaf from the DTOS book, SEDarwin adopts an approach in which userspace applications providing services, such as the namespace, are responsible for labelling and access control, since only they have visibility into the semantics of methods invoked on ports. SEDarwin provides a label handle abstraction, which applications can use to query labels associated with the tasks making requests via IPC, and can also invoke the MAC Framework to authorise operations from a string-based object type and op- eration namespace that kernel-based policies can interpret – a significant divergence from the DTOS model, which performed policy computations in a userspace security service11.