Subject: Re: spec_poll vs. revoke
To: None <tech-kern@netbsd.org>
From: Jed Davis <jdev@panix.com>
List: tech-kern
Date: 08/24/2006 22:22:40
--=-=-=

Bill Studenmund <wrstuden@netbsd.org> writes:

> On Tue, Aug 22, 2006 at 07:29:43PM -0400, Jed Davis wrote:
>> 
>> I notice that spec_ioctl() was corrected for a similar problem in
>> r1.83 of spec_vnops.c.  So, is there any reason I shouldn't attempt to
>> apply a similar fix to spec_poll()?
>
> Please do so.

Attached; spec_poll appears to work afterwards, but as I can't
reproduce the race, I can't verify that aspect.

-- 
(let ((C call-with-current-continuation)) (apply (lambda (x y) (x y)) (map
((lambda (r) ((C C) (lambda (s) (r (lambda l (apply (s s) l))))))  (lambda
(f) (lambda (l) (if (null? l) C (lambda (k) (display (car l)) ((f (cdr l))
(C k)))))))    '((#\J #\d #\D #\v #\s) (#\e #\space #\a #\i #\newline)))))

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=spec_poll_race.diff

Index: miscfs/specfs/spec_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/specfs/spec_vnops.c,v
retrieving revision 1.80.2.1
diff -u -2 -r1.80.2.1 spec_vnops.c
--- miscfs/specfs/spec_vnops.c	26 Sep 2005 20:22:55 -0000	1.80.2.1
+++ miscfs/specfs/spec_vnops.c	24 Aug 2006 04:09:24 -0000
@@ -519,10 +519,26 @@
 	} */ *ap = v;
 	const struct cdevsw *cdev;
+	struct vnode *vp;
 	dev_t dev;
 
-	switch (ap->a_vp->v_type) {
+	/*
+	 * Extract all the info we need from the vnode, taking care to
+	 * avoid a race with VOP_REVOKE().
+	 */
+
+	vp = ap->a_vp;
+	dev = NODEV;
+	simple_lock(&vp->v_interlock);
+	if ((vp->v_flag & VXLOCK) == 0 && vp->v_specinfo) {
+		dev = vp->v_rdev;
+	}
+	simple_unlock(&vp->v_interlock);
+	if (dev == NODEV) {
+		return ENXIO;
+	}
+
+	switch (vp->v_type) {
 
 	case VCHR:
-		dev = ap->a_vp->v_rdev;
 		cdev = cdevsw_lookup(dev);
 		if (cdev == NULL)

--=-=-=--