Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 May 2014 22:00:00 GMT
From:      Nathan Whitehorn <nwhitehorn@freebsd.org>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/121073: [kernel] [patch] run chroot as an unprivileged user
Message-ID:  <201405302200.s4UM00dk044565@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/121073; it has been noted by GNATS.

From: Nathan Whitehorn <nwhitehorn@freebsd.org>
To: bug-followup@freebsd.org, jille@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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405302200.s4UM00dk044565>