Diff for /src/sys/kern/vfs_syscalls.c between versions 1.29 and 1.30

version 1.29, 2004/03/01 06:33:17 version 1.30, 2004/03/16 17:53:53
Line 71 Line 71
   
 #include <sys/file2.h>  #include <sys/file2.h>
   
static int change_dir (struct nameidata *ndp, struct thread *td);static int checkvp_chdir (struct vnode *vn, struct thread *td);
 static void checkdirs (struct vnode *olddp);  static void checkdirs (struct vnode *olddp);
 static int chroot_refuse_vdir_fds (struct filedesc *fdp);  static int chroot_refuse_vdir_fds (struct filedesc *fdp);
 static int getutimes (const struct timeval *, struct timespec *);  static int getutimes (const struct timeval *, struct timespec *);
Line 790  kern_chdir(struct nameidata *nd) Line 790  kern_chdir(struct nameidata *nd)
         struct filedesc *fdp = p->p_fd;          struct filedesc *fdp = p->p_fd;
         int error;          int error;
   
        error = change_dir(nd, td);        if ((error = namei(nd)) != 0)
        if (error) 
                 return (error);                  return (error);
        NDFREE(nd, NDF_ONLY_PNBUF);        if ((error = checkvp_chdir(nd->ni_vp, td)) == 0) {
        vrele(fdp->fd_cdir);                vrele(fdp->fd_cdir);
        fdp->fd_cdir = nd->ni_vp;                fdp->fd_cdir = nd->ni_vp;
        return (0);                VREF(fdp->fd_cdir);
         }
         NDFREE(nd, ~(NDF_NO_FREE_PNBUF | NDF_NO_VP_PUT));
         return (error);
 }  }
   
 /*  /*
Line 858  SYSCTL_INT(_kern, OID_AUTO, chroot_allow Line 860  SYSCTL_INT(_kern, OID_AUTO, chroot_allow
      &chroot_allow_open_directories, 0, "");       &chroot_allow_open_directories, 0, "");
   
 /*  /*
    * Chroot to the specified vnode.  vp must be locked and referenced on
    * call, and will be left locked and referenced on return.  This routine
    * may acquire additional refs on the vnode when associating it with
    * the process's root and/or jail dirs.
    */
   int
   kern_chroot(struct vnode *vp)
   {
           struct thread *td = curthread;
           struct proc *p = td->td_proc;
           struct filedesc *fdp = p->p_fd;
           int error;
   
           /*
            * Only root can chroot
            */
           if ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0)
                   return (error);
   
           /*
            * Disallow open directory descriptors (fchdir() breakouts).
            */
           if (chroot_allow_open_directories == 0 ||
              (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
                   if ((error = chroot_refuse_vdir_fds(fdp)) != 0)
                           return (error);
           }
   
           /*
            * Check the validity of vp as a directory to change to and 
            * associate it with rdir/jdir.
            */
           if ((error = checkvp_chdir(vp, td)) == 0) {
                   vrele(fdp->fd_rdir);
                   fdp->fd_rdir = vp;
                   VREF(fdp->fd_rdir);
                   if (fdp->fd_jdir == NULL) {
                           fdp->fd_jdir = vp;
                           VREF(fdp->fd_jdir);
                   }
           }
           return (error);
   }
   
   /*
  * chroot_args(char *path)   * chroot_args(char *path)
  *   *
  * Change notion of root (``/'') directory.   * Change notion of root (``/'') directory.
Line 867  int Line 914  int
 chroot(struct chroot_args *uap)  chroot(struct chroot_args *uap)
 {  {
         struct thread *td = curthread;          struct thread *td = curthread;
         struct proc *p = td->td_proc;  
         struct filedesc *fdp = p->p_fd;  
         int error;  
         struct nameidata nd;          struct nameidata nd;
           int error;
   
        KKASSERT(p);        KKASSERT(td->td_proc);
        error = suser_cred(p->p_ucred, PRISON_ROOT); 
        if (error) 
                return (error); 
        if (chroot_allow_open_directories == 0 || 
            (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) 
                error = chroot_refuse_vdir_fds(fdp); 
        if (error) 
                return (error); 
         NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,          NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
            SCARG(uap, path), td);                SCARG(uap, path), td);
        if ((error = change_dir(&nd, td)) != 0)        if ((error = namei(&nd)) == 0) {
                return (error);                error = kern_chroot(nd.ni_vp);
        NDFREE(&nd, NDF_ONLY_PNBUF);                NDFREE(&nd, ~(NDF_NO_FREE_PNBUF | NDF_NO_VP_PUT));
        vrele(fdp->fd_rdir); 
        fdp->fd_rdir = nd.ni_vp; 
        if (!fdp->fd_jdir) { 
                fdp->fd_jdir = nd.ni_vp; 
                VREF(fdp->fd_jdir); 
         }          }
        return (0);        return (error);
 }  }
   
 /*  /*
 * Common routine for chroot and chdir. * Common routine for chroot and chdir.  Given a locked, referenced vnode,
  * determine whether it is legal to chdir to the vnode.  The vnode's state
  * is not changed by this call.
  */   */
static intint
change_dir(struct nameidata *ndp, struct thread *td)checkvp_chdir(struct vnode *vp, struct thread *td)
 {  {
         struct vnode *vp;  
         int error;          int error;
   
         error = namei(ndp);  
         if (error)  
                 return (error);  
         vp = ndp->ni_vp;  
         if (vp->v_type != VDIR)          if (vp->v_type != VDIR)
                 error = ENOTDIR;                  error = ENOTDIR;
         else          else
                error = VOP_ACCESS(vp, VEXEC, ndp->ni_cnd.cn_cred, td);                error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td);
        if (error) 
                vput(vp); 
        else 
                VOP_UNLOCK(vp, NULL, 0, td); 
         return (error);          return (error);
 }  }
   
Line 1337  symlink(struct symlink_args *uap) Line 1362  symlink(struct symlink_args *uap)
   
         path = zalloc(namei_zone);          path = zalloc(namei_zone);
         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);          error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
        if (error)        if (error == 0) {
                return (error);                NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, 
        NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, UIO_USERSPACE,                        UIO_USERSPACE, uap->link, td);
            uap->link, td);                error = kern_symlink(path, &nd);
        }
        error = kern_symlink(path, &nd); 
 
         zfree(namei_zone, path);          zfree(namei_zone, path);
         return (error);          return (error);
 }  }

Removed from v.1.29  
changed lines
  Added in v.1.30