summaryrefslogtreecommitdiffstats
path: root/sys/fs/pseudofs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-06-10 13:57:36 +0000
committerkib <kib@FreeBSD.org>2009-06-10 13:57:36 +0000
commite0d7459c716fb9105aa2ae9ebf00c6de6a1f8796 (patch)
tree073060ebf4b60bba932ec2b080cc808f1b347c02 /sys/fs/pseudofs
parentff56813d72ced1434a2e9649783a322834dc196f (diff)
downloadFreeBSD-src-e0d7459c716fb9105aa2ae9ebf00c6de6a1f8796.zip
FreeBSD-src-e0d7459c716fb9105aa2ae9ebf00c6de6a1f8796.tar.gz
VOP_IOCTL takes unlocked vnode as an argument. Due to this, v_data may
be NULL or derefenced memory may become free at arbitrary moment. Lock the vnode in cd9660, devfs and pseudofs implementation of VOP_IOCTL to prevent reclaim; check whether the vnode was already reclaimed after the lock is granted. Reported by: georg at dts su Reviewed by: des (pseudofs) MFC after: 2 weeks
Diffstat (limited to 'sys/fs/pseudofs')
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 7cd9ca4..8421d17 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -260,34 +260,50 @@ pfs_getattr(struct vop_getattr_args *va)
static int
pfs_ioctl(struct vop_ioctl_args *va)
{
- struct vnode *vn = va->a_vp;
- struct pfs_vdata *pvd = vn->v_data;
- struct pfs_node *pn = pvd->pvd_pn;
+ struct vnode *vn;
+ struct pfs_vdata *pvd;
+ struct pfs_node *pn;
struct proc *proc;
int error;
+ vn = va->a_vp;
+ vn_lock(vn, LK_SHARED | LK_RETRY);
+ if (vn->v_iflag & VI_DOOMED) {
+ VOP_UNLOCK(vn, 0);
+ return (EBADF);
+ }
+ pvd = vn->v_data;
+ pn = pvd->pvd_pn;
+
PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command));
pfs_assert_not_owned(pn);
- if (vn->v_type != VREG)
+ if (vn->v_type != VREG) {
+ VOP_UNLOCK(vn, 0);
PFS_RETURN (EINVAL);
+ }
KASSERT_PN_IS_FILE(pn);
- if (pn->pn_ioctl == NULL)
+ if (pn->pn_ioctl == NULL) {
+ VOP_UNLOCK(vn, 0);
PFS_RETURN (ENOTTY);
+ }
/*
* This is necessary because process' privileges may
* have changed since the open() call.
*/
- if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
+ if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) {
+ VOP_UNLOCK(vn, 0);
PFS_RETURN (EIO);
+ }
error = pn_ioctl(curthread, proc, pn, va->a_command, va->a_data);
if (proc != NULL)
PROC_UNLOCK(proc);
+ VOP_UNLOCK(vn, 0);
PFS_RETURN (error);
}
OpenPOWER on IntegriCloud