aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2002-07-13 04:07:12 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2002-07-13 04:07:12 +0000
commit03d7a9fffb0aba754dad0035ed8b53bc26cedc21 (patch)
tree2e3f9a69f51eb683e7a7967b23ce4aa7ed122eef /sys/kern/vfs_syscalls.c
parentd73b19ef9da0a0335548b8e8ded5f3216eb9de74 (diff)
downloadsrc-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.c34
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);
}
/*