Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] wifi: cfg80211: publish PMSR request before starting the driver
@ 2026-07-23  1:09 Zhao Li
  0 siblings, 0 replies; only message in thread
From: Zhao Li @ 2026-07-23  1:09 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, linux-kernel, Zhao Li

nl80211_pmsr_start() assigns the request cookie, calls the driver's
->start_pmsr() callback, and only then adds the request to
wdev->pmsr_list, without holding pmsr_lock for the addition.

mac80211_hwsim saves the request in its start callback and returns. Since
nl80211 uses parallel_ops, an immediate REPORT_PMSR can then run before
nl80211_pmsr_start() reaches its post-start list_add_tail(). hwsim also
dispatches reports from its virtio receive workqueue. Completion removes
the request from wdev->pmsr_list under pmsr_lock and frees it.

Thus completion can precede publication, race the unlocked list mutation,
or free the request before nl80211_pmsr_start() reads req->cookie for the
netlink reply.

Add the request to wdev->pmsr_list under pmsr_lock before calling the
driver, and use a cookie value saved before the call so the request is not
dereferenced after a successful start. On an error return the driver has
not retained or completed the request, so remove it from the list under the
lock and free it.

This ordering also permits a successful driver callback to complete the
request synchronously. Document the resulting start_pmsr lifetime contract.

Fixes: 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM initiator API")
Assisted-by: Codex:gpt-5
Assisted-by: Claude:opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
---
 include/net/cfg80211.h |  6 +++++-
 include/net/mac80211.h |  6 +++++-
 net/wireless/pmsr.c    | 21 +++++++++++++++++----
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f5abf1db7558..a8ba484ecad6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5202,7 +5202,11 @@ struct mgmt_frame_regs {
  *
  * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
  *	Statistics should be cumulative, currently no way to reset is provided.
- * @start_pmsr: start peer measurement (e.g. FTM)
+ * @start_pmsr: start peer measurement (e.g. FTM). The callback may
+ *	complete the request before returning success. After completing it,
+ *	the driver must not access the request. If the callback returns an
+ *	error, the driver must not retain the request or later report results
+ *	or completion for it.
  * @abort_pmsr: abort peer measurement
  *
  * @update_owe_info: Provide updated OWE info to driver. Driver implementing SME
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4f95da023746..64600e7bd251 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4661,7 +4661,11 @@ struct ieee80211_prep_tx_info {
  * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
  *	Statistics should be cumulative, currently no way to reset is provided.
  *
- * @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep)
+ * @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep).
+ *	The callback may complete the request before returning success.
+ *	After completing it, the driver must not access the request. If the
+ *	callback returns an error, the driver must not retain the request or
+ *	later report results or completion for it.
  * @abort_pmsr: abort peer measurement (this call can sleep)
  * @set_tid_config: Apply TID specific configurations. This callback may sleep.
  * @reset_tid_config: Reset TID specific configuration for the peer.
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index d1e2fae5bc0e..3484956ebb50 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -420,6 +420,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
 	const struct cfg80211_pmsr_capabilities *capa;
 	struct cfg80211_pmsr_request *req;
 	struct nlattr *peers, *peer;
+	u64 cookie;
 
 	capa = rdev->wiphy.pmsr_capa;
 
@@ -521,14 +522,26 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
 	}
 	req->cookie = cfg80211_assign_cookie(rdev);
 	req->nl_portid = info->snd_portid;
+	cookie = req->cookie;
+
+	/*
+	 * Publish before the driver can complete the request. Completion may free
+	 * it before rdev_start_pmsr() returns, so use the cookie snapshot below.
+	 */
+	spin_lock_bh(&wdev->pmsr_lock);
+	list_add_tail(&req->list, &wdev->pmsr_list);
+	spin_unlock_bh(&wdev->pmsr_lock);
 
 	err = rdev_start_pmsr(rdev, wdev, req);
-	if (err)
+	if (err) {
+		/* An error return leaves the request owned by this path. */
+		spin_lock_bh(&wdev->pmsr_lock);
+		list_del(&req->list);
+		spin_unlock_bh(&wdev->pmsr_lock);
 		goto out_err;
+	}
 
-	list_add_tail(&req->list, &wdev->pmsr_list);
-
-	nl_set_extack_cookie_u64(info->extack, req->cookie);
+	nl_set_extack_cookie_u64(info->extack, cookie);
 	return 0;
 out_err:
 	kfree(req);
-- 
2.50.1 (Apple Git-155)

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-23  1:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23  1:09 [PATCH] wifi: cfg80211: publish PMSR request before starting the driver Zhao Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox