Recently my free time has mostly been dedicated to learning more about parallel computing. But I did take a little detour into the world of old-timey chroot(8) jails on OS X. They work, even on 10.8.4, even running a shell. The big trick on OS X is that you need to include the dynamic link editor
/usr/lib/dyld in the jail.
Of course you also need to include the programs you want to run in the jail and their dependencies. The
otool -L operation on OS X and the
ldd command on linux are key to finding these dependencies. There are a lot, and you’ll need to recursively resolve them. Additionally on OS X, when you are recursively finding the dependencies, you’ll need to account for Mach-O’s
@rpath variables. This can get a little tricky. On Linux, the libraries are easier but things like PAM can be tricky. This is why you want software like jailkit, which can help automate the process of creating and running jails.
While jails aren’t so good for security applications, they can be very helpful in trying to reign-in a proprietary installer.
For my purposes, jailkit wasn’t getting the library dependencies on OS X. So I made a little python module and a script to get that part of the job done.
$ ./mkjail.py -h usage: mkjail.py [-h] [-l] jail_name jail_programs [jail_programs ...] Create a "jail" directory appropriate for chroot, with copies of the specified programs and their dependencies positional arguments: jail_name the name of the jail to create jail_programs full path programs to import into the jail optional arguments: -h, --help show this help message and exit -l, --link use hard links instead of copies. !!!WARNING!!!: Changes made to hard-linked files in a jail will also affect the "original" (and probably important) files outside the jail. Additionally, hard links cannot span filesystems. DO NOT USE THIS OPTION UNLESS YOU KNOW WHAT YOU ARE DOING!
An example of creating and entering a jail with everything in
/bin and a couple commands from
/usr/bin looks like this:
sh-3.2$ sudo ./mkjail.py alcatraz /bin/* /usr/bin/find /usr/bin/whoami sh-3.2$ sudo chroot -u nobody -g nobody alcatraz bash-3.2$ pwd / bash-3.2$ whoami nobody bash-3.2$ find / / /Applications /Applications/Utilities /bin /bin/[ /bin/bash /bin/cat /bin/chmod [... and everything else from /bin ...] /bin/zsh /dev /etc /sbin /System /System/Library /System/Library/Frameworks /System/Library/Frameworks/CoreFoundation.framework /System/Library/Frameworks/CoreFoundation.framework/Versions /System/Library/Frameworks/CoreFoundation.framework/Versions/A /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation /System/Library/Frameworks/IOKit.framework /System/Library/Frameworks/IOKit.framework/Versions /System/Library/Frameworks/IOKit.framework/Versions/A /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit /tmp /Users /Users/Shared /usr /usr/bin /usr/bin/find /usr/bin/whoami /usr/include /usr/lib /usr/lib/dyld /usr/lib/libauditd.0.dylib /usr/lib/libauto.dylib /usr/lib/libbsm.0.dylib /usr/lib/libc++.1.dylib /usr/lib/libc++abi.dylib /usr/lib/libDiagnosticMessagesClient.dylib /usr/lib/libedit.3.dylib /usr/lib/libiconv.2.dylib /usr/lib/libicucore.A.dylib /usr/lib/libncurses.5.4.dylib /usr/lib/libobjc.A.dylib /usr/lib/libstdc++.6.dylib /usr/lib/libSystem.B.dylib /usr/lib/libutil.dylib /usr/lib/libz.1.dylib /usr/lib/system /usr/lib/system/libcache.dylib /usr/lib/system/libcommonCrypto.dylib /usr/lib/system/libcompiler_rt.dylib /usr/lib/system/libcopyfile.dylib /usr/lib/system/libcorecrypto.dylib /usr/lib/system/libdispatch.dylib /usr/lib/system/libdnsinfo.dylib /usr/lib/system/libdyld.dylib /usr/lib/system/libkeymgr.dylib /usr/lib/system/libkxld.dylib /usr/lib/system/liblaunch.dylib /usr/lib/system/libmacho.dylib /usr/lib/system/libquarantine.dylib /usr/lib/system/libremovefile.dylib /usr/lib/system/libsystem_blocks.dylib /usr/lib/system/libsystem_c.dylib /usr/lib/system/libsystem_dnssd.dylib /usr/lib/system/libsystem_info.dylib /usr/lib/system/libsystem_kernel.dylib /usr/lib/system/libsystem_m.dylib /usr/lib/system/libsystem_network.dylib /usr/lib/system/libsystem_notify.dylib /usr/lib/system/libsystem_sandbox.dylib /usr/lib/system/libunc.dylib /usr/lib/system/libunwind.dylib /usr/lib/system/libxpc.dylib /usr/libexec /usr/local /usr/sbin /usr/share /var /var/db /var/folders /var/log /var/run /var/tmp bash-3.2$ exit
Then you can use jailkit to put all the config files and non-library dependencies into the jail. Something like this:
jk_init -v -j alcatraz basicshell editors extendedshell netutils ssh sftp scp
Hopefully I’ll find some time to port these changes to jailkit itself.
You can find the code for mkjail on github.