diff mbox series

wpa_supplicant: Don't process EAPOLs while disconnecting

Message ID 20210307214002.29126-1-andrei.otcheretianski@intel.com
State Accepted
Headers show
Series wpa_supplicant: Don't process EAPOLs while disconnecting | expand

Commit Message

Otcheretianski, Andrei March 7, 2021, 9:40 p.m. UTC
An EAPOL frame may be pending when the supplicant requests to
deauthenticate. At this stage the EAP SM cache is already cleaned by
calling eapol_sm_invalidate_cached_session(). Since at this stage the
wpa_supplicant's state is still set to associated, the EAPOL is
processed and results in a crash due to NULL dereference.
This wasn't seen previously as nl80211 wouldn't process the
NL80211_CMD_CONTROL_PORT_FRAME, since wpa_driver_nl80211_mlme() would
set the valid_handler to NULL. This behavior was changed in ab8929192
("nl80211: use the process_bss_event for the nl_connect handler"),
exposing this race.
Fix it by ignoring EAPOL frames while the deauthentication is in
progress.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
---
 wpa_supplicant/wpa_supplicant.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Jouni Malinen March 12, 2021, 9:50 a.m. UTC | #1
On Sun, Mar 07, 2021 at 11:40:01PM +0200, Andrei Otcheretianski wrote:
> An EAPOL frame may be pending when the supplicant requests to
> deauthenticate. At this stage the EAP SM cache is already cleaned by
> calling eapol_sm_invalidate_cached_session(). Since at this stage the
> wpa_supplicant's state is still set to associated, the EAPOL is
> processed and results in a crash due to NULL dereference.
> This wasn't seen previously as nl80211 wouldn't process the
> NL80211_CMD_CONTROL_PORT_FRAME, since wpa_driver_nl80211_mlme() would
> set the valid_handler to NULL. This behavior was changed in ab8929192
> ("nl80211: use the process_bss_event for the nl_connect handler"),
> exposing this race.
> Fix it by ignoring EAPOL frames while the deauthentication is in
> progress.

Thanks, applied. However, I was unable to reproduce that NULL
dereference by trying to add calls to
eapol_sm_invalidate_cached_session() in inconvenient places. Can you
please provide more details on that crash and which pointer is being
dereferenced? I'd like to add more protection against unexpected cases,
but cannot do that here since I could not figure out where this NULL
dereferencing could have happened.
Otcheretianski, Andrei March 14, 2021, 9:25 a.m. UTC | #2
> Thanks, applied. However, I was unable to reproduce that NULL dereference
> by trying to add calls to
> eapol_sm_invalidate_cached_session() in inconvenient places. Can you
> please provide more details on that crash and which pointer is being
> dereferenced? I'd like to add more protection against unexpected cases, but
> cannot do that here since I could not figure out where this NULL
> dereferencing could have happened.

Hi,
I was able to reproduce it rerunning eap_tls_errors() several times..
Here's the stack trace:

