Push kernel lock down to rt_setsource() to make `ifa' dereference safe.
authormvs <mvs@openbsd.org>
Fri, 26 Mar 2021 22:40:08 +0000 (22:40 +0000)
committermvs <mvs@openbsd.org>
Fri, 26 Mar 2021 22:40:08 +0000 (22:40 +0000)
Netlock doesn't make sense here because ifa_ifwithaddr() holds kernel
lock while performs lists walkthrough.

This was made to decrease the future diff for PF_ROUTE sockets
unlocking. This time kernel lock is still held while we perform
rt_setsource().

ok mpi@

sys/net/rtsock.c

index 71340f8..52ccd7f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtsock.c,v 1.308 2021/03/18 15:55:19 claudio Exp $    */
+/*     $OpenBSD: rtsock.c,v 1.309 2021/03/26 22:40:08 mvs Exp $        */
 /*     $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $  */
 
 /*
@@ -2294,6 +2294,7 @@ int
 rt_setsource(unsigned int rtableid, struct sockaddr *src)
 {
        struct ifaddr   *ifa;
+       int             error;
        /*
         * If source address is 0.0.0.0 or ::
         * use automatic source selection
@@ -2317,14 +2318,20 @@ rt_setsource(unsigned int rtableid, struct sockaddr *src)
                return (EAFNOSUPPORT);
        }
 
+       KERNEL_LOCK();
        /*
         * Check if source address is assigned to an interface in the
         * same rdomain
         */
-       if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL)
+       if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL) {
+               KERNEL_UNLOCK();
                return (EINVAL);
+       }
+
+       error = rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
+       KERNEL_UNLOCK();
 
-       return (rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr));
+       return (error);
 }
 
 /*