Monthly Archive for November, 2007

Apple Sandboxes Part 2

Here are a couple of examples of using sandboxes in Leopard. Both examples involve confining a test application that needs to read a file, but should not be able to write that file. I realize that this could be easily implemented with standard Discretionary Access Control (DAC) mechanisms, but this example is solely for the purposes of demonstrating the mechanism. Perhaps later I’ll show off some more useful examples.

Example 1
This example uses sandbox_init() with one of the predefined policies Apple provides. In this case, we’re going to use the kSBXProfileNoWrite policy, which prevents the process from writing any files to disk. The example program is:

#include <sandbox.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
	int ret, fd;
	char **errbuf;
	char buf[50], buf2[] = "blah blah\n";

	ret = sandbox_init(kSBXProfileNoWrite, SANDBOX_NAMED, errbuf);
	if (ret != 0) {
		printf("Error initializing sandbox\n");
		return 1;
	fd = open("temp", O_RDONLY);
	if (fd < 0)
		perror("Error reading temp");
	else {
		read(fd, buf, 50);
	fd = open("temp", O_WRONLY);
	if (fd < 0)
		perror("Error writing temp");
	else {
		write(fd, buf2, strlen(buf));
	return ret;

This code simply initializes a sandbox with the chosen profile, then attempts to open a temp file for reading, then again for writing. Running this yields the following result:

chadsbook:leopard chad$ ./test1
Error writing temp: Operation not permitted

As expected, the test program can read the file, but not write to it. Looking in /var/log/system.log shows no messages, so apparently the kSBXProfileNoWrite policy does not log denials.

Continue reading ‘Apple Sandboxes Part 2′

Apple Sandboxes Part 1

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.