From bd88ed60fa9e45c67aeab45a5b7bd6d536cbf14d Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Thu, 20 Sep 2018 13:26:07 +0530 Subject: [PATCH] eap_proxy: Fix memory leaks when using eap_peer_erp_init() The external session_id and emsk from eap_proxy_get_eap_session_id() and eap_proxy_get_emsk() need to be freed consistently in all code paths within eap_peer_erp_init() and outside it in the case ERP is not initialized. Signed-off-by: Jouni Malinen --- src/eap_peer/eap.c | 10 ++++++++-- src/eapol_supp/eapol_supp_sm.c | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index e55e2d523..974c475ff 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -670,6 +670,9 @@ void eap_peer_erp_free_keys(struct eap_sm *sm) } +/* Note: If ext_session and/or ext_emsk are passed to this function, they are + * expected to point to allocated memory and those allocations will be freed + * unconditionally. */ void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id, size_t ext_session_id_len, u8 *ext_emsk, size_t ext_emsk_len) @@ -688,7 +691,7 @@ void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id, realm = eap_home_realm(sm); if (!realm) - return; + goto fail; realm_len = os_strlen(realm); wpa_printf(MSG_DEBUG, "EAP: Realm for ERP keyName-NAI: %s", realm); eap_erp_remove_keys_realm(sm, realm); @@ -775,7 +778,10 @@ void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id, dl_list_add(&sm->erp_keys, &erp->list); erp = NULL; fail: - bin_clear_free(emsk, emsk_len); + if (ext_emsk) + bin_clear_free(ext_emsk, ext_emsk_len); + else + bin_clear_free(emsk, emsk_len); bin_clear_free(ext_session_id, ext_session_id_len); bin_clear_free(erp, sizeof(*erp)); os_free(realm); diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index bfbc995f6..9f029b0d3 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -503,10 +503,14 @@ SM_STATE(SUPP_BE, SUCCESS) session_id = eap_proxy_get_eap_session_id( sm->eap_proxy, &session_id_len); emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len); - if (sm->config->erp && session_id && emsk) + if (sm->config->erp && session_id && emsk) { eap_peer_erp_init(sm->eap, session_id, session_id_len, emsk, emsk_len); + } else { + os_free(session_id); + bin_clear_free(emsk, emsk_len); + } } return; }