Linux isn’t the only operating system with activity in the enhanced access control department. Apple recently released Mac OS X 10.5 Leopard, which includes a new feature called a sandbox (or seatbelt, depending on where you’re looking) as well. I delved into the sandbox mechanisms a bit and wanted to report my findings.
First, let me say that much of this is gleaned or inferred from looking at a running system and the XNU source code. There is a bit of documentation on this feature, but it is limited. In addition, much of what is possible is labeled as “Apple System Private Interface and are subject to change at any time and without notice” so I wouldn’t plan my corporate infrastructure around using it just yet.
Apple has implemented the sandbox mechanism by utilizing the MAC Framework developed by the TrustedBSD project. This is a kernel framework similar to the Linux Security Module (LSM) framework that SELinux uses to hook into the Linux kernel. Note that TrustedBSD’s SEDarwin project also ported the SELinux policy decision engine to Darwin, but Apple decided to implement their own policy decision engine instead of using SEDarwin’s. That engine is called seatbelt, and it’s a kernel extension (found in /System/Library/Extensions/seatbelt.kext).
Seatbelt does not appear to be released as source, so I can only surmise how it works from attempts to use it. It appears to provide pathname-based access control (not my favorite). Additionally, processes are not confined by seatbelt by default. Instead, a process must opt-in (by calling sandbox_init()) to be confined. Once confined, all children are also confined by the same policy, meaning that you can have a wrapper call sandbox_init() and then execute the program you really want to confine. In fact, it looks like Apple thought this might be useful as they included a command-line utility called sandbox-exec which appears to do just that.
A process selects which policy will confine it at sandbox_init() time. There are two ways to do this. The first way, which is the only one officially supported by Apple according to the documentation, is to choose a policy that is statically compiled into the kernel. Apple documented five of these, each with a high-level goal. These goals include no internet, no networking, no file writing, no file writing except temporary files, and pure computation.
The second way of selecting a policy, which is clearly marked as a private API that is subject to change, is to provide a pathname to a policy file. While there is no documentation of the format of the policy file, there are several examples available in /usr/share/sandbox which give clues to what a policy can do. These policies seem to use a Scheme-like syntax and provide abilities to restrict file access (based on pathname), restrict interprocess communication (IPC) such as shared memory, restrict network access, restrict signals, restrict many process-related actions, restrict sysctls, and more.
Stay tuned for some examples of using sandboxes on Leopard.