All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC batadv] batman-adv: bla: fix report_work leak on backbone_gw purge
@ 2026-05-10 10:03 Sven Eckelmann
  2026-05-12 12:09 ` Simon Wunderlich
  0 siblings, 1 reply; 2+ messages in thread
From: Sven Eckelmann @ 2026-05-10 10:03 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: sw, Sven Eckelmann

batadv_bla_purge_backbone_gw() removes stale backbone gateway entries,
but fails to properly handle their associated report_work:

- If report_work is running, the purge must wait for it to finish before
  freeing the backbone_gw, otherwise the worker may access freed memory
  (e.g. bat_priv).
- If report_work is pending, the purge must cancel it and release the
  reference held for that pending work item.

The previous implementation called hlist_for_each_entry_safe() inside a
spin_lock_bh() section, but cancel_work_sync() may sleep and therefore
cannot be called from within a spinlock-protected region.

Restructure the loop to handle one entry per spinlock critical section:
acquire the lock, find the next entry to purge, remove it from the hash
list, then release the lock before calling cancel_work_sync() and
dropping the hash_entry reference. Repeat until no more entries require
purging.

Fixes: a998bf5dfbd7 ("batman-adv: add detection for complex bridge loops")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
See
https://sashiko.dev/#/patchset/20260508154314.12817-1-sw@simonwunderlich.de?part=7
---
 net/batman-adv/bridge_loop_avoidance.c | 53 ++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index cec11f12..ff2097eb 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1224,6 +1224,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 	struct hlist_head *head;
 	struct batadv_hashtable *hash;
 	spinlock_t *list_lock;	/* protects write access to the hash lists */
+	bool purged;
 	int i;
 
 	hash = bat_priv->bla.backbone_hash;
@@ -1234,30 +1235,44 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 		head = &hash->table[i];
 		list_lock = &hash->list_locks[i];
 
-		spin_lock_bh(list_lock);
-		hlist_for_each_entry_safe(backbone_gw, node_tmp,
-					  head, hash_entry) {
-			if (now)
-				goto purge_now;
-			if (!batadv_has_timed_out(backbone_gw->lasttime,
-						  BATADV_BLA_BACKBONE_TIMEOUT))
-				continue;
+		do {
+			purged = false;
 
-			batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
-				   "%s(): backbone gw %pM timed out\n",
-				   __func__, backbone_gw->orig);
+			spin_lock_bh(list_lock);
+			hlist_for_each_entry_safe(backbone_gw, node_tmp,
+						  head, hash_entry) {
+				if (now)
+					goto purge_now;
+				if (!batadv_has_timed_out(backbone_gw->lasttime,
+							  BATADV_BLA_BACKBONE_TIMEOUT))
+					continue;
+
+				batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
+					   "%s(): backbone gw %pM timed out\n",
+					   __func__, backbone_gw->orig);
 
 purge_now:
-			/* don't wait for the pending request anymore */
-			if (atomic_read(&backbone_gw->request_sent))
-				atomic_dec(&bat_priv->bla.num_requests);
+				purged = true;
+				/* don't wait for the pending request anymore */
+				if (atomic_read(&backbone_gw->request_sent))
+					atomic_dec(&bat_priv->bla.num_requests);
 
-			batadv_bla_del_backbone_claims(backbone_gw);
+				batadv_bla_del_backbone_claims(backbone_gw);
 
-			hlist_del_rcu(&backbone_gw->hash_entry);
-			batadv_backbone_gw_put(backbone_gw);
-		}
-		spin_unlock_bh(list_lock);
+				hlist_del_rcu(&backbone_gw->hash_entry);
+				break;
+			}
+			spin_unlock_bh(list_lock);
+
+			if (purged) {
+				/* reference for pending report_work */
+				if (cancel_work_sync(&backbone_gw->report_work))
+					batadv_backbone_gw_put(backbone_gw);
+
+				/* reference for hash_entry */
+				batadv_backbone_gw_put(backbone_gw);
+			}
+		} while (purged);
 	}
 }
 

---
base-commit: 05abe1217c5104b3514ef1945dacf511b012b921
change-id: 20260510-bla-cancel-work-8dc6f3c2cb14

Best regards,
--  
Sven Eckelmann <sven@narfation.org>


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH RFC batadv] batman-adv: bla: fix report_work leak on backbone_gw purge
  2026-05-10 10:03 [PATCH RFC batadv] batman-adv: bla: fix report_work leak on backbone_gw purge Sven Eckelmann
@ 2026-05-12 12:09 ` Simon Wunderlich
  0 siblings, 0 replies; 2+ messages in thread
From: Simon Wunderlich @ 2026-05-12 12:09 UTC (permalink / raw)
  To: b.a.t.m.a.n, Sven Eckelmann

On Sunday, May 10, 2026 12:03:42 PM Central European Summer Time Sven 
Eckelmann wrote:
> batadv_bla_purge_backbone_gw() removes stale backbone gateway entries,
> but fails to properly handle their associated report_work:
> 
> - If report_work is running, the purge must wait for it to finish before
>   freeing the backbone_gw, otherwise the worker may access freed memory
>   (e.g. bat_priv).
> - If report_work is pending, the purge must cancel it and release the
>   reference held for that pending work item.
> 
> The previous implementation called hlist_for_each_entry_safe() inside a
> spin_lock_bh() section, but cancel_work_sync() may sleep and therefore
> cannot be called from within a spinlock-protected region.
> 
> Restructure the loop to handle one entry per spinlock critical section:
> acquire the lock, find the next entry to purge, remove it from the hash
> list, then release the lock before calling cancel_work_sync() and
> dropping the hash_entry reference. Repeat until no more entries require
> purging.
> 
> Fixes: a998bf5dfbd7 ("batman-adv: add detection for complex bridge loops")
> Signed-off-by: Sven Eckelmann <sven@narfation.org>

This looks good, thank you!

Reviewed-by: Simon Wunderlich <sw@simonwunderlich.de>

Cheers,
       Simon



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-05-12 12:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-10 10:03 [PATCH RFC batadv] batman-adv: bla: fix report_work leak on backbone_gw purge Sven Eckelmann
2026-05-12 12:09 ` Simon Wunderlich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.