Skip to content

Commit 3ddc223

Browse files
edumazetdavem330
authored andcommitted
inet: annotate data-races around ifa->ifa_flags
ifa->ifa_flags can be read locklessly. Add appropriate READ_ONCE()/WRITE_ONCE() annotations. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9f6fa3c commit 3ddc223

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

net/ipv4/devinet.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,10 @@ static void check_lifetime(struct work_struct *work)
716716
unsigned long age, tstamp;
717717
u32 preferred_lft;
718718
u32 valid_lft;
719+
u32 flags;
719720

720-
if (ifa->ifa_flags & IFA_F_PERMANENT)
721+
flags = READ_ONCE(ifa->ifa_flags);
722+
if (flags & IFA_F_PERMANENT)
721723
continue;
722724

723725
preferred_lft = READ_ONCE(ifa->ifa_preferred_lft);
@@ -737,7 +739,7 @@ static void check_lifetime(struct work_struct *work)
737739
if (time_before(tstamp + valid_lft * HZ, next))
738740
next = tstamp + valid_lft * HZ;
739741

740-
if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
742+
if (!(flags & IFA_F_DEPRECATED))
741743
change_needed = true;
742744
} else if (time_before(tstamp + preferred_lft * HZ,
743745
next)) {
@@ -805,21 +807,23 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
805807
__u32 prefered_lft)
806808
{
807809
unsigned long timeout;
810+
u32 flags;
808811

809-
ifa->ifa_flags &= ~(IFA_F_PERMANENT | IFA_F_DEPRECATED);
812+
flags = ifa->ifa_flags & ~(IFA_F_PERMANENT | IFA_F_DEPRECATED);
810813

811814
timeout = addrconf_timeout_fixup(valid_lft, HZ);
812815
if (addrconf_finite_timeout(timeout))
813816
WRITE_ONCE(ifa->ifa_valid_lft, timeout);
814817
else
815-
ifa->ifa_flags |= IFA_F_PERMANENT;
818+
flags |= IFA_F_PERMANENT;
816819

817820
timeout = addrconf_timeout_fixup(prefered_lft, HZ);
818821
if (addrconf_finite_timeout(timeout)) {
819822
if (timeout == 0)
820-
ifa->ifa_flags |= IFA_F_DEPRECATED;
823+
flags |= IFA_F_DEPRECATED;
821824
WRITE_ONCE(ifa->ifa_preferred_lft, timeout);
822825
}
826+
WRITE_ONCE(ifa->ifa_flags, flags);
823827
WRITE_ONCE(ifa->ifa_tstamp, jiffies);
824828
if (!ifa->ifa_cstamp)
825829
WRITE_ONCE(ifa->ifa_cstamp, ifa->ifa_tstamp);
@@ -1313,7 +1317,7 @@ static __be32 in_dev_select_addr(const struct in_device *in_dev,
13131317
const struct in_ifaddr *ifa;
13141318

13151319
in_dev_for_each_ifa_rcu(ifa, in_dev) {
1316-
if (ifa->ifa_flags & IFA_F_SECONDARY)
1320+
if (READ_ONCE(ifa->ifa_flags) & IFA_F_SECONDARY)
13171321
continue;
13181322
if (ifa->ifa_scope != RT_SCOPE_LINK &&
13191323
ifa->ifa_scope <= scope)
@@ -1341,7 +1345,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
13411345
localnet_scope = RT_SCOPE_LINK;
13421346

13431347
in_dev_for_each_ifa_rcu(ifa, in_dev) {
1344-
if (ifa->ifa_flags & IFA_F_SECONDARY)
1348+
if (READ_ONCE(ifa->ifa_flags) & IFA_F_SECONDARY)
13451349
continue;
13461350
if (min(ifa->ifa_scope, localnet_scope) > scope)
13471351
continue;
@@ -1688,7 +1692,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
16881692
ifm = nlmsg_data(nlh);
16891693
ifm->ifa_family = AF_INET;
16901694
ifm->ifa_prefixlen = ifa->ifa_prefixlen;
1691-
ifm->ifa_flags = ifa->ifa_flags;
1695+
ifm->ifa_flags = READ_ONCE(ifa->ifa_flags);
16921696
ifm->ifa_scope = ifa->ifa_scope;
16931697
ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
16941698

@@ -1728,7 +1732,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
17281732
nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
17291733
(ifa->ifa_proto &&
17301734
nla_put_u8(skb, IFA_PROTO, ifa->ifa_proto)) ||
1731-
nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
1735+
nla_put_u32(skb, IFA_FLAGS, ifm->ifa_flags) ||
17321736
(ifa->ifa_rt_priority &&
17331737
nla_put_u32(skb, IFA_RT_PRIORITY, ifa->ifa_rt_priority)) ||
17341738
put_cacheinfo(skb, READ_ONCE(ifa->ifa_cstamp), tstamp,

0 commit comments

Comments
 (0)