I’ve been playing with Linux namespaces and the results are very satisfying. This process isolation has several benefits:
- The setup is automatically destroyed when the process and its children exit — easy maintenance.
- Non-privileged processes cannot alter the setup — great security.
- The isolated resource type is completely invisible by processes in other namespaces — great security.
- The setup is inherited by any forked children — great for security and maintenance.
If you review the man page of the “unshare” command or syscall, you will see that currently we can have the following private namespaces:
- mount namespace — mounting and unmounting filesystems will not affect rest of the system, except for filesystems which are explicitly marked as shared
- UTS namespace — setting hostname, domainname will not affect rest of the system
- IPC namespace — the process will have independent namespace for System V message queues, semaphore sets and shared memory segments
- network namespace — the process will have independent IPv4 and IPv6 stacks, IP routing tables, iptables firewall rules, the /proc/net and /sys/class/net directory trees, sockets, etc.
- pid namespace (new) — children will have a distinct set of PID to process mappings from their parent
- user namespace (new) — the process will have a distinct set of UIDs, GIDs and capabilities
In this article we will demonstrate the use of the “mount” namespace which lets us mount a filesystem per-process without affecting the rest of the system. Using such a private mount for “/tmp” has mainly security but also usability benefits.
Here are all the commands which you need, in order to start a process with a private “/tmp” directory:
TARGET_USER='www-data' TARGET_CMD='/bin/bash' # but it can be any command NEWTMP="$(mktemp -d)" # securely create a new empty tmp folder chown "root:$TARGET_USER" "$NEWTMP" chmod 770 "$NEWTMP" unshare --mount -- /bin/bash -c "mount -o bind,noexec,nosuid,nodev '$NEWTMP' /tmp && sudo -u '$TARGET_USER' $TARGET_CMD"
A longer version with more explanations follow:
# # setup operations done as "root" # root@vbox:~# TARGET_USER='www-data' root@vbox:~# TARGET_CMD='/bin/bash' # but it can be any command root@vbox:~# NEWTMP="$(mktemp -d)" # securely create a new empty tmp folder root@vbox:~# chown "root:$TARGET_USER" "$NEWTMP" root@vbox:~# chmod 770 "$NEWTMP" # # review the result in the real file-system "/tmp" # root@vbox:~# echo $NEWTMP /tmp/tmp.IyoUhputAW root@vbox:~# ls -la /tmp total 60 drwxrwxrwt 12 root root 12288 Jun 4 13:53 . drwxr-xr-x 23 root root 4096 Jan 24 15:31 .. drwxrwxrwt 2 root root 4096 Jun 1 22:54 .ICE-unix drwxrwx--- 2 root www-data 4096 Jun 4 13:53 tmp.IyoUhputAW root@vbox:~# ls -la "$NEWTMP" total 16 drwxrwx--- 2 root www-data 4096 Jun 4 13:53 . drwxrwxrwt 12 root root 12288 Jun 4 13:53 .. # # start the non-privileged process with a private "/tmp" mount # root@vbox:~# unshare --mount -- /bin/bash -c "mount -o bind,noexec,nosuid,nodev '$NEWTMP' /tmp && sudo -u '$TARGET_USER' $TARGET_CMD" # # sample operations done inside the non-privileged process # www-data@vbox:~$ ls -la / | grep tmp drwxrwx--- 2 root www-data 4096 Jun 4 13:53 tmp www-data@vbox:~$ touch /tmp/test-www-data-file www-data@vbox:~$ ls -la /tmp # the process has a private "/tmp" mount total 8 drwxrwx--- 2 root www-data 4096 Jun 4 13:55 . drwxr-xr-x 23 root root 4096 Jan 24 15:31 .. -rw-r--r-- 1 www-data www-data 0 Jun 4 13:55 test-www-data-file # # see the result in the real file-system "/tmp" # root@vbox:~# ls -la /tmp total 60 drwxrwxrwt 12 root root 12288 Jun 4 13:53 . drwxr-xr-x 23 root root 4096 Jan 24 15:31 .. drwxrwxrwt 2 root root 4096 Jun 1 22:54 .ICE-unix drwxrwx--- 2 root www-data 4096 Jun 4 13:55 tmp.IyoUhputAW root@vbox:~# echo "$NEWTMP" /tmp/tmp.IyoUhputAW root@vbox:~# ls -la "$NEWTMP" total 16 drwxrwx--- 2 root www-data 4096 Jun 4 13:55 . drwxrwxrwt 12 root root 12288 Jun 4 13:53 .. -rw-r--r-- 1 www-data www-data 0 Jun 4 13:55 test-www-data-file
Note that we are mounting a directory inside another directory using the “bind” mount feature of Linux.
Resources:
April 24, 2017 at 1:35 am
Thank you for the example. This is an elegant way to address the security issues that are inherent in the /tmp directory.