kern/121073: [kernel] [patch] run chroot as an unprivileged user
Nathan Whitehorn
nwhitehorn at freebsd.org
Fri May 30 22:00:01 UTC 2014
The following reply was made to PR kern/121073; it has been noted by GNATS.
From: Nathan Whitehorn <nwhitehorn at freebsd.org>
To: bug-followup at freebsd.org, jille at quis.cx
Cc:
Subject: Re: kern/121073: [kernel] [patch] run chroot as an unprivileged user
Date: Fri, 30 May 2014 14:54:07 -0700
This is a multi-part message in MIME format.
--------------010409080200010001080602
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
This patch would be extremely useful for package building, as I think it
would allow all operations to be done without root. It has gone stale
since the bug was filed, so I've updated it and attached a new version.
-Nathan
--------------010409080200010001080602
Content-Type: text/plain; charset=us-ascii;
name="chroot.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="chroot.patch"
Index: lib/libc/sys/chroot.2
===================================================================
--- lib/libc/sys/chroot.2 (revision 266749)
+++ lib/libc/sys/chroot.2 (working copy)
@@ -61,7 +61,13 @@
.Fn chroot
has no effect on the process's current directory.
.Pp
-This call is restricted to the super-user.
+By default, this call is restricted to the super-user. If
+.Ql kern.chroot_allow_unprivileged
+is set to a non-zero value, all users are capable of performing the
+.Fn chroot
+call. When called by an unprivileged user, the process and its children
+won't honor the setuid and setgid bits when performing an
+.Xr execve 2 .
.Pp
Depending on the setting of the
.Ql kern.chroot_allow_open_directories
@@ -141,6 +147,11 @@
open directories, or a MAC check), it is possible that this system
call may return an error, with the working directory of the process
left changed.
+.Pp
+When a call to
+.Fn chroot
+fails when invoked by an unprivileged user, the process is not properly
+capable of executing setuid or setgid applications anymore.
.Sh SECURITY CONSIDERATIONS
The system have many hardcoded paths to files where it may load after
the process starts.
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c (revision 266749)
+++ sys/kern/kern_exec.c (working copy)
@@ -695,7 +695,7 @@
((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&
#endif
(imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
- (p->p_flag & P_TRACED) == 0) {
+ (p->p_flag & P_TRACED) == 0 && (p->p_flag2 & P2_NOSUGID) == 0) {
/*
* Turn off syscall tracing for set-id programs, except for
* root. Record any set-id flags first to make sure that
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c (revision 266749)
+++ sys/kern/kern_fork.c (working copy)
@@ -571,6 +571,7 @@
* been preserved.
*/
p2->p_flag |= p1->p_flag & P_SUGID;
+ p2->p_flag2 |= p1->p_flag2 & P2_NOSUGID;
td2->td_pflags |= td->td_pflags & TDP_ALTSTACK;
SESS_LOCK(p1->p_session);
if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c (revision 266749)
+++ sys/kern/vfs_syscalls.c (working copy)
@@ -855,6 +855,11 @@
&chroot_allow_open_directories, 0,
"Allow a process to chroot(2) if it has a directory open");
+/* This one allows unprivileged users to run chroot */
+static int chroot_allow_unprivileged = 0;
+SYSCTL_INT(_kern, OID_AUTO, chroot_allow_unprivileged, CTLFLAG_RW,
+ &chroot_allow_unprivileged, 0, "");
+
/*
* Change notion of root (``/'') directory.
*/
@@ -871,11 +876,26 @@
} */ *uap;
{
struct nameidata nd;
+ struct proc *p;
int error;
error = priv_check(td, PRIV_VFS_CHROOT);
- if (error != 0)
- return (error);
+ if (error) {
+ if (!chroot_allow_unprivileged)
+ return (error);
+
+ /*
+ * Disallow this process and its children to use setuid
+ * bits. Users could hardlink setuid applications into a
+ * chroot which contains a fake C library to obtain
+ * super-user privileges.
+ */
+ p = td->td_proc;
+ PROC_LOCK(p);
+ p->p_flag2 |= P2_NOSUGID;
+ PROC_UNLOCK(p);
+ }
+
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
UIO_USERSPACE, uap->path, td);
error = namei(&nd);
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h (revision 266749)
+++ sys/sys/proc.h (working copy)
@@ -646,6 +646,7 @@
/* These flags are kept in p_flag2. */
#define P2_INHERIT_PROTECTED 0x00000001 /* New children get P_PROTECTED. */
+#define P2_NOSUGID 0x00000002 /* Ignore set[ug]id on exec. */
/*
* These were process status values (p_stat), now they are only used in
--------------010409080200010001080602--
More information about the freebsd-bugs
mailing list