Trying to grab the NET_LOCK() while holding an ifp reference is wrong.
This creates deadlock as found by Hrvoje Popovski.  The reason is that
if_detach() sleeps holding the NET_LOCK() while waiting for others
threads to release their reference.

Diff below fixes the linkstate vs if_detach() deadlock.

ok?

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.499
diff -u -p -r1.499 if.c
--- net/if.c    28 May 2017 12:51:33 -0000      1.499
+++ net/if.c    28 May 2017 16:23:16 -0000
@@ -1559,15 +1559,14 @@ if_linkstate_task(void *xifidx)
        struct ifnet *ifp;
        int s;
 
-       ifp = if_get(ifidx);
-       if (ifp == NULL)
-               return;
-
        NET_LOCK(s);
-       if_linkstate(ifp);
-       NET_UNLOCK(s);
 
+       ifp = if_get(ifidx);
+       if (ifp != NULL)
+               if_linkstate(ifp);
        if_put(ifp);
+
+       NET_UNLOCK(s);
 }
 
 void

Reply via email to