l2_packet: Extend bridge workaround RX processing to cover two frames
There was a race condition in how the l2_packet sockets got read that could result in the same socket (e.g., non-bridge) to process both the EAP-Success and the immediately following EAPOL-Key msg 1/4 instead of each frame going in alternative order between the bridge and non-bridge sockets. This could be hit, e.g., if the wpa_supplicant process did not have enough CPU to process all the incoming frames without them getting buffered and both sockets reporting frames simultaneously. This resulted in the duplicated EAP-Success frame getting delivered twice for processing and likely also the EAPOL-Key msg 1/4 getting processed twice. While the latter does not do much harm, the former did clear the EAP authentication state and could result in issues. Fix this by extended the l2_packet Linux packet socket workaround for bridge to check for duplicates against the last two received frames instead of just the last one. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
447fb0b0da
commit
64845c1f1a
1 changed files with 17 additions and 1 deletions
|
@ -33,8 +33,9 @@ struct l2_packet_data {
|
||||||
#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
|
#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
|
||||||
/* For working around Linux packet socket behavior and regression. */
|
/* For working around Linux packet socket behavior and regression. */
|
||||||
int fd_br_rx;
|
int fd_br_rx;
|
||||||
int last_from_br;
|
int last_from_br, last_from_br_prev;
|
||||||
u8 last_hash[SHA1_MAC_LEN];
|
u8 last_hash[SHA1_MAC_LEN];
|
||||||
|
u8 last_hash_prev[SHA1_MAC_LEN];
|
||||||
unsigned int num_rx_br;
|
unsigned int num_rx_br;
|
||||||
#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
|
#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
|
||||||
};
|
};
|
||||||
|
@ -171,6 +172,14 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (l2->last_from_br_prev &&
|
||||||
|
os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
|
||||||
|
l2->last_from_br_prev = l2->last_from_br;
|
||||||
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
|
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +228,13 @@ static void l2_packet_receive_br(int sock, void *eloop_ctx, void *sock_ctx)
|
||||||
wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
|
wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!l2->last_from_br_prev &&
|
||||||
|
os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
|
||||||
|
l2->last_from_br_prev = l2->last_from_br;
|
||||||
l2->last_from_br = 1;
|
l2->last_from_br = 1;
|
||||||
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
|
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
|
||||||
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
|
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
|
||||||
|
|
Loading…
Reference in a new issue