Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Nov 2005 22:47:38 +0100
From:      Csaba Henk <csaba-ml@creo.hu>
To:        freebsd-current@freebsd.org
Subject:   double close strikes panic if md attaching a corrupt file
Message-ID:  <20051125214738.GL2911@beastie.creo.hu>

next in thread | raw e-mail | index | archive | help

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

Imagine the following:

You have a corrupt file (so that you can open it, but when you try reading
from it, it returns EIO). Pretty common with crappy optical media.

You try "mdconfig -a -t vnode" on it.

This will lead to a call to xmdioctl() such that mdio->md_type is 
MD_VNODE. So you get the following call chain:

 xmdioctl -> mdcreate_vnode -> mdsetcred -> VOP_READ

VOP_READ returns EIO. This error value will be propagated to mdcreate_vnode,
who will then feel like vn_close-ing the vnode, and propagate the error
further.

Now we got back to xmdioctl, who will call for mddestroy because of the error.
mddestroy still sees the vnode, and will vn_close it again.

This will yield a "negative refcount" panic.

Two different ideas for fixing this:

1. Don't vn_close in mdcreate_vnode when there is an error.
2. Not just vn_close in mdcreate_vnode upon error but also
   nullify the sc->vnode field.

I attach two patches, they realize the above ideas, respectively.
Note that I didn't test either.

Regards,
Csaba

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="md-doubleclose-1.diff"

--- /sys/dev/md/md.c	Sun Nov 13 10:43:06 2005
+++ -	Fri Nov 25 22:42:29 2005
@@ -889,11 +889,7 @@ mdcreate_vnode(struct md_s *sc, struct m
 	sc->vnode = nd.ni_vp;
 
 	error = mdsetcred(sc, td->td_ucred);
-	if (error != 0) {
-		(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
-		return (error);
-	}
-	return (0);
+	return (error);
 }
 
 static int

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="md-doubleclose-2.diff"

--- /sys/dev/md/md.c	Sun Nov 13 10:43:06 2005
+++ -	Fri Nov 25 22:41:40 2005
@@ -891,6 +891,7 @@ mdcreate_vnode(struct md_s *sc, struct m
 	error = mdsetcred(sc, td->td_ucred);
 	if (error != 0) {
 		(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
+		sc->vnode = NULL;
 		return (error);
 	}
 	return (0);

--sm4nu43k4a2Rpi4c--



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