diff options
author | John Baldwin <jhb@FreeBSD.org> | 2002-07-13 04:07:12 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2002-07-13 04:07:12 +0000 |
commit | 03d7a9fffb0aba754dad0035ed8b53bc26cedc21 (patch) | |
tree | 2e3f9a69f51eb683e7a7967b23ce4aa7ed122eef /sys/kern/vfs_syscalls.c | |
parent | d73b19ef9da0a0335548b8e8ded5f3216eb9de74 (diff) | |
download | src-03d7a9fffb0aba754dad0035ed8b53bc26cedc21.tar.gz src-03d7a9fffb0aba754dad0035ed8b53bc26cedc21.zip |
- Change chroot_refuse_vdir_fds() to require that the passed in struct
filedesc is already locked rather than having chroot() unlock the
filedesc so chroot_refuse_vdir_fds() can immediately relock it.
- Reorder chroot() a bitso that we do the namei lookup before checking
the process's struct filedesc. This closes at least one potential race
and allows us to only acquire the filedsec lock once in chroot().
- Push down Giant slightly into chroot().
Notes
Notes:
svn path=/head/; revision=99898
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 17da2702d8cb..69159e77055b 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -450,20 +450,17 @@ chroot_refuse_vdir_fds(fdp) struct file *fp; int fd; - FILEDESC_LOCK(fdp); + FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); for (fd = 0; fd < fdp->fd_nfiles ; fd++) { fp = fget_locked(fdp, fd); if (fp == NULL) continue; if (fp->f_type == DTYPE_VNODE) { vp = (struct vnode *)fp->f_data; - if (vp->v_type == VDIR) { - FILEDESC_UNLOCK(fdp); + if (vp->v_type == VDIR) return (EPERM); - } } } - FILEDESC_UNLOCK(fdp); return (0); } @@ -504,21 +501,18 @@ chroot(td, uap) error = suser_cred(td->td_ucred, PRISON_ROOT); if (error) return (error); - FILEDESC_LOCK(fdp); - if (chroot_allow_open_directories == 0 || - (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { - FILEDESC_UNLOCK(fdp); - error = chroot_refuse_vdir_fds(fdp); - } else - FILEDESC_UNLOCK(fdp); - if (error) - return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), td); + mtx_lock(&Giant); if ((error = change_dir(&nd, td)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); + goto error; FILEDESC_LOCK(fdp); + if (chroot_allow_open_directories == 0 || + (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { + error = chroot_refuse_vdir_fds(fdp); + if (error) + goto error_unlock; + } vp = fdp->fd_rdir; fdp->fd_rdir = nd.ni_vp; if (!fdp->fd_jdir) { @@ -526,8 +520,16 @@ chroot(td, uap) VREF(fdp->fd_jdir); } FILEDESC_UNLOCK(fdp); + NDFREE(&nd, NDF_ONLY_PNBUF); vrele(vp); + mtx_unlock(&Giant); return (0); +error_unlock: + FILEDESC_UNLOCK(fdp); +error: + mtx_unlock(&Giant); + NDFREE(&nd, 0); + return (error); } /* |