]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
inet: annotate data-races around ifa->ifa_preferred_lft
authorEric Dumazet <edumazet@google.com>
Thu, 29 Feb 2024 11:40:13 +0000 (11:40 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Mar 2024 11:09:39 +0000 (11:09 +0000)
ifa->ifa_preferred_lft 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>
net/ipv4/devinet.c

index 99f3e7c57d36ff028edadd4efd66d996ddc5d9b4..368fb56e1f1b2e3b7888f611a3f113f3bd5fc2af 100644 (file)
@@ -714,11 +714,13 @@ static void check_lifetime(struct work_struct *work)
                rcu_read_lock();
                hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {
                        unsigned long age, tstamp;
+                       u32 preferred_lft;
                        u32 valid_lft;
 
                        if (ifa->ifa_flags & IFA_F_PERMANENT)
                                continue;
 
+                       preferred_lft = READ_ONCE(ifa->ifa_preferred_lft);
                        valid_lft = READ_ONCE(ifa->ifa_valid_lft);
                        tstamp = READ_ONCE(ifa->ifa_tstamp);
                        /* We try to batch several events at once. */
@@ -728,20 +730,18 @@ static void check_lifetime(struct work_struct *work)
                        if (valid_lft != INFINITY_LIFE_TIME &&
                            age >= valid_lft) {
                                change_needed = true;
-                       } else if (ifa->ifa_preferred_lft ==
+                       } else if (preferred_lft ==
                                   INFINITY_LIFE_TIME) {
                                continue;
-                       } else if (age >= ifa->ifa_preferred_lft) {
+                       } else if (age >= preferred_lft) {
                                if (time_before(tstamp + valid_lft * HZ, next))
                                        next = tstamp + valid_lft * HZ;
 
                                if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
                                        change_needed = true;
-                       } else if (time_before(tstamp +
-                                              ifa->ifa_preferred_lft * HZ,
+                       } else if (time_before(tstamp + preferred_lft * HZ,
                                               next)) {
-                               next = tstamp +
-                                      ifa->ifa_preferred_lft * HZ;
+                               next = tstamp + preferred_lft * HZ;
                        }
                }
                rcu_read_unlock();
@@ -818,7 +818,7 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
        if (addrconf_finite_timeout(timeout)) {
                if (timeout == 0)
                        ifa->ifa_flags |= IFA_F_DEPRECATED;
-               ifa->ifa_preferred_lft = timeout;
+               WRITE_ONCE(ifa->ifa_preferred_lft, timeout);
        }
        WRITE_ONCE(ifa->ifa_tstamp, jiffies);
        if (!ifa->ifa_cstamp)
@@ -1698,7 +1698,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 
        tstamp = READ_ONCE(ifa->ifa_tstamp);
        if (!(ifm->ifa_flags & IFA_F_PERMANENT)) {
-               preferred = ifa->ifa_preferred_lft;
+               preferred = READ_ONCE(ifa->ifa_preferred_lft);
                valid = READ_ONCE(ifa->ifa_valid_lft);
                if (preferred != INFINITY_LIFE_TIME) {
                        long tval = (jiffies - tstamp) / HZ;