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@
-/* $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 <damien.bergamini@free.fr>
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)
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