Sandboxing processes
Yesterday, my interest in sandboxing a program I didn’t fully trust finally surpassed my laziness to look at namespaces again. And after a few hours of coding, I created a small script that uses unshare
to encapsulate the newly launched process in new namespaces of all kinds (not much work there) and hardens the filesystem so that effectively, (hopefully) the only writable persistent directory is $PWD
, the process sees a minimal /dev
and fresh copies of temporary filesystems. In case you are interested in the script, here it is:#!/bin/sh
CMD="${@:-bash}"
unshare -unpirf --mount-proc sh -c '
hostname sandbox
TMPNAME=$(mktemp -d)
# replace /dev by minimal dummy version
mount -t tmpfs -o nosuid,mode=755 none $TMPNAME
for dev in null zero full random urandom console tty; do
touch $TMPNAME/$dev
mount --bind /dev/$dev $TMPNAME/$dev
done
mount --move $TMPNAME /dev
# Make some symlinks
ln -s null /dev/kmsg
ln -s /proc/self/fd/0 /dev/stdin
ln -s /proc/self/fd/1 /dev/stdout
ln -s /proc/self/fd/2 /dev/stderr
# save a r/w bind mount of our original cwd
if [ "${PWD#/home}" != "$PWD" ]; then
mount --bind "$PWD" $TMPNAME
fi
# make /home read-only
mount -o remount,bind,ro /home
# restore the original r/w cwd
if [ "${PWD#/home}" != "$PWD" ]; then
mount --move $TMPNAME $PWD
fi
# shadow temporary filesystems with fresh copies
mount -t tmpfs -o nosuid,nodev,noexec,mode=755 none /run
mount -t tmpfs -o nosuid,nodev none /var/tmp
if [ "${PWD#/tmp}" != "$PWD" ]; then
mount -t tmpfs -o nosuid,nodev none $TMPNAME
mkdir -p "$TMPNAME${PWD#/tmp}"
mount --bind "$PWD" "$TMPNAME${PWD#/tmp}"
mount --move $TMPNAME /tmp
else
rmdir $TMPNAME
mount -t tmpfs -o nosuid,nodev none /tmp
fi
# refresh cwd handle
cd "$PWD"
# get lost of uid 0 by starting yet another user namespace
exec unshare -U '"$CMD"
I’m always open for feedback, either via e-mail or on Github!