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 int  int
 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