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.

Example 2
This example uses the sandbox-exec command-line utility to place a test program in a sandbox that we create. Note that this is clearly marked as a private API that is subject to change in the header files, so try this with care. The test program is the same as the above without the sandbox_init() part (available here if you don’t trust me). The policy, written in the seatbelt Scheme-like language is as follows:

;; Test seatbelt sandbox policy
(version 1)

;; Turn on debugging for denials
(debug deny)

;; Import basic rules from bsd policy
(import "/usr/share/sandbox/")

;; Allow all process perms
(allow process*)

;; Allow reading a dylib that isn't part of for some reason
(allow file-read-data
  (regex "^/private/var/db/dyld/dyld_shared_cache_i386$"))

;; Allow reading sysctls
(allow sysctl-read)

;; Allow reading test data, but not writing
(allow file-read-data
  (regex "^/Users/chad/Tresys/svn/leopard.*"))

This policy has comments explaining what it does. Note that I have a (debug deny) message at the beginning, telling the kernel to log denials. This allowed me to look in /var/log/system.log to see what was being denied and allow it if necessary. That’s how I can up with several of these allow rules. Running the test program with this policy yields:

chadsbook:leopard chad$ sandbox-exec -f ./test2
Error writing temp: Permission denied

Again, the result we expect. This time, though, we’ve got the kernel logging denials. So, looking in /var/log/system.log yields:

Nov  8 16:09:50 chadsbook kernel[0]: test2 4511 FS_WRITE_DATA SBF /Users/chad/Tresys/svn/leopard/temp 13 (seatbelt)

Here we see that indeed seatbelt blocked our test program from writing to our file, confirming what we’ve seen.

At some point, I’ll try to talk about useful things you can do with Apple’s sandbox mechanism, as well as potentially compare/contrast it with SELinux. For now, though, just know that Apple’s pursuing stronger security mechanisms as well. That said, the list of applications actually sandboxed by default on Leopard is very small, so don’t think you’re getting a lot of protection from this today. This is more of an indicator of the good things to come as well as a mechanism you can use to protect your apps today.

0 Responses to “Apple Sandboxes Part 2”

  1. No Comments
  1. 1 Jabbering Giraffe » sandbox(7)

Leave a Reply