Hi Stefan,
I'm not yet ready to test new diffs, but I was going through old
wireless stack related emails and was wondering did below patch got
committed? Per my git / cvs search I don't think so. Is below diff
still relevant or can below change be ignored?
On Thu, Jul 01, 2021 at 12:23:33PM +0200, Stefan Sperling wrote:
> Some wifi drivers defer installation of keys into a process context.
> There was a noticable race in the past which was fixed thanks to krw@
> where link state was set to UP before key installation had completed in
> hardware. This race could result in dhclient failing to get a lease.
>
> Other races remain. These concern state which controls encryption of
> frames in the output path of net80211 (TXRXPROT flag), and marks the
> pairwise key as installed (PTKDONE state) which in turn affects our
> acceptance of group key updates sent by the AP. While either of these
> flags is set and hardware is not configured for encryption we are running
> in an inconsistent state. I don't know if this causes problems in practice
> but we should be avoiding such races. The fix is fairly mechanical and
> essentially defers modification of relevant flags from net80211 into the
> affected drivers.
>
> Affected drivers are: iwx, bfwm, athn (USB only!), urtwn, run, rsu, otus.
> I have tested on iwx, athn, urtwn, and run. More tests are welcome.
>
> ok?
>
> diff 86b3b873864f7e98e688c12d8e455803ff30eadb
> 27f93922f2b250b31e9534b457665df3dcf58794
> blob - ea245574f624ada1b8d0c9e8e8a0653fb2c3adc4
> blob + 0bac2cda2290c4a44de8f5b8110a4399f75de88d
> --- sys/dev/ic/bwfm.c
> +++ sys/dev/ic/bwfm.c
> @@ -2714,7 +2714,13 @@ bwfm_set_key_cb(struct bwfm_softc *sc, void *arg)
> wsec |= wsec_enable;
> bwfm_fwvar_var_set_int(sc, "wsec", wsec);
>
> + if ((k->k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> +
> if (sc->sc_key_tasks == 0) {
> + if (k->k_flags & IEEE80211_KEY_SECURE)
> + ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("%s: marking port %s valid\n", DEVNAME(sc),
> ether_sprintf(cmd->ni->ni_macaddr)));
> cmd->ni->ni_port_valid = 1;
> blob - bdf8ce3e1afa332f698e3dc56af77e6acb4f8689
> blob + 5be1d92ee862f584df5901fe54ebe30e0c937d36
> --- sys/dev/pci/if_iwx.c
> +++ sys/dev/pci/if_iwx.c
> @@ -6747,12 +6747,17 @@ iwx_add_sta_key(struct iwx_softc *sc, int sta_id, stru
> return err;
> }
>
> - if (k->k_flags & IEEE80211_KEY_GROUP)
> + if (k->k_flags & IEEE80211_KEY_GROUP) {
> in->in_flags |= IWX_NODE_FLAG_HAVE_GROUP_KEY;
> - else
> + } else {
> in->in_flags |= IWX_NODE_FLAG_HAVE_PAIRWISE_KEY;
> + if (ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> + }
>
> if ((in->in_flags & want_keymask) == want_keymask) {
> + if (k->k_flags & IEEE80211_KEY_SECURE)
> + ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("marking port %s valid\n",
> ether_sprintf(ni->ni_macaddr)));
> ni->ni_port_valid = 1;
> blob - 08ffda8c9aaede9c901d97a43bf2873591e8df19
> blob + 0c141fc5df7ba1a774af98a59a2b718bdcc721bb
> --- sys/dev/usb/if_athn_usb.c
> +++ sys/dev/usb/if_athn_usb.c
> @@ -1662,7 +1662,12 @@ athn_usb_set_key_cb(struct athn_usb_softc *usc, void *
> s = splnet();
> athn_usb_write_barrier(&usc->sc_sc);
> athn_set_key(ic, cmd->ni, cmd->key);
> + if ((cmd->key->k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + cmd->ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + cmd->ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> if (usc->sc_key_tasks == 0) {
> + if (cmd->key->k_flags & IEEE80211_KEY_SECURE)
> + cmd->ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("marking port %s valid\n",
> ether_sprintf(cmd->ni->ni_macaddr)));
> cmd->ni->ni_port_valid = 1;
> blob - bb220831ffc852347afdcda18c9bca0589d6d939
> blob + 8e426e9cab0b389f2e1260139ad451b30e10287e
> --- sys/dev/usb/if_otus.c
> +++ sys/dev/usb/if_otus.c
> @@ -2116,7 +2116,12 @@ otus_set_key_cb(struct otus_softc *sc, void *arg)
> memcpy(key.key, k->k_key + 16, 16);
> (void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof key, NULL);
>
> + if ((k->k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + cmd->ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + cmd->ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> if (sc->sc_key_tasks == 0) {
> + if (k->k_flags & IEEE80211_KEY_SECURE)
> + cmd->ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("marking port %s valid\n",
> ether_sprintf(cmd->ni->ni_macaddr)));
> cmd->ni->ni_port_valid = 1;
> blob - 929d8f161d50cd294569dd74e0a4e2980e5607ca
> blob + 5e30f1b680b1b58c020ba9627aa5a8776aa1b3a4
> --- sys/dev/usb/if_rsu.c
> +++ sys/dev/usb/if_rsu.c
> @@ -940,7 +940,12 @@ rsu_set_key_cb(struct rsu_softc *sc, void *arg)
> memcpy(key.key, k->k_key, MIN(k->k_len, sizeof(key.key)));
> (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
>
> + if ((k->k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + cmd->ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + cmd->ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> if (sc->sc_key_tasks == 0) {
> + if (k->k_flags & IEEE80211_KEY_SECURE)
> + cmd->ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("marking port %s valid\n",
> ether_sprintf(cmd->ni->ni_macaddr)));
> cmd->ni->ni_port_valid = 1;
> blob - 7759d6e0cea12b48a1373d90942b20a8d55bd7fb
> blob + 70acde2498e9adcadac12fcf3c6886ca7a753ef9
> --- sys/dev/usb/if_run.c
> +++ sys/dev/usb/if_run.c
> @@ -2017,7 +2017,12 @@ run_set_key_cb(struct run_softc *sc, void *arg)
> run_write(sc, RT2860_WCID_ATTR(wcid), attr);
> }
>
> + if ((k->k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + cmd->ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + cmd->ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> if (sc->sc_key_tasks == 0) {
> + if (k->k_flags & IEEE80211_KEY_SECURE)
> + cmd->ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> cmd->ni->ni_port_valid = 1;
> ieee80211_set_link_state(ic, LINK_STATE_UP);
> }
> blob - c2133041168e826909415759d2009bd74dd48aee
> blob + 82c02d91a36e5ce5d91f78f230789f348c09f5dd
> --- sys/dev/usb/if_urtwn.c
> +++ sys/dev/usb/if_urtwn.c
> @@ -1062,7 +1062,12 @@ urtwn_set_key_cb(struct urtwn_softc *sc, void *arg)
> sc->sc_key_tasks--;
>
> if (rtwn_set_key(ic, cmd->ni, &cmd->key) == 0) {
> + if ((cmd->key.k_flags & IEEE80211_KEY_GROUP) == 0 &&
> + cmd->ni->ni_rsn_supp_state == RSNA_SUPP_PTKNEGOTIATING)
> + cmd->ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> if (sc->sc_key_tasks == 0) {
> + if (cmd->key.k_flags & IEEE80211_KEY_SECURE)
> + cmd->ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> DPRINTF(("marking port %s valid\n",
> ether_sprintf(cmd->ni->ni_macaddr)));
> cmd->ni->ni_port_valid = 1;
> blob - 748b44b3f8c309dfd40b347ac408f234588b404b
> blob + e14b46a0ff9c9b824b59a93c866b955ce3338c24
> --- sys/net80211/ieee80211_crypto.h
> +++ sys/net80211/ieee80211_crypto.h
> @@ -79,6 +79,7 @@ struct ieee80211_key {
> #define IEEE80211_KEY_TX 0x00000002 /* Tx+Rx */
> #define IEEE80211_KEY_IGTK 0x00000004 /* integrity group key */
> #define IEEE80211_KEY_SWCRYPTO 0x00000080 /* loaded for software
> crypto */
> +#define IEEE80211_KEY_SECURE 0x00000100 /* initial key exchange done */
>
> u_int k_len;
> u_int64_t k_rsc[IEEE80211_NUM_TID];
> blob - daf550f591fdf675e073f82a968efbdbb49fdb46
> blob + 19413bef0b9c3e5df41bb3b8bcc17c88ae331e47
> --- sys/net80211/ieee80211_pae_input.c
> +++ sys/net80211/ieee80211_pae_input.c
> @@ -564,9 +564,12 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
> k->k_rsc[0] = prsc;
> k->k_len = keylen;
> memcpy(k->k_key, ni->ni_ptk.tk, k->k_len);
> + if (info & (EAPOL_KEY_INSTALL | EAPOL_KEY_SECURE))
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the PTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> + ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> break;
> case EBUSY:
> deferlink = 1;
> @@ -576,8 +579,9 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
> goto deauth;
> }
> ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK;
> - ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;
> - ni->ni_flags |= IEEE80211_NODE_RXPROT;
> + ni->ni_flags &= ~IEEE80211_NODE_TXPROT;
> + if (deferlink == 0)
> + ni->ni_flags |= IEEE80211_NODE_RXPROT;
> } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)
> printf("%s: unexpected pairwise key update received from %s\n",
> ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
> @@ -604,6 +608,8 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
> k->k_rsc[0] = LE_READ_6(key->rsc);
> k->k_len = keylen;
> memcpy(k->k_key, >k[8], k->k_len);
> + if (info & EAPOL_KEY_SECURE)
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the GTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> @@ -641,6 +647,8 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
> k->k_mgmt_rsc = LE_READ_6(&igtk[8]); /* IPN */
> k->k_len = 16;
> memcpy(k->k_key, &igtk[14], k->k_len);
> + if (info & EAPOL_KEY_SECURE)
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the IGTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> @@ -654,11 +662,9 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
> }
> }
> }
> - if (info & EAPOL_KEY_INSTALL)
> + if (deferlink == 0 && (info & (EAPOL_KEY_INSTALL | EAPOL_KEY_SECURE)))
> ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> -
> if (info & EAPOL_KEY_SECURE) {
> - ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
> #ifndef IEEE80211_STA_ONLY
> if (ic->ic_opmode != IEEE80211_M_IBSS ||
> ++ni->ni_key_count == 2)
> @@ -814,7 +820,7 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
> const u_int8_t *frm, *efrm;
> const u_int8_t *gtk, *igtk;
> u_int16_t info, kid, reason = 0;
> - int keylen;
> + int keylen, deferlink = 0;
>
> #ifndef IEEE80211_STA_ONLY
> if (ic->ic_opmode != IEEE80211_M_STA &&
> @@ -897,10 +903,14 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
> k->k_rsc[0] = LE_READ_6(key->rsc);
> k->k_len = keylen;
> memcpy(k->k_key, >k[8], k->k_len);
> + if (info & EAPOL_KEY_SECURE)
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the GTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> + break;
> case EBUSY:
> + deferlink = 1;
> break;
> default:
> reason = IEEE80211_REASON_AUTH_LEAVE;
> @@ -929,10 +939,14 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
> k->k_mgmt_rsc = LE_READ_6(&igtk[8]); /* IPN */
> k->k_len = 16;
> memcpy(k->k_key, &igtk[14], k->k_len);
> + if (info & EAPOL_KEY_SECURE)
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the IGTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> + break;
> case EBUSY:
> + deferlink = 1;
> break;
> default:
> reason = IEEE80211_REASON_AUTH_LEAVE;
> @@ -946,10 +960,12 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
> ++ni->ni_key_count == 2)
> #endif
> {
> - DPRINTF(("marking port %s valid\n",
> - ether_sprintf(ni->ni_macaddr)));
> - ni->ni_port_valid = 1;
> - ieee80211_set_link_state(ic, LINK_STATE_UP);
> + if (deferlink == 0) {
> + DPRINTF(("marking port %s valid\n",
> + ether_sprintf(ni->ni_macaddr)));
> + ni->ni_port_valid = 1;
> + ieee80211_set_link_state(ic, LINK_STATE_UP);
> + }
> ni->ni_assoc_fail = 0;
> }
> }
> @@ -979,7 +995,7 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
> struct ieee80211_key *k;
> u_int16_t info;
> u_int8_t kid;
> - int keylen;
> + int keylen, deferlink = 0;
> const uint8_t *gtk;
>
> #ifndef IEEE80211_STA_ONLY
> @@ -1037,10 +1053,14 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
> k->k_rsc[0] = LE_READ_6(key->rsc);
> k->k_len = keylen;
> memcpy(k->k_key, gtk, k->k_len);
> + if (info & EAPOL_KEY_SECURE)
> + k->k_flags |= IEEE80211_KEY_SECURE;
> /* install the GTK */
> switch ((*ic->ic_set_key)(ic, ni, k)) {
> case 0:
> + break;
> case EBUSY:
> + deferlink = 1;
> break;
> default:
> IEEE80211_SEND_MGMT(ic, ni,
> IEEE80211_FC0_SUBTYPE_DEAUTH,
> @@ -1055,10 +1075,12 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
> ++ni->ni_key_count == 2)
> #endif
> {
> - DPRINTF(("marking port %s valid\n",
> - ether_sprintf(ni->ni_macaddr)));
> - ni->ni_port_valid = 1;
> - ieee80211_set_link_state(ic, LINK_STATE_UP);
> + if (deferlink == 0) {
> + DPRINTF(("marking port %s valid\n",
> + ether_sprintf(ni->ni_macaddr)));
> + ni->ni_port_valid = 1;
> + ieee80211_set_link_state(ic, LINK_STATE_UP);
> + }
> ni->ni_assoc_fail = 0;
> }
> }
> blob - 35a00ff8b6b7315718558ad26178d8646308c6dc
> blob + 2a48158c2c93da086e7860a69a01e944991797c9
> --- sys/net80211/ieee80211_pae_output.c
> +++ sys/net80211/ieee80211_pae_output.c
> @@ -444,7 +444,6 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, stru
> struct mbuf *m;
> u_int16_t info;
>
> - ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
> m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
> if (m == NULL)
> return ENOMEM;
>
--
Regards,
Mikolaj