From 8a08cec1660617204ccb44ee29cf3be4d1e63d33 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Sat, 11 Jul 2015 16:22:48 +0000 Subject: [PATCH] Create a dedicated function for ensuring that cdir and rdir are populated. Previously several places were doing it on its own, partially incorrectly (e.g. without the filedesc locked) or even actively harmful by populating jdir or assigning rootvnode without vrefing it. Reviewed by: kib --- sys/cam/ctl/ctl_backend_block.c | 13 +------------ .../opensolaris/kern/opensolaris_kobj.c | 13 +------------ sys/cddl/compat/opensolaris/sys/vnode.h | 13 +------------ sys/compat/ndis/subr_ndis.c | 5 +---- sys/dev/xen/blkback/blkback.c | 13 +------------ sys/kern/kern_descrip.c | 19 +++++++++++++++++++ sys/kern/subr_firmware.c | 13 +------------ sys/sys/filedesc.h | 1 + 8 files changed, 26 insertions(+), 64 deletions(-) diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index c56023bf787..8ea52aa323d 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -2123,18 +2123,7 @@ ctl_be_block_open(struct ctl_be_block_softc *softc, return (1); } - if (!curthread->td_proc->p_fd->fd_cdir) { - curthread->td_proc->p_fd->fd_cdir = rootvnode; - VREF(rootvnode); - } - if (!curthread->td_proc->p_fd->fd_rdir) { - curthread->td_proc->p_fd->fd_rdir = rootvnode; - VREF(rootvnode); - } - if (!curthread->td_proc->p_fd->fd_jdir) { - curthread->td_proc->p_fd->fd_jdir = rootvnode; - VREF(rootvnode); - } + pwd_ensure_dirs(); again: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path, curthread); diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c index 9ff798a15b7..52d695b4f5a 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c @@ -67,21 +67,10 @@ static void * kobj_open_file_vnode(const char *file) { struct thread *td = curthread; - struct filedesc *fd; struct nameidata nd; int error, flags; - fd = td->td_proc->p_fd; - FILEDESC_XLOCK(fd); - if (fd->fd_rdir == NULL) { - fd->fd_rdir = rootvnode; - vref(fd->fd_rdir); - } - if (fd->fd_cdir == NULL) { - fd->fd_cdir = rootvnode; - vref(fd->fd_cdir); - } - FILEDESC_XUNLOCK(fd); + pwd_ensure_dirs(); flags = FREAD | O_NOFOLLOW; NDINIT(&nd, LOOKUP, 0, UIO_SYSSPACE, file, td); diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h index 22256cf1f1e..d7bc7f7a1b2 100644 --- a/sys/cddl/compat/opensolaris/sys/vnode.h +++ b/sys/cddl/compat/opensolaris/sys/vnode.h @@ -162,7 +162,6 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode, int fd) { struct thread *td = curthread; - struct filedesc *fdc; struct nameidata nd; int error, operation; @@ -179,17 +178,7 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode, } ASSERT(umask == 0); - fdc = td->td_proc->p_fd; - FILEDESC_XLOCK(fdc); - if (fdc->fd_rdir == NULL) { - fdc->fd_rdir = rootvnode; - vref(fdc->fd_rdir); - } - if (fdc->fd_cdir == NULL) { - fdc->fd_cdir = rootvnode; - vref(fdc->fd_rdir); - } - FILEDESC_XUNLOCK(fdc); + pwd_ensure_dirs(); if (startvp != NULL) vref(startvp); diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index f3ba7008411..ac26a2e093f 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -2817,10 +2817,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) /* Some threads don't have a current working directory. */ - if (td->td_proc->p_fd->fd_rdir == NULL) - td->td_proc->p_fd->fd_rdir = rootvnode; - if (td->td_proc->p_fd->fd_cdir == NULL) - td->td_proc->p_fd->fd_cdir = rootvnode; + pwd_ensure_dirs(); NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 459271ea26f..f266ffd2902 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -2692,18 +2692,7 @@ xbb_open_backend(struct xbb_softc *xbb) if ((xbb->flags & XBBF_READ_ONLY) == 0) flags |= FWRITE; - if (!curthread->td_proc->p_fd->fd_cdir) { - curthread->td_proc->p_fd->fd_cdir = rootvnode; - VREF(rootvnode); - } - if (!curthread->td_proc->p_fd->fd_rdir) { - curthread->td_proc->p_fd->fd_rdir = rootvnode; - VREF(rootvnode); - } - if (!curthread->td_proc->p_fd->fd_jdir) { - curthread->td_proc->p_fd->fd_jdir = rootvnode; - VREF(rootvnode); - } + pwd_ensure_dirs(); again: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, xbb->dev_name, curthread); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7e54d1835a4..4229cc9ece4 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -308,6 +309,24 @@ fdfree(struct filedesc *fdp, int fd) #endif } +void +pwd_ensure_dirs(void) +{ + struct filedesc *fdp; + + fdp = curproc->p_fd; + FILEDESC_XLOCK(fdp); + if (fdp->fd_cdir == NULL) { + fdp->fd_cdir = rootvnode; + VREF(rootvnode); + } + if (fdp->fd_rdir == NULL) { + fdp->fd_rdir = rootvnode; + VREF(rootvnode); + } + FILEDESC_XUNLOCK(fdp); +} + /* * System calls on descriptors. */ diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c index 20ab76e282b..172d7198dc6 100644 --- a/sys/kern/subr_firmware.c +++ b/sys/kern/subr_firmware.c @@ -383,19 +383,8 @@ firmware_put(const struct firmware *p, int flags) static void set_rootvnode(void *arg, int npending) { - struct thread *td = curthread; - struct proc *p = td->td_proc; - FILEDESC_XLOCK(p->p_fd); - if (p->p_fd->fd_cdir == NULL) { - p->p_fd->fd_cdir = rootvnode; - VREF(rootvnode); - } - if (p->p_fd->fd_rdir == NULL) { - p->p_fd->fd_rdir = rootvnode; - VREF(rootvnode); - } - FILEDESC_XUNLOCK(p->p_fd); + pwd_ensure_dirs(); free(arg, M_TEMP); } diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index e569a3b5e0e..727a09827f1 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -208,6 +208,7 @@ fd_modified(struct filedesc *fdp, int fd, seq_t seq) /* cdir/rdir/jdir manipulation functions. */ void pwd_chdir(struct thread *td, struct vnode *vp); int pwd_chroot(struct thread *td, struct vnode *vp); +void pwd_ensure_dirs(void); #endif /* _KERNEL */