1615712557.476359: WPA_TRACE: eloop SIGSEGV - START
1615712557.476676: [1]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(+0x708d0) [0x55ca0fdcd8d0]
1615712557.476699:      eloop_sigsegv_handler() ../src/utils/eloop.c:123
1615712557.476709: [2]: /lib/x86_64-linux-gnu/libc.so.6(+0x3ef20) [0x7f2a23cfef20]
1615712557.476723: [3]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(+0x15c369) [0x55ca0feb9369]
1615712557.476734:      sm_EAP_SUCCESS_Enter() ../src/eap_peer/eap.c:1072
1615712557.476746: [4]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(eap_peer_sm_step+0x346) [0x55ca0feba206]
1615712557.476757:      eap_peer_sm_step_idle() ../src/eap_peer/eap.c:1152
1615712557.476765:      eap_peer_sm_step_local() ../src/eap_peer/eap.c:1280
1615712557.476773:      sm_EAP_Step() ../src/eap_peer/eap.c:1365
1615712557.476781:      eap_peer_sm_step() ../src/eap_peer/eap.c:2237
1615712557.476791: [5]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(eapol_sm_step+0x13c) [0x55ca0feb69dc]
1615712557.476802:      eapol_sm_step() ../src/eapol_supp/eapol_supp_sm.c:999
1615712557.476812: [6]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(eapol_sm_rx_eapol+0x138) [0x55ca0feb7428]
1615712557.476840:      eapol_sm_rx_eapol() ../src/eapol_supp/eapol_supp_sm.c:1293
1615712557.476852: [7]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(wpa_supplicant_rx_eapol+0x3d5) [0x55ca0ff6f1a5]
1615712557.476862:      wpa_supplicant_rx_eapol() wpa_supplicant.c:4894
1615712557.476873: [8]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(wpa_supplicant_event+0xbf3) [0x55ca0ff829e3]
1615712557.476884:      wpa_supplicant_event() events.c:5223
1615712557.476895: [9]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(process_bss_event+0x358) [0x55ca0ffa9f88]
1615712557.476905:      drv_event_eapol_rx() ../src/drivers/driver.h:6068
1615712557.476913:      nl80211_control_port_frame() ../src/drivers/driver_nl80211_event.c:2792
1615712557.476920:      process_bss_event() ../src/drivers/driver_nl80211_event.c:3164
1615712557.476930: [10]: /lib/x86_64-linux-gnu/libnl-3.so.200(nl_recvmsgs_report+0x3cc) [0x7f2a2500ac1c]
1615712557.476941: [11]: /lib/x86_64-linux-gnu/libnl-3.so.200(nl_recvmsgs+0x9) [0x7f2a2500b049]
1615712557.476954: [12]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(+0x232cab) [0x55ca0ff8fcab]
1615712557.476966:      send_and_recv() ../src/drivers/driver_nl80211.c:450
1615712557.476978: [13]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(wpa_driver_nl80211_mlme+0xcf) [0x55ca0ff9c9af]
1615712557.476988:      wpa_driver_nl80211_mlme() ../src/drivers/driver_nl80211.c:3577
1615712557.476999: [14]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(+0x240a40) [0x55ca0ff9da40]
1615712557.477010:      wpa_driver_nl80211_deauthenticate() ../src/drivers/driver_nl80211.c:3635
1615712557.477021: [15]: /home/tester/devel/iwlwifi-hostap/tests/hwsim/../../wpa_supplicant/wpa_supplicant(wpa_supplicant_deauthenticate+0x1e7) [0x55ca0ff71da7]
1615712557.477033:      memset() usr/include/x86_64-linux-gnu/bits/string_fortified.h:71
1615712557.477043:      wpa_supplicant_deauthenticate() wpa_supplicant.c:4022
1615712557.477051: WPA_TRACE: eloop SIGSEGV - END

The full log is attached.

Thanks,
Andrei
> 
> --
> Jouni Malinen                                            PGP id EFC895FA
Jouni Malinen March 14, 2021, 10:54 p.m. UTC | #3
On Sun, Mar 14, 2021 at 09:25:28AM +0000, Otcheretianski, Andrei wrote:
> I was able to reproduce it rerunning eap_tls_errors() several times..
> Here's the stack trace:

> 1615712557.476734:      sm_EAP_SUCCESS_Enter() ../src/eap_peer/eap.c:1072

Thanks. I was not really able to reproduce this with eap_tls_errors no
matter what I tried, but I did manage to change the timing both in the
test script and wpa_supplicant to be able to trigger this.

The real issue here was caused by an earlier change where code was moved
to the EAP SUCCESS state handler without including the same checks for
the context state still being present before deferencing the pointers in
that location. Your patch is fine as-is, but it is just hiding the real
issue, so I'll add a fix for this regression as well so that this cannot
be triggered again regardless of how the code that calls into the EAP
state machine behaves with call and event order.
diff mbox series

Patch

diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6a02ed7c56..c8dcef21bd 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4773,6 +4773,11 @@  void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
 	wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
 	wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
 
+	if (wpa_s->own_disconnect_req) {
+		wpa_printf(MSG_DEBUG, "RX EAPOL - drop EAPOL frame as we are disconnecting");
+		return;
+	}
+
 #ifdef CONFIG_TESTING_OPTIONS
 	if (wpa_s->ignore_auth_resp) {
 		wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");