FBSD: Add proper locks when traversing net ifaces 98/13998/7
authorTim Creech <tcreech@tcreech.com>
Sun, 22 Dec 2019 00:22:40 +0000 (18:22 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Sun, 28 Feb 2021 02:24:51 +0000 (21:24 -0500)
When traversing the list of network interfaces, or the list of
addresses for a network interface, we're supposed to lock the relevant
resource with IFNET_RLOCK, if_addr_rlock, or IN_IFADDR_RLOCK. Add
these locks around our code that examines network interfaces, to
avoid issues if the interface or address list changes while we're
traversing them.

While we're doing this, move around some "AFS_DARWIN_ENV ||
AFS_FBSD_ENV" ifdefs, since these were getting a bit hard to read.
This commit adds some duplicated code, but the result should be easier
to follow.

Also for FreeBSD 12, we must be in NET_EPOCH_ENTER when calling
ifa_ifwithnet/rx_ifaddr_withnet (it panics if we don't, with
INVARIANTS). Add the needed NET_EPOCH_ENTER/EXIT calls, but do so a
bit higher up the call stack, since the returned structures are
potentially no longer valid after we NET_EPOCH_EXIT. Since this means
we're calling these in a few places in libafs, create a couple of rx
abstractions (RX_NET_EPOCH_ENTER) to handle the relevant ifdefs.

[adeason@dson.org: Various adjustments to locking calls; splitting up
DARWIN/FBSD ifdefs.]

Change-Id: I65d63b99b6f6ef3254325cce9338be27ef78478c
Reviewed-on: https://gerrit.openafs.org/13998
Reviewed-by: Tim Creech <tcreech@tcreech.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/afs_call.c
src/afs/afs_server.c
src/afs/sysincludes.h
src/rx/rx_kcommon.c
src/rx/rx_kernel.h

index 367265d..ca93bf9 100644 (file)
@@ -1231,9 +1231,12 @@ afs_syscall_call(long parm, long parm2, long parm3,
        mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
 # else /* AFS_USERSPACE_IP_ADDR */
        rx_ifnet_t tifnp;
+       RX_NET_EPOCH_ENTER();
 
        tifnp = rxi_FindIfnet(parm2, NULL);     /*  make iterative */
        mtu = (tifnp ? rx_ifnet_mtu(tifnp) : htonl(1500));
+
+       RX_NET_EPOCH_EXIT();
 # endif /* else AFS_USERSPACE_IP_ADDR */
 #endif /* !AFS_SUN5_ENV */
        if (!code)
@@ -1252,10 +1255,13 @@ afs_syscall_call(long parm, long parm2, long parm3,
        }
 # else /* AFS_USERSPACE_IP_ADDR */
        rx_ifnet_t tifnp;
+       RX_NET_EPOCH_ENTER();
 
        tifnp = rxi_FindIfnet(parm2, &mask);    /* make iterative */
        if (!tifnp)
            code = -1;
+
+       RX_NET_EPOCH_EXIT();
 # endif /* else AFS_USERSPACE_IP_ADDR */
 #endif /* !AFS_SUN5_ENV */
        if (!code)
index c6164f4..e705d0a 100644 (file)
@@ -1361,10 +1361,13 @@ afs_SetServerPrefs(struct srvAddr *const sa)
 #   elif defined(AFS_FBSD_ENV)
     {
        struct in_ifaddr *ifa;
+       struct rm_priotracker in_ifa_tracker;
        CURVNET_SET(rx_socket->so_vnet);
+       IN_IFADDR_RLOCK(&in_ifa_tracker);
        TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
            afsi_SetServerIPRank(sa, &ifa->ia_ifa);
        }
+       IN_IFADDR_RUNLOCK(&in_ifa_tracker);
        CURVNET_RESTORE();
     }
 #   elif defined(AFS_OBSD_ENV)
index dbe7ab6..1f281c5 100644 (file)
@@ -206,6 +206,7 @@ struct xfs_inode_info {
 #  include <sys/socket.h>
 #  include <net/if.h>
 #  include <net/if_var.h>
+#  include <sys/rmlock.h>
 # endif
 
 # ifdef        AFS_AIX_ENV
index a5b689c..97780d9 100644 (file)
@@ -389,6 +389,8 @@ rxi_InitPeerParams(struct rx_peer *pp)
 # else /* AFS_USERSPACE_IP_ADDR */
     rx_ifnet_t ifn;
 
+    RX_NET_EPOCH_ENTER();
+
 #  if !defined(AFS_SGI62_ENV)
     if (numMyNetAddrs == 0)
        (void)rxi_GetIFInfo();
@@ -416,6 +418,9 @@ rxi_InitPeerParams(struct rx_peer *pp)
        rx_rto_setPeerTimeoutSecs(pp, 3);
        pp->ifMTU = MIN(RX_REMOTE_PACKET_SIZE, rx_MyMaxSendSize);
     }
+
+    RX_NET_EPOCH_EXIT();
+
 # endif /* else AFS_USERSPACE_IP_ADDR */
 #else /* AFS_SUN5_ENV */
     afs_int32 mtu;
@@ -657,13 +662,14 @@ rxi_GetIFInfo(void)
        ifnet_list_free(ifns);
     }
 #  else /* AFS_DARWIN80_ENV */
