We use netlock to protect `if_list' and `ifa_list' lists, and the `ifa' dereference, so kernel lock within ifa_ifwithaddr() is wrong. We have no problems, because we call ifadel()/ifafree() with kernel lock held, but we should not rely on this.
So use netlock assertion within ifa_ifwithaddr() instead ok kernel lock. Also, use netlock within rt_setsource() and umb_add_inet{,6}_config(). It seems, within the umb_add_inet{,6}_config(), `rti_ifa' should hold the referenced `ifa' and release it after rtm_miss() call. I like to do this with separate diff. Also, ifa_ifwithdstaddr() should rely on netlock too. Index: sys/dev/usb/if_umb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_umb.c,v retrieving revision 1.50 diff -u -p -r1.50 if_umb.c --- sys/dev/usb/if_umb.c 31 Mar 2023 23:53:49 -0000 1.50 +++ sys/dev/usb/if_umb.c 17 Apr 2023 00:09:17 -0000 @@ -1829,6 +1829,7 @@ umb_add_inet_config(struct umb_softc *sc default_sin.sin_len = sizeof (default_sin); memset(&info, 0, sizeof(info)); + NET_LOCK(); info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */; info.rti_ifa = ifa_ifwithaddr(sintosa(&ifra.ifra_addr), ifp->if_rdomain); @@ -1836,7 +1837,6 @@ umb_add_inet_config(struct umb_softc *sc info.rti_info[RTAX_NETMASK] = sintosa(&default_sin); info.rti_info[RTAX_GATEWAY] = sintosa(&ifra.ifra_dstaddr); - NET_LOCK(); rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain); NET_UNLOCK(); if (rv) { @@ -1910,6 +1910,7 @@ umb_add_inet6_config(struct umb_softc *s default_sin6.sin6_len = sizeof (default_sin6); memset(&info, 0, sizeof(info)); + NET_LOCK(); info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */; info.rti_ifa = ifa_ifwithaddr(sin6tosa(&ifra.ifra_addr), ifp->if_rdomain); @@ -1917,7 +1918,6 @@ umb_add_inet6_config(struct umb_softc *s info.rti_info[RTAX_NETMASK] = sin6tosa(&default_sin6); info.rti_info[RTAX_GATEWAY] = sin6tosa(&ifra.ifra_dstaddr); - NET_LOCK(); rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain); NET_UNLOCK(); if (rv) { Index: sys/net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.688 diff -u -p -r1.688 if.c --- sys/net/if.c 8 Apr 2023 13:49:38 -0000 1.688 +++ sys/net/if.c 17 Apr 2023 00:09:17 -0000 @@ -1409,8 +1409,9 @@ ifa_ifwithaddr(struct sockaddr *addr, u_ struct ifaddr *ifa; u_int rdomain; + NET_ASSERT_LOCKED(); + rdomain = rtable_l2(rtableid); - KERNEL_LOCK(); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rdomain) continue; @@ -1420,12 +1421,10 @@ ifa_ifwithaddr(struct sockaddr *addr, u_ continue; if (equal(addr, ifa->ifa_addr)) { - KERNEL_UNLOCK(); return (ifa); } } } - KERNEL_UNLOCK(); return (NULL); } Index: sys/net/rtsock.c =================================================================== RCS file: /cvs/src/sys/net/rtsock.c,v retrieving revision 1.359 diff -u -p -r1.359 rtsock.c --- sys/net/rtsock.c 22 Jan 2023 12:05:44 -0000 1.359 +++ sys/net/rtsock.c 17 Apr 2023 00:09:17 -0000 @@ -2374,18 +2374,18 @@ rt_setsource(unsigned int rtableid, stru return (EAFNOSUPPORT); } - KERNEL_LOCK(); + NET_LOCK(); /* * Check if source address is assigned to an interface in the * same rdomain */ if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL) { - KERNEL_UNLOCK(); + NET_UNLOCK(); return (EINVAL); } error = rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr); - KERNEL_UNLOCK(); + NET_UNLOCK(); return (error); }