Add missing kernel lock for Bi-directional Forwarding Detection data.
authormvs <mvs@openbsd.org>
Tue, 14 Sep 2021 09:15:55 +0000 (09:15 +0000)
committermvs <mvs@openbsd.org>
Tue, 14 Sep 2021 09:15:55 +0000 (09:15 +0000)
Also bfdset() calls pool_get(9) with PR_WAITOK flag so it should be done
before we check the existence of this `bfd', otherwise it could be added
multiple times.

We have BFD disabled in the default kernel so this diff is for
consistency mostly.

ok mpi@

sys/net/bfd.c
sys/net/rtsock.c

index 4299553..95e73ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bfd.c,v 1.77 2019/06/02 13:22:36 deraadt Exp $        */
+/*     $OpenBSD: bfd.c,v 1.78 2021/09/14 09:15:55 mvs Exp $    */
 
 /*
  * Copyright (c) 2016-2018 Peter Hessler <phessler@openbsd.org>
@@ -183,12 +183,15 @@ bfdset(struct rtentry *rt)
        if (ISSET(rt->rt_flags, RTF_GATEWAY) || !ISSET(rt->rt_flags, RTF_HOST))
                return (EINVAL);
 
+       /* Do our necessary memory allocations upfront */
+       bfd = pool_get(&bfd_pool, PR_WAITOK | PR_ZERO);
+
        /* make sure we don't already have this setup */
-       if (bfd_lookup(rt) != NULL)
+       if (bfd_lookup(rt) != NULL) {
+               pool_put(&bfd_pool, bfd);
                return (EADDRINUSE);
+       }
 
-       /* Do our necessary memory allocations upfront */
-       bfd = pool_get(&bfd_pool, PR_WAITOK | PR_ZERO);
        bfd->bc_neighbor = pool_get(&bfd_pool_neigh, PR_WAITOK | PR_ZERO);
        bfd->bc_time = pool_get(&bfd_pool_time, PR_WAITOK | PR_ZERO);
 
index 7cdd8fe..a717d11 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtsock.c,v 1.321 2021/09/07 16:07:46 mvs Exp $        */
+/*     $OpenBSD: rtsock.c,v 1.322 2021/09/14 09:15:55 mvs Exp $        */
 /*     $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $  */
 
 /*
@@ -630,8 +630,11 @@ rtm_report(struct rtentry *rt, u_char type, int seq, int tableid)
        info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
        info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
 #ifdef BFD
-       if (rt->rt_flags & RTF_BFD)
+       if (rt->rt_flags & RTF_BFD) {
+               KERNEL_LOCK();
                info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd);
+               KERNEL_UNLOCK();
+       }
 #endif
 #ifdef MPLS
        if (rt->rt_flags & RTF_MPLS) {
@@ -1148,11 +1151,16 @@ change:
 
 #ifdef BFD
                if (ISSET(rtm->rtm_flags, RTF_BFD)) {
-                       if ((error = bfdset(rt)))
+                       KERNEL_LOCK();
+                       error = bfdset(rt);
+                       KERNEL_UNLOCK();
+                       if (error)
                                break;
                } else if (!ISSET(rtm->rtm_flags, RTF_BFD) &&
                    ISSET(rtm->rtm_fmask, RTF_BFD)) {
+                       KERNEL_LOCK();
                        bfdclear(rt);
+                       KERNEL_UNLOCK();
                }
 #endif
 
@@ -1853,6 +1861,7 @@ rtm_bfd(struct bfd_config *bfd)
        bfdm = mtod(m, struct bfd_msghdr *);
        bfdm->bm_addrs = info.rti_addrs;
 
+       KERNEL_ASSERT_LOCKED();
        bfd2sa(bfd->bc_rt, &sa_bfd);
        memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd));
 
@@ -1955,8 +1964,10 @@ sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id)
        if_put(ifp);
        info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
 #ifdef BFD
-       if (rt->rt_flags & RTF_BFD)
+       if (rt->rt_flags & RTF_BFD) {
+               KERNEL_ASSERT_LOCKED();
                info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd);
+       }
 #endif
 #ifdef MPLS
        if (rt->rt_flags & RTF_MPLS) {