Commit 0598f8f3 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski

inet: annotate devconf data-races

Add READ_ONCE() in ipv4_devconf_get() and corresponding
WRITE_ONCE() in ipv4_devconf_set()

Add IPV4_DEVCONF_RO() and IPV4_DEVCONF_ALL_RO() macros,
and use them when reading devconf fields.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20240227092411.2315725-2-edumazet@google.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent e83ddcea
...@@ -53,13 +53,15 @@ struct in_device { ...@@ -53,13 +53,15 @@ struct in_device {
}; };
#define IPV4_DEVCONF(cnf, attr) ((cnf).data[IPV4_DEVCONF_ ## attr - 1]) #define IPV4_DEVCONF(cnf, attr) ((cnf).data[IPV4_DEVCONF_ ## attr - 1])
#define IPV4_DEVCONF_RO(cnf, attr) READ_ONCE(IPV4_DEVCONF(cnf, attr))
#define IPV4_DEVCONF_ALL(net, attr) \ #define IPV4_DEVCONF_ALL(net, attr) \
IPV4_DEVCONF((*(net)->ipv4.devconf_all), attr) IPV4_DEVCONF((*(net)->ipv4.devconf_all), attr)
#define IPV4_DEVCONF_ALL_RO(net, attr) READ_ONCE(IPV4_DEVCONF_ALL(net, attr))
static inline int ipv4_devconf_get(struct in_device *in_dev, int index) static inline int ipv4_devconf_get(const struct in_device *in_dev, int index)
{ {
index--; index--;
return in_dev->cnf.data[index]; return READ_ONCE(in_dev->cnf.data[index]);
} }
static inline void ipv4_devconf_set(struct in_device *in_dev, int index, static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
...@@ -67,7 +69,7 @@ static inline void ipv4_devconf_set(struct in_device *in_dev, int index, ...@@ -67,7 +69,7 @@ static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
{ {
index--; index--;
set_bit(index, in_dev->cnf.state); set_bit(index, in_dev->cnf.state);
in_dev->cnf.data[index] = val; WRITE_ONCE(in_dev->cnf.data[index], val);
} }
static inline void ipv4_devconf_setall(struct in_device *in_dev) static inline void ipv4_devconf_setall(struct in_device *in_dev)
...@@ -81,18 +83,18 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) ...@@ -81,18 +83,18 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
ipv4_devconf_set((in_dev), IPV4_DEVCONF_ ## attr, (val)) ipv4_devconf_set((in_dev), IPV4_DEVCONF_ ## attr, (val))
#define IN_DEV_ANDCONF(in_dev, attr) \ #define IN_DEV_ANDCONF(in_dev, attr) \
(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) && \ (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), attr) && \
IN_DEV_CONF_GET((in_dev), attr)) IN_DEV_CONF_GET((in_dev), attr))
#define IN_DEV_NET_ORCONF(in_dev, net, attr) \ #define IN_DEV_NET_ORCONF(in_dev, net, attr) \
(IPV4_DEVCONF_ALL(net, attr) || \ (IPV4_DEVCONF_ALL_RO(net, attr) || \
IN_DEV_CONF_GET((in_dev), attr)) IN_DEV_CONF_GET((in_dev), attr))
#define IN_DEV_ORCONF(in_dev, attr) \ #define IN_DEV_ORCONF(in_dev, attr) \
IN_DEV_NET_ORCONF(in_dev, dev_net(in_dev->dev), attr) IN_DEV_NET_ORCONF(in_dev, dev_net(in_dev->dev), attr)
#define IN_DEV_MAXCONF(in_dev, attr) \ #define IN_DEV_MAXCONF(in_dev, attr) \
(max(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr), \ (max(IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), attr), \
IN_DEV_CONF_GET((in_dev), attr))) IN_DEV_CONF_GET((in_dev), attr)))
#define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING) #define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
......
...@@ -1982,7 +1982,7 @@ static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev, ...@@ -1982,7 +1982,7 @@ static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
return -EMSGSIZE; return -EMSGSIZE;
for (i = 0; i < IPV4_DEVCONF_MAX; i++) for (i = 0; i < IPV4_DEVCONF_MAX; i++)
((u32 *) nla_data(nla))[i] = in_dev->cnf.data[i]; ((u32 *) nla_data(nla))[i] = READ_ONCE(in_dev->cnf.data[i]);
return 0; return 0;
} }
...@@ -2068,9 +2068,9 @@ static int inet_netconf_msgsize_devconf(int type) ...@@ -2068,9 +2068,9 @@ static int inet_netconf_msgsize_devconf(int type)
} }
static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
struct ipv4_devconf *devconf, u32 portid, const struct ipv4_devconf *devconf,
u32 seq, int event, unsigned int flags, u32 portid, u32 seq, int event,
int type) unsigned int flags, int type)
{ {
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct netconfmsg *ncm; struct netconfmsg *ncm;
...@@ -2095,27 +2095,28 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -2095,27 +2095,28 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
if ((all || type == NETCONFA_FORWARDING) && if ((all || type == NETCONFA_FORWARDING) &&
nla_put_s32(skb, NETCONFA_FORWARDING, nla_put_s32(skb, NETCONFA_FORWARDING,
IPV4_DEVCONF(*devconf, FORWARDING)) < 0) IPV4_DEVCONF_RO(*devconf, FORWARDING)) < 0)
goto nla_put_failure; goto nla_put_failure;
if ((all || type == NETCONFA_RP_FILTER) && if ((all || type == NETCONFA_RP_FILTER) &&
nla_put_s32(skb, NETCONFA_RP_FILTER, nla_put_s32(skb, NETCONFA_RP_FILTER,
IPV4_DEVCONF(*devconf, RP_FILTER)) < 0) IPV4_DEVCONF_RO(*devconf, RP_FILTER)) < 0)
goto nla_put_failure; goto nla_put_failure;
if ((all || type == NETCONFA_MC_FORWARDING) && if ((all || type == NETCONFA_MC_FORWARDING) &&
nla_put_s32(skb, NETCONFA_MC_FORWARDING, nla_put_s32(skb, NETCONFA_MC_FORWARDING,
IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) IPV4_DEVCONF_RO(*devconf, MC_FORWARDING)) < 0)
goto nla_put_failure; goto nla_put_failure;
if ((all || type == NETCONFA_BC_FORWARDING) && if ((all || type == NETCONFA_BC_FORWARDING) &&
nla_put_s32(skb, NETCONFA_BC_FORWARDING, nla_put_s32(skb, NETCONFA_BC_FORWARDING,
IPV4_DEVCONF(*devconf, BC_FORWARDING)) < 0) IPV4_DEVCONF_RO(*devconf, BC_FORWARDING)) < 0)
goto nla_put_failure; goto nla_put_failure;
if ((all || type == NETCONFA_PROXY_NEIGH) && if ((all || type == NETCONFA_PROXY_NEIGH) &&
nla_put_s32(skb, NETCONFA_PROXY_NEIGH, nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0) IPV4_DEVCONF_RO(*devconf, PROXY_ARP)) < 0)
goto nla_put_failure; goto nla_put_failure;
if ((all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) && if ((all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0) IPV4_DEVCONF_RO(*devconf,
IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
goto nla_put_failure; goto nla_put_failure;
out: out:
......
...@@ -120,12 +120,12 @@ ...@@ -120,12 +120,12 @@
*/ */
#define IGMP_V1_SEEN(in_dev) \ #define IGMP_V1_SEEN(in_dev) \
(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \ (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
((in_dev)->mr_v1_seen && \ ((in_dev)->mr_v1_seen && \
time_before(jiffies, (in_dev)->mr_v1_seen))) time_before(jiffies, (in_dev)->mr_v1_seen)))
#define IGMP_V2_SEEN(in_dev) \ #define IGMP_V2_SEEN(in_dev) \
(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \ (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
((in_dev)->mr_v2_seen && \ ((in_dev)->mr_v2_seen && \
time_before(jiffies, (in_dev)->mr_v2_seen))) time_before(jiffies, (in_dev)->mr_v2_seen)))
......
...@@ -395,7 +395,7 @@ static int snmp_seq_show_ipstats(struct seq_file *seq, void *v) ...@@ -395,7 +395,7 @@ static int snmp_seq_show_ipstats(struct seq_file *seq, void *v)
seq_printf(seq, " %s", snmp4_ipstats_list[i].name); seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
seq_printf(seq, "\nIp: %d %d", seq_printf(seq, "\nIp: %d %d",
IPV4_DEVCONF_ALL(net, FORWARDING) ? 1 : 2, IPV4_DEVCONF_ALL_RO(net, FORWARDING) ? 1 : 2,
READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); READ_ONCE(net->ipv4.sysctl_ip_default_ttl));
BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0); BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0);
......
...@@ -2313,7 +2313,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -2313,7 +2313,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (IN_DEV_BFORWARD(in_dev)) if (IN_DEV_BFORWARD(in_dev))
goto make_route; goto make_route;
/* not do cache if bc_forwarding is enabled */ /* not do cache if bc_forwarding is enabled */
if (IPV4_DEVCONF_ALL(net, BC_FORWARDING)) if (IPV4_DEVCONF_ALL_RO(net, BC_FORWARDING))
do_cache = false; do_cache = false;
goto brd_input; goto brd_input;
} }
...@@ -2993,7 +2993,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, ...@@ -2993,7 +2993,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
#ifdef CONFIG_IP_MROUTE #ifdef CONFIG_IP_MROUTE
if (ipv4_is_multicast(dst) && if (ipv4_is_multicast(dst) &&
!ipv4_is_local_multicast(dst) && !ipv4_is_local_multicast(dst) &&
IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { IPV4_DEVCONF_ALL_RO(net, MC_FORWARDING)) {
int err = ipmr_get_route(net, skb, int err = ipmr_get_route(net, skb,
fl4->saddr, fl4->daddr, fl4->saddr, fl4->daddr,
r, portid); r, portid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment