[RFC PATCH v2 23/23] provisioning-ranging: Add dedicated ranging socket and timeout handling

Peddolla Harshavardhan Reddy peddolla.reddy at oss.qualcomm.com
Thu Apr 2 05:24:28 PDT 2026


Use a dedicated netlink socket for ranging commands and track it in
struct pr_data as ranging_sock. Create the socket when starting
ranging and pass it down to the driver via wpa_drv_start_peer_measurement()
and wpa_drv_register_ranging_eloop().

Add wpas_pr_ranging_socket_timeout() to close the ranging socket,
free PASN ranging parameters, and clean up the PR interface when a
continuous ranging session times out. Ensure this timeout is canceled
on:

- ranging start failures
- successful completion of peer measurement
- PASN success transitioning into ranging
- ROC cancel / PR interface cleanup

On measurement completion and error paths, explicitly destroy the
ranging socket and clear pr_pasn_params, and call wpas_pr_pd_stop()
to stop the PD wdev. Also cancel the PASN timeout once PASN succeeds
to avoid premature PR cleanup while ranging is in progress.

This avoids leaking the ranging socket and prevents use-after-free
issues when the PR interface is removed while a timeout is still
pending.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>
---
 src/common/proximity_ranging.h |  3 ++
 wpa_supplicant/pr_supplicant.c | 99 ++++++++++++++++++++++++++++++++--
 2 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 6f597410f..b845b4213 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -584,6 +584,9 @@ struct pr_data {
 
 	/* PR PASN request tracking - similar to pasn_params in wpa_supplicant */
 	struct pr_pasn_ranging_params *pr_pasn_params;
+
+	/* Dedicated netlink socket for ranging commands */
+	void *ranging_sock;
 };
 
 /* PR Device Identity Resolution Attribute parameters */
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index ab6ef18fc..8c6baa324 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -377,6 +377,36 @@ static void wpas_pr_pasn_result(void *ctx, u8 role, u8 protocol_type,
 }
 
 
+static void wpas_pr_ranging_socket_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct pr_data *pr = wpa_s->global->pr;
+
+	wpa_printf(MSG_DEBUG,
+		   "PR: Ranging session timeout - closing socket and cleaning up");
+
+	/* Close the ranging socket */
+	if (pr && pr->ranging_sock) {
+		wpa_drv_destroy_ranging_handle(wpa_s, &pr->ranging_sock);
+		pr->ranging_sock = NULL;
+		wpa_printf(MSG_DEBUG, "PR: Ranging socket closed by timeout");
+	}
+
+	/* Free ranging params */
+	if (pr && pr->pr_pasn_params) {
+		os_free(pr->pr_pasn_params);
+		pr->pr_pasn_params = NULL;
+	}
+
+	/*
+	 * Clean up the PR interface now that the ranging session has ended.
+	 * This is the normal completion path when a session timeout is
+	 * configured.
+	 */
+	wpas_pr_cleanup_interface(wpa_s->global);
+}
+
+
 /**
  * wpas_pr_trigger_ranging - Trigger ranging measurement after PASN auth
  * @wpa_s: Pointer to wpa_supplicant data
@@ -410,6 +440,16 @@ static int wpas_pr_trigger_ranging(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
+	if (!pr->ranging_sock) {
+		pr->ranging_sock = wpa_drv_create_ranging_handle(wpa_s);
+		if (!pr->ranging_sock) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Failed to create ranging socket");
+			return -1;
+		}
+		wpa_printf(MSG_DEBUG, "PR: Created ranging socket");
+	}
+
 	params = pr->pr_pasn_params;
 
 	wpa_printf(MSG_DEBUG,
@@ -465,17 +505,40 @@ static int wpas_pr_trigger_ranging(struct wpa_supplicant *wpa_s,
 
 	/* Call driver operation to start peer measurement */
 	if (wpa_drv_start_peer_measurement(wpa_s, peer_addr, freq, op_channel,
-					   channel_width, params, NULL) < 0) {
+					   channel_width, params,
+					   pr->ranging_sock) < 0) {
 		wpa_printf(MSG_ERROR, "PR: Failed to start peer measurement");
 		goto fail;
 	}
 
+	/* Register ranging socket with eloop to receive measurement results */
+	wpa_drv_register_ranging_eloop(wpa_s, &pr->ranging_sock);
+
 	wpa_printf(MSG_DEBUG, "PR: Successfully triggered ranging measurement");
 
