Index | Thread | Search

From:
Peter Hessler <phessler@theapt.org>
Subject:
Re: qwx wpa handshake race
To:
tech@openbsd.org
Date:
Mon, 24 Nov 2025 07:58:53 +0100

Download raw body.

Thread
On 2025 Nov 19 (Wed) at 12:00:20 +0100 (+0100), Stefan Sperling wrote:
:Improve chances of qwx receiving the initial WPA handshake message.
:
:Run some qwx firmware commands earlier during the association sequence.
:We need to wait for these commands to complete, and timing is much less
:critical before we have sent our association request. Once we have sent
:this request, the AP may try to send the first WPA handshake message
:immediately after sending the association response frame. And we could miss
:the first WPA message while still setting up firmware state for association.
:In the case I observed, losing this race would result in a loop of failed
:attempts to join the network.
:
:ok?
:

OK


:M  sys/dev/ic/qwx.c  |  32+  12-
:
:1 file changed, 32 insertions(+), 12 deletions(-)
:
:commit - fac7d93c02bbab40f1f2e9b9118ae92fcaad733d
:commit + e22c289135c2e5adcf38aacb10e888e3d7ba7562
:blob - ad3588d5c0f88b8de4171f7617551bfc058e6a36
:blob + dac4cfd24dabbbce8ff50e7596797c687257cd77
:--- sys/dev/ic/qwx.c
:+++ sys/dev/ic/qwx.c
:@@ -178,6 +178,7 @@ int qwx_scan(struct qwx_softc *, int);
: void qwx_scan_abort(struct qwx_softc *);
: int qwx_auth(struct qwx_softc *);
: int qwx_deauth(struct qwx_softc *);
:+int qwx_assoc(struct qwx_softc *);
: int qwx_run(struct qwx_softc *);
: int qwx_run_stop(struct qwx_softc *);
: 
:@@ -1148,6 +1149,7 @@ next_scan:
: 		break;
: 
: 	case IEEE80211_S_ASSOC:
:+		err = qwx_assoc(sc);
: 		break;
: 
: 	case IEEE80211_S_RUN:
:@@ -26057,15 +26059,6 @@ qwx_deauth(struct qwx_softc *sc)
: 		return ret;
: 	}
: 
:-
:-	ret = qwx_wmi_set_peer_param(sc, peer->addr, arvif->vdev_id,
:-	    pdev_id, WMI_PEER_AUTHORIZE, 0);
:-	if (ret) {
:-		printf("%s: unable to deauthorize BSS peer: %d\n",
:-		   sc->sc_dev.dv_xname, ret);
:-		return ret;
:-	}
:-
: 	qwx_clear_pn_replay_config(sc, peer);
: 	qwx_clear_hwkeys(sc, peer);
: 
:@@ -26472,7 +26465,7 @@ qwx_setup_peer_smps(struct qwx_softc *sc, uint8_t pdev
: }
: 
: int
:-qwx_run(struct qwx_softc *sc)
:+qwx_assoc(struct qwx_softc *sc)
: {
: 	struct ieee80211com *ic = &sc->sc_ic;
: 	struct ieee80211_node *ni = ic->ic_bss;
:@@ -26535,6 +26528,25 @@ qwx_run(struct qwx_softc *sc)
: 	IEEE80211_ADDR_COPY(arvif->bssid, ni->ni_bssid);
: 	sc->bss_peer_id = nq->peer_id;
: 
:+	/*
:+	 * Enable reception of data frames now, if not already enabled.
:+	 * We may need to receive EAPOL data frames very soon after the
:+	 * AP sends a response to our assoc request.
:+	 */
:+	sc->ops.irq_enable(sc);
:+
:+	return 0;
:+}
:+
:+int
:+qwx_run(struct qwx_softc *sc)
:+{
:+	struct ieee80211com *ic = &sc->sc_ic;
:+	struct ieee80211_node *ni = ic->ic_bss;
:+	struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
:+	uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
:+	int ret;
:+
: 	ret = qwx_wmi_vdev_up(sc, arvif->vdev_id, pdev_id, arvif->aid,
: 	    arvif->bssid, NULL, 0, 0);
: 	if (ret) {
:@@ -26559,7 +26571,6 @@ qwx_run(struct qwx_softc *sc)
: 		return ret;
: 	}
: 
:-	sc->ops.irq_enable(sc);
: 	return 0;
: }
: 
:@@ -26569,11 +26580,20 @@ qwx_run_stop(struct qwx_softc *sc)
: 	struct ieee80211com *ic = &sc->sc_ic;
: 	struct qwx_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
: 	uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
:-	struct qwx_node *nq = (void *)ic->ic_bss;
:+	struct ieee80211_node *ni = ic->ic_bss;
:+	struct qwx_node *nq = (void *)ni;
: 	int ret;
: 
: 	sc->ops.irq_disable(sc);
: 
:+	ret = qwx_wmi_set_peer_param(sc, ni->ni_macaddr, arvif->vdev_id,
:+	    pdev_id, WMI_PEER_AUTHORIZE, 0);
:+	if (ret) {
:+		printf("%s: unable to deauthorize BSS peer: %d\n",
:+		   sc->sc_dev.dv_xname, ret);
:+		return ret;
:+	}
:+
: 	if (ic->ic_opmode == IEEE80211_M_STA) {
: 		ic->ic_bss->ni_txrate = 0;
: 		nq->flags = 0;
:

-- 
In Corning, Iowa, it's a misdemeanor for a man to ask his wife to ride
in any motor vehicle.