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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ipv6-more-data-race-annotations'

Eric Dumazet says:

====================
ipv6: more data-race annotations

Inspired by one unrelated syzbot report.

This series adds missing (and boring) data-race annotations in IPv6.

Only the first patch adds sysctl_ipv6_flowlabel group
to speedup ip6_make_flowlabel() a bit.
====================

Link: https://patch.msgid.link/20260115094141.3124990-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+57 -43
+19 -15
include/net/ipv6.h
··· 931 931 932 932 #if IS_ENABLED(CONFIG_IPV6) 933 933 934 - static inline bool ipv6_can_nonlocal_bind(struct net *net, 935 - struct inet_sock *inet) 934 + static inline bool ipv6_can_nonlocal_bind(const struct net *net, 935 + const struct inet_sock *inet) 936 936 { 937 - return net->ipv6.sysctl.ip_nonlocal_bind || 937 + return READ_ONCE(net->ipv6.sysctl.ip_nonlocal_bind) || 938 938 test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) || 939 939 test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags); 940 940 } ··· 949 949 950 950 #define IP6_DEFAULT_AUTO_FLOW_LABELS IP6_AUTO_FLOW_LABEL_OPTOUT 951 951 952 - static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, 952 + static inline __be32 ip6_make_flowlabel(const struct net *net, 953 + struct sk_buff *skb, 953 954 __be32 flowlabel, bool autolabel, 954 955 struct flowi6 *fl6) 955 956 { 957 + u8 auto_flowlabels; 956 958 u32 hash; 957 959 958 960 /* @flowlabel may include more than a flow label, eg, the traffic class. ··· 962 960 */ 963 961 flowlabel &= IPV6_FLOWLABEL_MASK; 964 962 965 - if (flowlabel || 966 - net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF || 967 - (!autolabel && 968 - net->ipv6.sysctl.auto_flowlabels != IP6_AUTO_FLOW_LABEL_FORCED)) 963 + if (flowlabel) 964 + return flowlabel; 965 + 966 + auto_flowlabels = READ_ONCE(net->ipv6.sysctl.auto_flowlabels); 967 + if (auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF || 968 + (!autolabel && auto_flowlabels != IP6_AUTO_FLOW_LABEL_FORCED)) 969 969 return flowlabel; 970 970 971 971 hash = skb_get_hash_flowi6(skb, fl6); ··· 980 976 981 977 flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK; 982 978 983 - if (net->ipv6.sysctl.flowlabel_state_ranges) 979 + if (READ_ONCE(net->ipv6.sysctl.flowlabel_state_ranges)) 984 980 flowlabel |= IPV6_FLOWLABEL_STATELESS_FLAG; 985 981 986 982 return flowlabel; 987 983 } 988 984 989 - static inline int ip6_default_np_autolabel(struct net *net) 985 + static inline int ip6_default_np_autolabel(const struct net *net) 990 986 { 991 - switch (net->ipv6.sysctl.auto_flowlabels) { 987 + switch (READ_ONCE(net->ipv6.sysctl.auto_flowlabels)) { 992 988 case IP6_AUTO_FLOW_LABEL_OFF: 993 989 case IP6_AUTO_FLOW_LABEL_OPTIN: 994 990 default: ··· 999 995 } 1000 996 } 1001 997 #else 1002 - static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, 998 + static inline __be32 ip6_make_flowlabel(const struct net *net, struct sk_buff *skb, 1003 999 __be32 flowlabel, bool autolabel, 1004 1000 struct flowi6 *fl6) 1005 1001 { 1006 1002 return flowlabel; 1007 1003 } 1008 - static inline int ip6_default_np_autolabel(struct net *net) 1004 + static inline int ip6_default_np_autolabel(const struct net *net) 1009 1005 { 1010 1006 return 0; 1011 1007 } ··· 1014 1010 #if IS_ENABLED(CONFIG_IPV6) 1015 1011 static inline int ip6_multipath_hash_policy(const struct net *net) 1016 1012 { 1017 - return net->ipv6.sysctl.multipath_hash_policy; 1013 + return READ_ONCE(net->ipv6.sysctl.multipath_hash_policy); 1018 1014 } 1019 1015 static inline u32 ip6_multipath_hash_fields(const struct net *net) 1020 1016 { 1021 - return net->ipv6.sysctl.multipath_hash_fields; 1017 + return READ_ONCE(net->ipv6.sysctl.multipath_hash_fields); 1022 1018 } 1023 1019 #else 1024 1020 static inline int ip6_multipath_hash_policy(const struct net *net)
+7 -3
include/net/netns/ipv6.h
··· 30 30 int ip6_rt_min_advmss; 31 31 u32 multipath_hash_fields; 32 32 u8 multipath_hash_policy; 33 - u8 bindv6only; 33 + 34 + __cacheline_group_begin(sysctl_ipv6_flowlabel); 34 35 u8 flowlabel_consistency; 35 36 u8 auto_flowlabels; 36 - int icmpv6_time; 37 + u8 flowlabel_state_ranges; 38 + __cacheline_group_end(sysctl_ipv6_flowlabel); 39 + 37 40 u8 icmpv6_echo_ignore_all; 38 41 u8 icmpv6_echo_ignore_multicast; 39 42 u8 icmpv6_echo_ignore_anycast; 43 + int icmpv6_time; 40 44 DECLARE_BITMAP(icmpv6_ratemask, ICMPV6_MSG_MAX + 1); 41 45 unsigned long *icmpv6_ratemask_ptr; 42 46 u8 anycast_src_echo_reply; 47 + u8 bindv6only; 43 48 u8 ip_nonlocal_bind; 44 49 u8 fwmark_reflect; 45 - u8 flowlabel_state_ranges; 46 50 int idgen_retries; 47 51 int idgen_delay; 48 52 int flowlabel_reflect;
+2 -2
net/ipv6/af_inet6.c
··· 224 224 inet6_set_bit(MC6_LOOP, sk); 225 225 inet6_set_bit(MC6_ALL, sk); 226 226 np->pmtudisc = IPV6_PMTUDISC_WANT; 227 - inet6_assign_bit(REPFLOW, sk, net->ipv6.sysctl.flowlabel_reflect & 228 - FLOWLABEL_REFLECT_ESTABLISHED); 227 + inet6_assign_bit(REPFLOW, sk, READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) & 228 + FLOWLABEL_REFLECT_ESTABLISHED); 229 229 sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; 230 230 sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); 231 231
+6 -4
net/ipv6/exthdrs.c
··· 314 314 } 315 315 316 316 extlen = (skb_transport_header(skb)[1] + 1) << 3; 317 - if (extlen > net->ipv6.sysctl.max_dst_opts_len) 317 + if (extlen > READ_ONCE(net->ipv6.sysctl.max_dst_opts_len)) 318 318 goto fail_and_free; 319 319 320 320 opt->lastopt = opt->dst1 = skb_network_header_len(skb); ··· 322 322 dstbuf = opt->dst1; 323 323 #endif 324 324 325 - if (ip6_parse_tlv(false, skb, net->ipv6.sysctl.max_dst_opts_cnt)) { 325 + if (ip6_parse_tlv(false, skb, 326 + READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) { 326 327 skb->transport_header += extlen; 327 328 opt = IP6CB(skb); 328 329 #if IS_ENABLED(CONFIG_IPV6_MIP6) ··· 1050 1049 } 1051 1050 1052 1051 extlen = (skb_transport_header(skb)[1] + 1) << 3; 1053 - if (extlen > net->ipv6.sysctl.max_hbh_opts_len) 1052 + if (extlen > READ_ONCE(net->ipv6.sysctl.max_hbh_opts_len)) 1054 1053 goto fail_and_free; 1055 1054 1056 1055 opt->flags |= IP6SKB_HOPBYHOP; 1057 - if (ip6_parse_tlv(true, skb, net->ipv6.sysctl.max_hbh_opts_cnt)) { 1056 + if (ip6_parse_tlv(true, skb, 1057 + READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) { 1058 1058 skb->transport_header += extlen; 1059 1059 opt = IP6CB(skb); 1060 1060 opt->nhoff = sizeof(struct ipv6hdr);
+2 -1
net/ipv6/icmp.c
··· 958 958 tmp_hdr.icmp6_type = type; 959 959 960 960 memset(&fl6, 0, sizeof(fl6)); 961 - if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES) 961 + if (READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) & 962 + FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES) 962 963 fl6.flowlabel = ip6_flowlabel(ipv6_hdr(skb)); 963 964 964 965 fl6.flowi6_proto = IPPROTO_ICMPV6;
+6 -6
net/ipv6/ip6_fib.c
··· 1374 1374 if (!timer_pending(&net->ipv6.ip6_fib_timer) && 1375 1375 (rt->fib6_flags & RTF_EXPIRES)) 1376 1376 mod_timer(&net->ipv6.ip6_fib_timer, 1377 - jiffies + net->ipv6.sysctl.ip6_rt_gc_interval); 1377 + jiffies + READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval)); 1378 1378 } 1379 1379 1380 1380 void fib6_force_start_gc(struct net *net) 1381 1381 { 1382 1382 if (!timer_pending(&net->ipv6.ip6_fib_timer)) 1383 1383 mod_timer(&net->ipv6.ip6_fib_timer, 1384 - jiffies + net->ipv6.sysctl.ip6_rt_gc_interval); 1384 + jiffies + READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval)); 1385 1385 } 1386 1386 1387 1387 static void __fib6_update_sernum_upto_root(struct fib6_info *rt, ··· 2413 2413 void fib6_run_gc(unsigned long expires, struct net *net, bool force) 2414 2414 { 2415 2415 struct fib6_gc_args gc_args; 2416 + int ip6_rt_gc_interval; 2416 2417 unsigned long now; 2417 2418 2418 2419 if (force) { ··· 2422 2421 mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ); 2423 2422 return; 2424 2423 } 2425 - gc_args.timeout = expires ? (int)expires : 2426 - net->ipv6.sysctl.ip6_rt_gc_interval; 2424 + ip6_rt_gc_interval = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval); 2425 + gc_args.timeout = expires ? (int)expires : ip6_rt_gc_interval; 2427 2426 gc_args.more = 0; 2428 2427 2429 2428 fib6_gc_all(net, &gc_args); ··· 2432 2431 2433 2432 if (gc_args.more) 2434 2433 mod_timer(&net->ipv6.ip6_fib_timer, 2435 - round_jiffies(now 2436 - + net->ipv6.sysctl.ip6_rt_gc_interval)); 2434 + round_jiffies(now + ip6_rt_gc_interval)); 2437 2435 else 2438 2436 timer_delete(&net->ipv6.ip6_fib_timer); 2439 2437 spin_unlock_bh(&net->ipv6.fib6_gc_lock);
+13 -11
net/ipv6/route.c
··· 2895 2895 2896 2896 dst_metric_set(&rt->dst, RTAX_MTU, mtu); 2897 2897 rt->rt6i_flags |= RTF_MODIFIED; 2898 - rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); 2898 + rt6_update_expires(rt, READ_ONCE(net->ipv6.sysctl.ip6_rt_mtu_expires)); 2899 2899 } 2900 2900 2901 2901 static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) ··· 3256 3256 rcu_read_lock(); 3257 3257 3258 3258 net = dst_dev_net_rcu(dst); 3259 - if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) 3260 - mtu = net->ipv6.sysctl.ip6_rt_min_advmss; 3259 + mtu = max_t(unsigned int, mtu, 3260 + READ_ONCE(net->ipv6.sysctl.ip6_rt_min_advmss)); 3261 3261 3262 3262 rcu_read_unlock(); 3263 3263 ··· 3359 3359 static void ip6_dst_gc(struct dst_ops *ops) 3360 3360 { 3361 3361 struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops); 3362 - int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; 3363 - int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; 3364 - int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; 3365 - unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; 3362 + int rt_min_interval = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_min_interval); 3363 + int rt_elasticity = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_elasticity); 3364 + int rt_gc_timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_timeout); 3365 + unsigned long rt_last_gc = READ_ONCE(net->ipv6.ip6_rt_last_gc); 3366 3366 unsigned int val; 3367 3367 int entries; 3368 3368 ··· 5005 5005 }; 5006 5006 struct net *net = dev_net(dev); 5007 5007 5008 - if (net->ipv6.sysctl.skip_notify_on_dev_down) 5008 + if (READ_ONCE(net->ipv6.sysctl.skip_notify_on_dev_down)) 5009 5009 fib6_clean_all_skip_notify(net, fib6_ifdown, &arg); 5010 5010 else 5011 5011 fib6_clean_all(net, fib6_ifdown, &arg); ··· 6405 6405 void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i, 6406 6406 bool offload, bool trap, bool offload_failed) 6407 6407 { 6408 + u8 fib_notify_on_flag_change; 6408 6409 struct sk_buff *skb; 6409 6410 int err; 6410 6411 ··· 6417 6416 WRITE_ONCE(f6i->offload, offload); 6418 6417 WRITE_ONCE(f6i->trap, trap); 6419 6418 6419 + fib_notify_on_flag_change = READ_ONCE(net->ipv6.sysctl.fib_notify_on_flag_change); 6420 6420 /* 2 means send notifications only if offload_failed was changed. */ 6421 - if (net->ipv6.sysctl.fib_notify_on_flag_change == 2 && 6421 + if (fib_notify_on_flag_change == 2 && 6422 6422 READ_ONCE(f6i->offload_failed) == offload_failed) 6423 6423 return; 6424 6424 ··· 6431 6429 */ 6432 6430 return; 6433 6431 6434 - if (!net->ipv6.sysctl.fib_notify_on_flag_change) 6432 + if (!fib_notify_on_flag_change) 6435 6433 return; 6436 6434 6437 6435 skb = nlmsg_new(rt6_nlmsg_size(f6i), GFP_KERNEL); ··· 6528 6526 return ret; 6529 6527 6530 6528 net = (struct net *)ctl->extra1; 6531 - delay = net->ipv6.sysctl.flush_delay; 6529 + delay = READ_ONCE(net->ipv6.sysctl.flush_delay); 6532 6530 fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0); 6533 6531 return 0; 6534 6532 }
+2 -1
net/ipv6/tcp_ipv6.c
··· 1085 1085 txhash = inet_twsk(sk)->tw_txhash; 1086 1086 } 1087 1087 } else { 1088 - if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_TCP_RESET) 1088 + if (READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) & 1089 + FLOWLABEL_REFLECT_TCP_RESET) 1089 1090 label = ip6_flowlabel(ipv6h); 1090 1091 } 1091 1092