ipv6: lockless IPV6_MULTICAST_ALL implementation
authorEric Dumazet <edumazet@google.com>
Tue, 12 Sep 2023 16:02:05 +0000 (16:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Sep 2023 09:33:47 +0000 (10:33 +0100)
Move np->mc_all to an atomic flags to fix data-races.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/ipv6.h
include/net/inet_sock.h
net/ipv6/af_inet6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c

index 0d2b0a1b2daeaee51a03624adab5a385cc852cc7..d88e91b7f0a319a816488025ef213c4fb90ed359 100644 (file)
@@ -255,7 +255,6 @@ struct ipv6_pinfo {
                                dontfrag:1,
                                autoflowlabel:1,
                                autoflowlabel_set:1,
-                               mc_all:1,
                                rtalert_isolate:1;
        __u8                    min_hopcount;
        __u8                    tclass;
index 8cf1f7b442348bef83cc3d9648521a01667efae7..97e70a97dae888e6ab93c6446f4f3ba58cd8583e 100644 (file)
@@ -270,6 +270,7 @@ enum {
        INET_FLAGS_DEFER_CONNECT = 19,
        INET_FLAGS_MC6_LOOP     = 20,
        INET_FLAGS_RECVERR6_RFC4884 = 21,
+       INET_FLAGS_MC6_ALL      = 22,
 };
 
 /* cmsg flags for inet */
index bbd4aa1b96d09d346c521dab2194045123e7a5a6..372fb7b9112c8dfed09b6ddfdb37016a1a668494 100644 (file)
@@ -218,7 +218,7 @@ lookup_protocol:
        np->hop_limit   = -1;
        np->mcast_hops  = IPV6_DEFAULT_MCASTHOPS;
        inet6_set_bit(MC6_LOOP, sk);
-       np->mc_all      = 1;
+       inet6_set_bit(MC6_ALL, sk);
        np->pmtudisc    = IPV6_PMTUDISC_WANT;
        np->repflow     = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED;
        sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
index b65e73ac2ccdee79aa293948d3ba9853966e1e2d..7a181831f226c67813446145f8f58fa58908e3ae 100644 (file)
@@ -469,6 +469,11 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                        return -EINVAL;
                inet6_assign_bit(RECVERR6_RFC4884, sk, valbool);
                return 0;
+       case IPV6_MULTICAST_ALL:
+               if (optlen < sizeof(int))
+                       return -EINVAL;
+               inet6_assign_bit(MC6_ALL, sk, valbool);
+               return 0;
        }
        if (needs_rtnl)
                rtnl_lock();
@@ -890,13 +895,6 @@ done:
                        retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
                break;
        }
-       case IPV6_MULTICAST_ALL:
-               if (optlen < sizeof(int))
-                       goto e_inval;
-               np->mc_all = valbool;
-               retv = 0;
-               break;
-
        case MCAST_JOIN_GROUP:
        case MCAST_LEAVE_GROUP:
                if (in_compat_syscall())
@@ -1372,7 +1370,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case IPV6_MULTICAST_ALL:
-               val = np->mc_all;
+               val = inet6_test_bit(MC6_ALL, sk);
                break;
 
        case IPV6_UNICAST_IF:
index 4a7967623909412bc7e63edd0f0e20ecda901c6e..99e28b444a4c7d695ed6ffb8c6307f1b0d69b61f 100644 (file)
@@ -642,7 +642,7 @@ bool inet6_mc_check(const struct sock *sk, const struct in6_addr *mc_addr,
        }
        if (!mc) {
                rcu_read_unlock();
-               return np->mc_all;
+               return inet6_test_bit(MC6_ALL, sk);
        }
        psl = rcu_dereference(mc->sflist);
        if (!psl) {