diff options
author | Eric Dumazet <edumazet@google.com> | 2023-09-12 16:02:03 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-09-15 10:33:47 +0100 |
commit | 273784d3c5741522199011772651dbb50db8c810 (patch) | |
tree | eca1da6e908354532c818456152282eb279c11dd | |
parent | 15f926c4457aa65b1ac83bda1bbdcaad3f48e4e7 (diff) | |
download | linux-stable-273784d3c5741522199011772651dbb50db8c810.tar.gz linux-stable-273784d3c5741522199011772651dbb50db8c810.tar.bz2 linux-stable-273784d3c5741522199011772651dbb50db8c810.zip |
ipv6: lockless IPV6_MINHOPCOUNT implementation
Add one missing READ_ONCE() annotation in do_ipv6_getsockopt()
and make IPV6_MINHOPCOUNT setsockopt() lockless.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 3b2a34828daa..bbc8a009e05d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -448,6 +448,20 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, return -EINVAL; WRITE_ONCE(np->frag_size, val); return 0; + case IPV6_MINHOPCOUNT: + if (optlen < sizeof(int)) + return -EINVAL; + if (val < 0 || val > 255) + return -EINVAL; + + if (val) + static_branch_enable(&ip6_min_hopcount); + + /* tcp_v6_err() and tcp_v6_rcv() might read min_hopcount + * while we are changing it. + */ + WRITE_ONCE(np->min_hopcount, val); + return 0; } if (needs_rtnl) rtnl_lock(); @@ -947,21 +961,6 @@ done: goto e_inval; retv = __ip6_sock_set_addr_preferences(sk, val); break; - case IPV6_MINHOPCOUNT: - if (optlen < sizeof(int)) - goto e_inval; - if (val < 0 || val > 255) - goto e_inval; - - if (val) - static_branch_enable(&ip6_min_hopcount); - - /* tcp_v6_err() and tcp_v6_rcv() might read min_hopcount - * while we are changing it. - */ - WRITE_ONCE(np->min_hopcount, val); - retv = 0; - break; case IPV6_DONTFRAG: np->dontfrag = valbool; retv = 0; @@ -1443,7 +1442,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname, break; case IPV6_MINHOPCOUNT: - val = np->min_hopcount; + val = READ_ONCE(np->min_hopcount); break; case IPV6_DONTFRAG: |