From: mpi Date: Thu, 21 Dec 2017 12:09:38 +0000 (+0000) Subject: Call if_start() directly to send the EAPOL key. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fe8baf1197e028568615e8150733e6ec25277cca;p=openbsd Call if_start() directly to send the EAPOL key. Using if_enqueue() here, from interrupt context, might result in the packet beeing enqueued, incorrectly encrypted, on the TX ring. This race has been recently exposed by the re-introduction of the TX mitigation. It exists because the net80211 stack sets IEEE80211_NODE_TXPROT on the node while processing the 3rd message, assuming the answer has already been transmitted. However a CPU returns from if_enqueue() it cannot assume that the send queue is empty. So call if_start() to flush this queue. Encrypting the 4th message of the 4way handshake with the new key breaks WPA handshake as found the hardway by anton@. Race analysed by dlg@, a lot of net80211 inputs and suggetions from stsp@. ok stsp@, dlg@ --- diff --git a/sys/net80211/ieee80211_pae_output.c b/sys/net80211/ieee80211_pae_output.c index d385b00ad9d..51d0fa44e6d 100644 --- a/sys/net80211/ieee80211_pae_output.c +++ b/sys/net80211/ieee80211_pae_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_pae_output.c,v 1.29 2017/03/01 19:28:48 stsp Exp $ */ +/* $OpenBSD: ieee80211_pae_output.c,v 1.30 2017/12/21 12:09:38 mpi Exp $ */ /*- * Copyright (c) 2007,2008 Damien Bergamini @@ -66,7 +66,7 @@ ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m, struct ether_header *eh; struct ieee80211_eapol_key *key; u_int16_t info; - int len; + int len, error; M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); if (m == NULL) @@ -123,7 +123,12 @@ ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m, if (info & EAPOL_KEY_KEYACK) timeout_add_msec(&ni->ni_eapol_to, 100); #endif - return if_enqueue(ifp, m); + + IFQ_ENQUEUE(&ifp->if_snd, m, error); + if (error) + return (error); + if_start(ifp); + return 0; } #ifndef IEEE80211_STA_ONLY