Author: mjg
Date: Sat Jul 11 16:19:11 2015
New Revision: 285390
URL: https://svnweb.freebsd.org/changeset/base/285390

Log:
  Move chdir/chroot-related fdp manipulation to kern_descrip.c
  
  Prefix exported functions with pwd_.
  
  Deduplicate some code by adding a helper for setting fd_cdir.
  
  Reviewed by:  kib

Modified:
  head/sys/compat/svr4/svr4_misc.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_jail.c
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/filedesc.h
  head/sys/sys/vnode.h
  head/sys/ufs/ffs/ffs_alloc.c

Modified: head/sys/compat/svr4/svr4_misc.c
==============================================================================
--- head/sys/compat/svr4/svr4_misc.c    Sat Jul 11 16:02:06 2015        
(r285389)
+++ head/sys/compat/svr4/svr4_misc.c    Sat Jul 11 16:19:11 2015        
(r285390)
@@ -643,7 +643,7 @@ svr4_sys_fchroot(td, uap)
                goto fail;
 #endif
        VOP_UNLOCK(vp, 0);
-       error = change_root(vp, td);
+       error = pwd_chroot(td, vp);
        vrele(vp);
        return (error);
 fail:

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Sat Jul 11 16:02:06 2015        
(r285389)
+++ head/sys/kern/kern_descrip.c        Sat Jul 11 16:19:11 2015        
(r285390)
@@ -2855,6 +2855,96 @@ dupfdopen(struct thread *td, struct file
 }
 
 /*
+ * This sysctl determines if we will allow a process to chroot(2) if it
+ * has a directory open:
+ *     0: disallowed for all processes.
+ *     1: allowed for processes that were not already chroot(2)'ed.
+ *     2: allowed for all processes.
+ */
+
+static int chroot_allow_open_directories = 1;
+
+SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
+    &chroot_allow_open_directories, 0,
+    "Allow a process to chroot(2) if it has a directory open");
+
+/*
+ * Helper function for raised chroot(2) security function:  Refuse if
+ * any filedescriptors are open directories.
+ */
+static int
+chroot_refuse_vdir_fds(struct filedesc *fdp)
+{
+       struct vnode *vp;
+       struct file *fp;
+       int fd;
+
+       FILEDESC_LOCK_ASSERT(fdp);
+
+       for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
+               fp = fget_locked(fdp, fd);
+               if (fp == NULL)
+                       continue;
+               if (fp->f_type == DTYPE_VNODE) {
+                       vp = fp->f_vnode;
+                       if (vp->v_type == VDIR)
+                               return (EPERM);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Common routine for kern_chroot() and jail_attach().  The caller is
+ * responsible for invoking priv_check() and mac_vnode_check_chroot() to
+ * authorize this operation.
+ */
+int
+pwd_chroot(struct thread *td, struct vnode *vp)
+{
+       struct filedesc *fdp;
+       struct vnode *oldvp;
+       int error;
+
+       fdp = td->td_proc->p_fd;
+       FILEDESC_XLOCK(fdp);
+       if (chroot_allow_open_directories == 0 ||
+           (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
+               error = chroot_refuse_vdir_fds(fdp);
+               if (error != 0) {
+                       FILEDESC_XUNLOCK(fdp);
+                       return (error);
+               }
+       }
+       oldvp = fdp->fd_rdir;
+       VREF(vp);
+       fdp->fd_rdir = vp;
+       if (fdp->fd_jdir == NULL) {
+               VREF(vp);
+               fdp->fd_jdir = vp;
+       }
+       FILEDESC_XUNLOCK(fdp);
+       vrele(oldvp);
+       return (0);
+}
+
+void
+pwd_chdir(struct thread *td, struct vnode *vp)
+{
+       struct filedesc *fdp;
+       struct vnode *oldvp;
+
+       fdp = td->td_proc->p_fd;
+       FILEDESC_XLOCK(fdp);
+       VNASSERT(vp->v_usecount > 0, vp,
+           ("chdir to a vnode with zero usecount"));
+       oldvp = fdp->fd_cdir;
+       fdp->fd_cdir = vp;
+       FILEDESC_XUNLOCK(fdp);
+       vrele(oldvp);
+}
+
+/*
  * Scan all active processes and prisons to see if any of them have a current
  * or root directory of `olddp'. If so, replace them with the new mount point.
  */

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c   Sat Jul 11 16:02:06 2015        (r285389)
+++ head/sys/kern/kern_jail.c   Sat Jul 11 16:19:11 2015        (r285390)
@@ -2432,7 +2432,7 @@ do_jail_attach(struct thread *td, struct
                goto e_unlock;
 #endif
        VOP_UNLOCK(pr->pr_root, 0);
-       if ((error = change_root(pr->pr_root, td)))
+       if ((error = pwd_chroot(td, pr->pr_root)))
                goto e_revert_osd;
 
        newcred = crget();

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c        Sat Jul 11 16:02:06 2015        
(r285389)
+++ head/sys/kern/vfs_syscalls.c        Sat Jul 11 16:19:11 2015        
(r285390)
@@ -728,8 +728,7 @@ sys_fchdir(td, uap)
                int fd;
        } */ *uap;
 {
-       register struct filedesc *fdp = td->td_proc->p_fd;
-       struct vnode *vp, *tdp, *vpold;
+       struct vnode *vp, *tdp;
        struct mount *mp;
        struct file *fp;
        cap_rights_t rights;
@@ -761,11 +760,7 @@ sys_fchdir(td, uap)
                return (error);
        }
        VOP_UNLOCK(vp, 0);
-       FILEDESC_XLOCK(fdp);
-       vpold = fdp->fd_cdir;
-       fdp->fd_cdir = vp;
-       FILEDESC_XUNLOCK(fdp);
-       vrele(vpold);
+       pwd_chdir(td, vp);
        return (0);
 }
 
@@ -791,9 +786,7 @@ sys_chdir(td, uap)
 int
 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
 {
-       register struct filedesc *fdp = td->td_proc->p_fd;
        struct nameidata nd;
-       struct vnode *vp;
        int error;
 
        NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
@@ -807,56 +800,11 @@ kern_chdir(struct thread *td, char *path
        }
        VOP_UNLOCK(nd.ni_vp, 0);
        NDFREE(&nd, NDF_ONLY_PNBUF);
-       FILEDESC_XLOCK(fdp);
-       vp = fdp->fd_cdir;
-       fdp->fd_cdir = nd.ni_vp;
-       FILEDESC_XUNLOCK(fdp);
-       vrele(vp);
+       pwd_chdir(td, nd.ni_vp);
        return (0);
 }
 
 /*
- * Helper function for raised chroot(2) security function:  Refuse if
- * any filedescriptors are open directories.
- */
-static int
-chroot_refuse_vdir_fds(fdp)
-       struct filedesc *fdp;
-{
-       struct vnode *vp;
-       struct file *fp;
-       int fd;
-
-       FILEDESC_LOCK_ASSERT(fdp);
-
-       for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
-               fp = fget_locked(fdp, fd);
-               if (fp == NULL)
-                       continue;
-               if (fp->f_type == DTYPE_VNODE) {
-                       vp = fp->f_vnode;
-                       if (vp->v_type == VDIR)
-                               return (EPERM);
-               }
-       }
-       return (0);
-}
-
-/*
- * This sysctl determines if we will allow a process to chroot(2) if it
- * has a directory open:
- *     0: disallowed for all processes.
- *     1: allowed for processes that were not already chroot(2)'ed.
- *     2: allowed for all processes.
- */
-
-static int chroot_allow_open_directories = 1;
-
-SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
-     &chroot_allow_open_directories, 0,
-     "Allow a process to chroot(2) if it has a directory open");
-
-/*
  * Change notion of root (``/'') directory.
  */
 #ifndef _SYS_SYSPROTO_H_
