svn commit: r238309 - head/sys/net

2012-07-09 Thread Mikolaj Golub
Author: trociny
Date: Mon Jul  9 20:38:18 2012
New Revision: 238309
URL: http://svn.freebsd.org/changeset/base/238309

Log:
  In epair_clone_destroy(), when destroying the second half, we have to
  switch to its vnet before calling ether_ifdetach(). Otherwise if the
  second half resides in a different vnet, if_detach() silently fails
  leaving a stale pointer in V_ifnet list, and the system crashes trying
  to access this pointer later.
  
  Another solution could be not to allow to destroy epair unless both
  ends are in the home vnet.
  
  Discussed with:   bz
  Tested by:delphij

Modified:
  head/sys/net/if_epair.c

Modified: head/sys/net/if_epair.c
==
--- head/sys/net/if_epair.c Mon Jul  9 20:11:32 2012(r238308)
+++ head/sys/net/if_epair.c Mon Jul  9 20:38:18 2012(r238309)
@@ -904,39 +904,41 @@ epair_clone_destroy(struct if_clone *ifc
if_link_state_change(oifp, LINK_STATE_DOWN);
ifp-if_drv_flags = ~IFF_DRV_RUNNING;
oifp-if_drv_flags = ~IFF_DRV_RUNNING;
+
+   /*
+* Get rid of our second half. As the other of the two
+* interfaces may reside in a different vnet, we need to
+* switch before freeing them.
+*/
+   CURVNET_SET_QUIET(oifp-if_vnet);
ether_ifdetach(oifp);
-   ether_ifdetach(ifp);
/*
 * Wait for all packets to be dispatched to if_input.
-* The numbers can only go down as the interfaces are
+* The numbers can only go down as the interface is
 * detached so there is no need to use atomics.
 */
-   DPRINTF(sca refcnt=%u scb refcnt=%u\n, sca-refcount, scb-refcount);
-   EPAIR_REFCOUNT_ASSERT(sca-refcount == 1  scb-refcount == 1,
-   (%s: ifp=%p sca-refcount!=1: %d || ifp=%p scb-refcount!=1: %d,
-   __func__, ifp, sca-refcount, oifp, scb-refcount));
-
-   /*
-* Get rid of our second half.
-*/
+   DPRINTF(scb refcnt=%u\n, scb-refcount);
+   EPAIR_REFCOUNT_ASSERT(scb-refcount == 1,
+   (%s: ifp=%p scb-refcount!=1: %d, __func__, oifp, scb-refcount));
oifp-if_softc = NULL;
error = if_clone_destroyif(ifc, oifp);
if (error)
panic(%s: if_clone_destroyif() for our 2nd iface failed: %d,
__func__, error);
+   if_free(oifp);
+   ifmedia_removeall(scb-media);
+   free(scb, M_EPAIR);
+   CURVNET_RESTORE();
 
+   ether_ifdetach(ifp);
/*
-* Finish cleaning up. Free them and release the unit.
-* As the other of the two interfaces my reside in a different vnet,
-* we need to switch before freeing them.
+* Wait for all packets to be dispatched to if_input.
 */
-   CURVNET_SET_QUIET(oifp-if_vnet);
-   if_free(oifp);
-   CURVNET_RESTORE();
+   DPRINTF(sca refcnt=%u\n, sca-refcount);
+   EPAIR_REFCOUNT_ASSERT(sca-refcount == 1,
+   (%s: ifp=%p sca-refcount!=1: %d, __func__, ifp, sca-refcount));
if_free(ifp);
ifmedia_removeall(sca-media);
-   ifmedia_removeall(scb-media);
-   free(scb, M_EPAIR);
free(sca, M_EPAIR);
ifc_free_unit(ifc, unit);
 
___
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to svn-src-all-unsubscr...@freebsd.org


Re: svn commit: r238309 - head/sys/net

2012-07-09 Thread Xin Li
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

On 07/09/12 13:38, Mikolaj Golub wrote:
 Author: trociny Date: Mon Jul  9 20:38:18 2012 New Revision:
 238309 URL: http://svn.freebsd.org/changeset/base/238309
 
 Log: In epair_clone_destroy(), when destroying the second half, we
 have to switch to its vnet before calling ether_ifdetach().
 Otherwise if the second half resides in a different vnet,
 if_detach() silently fails leaving a stale pointer in V_ifnet list,
 and the system crashes trying to access this pointer later.
 
 Another solution could be not to allow to destroy epair unless
 both ends are in the home vnet.
 
 Discussed with:   bz Tested by:   delphij

Thanks!

Since this affects RELENG_9 and RELENG_8, could you please also MFC
after a settle period?

Cheers,
- -- 
Xin LI delp...@delphij.nethttps://www.delphij.net/
FreeBSD - The Power to Serve!   Live free or die
-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.19 (FreeBSD)

iQEcBAEBCAAGBQJP+0PMAAoJEG80Jeu8UPuz/ugH/2RmmdfCapeP9eQkIPkaImpm
D5ghJ0fS6dOM87i5QY6c0rJU2TrcLZHkZGnuYv+BSMqCz5de8dw9s7UMM6sHLL92
i4tgpDE2DQxM4b5skR7yCBRES6IAiY6kDIgVskaS95PxA9wuJA4ohqS8pQ5Tp6h4
lM2urad7+FpYGLZRTWY2yOzgS/g2JZNEGSX6tPIAhg8xX1hryP869zjjHJGd4932
X6pPyRtNdTHB69t00UiVMbJPzcSLtue4ECTms0xCPKC7t0+VZXgiYWOJlNnPQYzy
lUkcYy8ZIyUUTD0duOdyun4oQ7xNEdZgZxcRI0Ids68AQs2xUoddL0IyX1ZMe9w=
=kSZl
-END PGP SIGNATURE-
___
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to svn-src-all-unsubscr...@freebsd.org


Re: svn commit: r238309 - head/sys/net

2012-07-09 Thread Mikolaj Golub

On Mon, 09 Jul 2012 13:49:17 -0700 Xin Li wrote:

 XL On 07/09/12 13:38, Mikolaj Golub wrote:
  Author: trociny Date: Mon Jul  9 20:38:18 2012 New Revision:
  238309 URL: http://svn.freebsd.org/changeset/base/238309
  
  Log: In epair_clone_destroy(), when destroying the second half, we
  have to switch to its vnet before calling ether_ifdetach().
  Otherwise if the second half resides in a different vnet,
  if_detach() silently fails leaving a stale pointer in V_ifnet list,
  and the system crashes trying to access this pointer later.
  
  Another solution could be not to allow to destroy epair unless
  both ends are in the home vnet.
  
  Discussed with:bz Tested by:delphij

 XL Thanks!

 XL Since this affects RELENG_9 and RELENG_8, could you please also MFC
 XL after a settle period?

Sure. Just forgot to add the 'MFC after' reminder. I am going to MFC it after
stable/9 unfreeze unless someone really wants it in 9.1 and tests it a
little. This does not look like a critical issue because of the existing
workaround (which can be considered as a best practice): move both ends to the
home vnet before destroying the epair.

-- 
Mikolaj Golub
___
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to svn-src-all-unsubscr...@freebsd.org