THIS PROJECT IS REPLACED BY BUBBLEWRAP -------------------------------------- Please see: https://github.com/projectatomic/bubblewrap THIS PROJECT IS REPLACED BY BUBBLEWRAP -------------------------------------- Historical README follows: Summary ------- This tool allows regular (non-root) users to call chroot(2), create Linux bind mounts, and use some Linux container features. It's primarily intended for use by build systems. Contributing ------------ Currently, linux-user-chroot reuses the https://mail.gnome.org/mailman/listinfo/ostree-list mailing list. Please send patches there. Why is this useful? ------------------- There are a few well-known approaches for software build roots: - Set up a chroot as root, then chroot in, and become non-root This is the model currently used by both rpm and dpkg. The problem with this is that if you want to build *two* packages where B depends on A, then the `%post` type scripts from A run as root, and hence need to be fully trusted. - Use `LD_PRELOAD` emulation This is implemented by https://github.com/wrpseudo/pseudo The problem with this is that it's a speed hit, and maintaining that sort of emulation is a long-term maintenance pain. - Don't do any chrooting, use environment variables This is implemented by `jhbuild`. The problem with this is there are a *lot* of these, and it's really easy to get "host contamination", where we silently pick up `/usr/include/foo.h` instead of the one from the root. What linux-user-chroot does is a variant of the first, except instead of using root-owned files for the chroot, you simply make the chroot data as non-root, and run `%post` type scripts as non-root too. This works because we believe linux-user-chroot is secure; see below. Security -------- **** IMPORTANT NOTE **** Installing this tool accessible to all users increases their ability to perform local, authenticated denial of service attacks. One mitigation against this is to ensure the tool is only executable by certain users. **** IMPORTANT NOTE **** The historical reason Unix doesn't allow chroot(2) as non-root is because of setuid binaries. It's trivial to use chroot to create a hostile environment, then execute a setuid binary to subvert it. Since then, the Linux kernel has gained a per-process mode that disables setuid binaries, called `PR_SET_NO_NEW_PRIVS`: https://lwn.net/Articles/478062/ While this tool itself is setuid, it enables that mode, thus ensuring any other setuid binaries (including recursive invocations of this tool) cannot be exploited. However, this tool also allows creating bind mounts, which currently have no resource controls and occupy kernel memory. This is why this tool is not intended to be installed by default and accessible to all users. Abilities granted ----------------- However in order to make a usable system, it's not quite enough to be able to call chroot(2). A lot of Unix software expects e.g. /dev/null, and Linux /proc is also fairly widely used. So this tool also allows creating Linux "bind mounts". This is how one can expose the "host" /dev inside the chroot. Also, this tool allows mounting procfs. In addition, this tool exposes several of the Linux "unshare" capabilities such as: * CLONE_NEWNET - create a new, empty networking stack. Because the child process won't have the privilges to manipulate the network, this will result in no networking (including loopback) which ensures that e.g. the build process isn't downloading more code. * CLONE_NEWPID - create a new PID namespace. For example, if the build script runs some test scripts that start processes, "pidof" won't accidentally pick up a similarly-named process outside of the root. * CLONE_NEWIPC - get a new SysV IPC namespace. This is just further isolation. See "man 2 clone" for more information. Additionally, the 2015.1 release of linux-user-chroot also gained support for seccomp, which is a strong way to restrict what system calls build systems can use. Example usage ------------- Note here all files are owned by the user. $ mkdir -p /path/to/my/chroot/usr/src/project $ linux-user-chroot \ --seccomp-profile-version 0 \ --unshare-pid --unshare-net --unshare-pid \ --mount-proc /proc --mount-bind /dev /dev \ --mount-bind /home/user/source/project /usr/src/project \ /path/to/my/chroot /bin/sh Here we're creating a bind mount inside the chroot to outside. This helps avoid copying files around. Installing ---------- This binary can be installed in two modes: 1) uwsr-xr-x root:root - Executable by everyone 2) uwsr-x--- root:somegroup - Executable only by somegroup Programs using linux-user-chroot -------------------------------- - https://github.com/CodethinkLabs/sandboxlib - https://git.gnome.org/browse/gnome-continuous/ uses it for builds Related projects ---------------- Google's Bazel system has a similar tool: https://github.com/google/bazel/blob/master/src/main/tools/namespace-sandbox.c (Noted by the sandboxlib/README.rst list of related projects)