7 ms·
Implement unprivileged chroot
- thenoblesunfish 5y agoFor those, like me, lacking context, what are the implications of this?
- jsiepkes 5y agoYou can for example run a build in a chroot as a unprivileged user.
- phicoh 5y agoThe key feature of chroot is that you can provide a process with a completely different filesystem view. You can leave stuff out that exist in the standard view, or change things. Change the contents of system directories. The problem with traditional chroot is that you can typically import setuid applications in this new space which can get confused, for example by a new /etc/passwd file. For this reason, chroot can be used only by root. The advantage of such a NO_NEW_PRIVS flag is that this kind of abuse of setuid applications is not possible. This should make it safe to allow ordinary users to use chroot.
- codetrotter 5y agochroot is a system call that assigns a limited view of the file system to a process. In particular it makes it so that the specific directory will appear as the top level directory to the process. Some people like to run for example FTP servers in a chroot so that users have access only to a specific directory and its subdirectories, rather than being able to browse other files on the system. FreeBSD also has a technology called jails which is what you’d rather use for containerization. Anyway, previously you had to be root (the Unix admin user) in order to use chroot. FreeBSD now implementing unprivileged chroot means that regular users are able to run processes in chroot as well. So for example if you were a regular user on a system, you can now create a sub directory in your home directory and run an FTP demon chrooted to that directory and bound to an unprivileged port, and then you can give someone else FTP access to that directory without them being able to see the other files in your home directory, keeping your private data private from them.
- tyingq 5y agochroot existed, but could only be run as the root user. It was that way to prevent things like this (old actual exploit for Ultrix): $ mkdir /tmp/etc $ echo root::0:0::/:/bin/sh > /tmp/etc/passwd $ mkdir /tmp/bin $ cp /bin/sh /tmp/bin/sh $ cp /bin/chmod /tmp/bin/chmod $ chroot /tmp /bin/login # whoami root # chmod 4700 /bin/sh now, log out of the chroot and use your newly minted setuid shell Since they now have the "NO_NEW_PRIVS" protection, they can let regular users safely use chroot.
- deleted 5y ago[deleted]
- stabbles 5y agoOn many linux distro's you can already do this with user namespaces: $ mkdir rootfs $ docker export $(docker create ubuntu:20.04) | tar -C rootfs -xf - $ unshare -r chroot rootfs bash # ls bin dev home ... Very often when you use chroot you also want unprivileged mounts, in particular overlay mounts if you don't want to mutate the underlying rootfs. You can do that with mount namespaces: `unshare -rm`, but you need Linux kernel 5.13 (or a distro with a patched kernel like Ubuntu) to allow unpriviliged overlayfs.
- dividuum 5y agoAn alternative to unshare is also bubblewrap (https://github.com/containers/bubblewrap https://github.com/containers/bubblewrap) which also sets up a new namespace. You can build up your own new filesystem by binding existing paths into the new root and then run a process within it: $ mkdir -p root/bin $ cp /bin/busybox root/bin/ $ bwrap --bind root / /bin/busybox sh BusyBox v1.27.2 (Ubuntu 1:1.27.2-2ubuntu3.3) built-in shell (ash) Enter 'help' for a list of built-in commands. / $ ls -l / total 0 drwxrwxr-x 2 1000 1000 60 Jul 22 11:07 bin
- gigatexal 5y agoInteresting. Going to check out Bubblewrap
- Cloudef 5y agoI used bubblewrap to do a lightweight containers on top of arch + pacman. Basically you could install packages on overlays of the host and do whatever there without affecting the host fs. It was pretty nice.
- stabbles 5y agoSo how does this work? Can you mount / as the lower layer of the overlayfs? Doesn't that create a weird recursion because the mountpoint is a path inside /?
- marcodiego 5y ago*BSD have been quite innovative recently. The pledge and unveil syscalls, although achievable by other means on linux, are very simple and effective for what they do. I don't know a way on linux to use a system on a directory without being root; even if possible I'd still need root to mount --bind some dirs, but definitely something I'd like to do. I don't think containers should be needed for that.
- EdSchouten 5y agoFreeBSD already supported something like this effectively, but in my opinion better way. You can call cap_enter(), which disables open(), unlink(), mkdir(), etc. entirely. You can, however, still use openat(), unlinkat(), mkdirat() with relative paths that expand to a location underneath a directory file descriptor. This achieves the same thing, except that you can now have as many chroots as you want. Not just one. Unfortunately, the idea never caught on, because virtually no software on UNIX uses the *at() functions. Also: the non-*at() functions are still available as symbols, meaning that you can't perform simple compile-time checks to ensure that you application works properly when this form of sandboxing is enabled. Turns out that off-the-shelf software (e.g., libraries) end up misbehaving in unpredictable ways if you disable ~50% of the POSIX API. It's a shame, because this feature effectively requires you to treat the file system in an object oriented/dependency injected way. Pretty good from a reusability/testability perspective.
- phicoh 5y agoThe problem is that many libraries need access to configuration files or other stuff that comes with the library. So if you start with a system that has some form of persistent objects, then very quickly a root namespace object is created to solve those library issues. And then you are mostly back to a Unix root directory.
- wahern 5y agocap_enter can be invoked after library initialization. Libraries can open the files and directories they need during initialization. A single jailed root is where you end up when you take the route of putting software into sandboxes for which they weren't designed, because now you need to emulate a traditional environment. pledge and unveil are a middle ground, albeit closer to Capsicum, in that they're much more accommodating of existing software patterns. But they do still require application refactoring. OpenBSD has refactored their entire userland codebase this way. That typically involves identifying the necessary resources a program needs and either shifting their acquisition to before privilege dropping (i.e. early in main), or arranging so that they're subsequently accessible (e.g. using unveil). It's a shame Linux never merged the Capsicum patches. While pledge and unveil are more convenient from a developer perspective, they can't easily be adopted in a standardized way by other operating systems, like Linux. Capsicum was the closest thing we could have gotten to a standardized sandboxing model in the POSIX universe. If it became widely available (cough Linux), I believe a large chunk of software, especially critical network-facing software, would slowly migrate; and an ecosystem of idioms, patterns, and libraries would evolve to increasingly smooth the transition. What's doubly shameful is that Capsicum is architecturally extremely simple. In principle it would be easy for any POSIX system to adopt. The APIs are trivial, and Linux is already nearly there now that it has process descriptors and an openat that can prevent parent directory traversal. Most of the leg work is in blocking access, after cap_enter has been invoked, to non-standard interfaces and syscalls that expose resources.
- krylon 5y agoThe commit message does NOT indicate when this will be available to mere mortals like myself. Can someone enlighten me if this will be part of FreeBSD 14, or if there is a chance it will become available earlier, perhaps with FreeBSD 13.1? EDIT: The commit message does NOT indicate etc. Silly me.
- 0mp 5y agoThe commit message does not mention any MFC timeline [1] so this feature is not planned to be merged back into existing stable branches. In other words, the first release with this feature is going to be FreeBSD 14.0-RELEASE. [1]: Also, you may look for the commit hash (a40cf4175c90142442d0c6515f6c83956336699) at https://mfc.kernelnomicon.org/ https://mfc.kernelnomicon.org/ to see the back-porting status.
- swills 5y agoThis feature should be in the weekly snapshot pretty soon: https://download.freebsd.org/ftp/snapshots/ISO-IMAGES/14.0/ https://download.freebsd.org/ftp/snapshots/ISO-IMAGES/14.0/
- geofft 5y agoI wish Linux would do this. Patches are available: https://lwn.net/Articles/849125/ https://lwn.net/Articles/849125/ Yes, you can do this on Linux with a user namespace, but a user namespace changes the view of user accounts. You have to map every usable UID inside the namespace to a UID you control outside the namespace. At best, you can map a range of UIDs you control to "real" users (root, 1000, etc.) inside the namespace, but they won't be real users outside the namespace. If you're on a multi-user system, seeing other people's files as owned by "nobody" is confusing. It should be enough to use NO_NEW_PRIVS mode, meaning setuid transitions are not allowed. Then it doesn't matter what user IDs you see inside the chroot. In fact, back when Linux introduced the NO_NEW_PRIVS flag (almost a decade ago!), this was one of the motivating use cases.
- HPsquared 5y agoIn Linux there's "PRoot" - used by Termux on Android to provide userspace chroot-like functionality (can run Debian, for instance). https://proot-me.github.io/ https://proot-me.github.io/