The lasttime field for claim, backbone_gw, and loopdetect tracks the
jiffies value of the most recent activity and is used to detect timeouts.
These accesses are not consistently protected by a lock, so
READ_ONCE/WRITE_ONCE must be used to prevent data races caused by compiler
optimizations.

Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code")
Signed-off-by: Sven Eckelmann <[email protected]>
---
 net/batman-adv/bridge_loop_avoidance.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c 
b/net/batman-adv/bridge_loop_avoidance.c
index ffe85401..7f643de4 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -512,7 +512,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, 
const u8 *orig,
                return NULL;
 
        entry->vid = vid;
-       entry->lasttime = jiffies;
+       WRITE_ONCE(entry->lasttime, jiffies);
        entry->crc = BATADV_BLA_CRC_INIT;
        entry->bat_priv = bat_priv;
        spin_lock_init(&entry->crc_lock);
@@ -580,7 +580,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv 
*bat_priv,
        if (unlikely(!backbone_gw))
                return;
 
-       backbone_gw->lasttime = jiffies;
+       WRITE_ONCE(backbone_gw->lasttime, jiffies);
        batadv_backbone_gw_put(backbone_gw);
 }
 
@@ -714,7 +714,7 @@ static void batadv_bla_add_claim(struct batadv_priv 
*bat_priv,
                ether_addr_copy(claim->addr, mac);
                spin_lock_init(&claim->backbone_lock);
                claim->vid = vid;
-               claim->lasttime = jiffies;
+               WRITE_ONCE(claim->lasttime, jiffies);
                kref_get(&backbone_gw->refcount);
                claim->backbone_gw = backbone_gw;
                kref_init(&claim->refcount);
@@ -736,7 +736,7 @@ static void batadv_bla_add_claim(struct batadv_priv 
*bat_priv,
                        return;
                }
        } else {
-               claim->lasttime = jiffies;
+               WRITE_ONCE(claim->lasttime, jiffies);
                if (claim->backbone_gw == backbone_gw)
                        /* no need to register a new backbone */
                        goto claim_free_ref;
@@ -769,7 +769,7 @@ static void batadv_bla_add_claim(struct batadv_priv 
*bat_priv,
        spin_lock_bh(&backbone_gw->crc_lock);
        backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
        spin_unlock_bh(&backbone_gw->crc_lock);
-       backbone_gw->lasttime = jiffies;
+       WRITE_ONCE(backbone_gw->lasttime, jiffies);
 
 claim_free_ref:
        batadv_claim_put(claim);
@@ -858,7 +858,7 @@ static bool batadv_handle_announce(struct batadv_priv 
*bat_priv, u8 *an_addr,
                return true;
 
        /* handle as ANNOUNCE frame */
-       backbone_gw->lasttime = jiffies;
+       WRITE_ONCE(backbone_gw->lasttime, jiffies);
        crc = ntohs(*((__force __be16 *)(&an_addr[4])));
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
@@ -1253,7 +1253,7 @@ static void batadv_bla_purge_backbone_gw(struct 
batadv_priv *bat_priv, int now)
                                                  head, hash_entry) {
                                if (now)
                                        goto purge_now;
-                               if (!batadv_has_timed_out(backbone_gw->lasttime,
+                               if 
(!batadv_has_timed_out(READ_ONCE(backbone_gw->lasttime),
                                                          
BATADV_BLA_BACKBONE_TIMEOUT))
                                        continue;
 
@@ -1334,7 +1334,7 @@ static void batadv_bla_purge_claims(struct batadv_priv 
*bat_priv,
                                                primary_if->net_dev->dev_addr))
                                goto skip;
 
-                       if (!batadv_has_timed_out(claim->lasttime,
+                       if (!batadv_has_timed_out(READ_ONCE(claim->lasttime),
                                                  BATADV_BLA_CLAIM_TIMEOUT))
                                goto skip;
 
@@ -1494,7 +1494,7 @@ static void batadv_bla_periodic_work(struct work_struct 
*work)
                eth_random_addr(bat_priv->bla.loopdetect_addr);
                bat_priv->bla.loopdetect_addr[0] = 0xba;
                bat_priv->bla.loopdetect_addr[1] = 0xbe;
-               bat_priv->bla.loopdetect_lasttime = jiffies;
+               WRITE_ONCE(bat_priv->bla.loopdetect_lasttime, jiffies);
                atomic_set(&bat_priv->bla.loopdetect_next,
                           BATADV_BLA_LOOPDETECT_PERIODS);
 
@@ -1515,7 +1515,7 @@ static void batadv_bla_periodic_work(struct work_struct 
*work)
                                                primary_if->net_dev->dev_addr))
                                continue;
 
-                       backbone_gw->lasttime = jiffies;
+                       WRITE_ONCE(backbone_gw->lasttime, jiffies);
 
                        batadv_bla_send_announce(bat_priv, backbone_gw);
                        if (send_loopdetect)
@@ -1899,7 +1899,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, 
struct sk_buff *skb,
        /* If the packet came too late, don't forward it on the mesh
         * but don't consider that as loop. It might be a coincidence.
         */
-       if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
+       if (batadv_has_timed_out(READ_ONCE(bat_priv->bla.loopdetect_lasttime),
                                 BATADV_BLA_LOOPDETECT_TIMEOUT))
                return true;
 
@@ -2014,7 +2014,7 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct 
sk_buff *skb,
 
        if (own_claim) {
                /* ... allow it in any case */
-               claim->lasttime = jiffies;
+               WRITE_ONCE(claim->lasttime, jiffies);
                goto allow;
        }
 
@@ -2116,7 +2116,7 @@ bool batadv_bla_tx(struct batadv_priv *bat_priv, struct 
sk_buff *skb,
                /* if yes, the client has roamed and we have
                 * to unclaim it.
                 */
-               if (batadv_has_timed_out(claim->lasttime, 100)) {
+               if (batadv_has_timed_out(READ_ONCE(claim->lasttime), 100)) {
                        /* only unclaim if the last claim entry is
                         * older than 100 ms to make sure we really
                         * have a roaming client here.
@@ -2361,7 +2361,7 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 
portid,
        backbone_crc = backbone_gw->crc;
        spin_unlock_bh(&backbone_gw->crc_lock);
 
-       msecs = jiffies_to_msecs(jiffies - backbone_gw->lasttime);
+       msecs = jiffies_to_msecs(jiffies - READ_ONCE(backbone_gw->lasttime));
 
        if (is_own)
                if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {

---
base-commit: ec9f686b42917e9b67725d7245b50de72f59fa9e
change-id: 20260526-lasttime-once-6a32cea79eb2

Best regards,
--  
Sven Eckelmann <[email protected]>

Reply via email to