]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
inet: implement lockless IP_MULTICAST_TTL
authorEric Dumazet <edumazet@google.com>
Fri, 22 Sep 2023 03:42:14 +0000 (03:42 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 1 Oct 2023 18:39:18 +0000 (19:39 +0100)
inet->mc_ttl can be read locklessly.

Implement proper lockless reads and writes to inet->mc_ttl

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/netfilter/ipvs/ip_vs_sync.c

index 6b14097e80ad35e42b9a7d5da977f5f0a7ea2c78..f07ce051760d879ae3772f550c1c96d17d14f8e5 100644 (file)
@@ -1430,7 +1430,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
        if (cork->ttl != 0)
                ttl = cork->ttl;
        else if (rt->rt_type == RTN_MULTICAST)
-               ttl = inet->mc_ttl;
+               ttl = READ_ONCE(inet->mc_ttl);
        else
                ttl = ip_select_ttl(inet, &rt->dst);
 
index cce9cb25f3b31cd57fa883ae0dedb6829d8da2fa..4ad3003378ae6b186513000264f77b54a7babe6d 100644 (file)
@@ -1039,6 +1039,17 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
 
                WRITE_ONCE(inet->min_ttl, val);
                return 0;
+       case IP_MULTICAST_TTL:
+               if (sk->sk_type == SOCK_STREAM)
+                       return -EINVAL;
+               if (optlen < 1)
+                       return -EINVAL;
+               if (val == -1)
+                       val = 1;
+               if (val < 0 || val > 255)
+                       return -EINVAL;
+               WRITE_ONCE(inet->mc_ttl, val);
+               return 0;
        }
 
        err = 0;
@@ -1101,17 +1112,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                        goto e_inval;
                inet->pmtudisc = val;
                break;
-       case IP_MULTICAST_TTL:
-               if (sk->sk_type == SOCK_STREAM)
-                       goto e_inval;
-               if (optlen < 1)
-                       goto e_inval;
-               if (val == -1)
-                       val = 1;
-               if (val < 0 || val > 255)
-                       goto e_inval;
-               inet->mc_ttl = val;
-               break;
        case IP_UNICAST_IF:
        {
                struct net_device *dev = NULL;
@@ -1592,6 +1592,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_MINTTL:
                val = READ_ONCE(inet->min_ttl);
                goto copyval;
+       case IP_MULTICAST_TTL:
+               val = READ_ONCE(inet->mc_ttl);
+               goto copyval;
        }
 
        if (needs_rtnl)
@@ -1649,9 +1652,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                }
                break;
        }
-       case IP_MULTICAST_TTL:
-               val = inet->mc_ttl;
-               break;
        case IP_UNICAST_IF:
                val = (__force int)htonl((__u32) inet->uc_index);
                break;
@@ -1718,7 +1718,8 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                        put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
                }
                if (inet_test_bit(TTL, sk)) {
-                       int hlim = inet->mc_ttl;
+                       int hlim = READ_ONCE(inet->mc_ttl);
+
                        put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
                }
                if (inet_test_bit(TOS, sk)) {
index 5820a8156c4701bb163f569d735c389d7a8e3820..3eed1670224888acf639cff06537ddf2505461bb 100644 (file)
@@ -1316,7 +1316,7 @@ static void set_mcast_ttl(struct sock *sk, u_char ttl)
 
        /* setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); */
        lock_sock(sk);
-       inet->mc_ttl = ttl;
+       WRITE_ONCE(inet->mc_ttl, ttl);
 #ifdef CONFIG_IP_VS_IPV6
        if (sk->sk_family == AF_INET6) {
                struct ipv6_pinfo *np = inet6_sk(sk);