Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: annotate data races around np->min_hopcount

No report yet from KCSAN, yet worth documenting the races.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
cc17c3c8 09b89846

+8 -3
+4 -1
net/ipv6/ipv6_sockglue.c
··· 950 950 goto e_inval; 951 951 if (val < 0 || val > 255) 952 952 goto e_inval; 953 - np->min_hopcount = val; 953 + /* tcp_v6_err() and tcp_v6_rcv() might read min_hopcount 954 + * while we are changing it. 955 + */ 956 + WRITE_ONCE(np->min_hopcount, val); 954 957 retv = 0; 955 958 break; 956 959 case IPV6_DONTFRAG:
+4 -2
net/ipv6/tcp_ipv6.c
··· 414 414 if (sk->sk_state == TCP_CLOSE) 415 415 goto out; 416 416 417 - if (ipv6_hdr(skb)->hop_limit < tcp_inet6_sk(sk)->min_hopcount) { 417 + /* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */ 418 + if (ipv6_hdr(skb)->hop_limit < READ_ONCE(tcp_inet6_sk(sk)->min_hopcount)) { 418 419 __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); 419 420 goto out; 420 421 } ··· 1727 1726 return 0; 1728 1727 } 1729 1728 } 1730 - if (hdr->hop_limit < tcp_inet6_sk(sk)->min_hopcount) { 1729 + /* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */ 1730 + if (hdr->hop_limit < READ_ONCE(tcp_inet6_sk(sk)->min_hopcount)) { 1731 1731 __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); 1732 1732 goto discard_and_relse; 1733 1733 }