-#   if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-#    if defined(AFS_FBSD_ENV)
+#   if defined(AFS_DARWIN_ENV)
+    TAILQ_FOREACH(ifn, &ifnet, if_link) {
+       if (i >= ADDRSPERSITE)
+           break;
+#   elif defined(AFS_FBSD_ENV)
     CURVNET_SET(rx_socket->so_vnet);
+    IFNET_RLOCK();
     TAILQ_FOREACH(ifn, &V_ifnet, if_link) {
-#    else
-    TAILQ_FOREACH(ifn, &ifnet, if_link) {
-#    endif
        if (i >= ADDRSPERSITE)
            break;
 #   elif defined(AFS_OBSD_ENV) || defined(AFS_NBSD_ENV)
@@ -673,7 +679,12 @@ rxi_GetIFInfo(void)
     for (ifn = ifnet; ifn != NULL && i < ADDRSPERSITE; ifn = ifn->if_next) {
 #   endif
        rxmtu = (ifn->if_mtu - RX_IPUDP_SIZE);
-#   if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#   if defined(AFS_DARWIN_ENV)
+       TAILQ_FOREACH(ifad, &ifn->if_addrhead, ifa_link) {
+           if (i >= ADDRSPERSITE)
+               break;
+#   elif defined(AFS_FBSD_ENV)
+       if_addr_rlock(ifn);
        TAILQ_FOREACH(ifad, &ifn->if_addrhead, ifa_link) {
            if (i >= ADDRSPERSITE)
                break;
@@ -706,6 +717,9 @@ rxi_GetIFInfo(void)
                }
            }
        }
+#   ifdef AFS_FBSD_ENV
+       if_addr_runlock(ifn);
+#   endif
     }
 #  endif /* !AFS_DARWIN80_ENV */
 
@@ -723,6 +737,7 @@ rxi_GetIFInfo(void)
     }
 
 #  ifdef AFS_FBSD_ENV
+    IFNET_RUNLOCK();
     CURVNET_RESTORE();
 #  endif
 
index 5a12473..1e7980d 100644 (file)
@@ -68,6 +68,14 @@ extern void osi_Panic(char *fmt, ...)
 #define        osi_YieldIfPossible()
 #define        osi_WakeupAndYieldIfPossible(x)     rx_Wakeup(x)
 
+#ifdef AFS_FBSD120_ENV
+# define RX_NET_EPOCH_ENTER() NET_EPOCH_ENTER()
+# define RX_NET_EPOCH_EXIT() NET_EPOCH_EXIT()
+#else
+# define RX_NET_EPOCH_ENTER() do { } while(0)
+# define RX_NET_EPOCH_EXIT() do { } while(0)
+#endif
+
 #if !defined(AFS_DARWIN80_ENV) || defined(UKERNEL)
 # ifdef UKERNEL
 #  define rx_ifnet_t struct usr_ifnet *