Page MenuHomeFreeBSD

kernel: Allow unprivileged chroot by default
Needs ReviewPublic

Authored by emaste on Sat, Aug 2, 4:41 PM.
Tags
None
Referenced Files
F125547240: D51702.diff
Sat, Aug 9, 1:42 AM
F125542238: D51702.id159635.diff
Fri, Aug 8, 11:57 PM
Unknown Object (File)
Tue, Aug 5, 2:58 PM
Unknown Object (File)
Tue, Aug 5, 5:38 AM
Unknown Object (File)
Tue, Aug 5, 5:27 AM
Unknown Object (File)
Tue, Aug 5, 5:26 AM
Unknown Object (File)
Tue, Aug 5, 4:44 AM

Details

Summary

Commit 460b4b550dc9 ("Implement unprivileged chroot") added support for chroot by unprivileged users, with sysctl security.bsd.unprivileged_chroot to enable it.

We took a conservative path at introduction, leaving it disabled by default, but are ready to enable it now.

(See D30939, D30940, D30130, https://bugs.freebsd.org/121073 for more context.)

Diff Detail

Repository
R9 FreeBSD doc repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

emaste requested review of this revision.Sat, Aug 2, 4:41 PM
emaste created this revision.

"now" could be before or after 15 branches, or something else.

IMO we need to add some discussion about unprivileged chroot to chroot(2) or point at the chroot(8) docs on it. Right now we just claim it's restricted to root there, and I think we probably want to be more clear if we're going to enable it by default.

D51703 to make note of unprivileged sysctl

Update man page note about unprivileged chroot.

I think this is a fine idea since the feature is pretty well-gated to avoid mishaps. This should probably be relnotes-tagged.

This revision is now accepted and ready to land.Sat, Aug 2, 6:44 PM

For chroot(8), it seems a little cryptic to only mention security.bsd.unprivileged_chroot in the -n flag section. Might I suggest adding a paragraph like the following up-top, before the options descriptions:

"Non-privileged users can perform chroots under FreeBSD if security.bsd.unprivileged_chroot=1 (the default). However, the -n flag must be specified to disable SUID/SGID. This prevents privilege escalations that would otherwise be possible using modified system files to control SUID/SGID programs in the chroot environment. Only the root user can call chroot if security.bsd.unprivileged_chroot=0."

Can we please add a regression test which verifies that unprivileged chroot fails if the flag isn't set? See socket_afinet_bindany for an example of a test which runs as an unprivileged user.

Yeah, having a regression test for this is a requirement before flipping the switch.

It occurred to me that it might be good to set NO_NEW_PRIVS automatically when chroot is not invoked by root, rather than error out and make the user specify -n.

--- /usr/src/usr.sbin/chroot/chroot.c   2023-11-09 18:07:54.000000000 -0600
+++ chroot.c    2025-08-05 09:58:19.047205000 -0500
@@ -74,7 +74,10 @@
        gid = 0;
        uid = 0;
        user = group = grouplist = NULL;
-       nonprivileged = false;
+       if ( getuid() == 0 )
+               nonprivileged = false;
+       else
+               nonprivileged = true;
        while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) {
                switch(ch) {
                case 'u':

It occurred to me that it might be good to set NO_NEW_PRIVS automatically when chroot is not invoked by root, rather than error out and make the user specify -n.

@theraven fedi-mentioned that as well, and it does seem reasonable. I can see an argument for an explicit flag though, in that the chrooted command behaves differently in a way other than just the chroot(2) itself. In any case that can be considered separately from the kernel's default.

Oops, accidentally pushed a doc update referencing this review. Reopen with correct diff.