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);
 }

Reply via email to