batman-adv: bla: annotate lasttime access with READ/WRITE_ONCE

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.

Cc: stable@kernel.org
Fixes: 23721387c4 ("batman-adv: add basic bridge loop avoidance code")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
This commit is contained in:
Sven Eckelmann 2026-05-26 21:50:51 +02:00
parent 4f117f5626
commit 98b0fb191c
No known key found for this signature in database
GPG Key ID: 4D0F772BD314F5CB

View File

@ -513,7 +513,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);
@ -581,7 +581,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);
}
@ -715,7 +715,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);
@ -737,7 +737,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;
@ -770,7 +770,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);
@ -859,7 +859,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,
@ -1254,7 +1254,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;
@ -1335,7 +1335,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;
@ -1495,7 +1495,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);
@ -1516,7 +1516,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)
@ -1900,7 +1900,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;
@ -2015,7 +2015,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;
}
@ -2117,7 +2117,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.
@ -2362,7 +2362,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)) {