+	/* Start session timeout timer if continuous ranging session time is set */
+	if (params->continuous_ranging_session_time > 0) {
+		unsigned int timeout_sec = params->continuous_ranging_session_time / 1000;
+		unsigned int timeout_usec = (params->continuous_ranging_session_time % 1000) * 1000;
+
+		wpa_printf(MSG_DEBUG,
+			   "PR: Starting ranging socket timeout timer for %u ms",
+			   params->continuous_ranging_session_time);
+
+		eloop_cancel_timeout(wpas_pr_ranging_socket_timeout, wpa_s, NULL);
+		eloop_register_timeout(timeout_sec, timeout_usec,
+				       wpas_pr_ranging_socket_timeout, wpa_s, NULL);
+	}
+
 	return 0;
 
 fail:
 	/* Clean up on failure */
+	eloop_cancel_timeout(wpas_pr_ranging_socket_timeout, wpa_s, NULL);
+	if (pr->ranging_sock) {
+		wpa_drv_destroy_ranging_handle(wpa_s, &pr->ranging_sock);
+		pr->ranging_sock = NULL;
+	}
 	os_free(pr->pr_pasn_params);
 	pr->pr_pasn_params = NULL;
 	return -1;
@@ -499,9 +562,25 @@ static void wpas_pr_ranging_params(void *ctx, const u8 *dev_addr,
 				      protocol_type, freq, op_channel, bw,
 				      format_bw);
 
+	wpa_printf(MSG_DEBUG, "PR: Attempting to start ranging");
+
+	/*
+	 * PASN succeeded - cancel the PASN timeout so it does not fire and
+	 * prematurely stop the PD wdev while ranging is in progress.
+	 * Cleanup will happen either when the session timeout fires or when
+	 * the final measurement result is received.
+	 */
+	eloop_cancel_timeout(wpas_pr_pasn_timeout, wpa_s, NULL);
+	wpa_printf(MSG_DEBUG,
+		   "PR: PASN succeeded, cancelled PASN timeout before ranging");
+
 	/* Trigger ranging measurement after successful PASN authentication */
-	wpas_pr_trigger_ranging(wpa_s, peer_addr, freq, op_class, op_channel,
-				format_bw, protocol_type);
+	if (wpas_pr_trigger_ranging(wpa_s, peer_addr, freq, op_class, op_channel,
+				    format_bw, protocol_type) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "PR: Failed to trigger ranging, stopping PD wdev");
+		wpas_pr_pd_stop(wpa_s);
+	}
 }
 
 
@@ -733,6 +812,13 @@ void wpas_pr_pd_stop(struct wpa_supplicant *wpa_s)
 	wpa_printf(MSG_DEBUG, "PR: Stopping PD wdev addr=" MACSTR,
 		   MAC2STR(wpa_s->pd_addr));
 
+	eloop_cancel_timeout(wpas_pr_ranging_socket_timeout, wpa_s, NULL);
+	if (pr && pr->ranging_sock) {
+		wpa_drv_destroy_ranging_handle(wpa_s, &pr->ranging_sock);
+		pr->ranging_sock = NULL;
+		wpa_printf(MSG_DEBUG, "PR: Ranging socket closed");
+	}
+
 	if (pr && pr->pr_pasn_params) {
 		os_free(pr->pr_pasn_params);
 		pr->pr_pasn_params = NULL;
@@ -806,10 +892,17 @@ void wpas_pr_measurement_result(struct wpa_supplicant *wpa_s,
 		wpa_msg(wpa_s, MSG_INFO, PR_EVENT_PEER_MEASUREMENT_COMPLETE
 			"addr=" MACSTR " status=%u",
 			MAC2STR(result->addr), result->status);
+		eloop_cancel_timeout(wpas_pr_ranging_socket_timeout, wpa_s,
+				     NULL);
 		if (pr) {
+			if (pr->ranging_sock) {
+				wpa_drv_destroy_ranging_handle(wpa_s, &pr->ranging_sock);
+				pr->ranging_sock = NULL;
+			}
 			os_free(pr->pr_pasn_params);
 			pr->pr_pasn_params = NULL;
 		}
+		wpas_pr_pd_stop(wpa_s);
 		return;
 	}
 
-- 
2.34.1




More information about the Hostap mailing list