mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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>
This commit is contained in:
commit
8f762b2e88
|
|
@ -931,10 +931,10 @@ static inline void iph_to_flow_copy_v6addrs(struct flow_keys *flow,
|
|||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
||||
static inline bool ipv6_can_nonlocal_bind(struct net *net,
|
||||
struct inet_sock *inet)
|
||||
static inline bool ipv6_can_nonlocal_bind(const struct net *net,
|
||||
const struct inet_sock *inet)
|
||||
{
|
||||
return net->ipv6.sysctl.ip_nonlocal_bind ||
|
||||
return READ_ONCE(net->ipv6.sysctl.ip_nonlocal_bind) ||
|
||||
test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
|
||||
test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
|
||||
}
|
||||
|
|
@ -949,10 +949,12 @@ static inline bool ipv6_can_nonlocal_bind(struct net *net,
|
|||
|
||||
#define IP6_DEFAULT_AUTO_FLOW_LABELS IP6_AUTO_FLOW_LABEL_OPTOUT
|
||||
|
||||
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
||||
static inline __be32 ip6_make_flowlabel(const struct net *net,
|
||||
struct sk_buff *skb,
|
||||
__be32 flowlabel, bool autolabel,
|
||||
struct flowi6 *fl6)
|
||||
{
|
||||
u8 auto_flowlabels;
|
||||
u32 hash;
|
||||
|
||||
/* @flowlabel may include more than a flow label, eg, the traffic class.
|
||||
|
|
@ -960,10 +962,12 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
|||
*/
|
||||
flowlabel &= IPV6_FLOWLABEL_MASK;
|
||||
|
||||
if (flowlabel ||
|
||||
net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
|
||||
(!autolabel &&
|
||||
net->ipv6.sysctl.auto_flowlabels != IP6_AUTO_FLOW_LABEL_FORCED))
|
||||
if (flowlabel)
|
||||
return flowlabel;
|
||||
|
||||
auto_flowlabels = READ_ONCE(net->ipv6.sysctl.auto_flowlabels);
|
||||
if (auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
|
||||
(!autolabel && auto_flowlabels != IP6_AUTO_FLOW_LABEL_FORCED))
|
||||
return flowlabel;
|
||||
|
||||
hash = skb_get_hash_flowi6(skb, fl6);
|
||||
|
|
@ -976,15 +980,15 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
|||
|
||||
flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
|
||||
|
||||
if (net->ipv6.sysctl.flowlabel_state_ranges)
|
||||
if (READ_ONCE(net->ipv6.sysctl.flowlabel_state_ranges))
|
||||
flowlabel |= IPV6_FLOWLABEL_STATELESS_FLAG;
|
||||
|
||||
return flowlabel;
|
||||
}
|
||||
|
||||
static inline int ip6_default_np_autolabel(struct net *net)
|
||||
static inline int ip6_default_np_autolabel(const struct net *net)
|
||||
{
|
||||
switch (net->ipv6.sysctl.auto_flowlabels) {
|
||||
switch (READ_ONCE(net->ipv6.sysctl.auto_flowlabels)) {
|
||||
case IP6_AUTO_FLOW_LABEL_OFF:
|
||||
case IP6_AUTO_FLOW_LABEL_OPTIN:
|
||||
default:
|
||||
|
|
@ -995,13 +999,13 @@ static inline int ip6_default_np_autolabel(struct net *net)
|
|||
}
|
||||
}
|
||||
#else
|
||||
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
||||
static inline __be32 ip6_make_flowlabel(const struct net *net, struct sk_buff *skb,
|
||||
__be32 flowlabel, bool autolabel,
|
||||
struct flowi6 *fl6)
|
||||
{
|
||||
return flowlabel;
|
||||
}
|
||||
static inline int ip6_default_np_autolabel(struct net *net)
|
||||
static inline int ip6_default_np_autolabel(const struct net *net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1010,11 +1014,11 @@ static inline int ip6_default_np_autolabel(struct net *net)
|
|||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static inline int ip6_multipath_hash_policy(const struct net *net)
|
||||
{
|
||||
return net->ipv6.sysctl.multipath_hash_policy;
|
||||
return READ_ONCE(net->ipv6.sysctl.multipath_hash_policy);
|
||||
}
|
||||
static inline u32 ip6_multipath_hash_fields(const struct net *net)
|
||||
{
|
||||
return net->ipv6.sysctl.multipath_hash_fields;
|
||||
return READ_ONCE(net->ipv6.sysctl.multipath_hash_fields);
|
||||
}
|
||||
#else
|
||||
static inline int ip6_multipath_hash_policy(const struct net *net)
|
||||
|
|
|
|||
|
|
@ -30,19 +30,23 @@ struct netns_sysctl_ipv6 {
|
|||
int ip6_rt_min_advmss;
|
||||
u32 multipath_hash_fields;
|
||||
u8 multipath_hash_policy;
|
||||
u8 bindv6only;
|
||||
|
||||
__cacheline_group_begin(sysctl_ipv6_flowlabel);
|
||||
u8 flowlabel_consistency;
|
||||
u8 auto_flowlabels;
|
||||
int icmpv6_time;
|
||||
u8 flowlabel_state_ranges;
|
||||
__cacheline_group_end(sysctl_ipv6_flowlabel);
|
||||
|
||||
u8 icmpv6_echo_ignore_all;
|
||||
u8 icmpv6_echo_ignore_multicast;
|
||||
u8 icmpv6_echo_ignore_anycast;
|
||||
int icmpv6_time;
|
||||
DECLARE_BITMAP(icmpv6_ratemask, ICMPV6_MSG_MAX + 1);
|
||||
unsigned long *icmpv6_ratemask_ptr;
|
||||
u8 anycast_src_echo_reply;
|
||||
u8 bindv6only;
|
||||
u8 ip_nonlocal_bind;
|
||||
u8 fwmark_reflect;
|
||||
u8 flowlabel_state_ranges;
|
||||
int idgen_retries;
|
||||
int idgen_delay;
|
||||
int flowlabel_reflect;
|
||||
|
|
|
|||
|
|
@ -224,8 +224,8 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
|
|||
inet6_set_bit(MC6_LOOP, sk);
|
||||
inet6_set_bit(MC6_ALL, sk);
|
||||
np->pmtudisc = IPV6_PMTUDISC_WANT;
|
||||
inet6_assign_bit(REPFLOW, sk, net->ipv6.sysctl.flowlabel_reflect &
|
||||
FLOWLABEL_REFLECT_ESTABLISHED);
|
||||
inet6_assign_bit(REPFLOW, sk, READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) &
|
||||
FLOWLABEL_REFLECT_ESTABLISHED);
|
||||
sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
|
||||
sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash);
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
|
|||
}
|
||||
|
||||
extlen = (skb_transport_header(skb)[1] + 1) << 3;
|
||||
if (extlen > net->ipv6.sysctl.max_dst_opts_len)
|
||||
if (extlen > READ_ONCE(net->ipv6.sysctl.max_dst_opts_len))
|
||||
goto fail_and_free;
|
||||
|
||||
opt->lastopt = opt->dst1 = skb_network_header_len(skb);
|
||||
|
|
@ -322,7 +322,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
|
|||
dstbuf = opt->dst1;
|
||||
#endif
|
||||
|
||||
if (ip6_parse_tlv(false, skb, net->ipv6.sysctl.max_dst_opts_cnt)) {
|
||||
if (ip6_parse_tlv(false, skb,
|
||||
READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) {
|
||||
skb->transport_header += extlen;
|
||||
opt = IP6CB(skb);
|
||||
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
||||
|
|
@ -1049,11 +1050,12 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
|
|||
}
|
||||
|
||||
extlen = (skb_transport_header(skb)[1] + 1) << 3;
|
||||
if (extlen > net->ipv6.sysctl.max_hbh_opts_len)
|
||||
if (extlen > READ_ONCE(net->ipv6.sysctl.max_hbh_opts_len))
|
||||
goto fail_and_free;
|
||||
|
||||
opt->flags |= IP6SKB_HOPBYHOP;
|
||||
if (ip6_parse_tlv(true, skb, net->ipv6.sysctl.max_hbh_opts_cnt)) {
|
||||
if (ip6_parse_tlv(true, skb,
|
||||
READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) {
|
||||
skb->transport_header += extlen;
|
||||
opt = IP6CB(skb);
|
||||
opt->nhoff = sizeof(struct ipv6hdr);
|
||||
|
|
|
|||
|
|
@ -958,7 +958,8 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb)
|
|||
tmp_hdr.icmp6_type = type;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES)
|
||||
if (READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) &
|
||||
FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES)
|
||||
fl6.flowlabel = ip6_flowlabel(ipv6_hdr(skb));
|
||||
|
||||
fl6.flowi6_proto = IPPROTO_ICMPV6;
|
||||
|
|
|
|||
|
|
@ -1374,14 +1374,14 @@ static void fib6_start_gc(struct net *net, struct fib6_info *rt)
|
|||
if (!timer_pending(&net->ipv6.ip6_fib_timer) &&
|
||||
(rt->fib6_flags & RTF_EXPIRES))
|
||||
mod_timer(&net->ipv6.ip6_fib_timer,
|
||||
jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
|
||||
jiffies + READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval));
|
||||
}
|
||||
|
||||
void fib6_force_start_gc(struct net *net)
|
||||
{
|
||||
if (!timer_pending(&net->ipv6.ip6_fib_timer))
|
||||
mod_timer(&net->ipv6.ip6_fib_timer,
|
||||
jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
|
||||
jiffies + READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval));
|
||||
}
|
||||
|
||||
static void __fib6_update_sernum_upto_root(struct fib6_info *rt,
|
||||
|
|
@ -2413,6 +2413,7 @@ static void fib6_gc_all(struct net *net, struct fib6_gc_args *gc_args)
|
|||
void fib6_run_gc(unsigned long expires, struct net *net, bool force)
|
||||
{
|
||||
struct fib6_gc_args gc_args;
|
||||
int ip6_rt_gc_interval;
|
||||
unsigned long now;
|
||||
|
||||
if (force) {
|
||||
|
|
@ -2421,8 +2422,8 @@ void fib6_run_gc(unsigned long expires, struct net *net, bool force)
|
|||
mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
|
||||
return;
|
||||
}
|
||||
gc_args.timeout = expires ? (int)expires :
|
||||
net->ipv6.sysctl.ip6_rt_gc_interval;
|
||||
ip6_rt_gc_interval = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval);
|
||||
gc_args.timeout = expires ? (int)expires : ip6_rt_gc_interval;
|
||||
gc_args.more = 0;
|
||||
|
||||
fib6_gc_all(net, &gc_args);
|
||||
|
|
@ -2431,8 +2432,7 @@ void fib6_run_gc(unsigned long expires, struct net *net, bool force)
|
|||
|
||||
if (gc_args.more)
|
||||
mod_timer(&net->ipv6.ip6_fib_timer,
|
||||
round_jiffies(now
|
||||
+ net->ipv6.sysctl.ip6_rt_gc_interval));
|
||||
round_jiffies(now + ip6_rt_gc_interval));
|
||||
else
|
||||
timer_delete(&net->ipv6.ip6_fib_timer);
|
||||
spin_unlock_bh(&net->ipv6.fib6_gc_lock);
|
||||
|
|
|
|||
|
|
@ -2895,7 +2895,7 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)
|
|||
|
||||
dst_metric_set(&rt->dst, RTAX_MTU, mtu);
|
||||
rt->rt6i_flags |= RTF_MODIFIED;
|
||||
rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
rt6_update_expires(rt, READ_ONCE(net->ipv6.sysctl.ip6_rt_mtu_expires));
|
||||
}
|
||||
|
||||
static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
|
||||
|
|
@ -3256,8 +3256,8 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
|
|||
rcu_read_lock();
|
||||
|
||||
net = dst_dev_net_rcu(dst);
|
||||
if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
|
||||
mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
|
||||
mtu = max_t(unsigned int, mtu,
|
||||
READ_ONCE(net->ipv6.sysctl.ip6_rt_min_advmss));
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
@ -3359,10 +3359,10 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
|
|||
static void ip6_dst_gc(struct dst_ops *ops)
|
||||
{
|
||||
struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
|
||||
int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
|
||||
int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
|
||||
int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
|
||||
unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
|
||||
int rt_min_interval = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_min_interval);
|
||||
int rt_elasticity = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_elasticity);
|
||||
int rt_gc_timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_timeout);
|
||||
unsigned long rt_last_gc = READ_ONCE(net->ipv6.ip6_rt_last_gc);
|
||||
unsigned int val;
|
||||
int entries;
|
||||
|
||||
|
|
@ -5005,7 +5005,7 @@ void rt6_sync_down_dev(struct net_device *dev, unsigned long event)
|
|||
};
|
||||
struct net *net = dev_net(dev);
|
||||
|
||||
if (net->ipv6.sysctl.skip_notify_on_dev_down)
|
||||
if (READ_ONCE(net->ipv6.sysctl.skip_notify_on_dev_down))
|
||||
fib6_clean_all_skip_notify(net, fib6_ifdown, &arg);
|
||||
else
|
||||
fib6_clean_all(net, fib6_ifdown, &arg);
|
||||
|
|
@ -6405,6 +6405,7 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt,
|
|||
void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
|
||||
bool offload, bool trap, bool offload_failed)
|
||||
{
|
||||
u8 fib_notify_on_flag_change;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
|
|
@ -6416,8 +6417,9 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
|
|||
WRITE_ONCE(f6i->offload, offload);
|
||||
WRITE_ONCE(f6i->trap, trap);
|
||||
|
||||
fib_notify_on_flag_change = READ_ONCE(net->ipv6.sysctl.fib_notify_on_flag_change);
|
||||
/* 2 means send notifications only if offload_failed was changed. */
|
||||
if (net->ipv6.sysctl.fib_notify_on_flag_change == 2 &&
|
||||
if (fib_notify_on_flag_change == 2 &&
|
||||
READ_ONCE(f6i->offload_failed) == offload_failed)
|
||||
return;
|
||||
|
||||
|
|
@ -6429,7 +6431,7 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
|
|||
*/
|
||||
return;
|
||||
|
||||
if (!net->ipv6.sysctl.fib_notify_on_flag_change)
|
||||
if (!fib_notify_on_flag_change)
|
||||
return;
|
||||
|
||||
skb = nlmsg_new(rt6_nlmsg_size(f6i), GFP_KERNEL);
|
||||
|
|
@ -6526,7 +6528,7 @@ static int ipv6_sysctl_rtcache_flush(const struct ctl_table *ctl, int write,
|
|||
return ret;
|
||||
|
||||
net = (struct net *)ctl->extra1;
|
||||
delay = net->ipv6.sysctl.flush_delay;
|
||||
delay = READ_ONCE(net->ipv6.sysctl.flush_delay);
|
||||
fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1085,7 +1085,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb,
|
|||
txhash = inet_twsk(sk)->tw_txhash;
|
||||
}
|
||||
} else {
|
||||
if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_TCP_RESET)
|
||||
if (READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) &
|
||||
FLOWLABEL_REFLECT_TCP_RESET)
|
||||
label = ip6_flowlabel(ipv6h);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user