[PATCH 2/3] netdev: reject reassociation while connect pending

Suchir Kavi <[email protected]> Wed, 15 Jul 2026 19:34:43 -0700
Newsgroups dev.linux.lists.iwd
Message-ID <[email protected]>
netdev_reassociate() replaces netdev->handshake and unrefs the old
handshake without freeing netdev->ap or dequeuing a pending connection
work item. If a reassociation begins while an earlier attempt's radio
work is still queued (reachable since station_cannot_roam() does not
cover the connecting states), the stale auth proto keeps a raw pointer
to the freed handshake. On the PMKSA-cache path netdev_connect_common()
does not replace netdev->ap, and it re-inserts the already-queued
embedded work item; when the work finally runs,
netdev_begin_connection() starts the stale auth proto and sae_start()
dereferences the freed handshake:

  #0  sae_choose_next_group   <- reads handshake->ecc_sae_pts == NULL
  #1  sae_start
  #2  netdev_begin_connection
  #3  netdev_connection_work_ready
  #4  wiphy_radio_work_next
  #5  get_scan_done

Mirror netdev_connect(), which already refuses to start while
netdev->connect_cmd_id or netdev->work.id is set. Both are zero at any
legitimate roam start since netdev_connect_ok() completes the work item,
and the station roam paths handle a negative return by failing the roam
cleanly.

Assisted-by: Claude:claude-fable-5
---
 src/netdev.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/netdev.c b/src/netdev.c
index e639a1f8..dadd90da 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4394,6 +4394,9 @@ int netdev_reassociate(struct netdev *netdev, const struct scan_bss *target_bss,
 	struct handshake_state *old_hs;
 	struct eapol_sm *old_sm;
 
+	if (netdev->connect_cmd_id || netdev->work.id)
+		return -EBUSY;
+
 	old_sm = netdev->sm;
 	old_hs = netdev->handshake;
 
-- 
2.54.0