batman-adv: bla: only purge non-released claims

When batadv_bla_purge_claims() goes through the list of claims, it is only
traversing the hash list with an rcu_read_lock(). Due to a potential
parallel batadv_claim_put(), it can happen that it encounters a claim which
was actually in the process of being released+freed by
batadv_claim_release(). In this case, backbone_gw is set to NULL before the
delayed RCU kfree is started. Calling batadv_bla_claim_get_backbone_gw() is
then no longer allowed because it would cause a NULL-ptr derefence.

To avoid this, only claims with a valid reference counter must be purged.
All others are already taken care of.

Cc: stable@kernel.org
Fixes: 23721387c4 ("batman-adv: add basic bridge loop avoidance code")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
master
Sven Eckelmann 2026-05-06 22:20:51 +02:00
parent 4ae1709a31
commit cf6b604011
No known key found for this signature in database
GPG Key ID: 4D0F772BD314F5CB
1 changed files with 8 additions and 0 deletions

View File

@ -1288,6 +1288,13 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
rcu_read_lock();
hlist_for_each_entry_rcu(claim, head, hash_entry) {
/* only purge claims not currently in the process of being released.
* Such claims could otherwise have a NULL-ptr backbone_gw set because
* they already went through batadv_claim_release()
*/
if (!kref_get_unless_zero(&claim->refcount))
continue;
backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
if (now)
goto purge_now;
@ -1313,6 +1320,7 @@ purge_now:
claim->addr, claim->vid);
skip:
batadv_backbone_gw_put(backbone_gw);
batadv_claim_put(claim);
}
rcu_read_unlock();
}