On Tue, Aug 24, 2021 at 08:07:15PM -0400, Daniel Jakots wrote:
> Hi,
> 
> Most of the time when I do `ifconfig wgX destroy` the machine stops
> responding. This has been forever. I had one a few days so I finally got
> a look at the console. This happened on a snapshot from 2021-08-14 but
> as I said, it's not a regression afaict.
> 

Hello Daniel,

I see this assertion wrong. if_get(9) returns NULL here if the interface
is going to die and already unlinked from the stack, but the routing
table entries are not yet removed by in{,6}_ifdetach(). So I propose to
return ESRCH and let concurrent if_detach() to follow it's way.

Also the following "ifp != NULL" assertions in rtm_output() are wrong
and kernel lock serialization doesn't work here because we are grabbing
netlock before if_get(9). We have the same case here: the returned NULL
means the requested interface is going to die and there is no reason to
perform ifp->if_rtrequest().

Does the diff below helps? The panic should gone, but I'm interesting
about the routing table consistency.

Index: sys/net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.319
diff -u -p -r1.319 rtsock.c
--- sys/net/rtsock.c    23 Jun 2021 16:10:45 -0000      1.319
+++ sys/net/rtsock.c    25 Aug 2021 09:26:19 -0000
@@ -970,9 +970,13 @@ rtm_output(struct rt_msghdr *rtm, struct
                        break;
                }
 
-               /* Detaching an interface requires the KERNEL_LOCK(). */
                ifp = if_get(rt->rt_ifidx);
-               KASSERT(ifp != NULL);
+               if (ifp == NULL) {
+                       rtfree(rt);
+                       rt = NULL;
+                       error = ESRCH;
+                       break;
+               }
 
                /*
                 * Invalidate the cache of automagically created and
@@ -1084,10 +1088,11 @@ rtm_output(struct rt_msghdr *rtm, struct
                        ifa = info->rti_ifa;
                        if (rt->rt_ifa != ifa) {
                                ifp = if_get(rt->rt_ifidx);
-                               KASSERT(ifp != NULL);
-                               ifp->if_rtrequest(ifp, RTM_DELETE, rt);
-                               ifafree(rt->rt_ifa);
-                               if_put(ifp);
+                               if (ifp != NULL) {
+                                       ifp->if_rtrequest(ifp, RTM_DELETE, rt);
+                                       ifafree(rt->rt_ifa);
+                                       if_put(ifp);
+                               }
 
                                ifa->ifa_refcnt++;
                                rt->rt_ifa = ifa;
@@ -1153,9 +1158,10 @@ change:
                rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
 
                ifp = if_get(rt->rt_ifidx);
-               KASSERT(ifp != NULL);
-               ifp->if_rtrequest(ifp, RTM_ADD, rt);
-               if_put(ifp);
+               if (ifp != NULL) {
+                       ifp->if_rtrequest(ifp, RTM_ADD, rt);
+                       if_put(ifp);
+               }
 
                if (info->rti_info[RTAX_LABEL] != NULL) {
                        char *rtlabel = ((struct sockaddr_rtlabel *)

Reply via email to