Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jan 2016 14:08:40 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r294502 - stable/10/sys/net
Message-ID:  <201601211408.u0LE8eMs040926@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Thu Jan 21 14:08:40 2016
New Revision: 294502
URL: https://svnweb.freebsd.org/changeset/base/294502

Log:
  MFC r292604:
  
   If vnets are torn down while ifconfig runs an ioctl to say, destroy an
   epair(4), we may hit if_detach_internal() without holding a lock and by
   the time we aquire it the interface might be gone.
   We should not panic() in this case as it is our fault for not holding
   the lock all the way. It is not ideal to return silently without error
   to user space, but other callers will all ignore the return values so
   do not change the entire KPI for little benefit for now.
   The ifp will be dealt with one way or another still.

Modified:
  stable/10/sys/net/if.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/net/if.c
==============================================================================
--- stable/10/sys/net/if.c	Thu Jan 21 14:06:16 2016	(r294501)
+++ stable/10/sys/net/if.c	Thu Jan 21 14:08:40 2016	(r294502)
@@ -176,7 +176,7 @@ static int	if_getgroup(struct ifgroupreq
 static int	if_getgroupmembers(struct ifgroupreq *);
 static void	if_delgroups(struct ifnet *);
 static void	if_attach_internal(struct ifnet *, int, struct if_clone *);
-static void	if_detach_internal(struct ifnet *, int, struct if_clone **);
+static int	if_detach_internal(struct ifnet *, int, struct if_clone **);
 
 #ifdef INET6
 /*
@@ -894,7 +894,7 @@ if_detach(struct ifnet *ifp)
 	CURVNET_RESTORE();
 }
 
-static void
+static int
 if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
 {
 	struct ifaddr *ifa;
@@ -917,11 +917,19 @@ if_detach_internal(struct ifnet *ifp, in
 #endif
 	IFNET_WUNLOCK();
 	if (!found) {
+		/*
+		 * While we would want to panic here, we cannot
+		 * guarantee that the interface is indeed still on
+		 * the list given we don't hold locks all the way.
+		 */
+		return (ENOENT);
+#if 0
 		if (vmove)
 			panic("%s: ifp=%p not on the ifnet tailq %p",
 			    __func__, ifp, &V_ifnet);
 		else
 			return; /* XXX this should panic as well? */
+#endif
 	}
 
 	/* Check if this is a cloned interface or not. */
@@ -1019,6 +1027,8 @@ if_detach_internal(struct ifnet *ifp, in
 			(*dp->dom_ifdetach)(ifp,
 			    ifp->if_afdata[dp->dom_family]);
 	}
+
+	return (0);
 }
 
 #ifdef VIMAGE
@@ -1034,12 +1044,16 @@ if_vmove(struct ifnet *ifp, struct vnet 
 {
 	u_short idx;
 	struct if_clone *ifc;
+	int rc;
 
 	/*
 	 * Detach from current vnet, but preserve LLADDR info, do not
 	 * mark as dead etc. so that the ifnet can be reattached later.
+	 * If we cannot find it, we lost the race to someone else.
 	 */
-	if_detach_internal(ifp, 1, &ifc);
+	rc = if_detach_internal(ifp, 1, &ifc);
+	if (rc != 0)
+		return;
 
 	/*
 	 * Unlink the ifnet from ifindex_table[] in current vnet, and shrink



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