The following reply was made to PR kern/121073; it has been noted by GNATS.

From: Nathan Whitehorn <[email protected]>
To: [email protected], [email protected]
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--
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to