Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jun 2009 13:57:37 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r193919 - in head/sys/fs: cd9660 devfs pseudofs
Message-ID:  <200906101357.n5ADvbGU015465@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Jun 10 13:57:36 2009
New Revision: 193919
URL: http://svn.freebsd.org/changeset/base/193919

Log:
  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

Modified:
  head/sys/fs/cd9660/cd9660_vnops.c
  head/sys/fs/devfs/devfs_vnops.c
  head/sys/fs/pseudofs/pseudofs_vnops.c

Modified: head/sys/fs/cd9660/cd9660_vnops.c
==============================================================================
--- head/sys/fs/cd9660/cd9660_vnops.c	Wed Jun 10 13:56:42 2009	(r193918)
+++ head/sys/fs/cd9660/cd9660_vnops.c	Wed Jun 10 13:57:36 2009	(r193919)
@@ -251,20 +251,31 @@ cd9660_ioctl(ap)
 		struct thread *a_td;
 	} */ *ap;
 {
-	struct vnode *vp = ap->a_vp;
-	struct iso_node *ip = VTOI(vp);
+	struct vnode *vp;
+	struct iso_node *ip;
+	int error;
 
-	if (vp->v_type == VCHR || vp->v_type == VBLK)
+	vp = ap->a_vp;
+	vn_lock(vp, LK_SHARED | LK_RETRY);
+	if (vp->v_type == VCHR || vp->v_type == VBLK) {
+		VOP_UNLOCK(vp, 0);
 		return (EOPNOTSUPP);
+	}
 
-	switch (ap->a_command) {
+	ip = VTOI(vp);
+	error = 0;
 
+	switch (ap->a_command) {
 	case FIOGETLBA:
 		*(int *)(ap->a_data) = ip->iso_start;
-		return 0;
+		break;
 	default:
-		return (ENOTTY);
+		error = ENOTTY;
+		break;
 	}
+
+	VOP_UNLOCK(vp, 0);
+	return (error);
 }
 
 /*

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c	Wed Jun 10 13:56:42 2009	(r193918)
+++ head/sys/fs/devfs/devfs_vnops.c	Wed Jun 10 13:57:36 2009	(r193919)
@@ -1276,11 +1276,19 @@ devfs_revoke(struct vop_revoke_args *ap)
 static int
 devfs_rioctl(struct vop_ioctl_args *ap)
 {
-	int error;
+	struct vnode *vp;
 	struct devfs_mount *dmp;
+	int error;
 
-	dmp = VFSTODEVFS(ap->a_vp->v_mount);
+	vp = ap->a_vp;
+	vn_lock(vp, LK_SHARED | LK_RETRY);
+	if (vp->v_iflag & VI_DOOMED) {
+		VOP_UNLOCK(vp, 0);
+		return (EBADF);
+	}
+	dmp = VFSTODEVFS(vp->v_mount);
 	sx_xlock(&dmp->dm_lock);
+	VOP_UNLOCK(vp, 0);
 	DEVFS_DMP_HOLD(dmp);
 	devfs_populate(dmp);
 	if (DEVFS_DMP_DROP(dmp)) {

Modified: head/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- head/sys/fs/pseudofs/pseudofs_vnops.c	Wed Jun 10 13:56:42 2009	(r193918)
+++ head/sys/fs/pseudofs/pseudofs_vnops.c	Wed Jun 10 13:57:36 2009	(r193919)
@@ -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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906101357.n5ADvbGU015465>