@@ -891,7 +839,7 @@ sys_chroot(td, uap)
                goto e_vunlock;
 #endif
        VOP_UNLOCK(nd.ni_vp, 0);
-       error = change_root(nd.ni_vp, td);
+       error = pwd_chroot(td, nd.ni_vp);
        vrele(nd.ni_vp);
        NDFREE(&nd, NDF_ONLY_PNBUF);
        return (error);
@@ -926,42 +874,6 @@ change_dir(vp, td)
        return (VOP_ACCESS(vp, VEXEC, td->td_ucred, td));
 }
 
-/*
- * Common routine for kern_chroot() and jail_attach().  The caller is
- * responsible for invoking priv_check() and mac_vnode_check_chroot() to
- * authorize this operation.
- */
-int
-change_root(vp, td)
-       struct vnode *vp;
-       struct thread *td;
-{
-       struct filedesc *fdp;
-       struct vnode *oldvp;
-       int error;
-
-       fdp = td->td_proc->p_fd;
-       FILEDESC_XLOCK(fdp);
-       if (chroot_allow_open_directories == 0 ||
-           (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
-               error = chroot_refuse_vdir_fds(fdp);
-               if (error != 0) {
-                       FILEDESC_XUNLOCK(fdp);
-                       return (error);
-               }
-       }
-       oldvp = fdp->fd_rdir;
-       fdp->fd_rdir = vp;
-       VREF(fdp->fd_rdir);
-       if (!fdp->fd_jdir) {
-               fdp->fd_jdir = vp;
-               VREF(fdp->fd_jdir);
-       }
-       FILEDESC_XUNLOCK(fdp);
-       vrele(oldvp);
-       return (0);
-}
-
 static __inline void
 flags_to_rights(int flags, cap_rights_t *rightsp)
 {

Modified: head/sys/sys/filedesc.h
==============================================================================
--- head/sys/sys/filedesc.h     Sat Jul 11 16:02:06 2015        (r285389)
+++ head/sys/sys/filedesc.h     Sat Jul 11 16:19:11 2015        (r285390)
@@ -205,6 +205,10 @@ fd_modified(struct filedesc *fdp, int fd
        return (!seq_consistent(fd_seq(fdp->fd_files, fd), seq));
 }
 
+/* cdir/rdir/jdir manipulation functions. */
+void   pwd_chdir(struct thread *td, struct vnode *vp);
+int    pwd_chroot(struct thread *td, struct vnode *vp);
+
 #endif /* _KERNEL */
 
 #endif /* !_SYS_FILEDESC_H_ */

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h        Sat Jul 11 16:02:06 2015        (r285389)
+++ head/sys/sys/vnode.h        Sat Jul 11 16:19:11 2015        (r285390)
@@ -616,7 +616,6 @@ void        cache_purge(struct vnode *vp);
 void   cache_purge_negative(struct vnode *vp);
 void   cache_purgevfs(struct mount *mp);
 int    change_dir(struct vnode *vp, struct thread *td);
-int    change_root(struct vnode *vp, struct thread *td);
 void   cvtstat(struct stat *st, struct ostat *ost);
 void   cvtnstat(struct stat *sb, struct nstat *nsb);
 int    getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c        Sat Jul 11 16:02:06 2015        
(r285389)
+++ head/sys/ufs/ffs/ffs_alloc.c        Sat Jul 11 16:19:11 2015        
(r285390)
@@ -2748,13 +2748,12 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
        struct thread *td = curthread;
        struct fsck_cmd cmd;
        struct ufsmount *ump;
-       struct vnode *vp, *vpold, *dvp, *fdvp;
+       struct vnode *vp, *dvp, *fdvp;
        struct inode *ip, *dp;
        struct mount *mp;
        struct fs *fs;
        ufs2_daddr_t blkno;
        long blkcnt, blksize;
-       struct filedesc *fdp;
        struct file *fp, *vfp;
        cap_rights_t rights;
        int filetype, error;
@@ -2968,12 +2967,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
                        break;
                }
                VOP_UNLOCK(vp, 0);
-               fdp = td->td_proc->p_fd;
-               FILEDESC_XLOCK(fdp);
-               vpold = fdp->fd_cdir;
-               fdp->fd_cdir = vp;
-               FILEDESC_XUNLOCK(fdp);
-               vrele(vpold);
+               pwd_chdir(td, vp);
                break;
 
        case FFS_SET_DOTDOT:
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to