From be765fe2b03e350836272eee5afb3931bdfb86d5 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Wed, 24 Sep 2025 21:20:22 +0900 Subject: [PATCH] [AMF/MME] Add size validation for NGAP/S1AP IE fields to prevent crashes (#4087) - Added explicit size checks for critical IE fields (PLMNIdentity, TAC, GTP-TEID, Cell-ID, UE security capability algorithms, etc.) before memcpy() operations. - When size mismatch is detected, log an error and return an Error Indication (or Setup Failure) with appropriate protocol cause (semantic_error or message_not_compatible_with_receiver_state). - Introduced s1ap_send_error_indication1(enb_ue_t *enb_ue, ...) as a helper for cases where ENB UE context is available directly. s1ap_send_error_indication2(mme_ue_t *mme_ue, ...) now delegates to the new function, reducing code duplication. - Replaced ogs_assert() checks with graceful error handling paths to avoid abnormal process termination. This improves robustness against malformed or non-compliant NGAP/S1AP messages and prevents potential AMF/MME crashes. --- src/amf/ngap-handler.c | 63 ++++++ src/mme/s1ap-handler.c | 496 ++++++++++++++++++++++++++++++++++++++--- src/mme/s1ap-path.c | 36 +-- src/mme/s1ap-path.h | 2 + 4 files changed, 557 insertions(+), 40 deletions(-) diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index b19610db5..ea4a502e8 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -2944,6 +2944,56 @@ void ngap_handle_path_switch_request( eUTRAintegrityProtectionAlgorithms = &UESecurityCapabilities->eUTRAintegrityProtectionAlgorithms; + if (nRencryptionAlgorithms->size != sizeof(nr_ea)) { + ogs_error("Invalid nRencryptionAlgorithms->size = %d (expected %d)", + (int)nRencryptionAlgorithms->size, + (int)sizeof(nr_ea)); + r = ngap_send_error_indication( + gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id, + NGAP_Cause_PR_protocol, + NGAP_CauseProtocol_message_not_compatible_with_receiver_state); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (nRintegrityProtectionAlgorithms->size != sizeof(nr_ia)) { + ogs_error("Invalid nRintegrityProtectionAlgorithms->size = %d " + "(expected %d)", + (int)nRintegrityProtectionAlgorithms->size, + (int)sizeof(nr_ia)); + r = ngap_send_error_indication( + gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id, + NGAP_Cause_PR_protocol, + NGAP_CauseProtocol_message_not_compatible_with_receiver_state); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (eUTRAencryptionAlgorithms->size != sizeof(eutra_ea)) { + ogs_error("Invalid eUTRAencryptionAlgorithms->size = %d (expected %d)", + (int)eUTRAencryptionAlgorithms->size, + (int)sizeof(eutra_ea)); + r = ngap_send_error_indication( + gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id, + NGAP_Cause_PR_protocol, + NGAP_CauseProtocol_message_not_compatible_with_receiver_state); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (eUTRAintegrityProtectionAlgorithms->size != sizeof(eutra_ia)) { + ogs_error("Invalid eUTRAintegrityProtectionAlgorithms->size = %d " + "(expected %d)", + (int)eUTRAintegrityProtectionAlgorithms->size, + (int)sizeof(eutra_ia)); + r = ngap_send_error_indication( + gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id, + NGAP_Cause_PR_protocol, + NGAP_CauseProtocol_message_not_compatible_with_receiver_state); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&nr_ea, nRencryptionAlgorithms->buf, sizeof(nr_ea)); nr_ea = be16toh(nr_ea); nr_ea0 = amf_ue->ue_security_capability.nr_ea0; @@ -4412,6 +4462,19 @@ void ngap_handle_ran_configuration_update( &BroadcastPLMNItem->pLMNIdentity; ogs_assert(pLMNIdentity); + if (pLMNIdentity->size != sizeof(ogs_plmn_id_t)) { + ogs_error("Invalid PLMNIdentity size = %d (expected %d)", + (int)pLMNIdentity->size, + (int)sizeof(ogs_plmn_id_t)); + group = NGAP_Cause_PR_protocol; + cause = NGAP_CauseProtocol_semantic_error; + r = ngap_send_ran_configuration_update_failure( + gnb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + memcpy(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id, pLMNIdentity->buf, sizeof(ogs_plmn_id_t)); ogs_debug(" PLMN_ID[MCC:%d MNC:%d]", diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 11ed6590b..304d9a52d 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -139,6 +139,19 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message) return; } + if (Global_ENB_ID->pLMNidentity.size != sizeof(enb->plmn_id)) { + ogs_error("Invalid PLMNIdentity size = %d (expected %d)", + (int)Global_ENB_ID->pLMNidentity.size, + (int)sizeof(enb->plmn_id)); + group = S1AP_Cause_PR_misc; + cause = S1AP_CauseProtocol_semantic_error; + + r = s1ap_send_s1_setup_failure(enb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (!SupportedTAs) { ogs_error("No SupportedTAs"); group = S1AP_Cause_PR_misc; @@ -193,6 +206,30 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message) break; } + if (tAC->size != sizeof(uint16_t)) { + ogs_error("Invalid tAC size = %d (expected %d)", + (int)tAC->size, (int)sizeof(uint16_t)); + group = S1AP_Cause_PR_misc; + cause = S1AP_CauseProtocol_semantic_error; + + r = s1ap_send_s1_setup_failure(enb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + + if (pLMNidentity->size != sizeof(ogs_plmn_id_t)) { + ogs_error("Invalid pLMNidentity size = %d (expected %d)", + (int)pLMNidentity->size, (int)sizeof(ogs_plmn_id_t)); + group = S1AP_Cause_PR_misc; + cause = S1AP_CauseProtocol_semantic_error; + + r = s1ap_send_s1_setup_failure(enb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac, tAC->buf, sizeof(uint16_t)); enb->supported_ta_list[enb->num_of_supported_ta_list].tac = @@ -335,6 +372,31 @@ void s1ap_handle_enb_configuration_update( break; } + if (tAC->size != sizeof(uint16_t)) { + ogs_error("Invalid tAC size = %d (expected %d)", + (int)tAC->size, (int)sizeof(uint16_t)); + group = S1AP_Cause_PR_misc; + cause = S1AP_CauseProtocol_semantic_error; + + r = s1ap_send_s1_setup_failure(enb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + + if (pLMNidentity->size != sizeof(ogs_plmn_id_t)) { + ogs_error("Invalid pLMNidentity size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(ogs_plmn_id_t)); + group = S1AP_Cause_PR_misc; + cause = S1AP_CauseProtocol_semantic_error; + + r = s1ap_send_s1_setup_failure(enb, group, cause); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + memcpy(&enb->supported_ta_list[ enb->num_of_supported_ta_list].tac, tAC->buf, sizeof(uint16_t)); @@ -500,8 +562,30 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) nas_guti.mme_gid = served_gummei->mme_gid[0]; /* size must be 1 */ + if (S_TMSI->mMEC.size != 1) { + ogs_error("Invalid S_TMSI->mMEC.size = %d (expected 1)", + (int)S_TMSI->mMEC.size); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&nas_guti.mme_code, S_TMSI->mMEC.buf, S_TMSI->mMEC.size); /* size must be 4 */ + if (S_TMSI->m_TMSI.size != 4) { + ogs_error("Invalid S_TMSI->m_TMSI.size = %d (expected 4)", + (int)S_TMSI->m_TMSI.size); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&nas_guti.m_tmsi, S_TMSI->m_TMSI.buf, S_TMSI->m_TMSI.size); nas_guti.m_tmsi = be32toh(nas_guti.m_tmsi); @@ -586,18 +670,61 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) } pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.tai.plmn_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(enb_ue->saved.tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.tai.plmn_id)); memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac); pLMNidentity = &EUTRAN_CGI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.e_cgi.plmn_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } cell_ID = &EUTRAN_CGI->cell_ID; - ogs_assert(cell_ID); + if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) { + ogs_error("Invalid cell_ID->size = %d (expected %d)", + (int)cell_ID->size, + (int)sizeof(enb_ue->saved.e_cgi.cell_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.e_cgi.plmn_id)); memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, @@ -745,9 +872,26 @@ void s1ap_handle_uplink_nas_transport( } pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(tai.plmn_id)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(tai.tac)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&tai.plmn_id, pLMNidentity->buf, sizeof(tai.plmn_id)); memcpy(&tai.tac, tAC->buf, sizeof(tai.tac)); tai.tac = be16toh(tai.tac); @@ -767,9 +911,27 @@ void s1ap_handle_uplink_nas_transport( ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index); pLMNidentity = &EUTRAN_CGI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.e_cgi.plmn_id)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } cell_ID = &EUTRAN_CGI->cell_ID; - ogs_assert(cell_ID); + if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) { + ogs_error("Invalid cell_ID->size = %d (expected %d)", + (int)cell_ID->size, + (int)sizeof(enb_ue->saved.e_cgi.cell_id)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.e_cgi.plmn_id)); memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, @@ -777,9 +939,26 @@ void s1ap_handle_uplink_nas_transport( enb_ue->saved.e_cgi.cell_id = (be32toh(enb_ue->saved.e_cgi.cell_id) >> 4); pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.tai.plmn_id)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(enb_ue->saved.tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.tai.plmn_id)); memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); @@ -1042,6 +1221,17 @@ void s1ap_handle_initial_context_setup_response( return; } + if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) { + ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)", + (int)e_rab->gTP_TEID.size, + (int)sizeof(bearer->enb_s1u_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, sizeof(bearer->enb_s1u_teid)); bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); @@ -1576,8 +1766,19 @@ void s1ap_handle_e_rab_setup_response( return; } + if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) { + ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)", + (int)e_rab->gTP_TEID.size, + (int)sizeof(bearer->enb_s1u_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, - sizeof(bearer->enb_s1u_teid)); + sizeof(bearer->enb_s1u_teid)); bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); rv = ogs_asn_BIT_STRING_to_ip( &e_rab->transportLayerAddress, &bearer->enb_s1u_ip); @@ -2222,6 +2423,17 @@ void s1ap_handle_e_rab_modification_indication( return; } + if (e_rab->dL_GTP_TEID.size != sizeof(bearer->enb_s1u_teid)) { + ogs_error("Invalid e_rab->dL_GTP_TEID.size = %d (expected %d)", + (int)e_rab->dL_GTP_TEID.size, + (int)sizeof(bearer->enb_s1u_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_s1u_teid, e_rab->dL_GTP_TEID.buf, sizeof(bearer->enb_s1u_teid)); bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); @@ -2317,7 +2529,47 @@ void s1ap_handle_enb_direct_information_transfer( switch (RIMRoutingAddress->present) { case S1AP_RIMRoutingAddress_PR_gERAN_Cell_ID: geran_cell_id = RIMRoutingAddress->choice.gERAN_Cell_ID; - ogs_assert(geran_cell_id); + if (!geran_cell_id) { + ogs_error("No gERAN_Cell_ID"); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (geran_cell_id->lAI.pLMNidentity.size != sizeof(plmn_id)) { + ogs_error("Invalid geran_cell_id->lAI.pLMNidentity.size = %d " + "(expected %d)", + (int)geran_cell_id->lAI.pLMNidentity.size, + (int)sizeof(plmn_id)); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (geran_cell_id->lAI.lAC.size != sizeof(uint16_t)) { + ogs_error("Invalid geran_cell_id->lAI.lAC.size = %d " + "(expected %d)", + (int)geran_cell_id->lAI.lAC.size, + (int)sizeof(uint16_t)); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (geran_cell_id->cI.size != sizeof(uint16_t)) { + ogs_error("Invalid geran_cell_id->cI.size = %d " + "(expected %d)", + (int)geran_cell_id->cI.size, + (int)sizeof(uint16_t)); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&plmn_id, geran_cell_id->lAI.pLMNidentity.buf, sizeof(plmn_id)); ogs_nas_from_plmn_id(&rai.lai.nas_plmn_id, &plmn_id); memcpy(&rai.lai.lac, geran_cell_id->lAI.lAC.buf, sizeof(uint16_t)); @@ -2508,9 +2760,26 @@ void s1ap_handle_path_switch_request( } pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(tai.plmn_id)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(tai.tac)); + r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&tai.plmn_id, pLMNidentity->buf, sizeof(tai.plmn_id)); memcpy(&tai.tac, tAC->buf, sizeof(tai.tac)); tai.tac = be16toh(tai.tac); @@ -2577,18 +2846,61 @@ void s1ap_handle_path_switch_request( enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.tai.plmn_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(enb_ue->saved.tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.tai.plmn_id)); memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac); pLMNidentity = &EUTRAN_CGI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(enb_ue->saved.e_cgi.plmn_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } cell_ID = &EUTRAN_CGI->cell_ID; - ogs_assert(cell_ID); + if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) { + ogs_error("Invalid cell_ID->size = %d (expected %d)", + (int)cell_ID->size, + (int)sizeof(enb_ue->saved.e_cgi.cell_id)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.e_cgi.plmn_id)); memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, @@ -2614,12 +2926,37 @@ void s1ap_handle_path_switch_request( integrityProtectionAlgorithms = &UESecurityCapabilities->integrityProtectionAlgorithms; + if (encryptionAlgorithms->size != sizeof(eea)) { + ogs_error("Invalid encryptionAlgorithms->size = %d (expected %d)", + (int)encryptionAlgorithms->size, + (int)sizeof(eea)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&eea, encryptionAlgorithms->buf, sizeof(eea)); eea = be16toh(eea); eea0 = mme_ue->ue_network_capability.eea0; mme_ue->ue_network_capability.eea = eea >> 9; mme_ue->ue_network_capability.eea0 = eea0; + if (integrityProtectionAlgorithms->size != sizeof(eia)) { + ogs_error("Invalid integrityProtectionAlgorithms->size = %d " + "(expected %d)", + (int)integrityProtectionAlgorithms->size, + (int)sizeof(eia)); + r = s1ap_send_error_indication1( + enb_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&eia, integrityProtectionAlgorithms->buf, sizeof(eia)); eia = be16toh(eia); eia0 = mme_ue->ue_network_capability.eia0; @@ -2670,6 +3007,17 @@ void s1ap_handle_path_switch_request( return; } + if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) { + ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)", + (int)e_rab->gTP_TEID.size, + (int)sizeof(bearer->enb_s1u_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, sizeof(bearer->enb_s1u_teid)); bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); @@ -2771,6 +3119,30 @@ void s1ap_handle_enb_configuration_transfer( ogs_s1ap_ENB_ID_to_uint32( &targeteNB_ID->global_ENB_ID.eNB_ID, &target_enb_id); + if (sourceeNB_ID->selected_TAI.tAC.size != sizeof(source_tac)) { + ogs_error("Invalid sourceeNB_ID->selected_TAI.tAC.size = %d " + "(expected %d)", + (int)sourceeNB_ID->selected_TAI.tAC.size, + (int)sizeof(source_tac)); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_radioNetwork, + S1AP_CauseRadioNetwork_unknown_targetID); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } + if (targeteNB_ID->selected_TAI.tAC.size != sizeof(target_tac)) { + ogs_error("Invalid targeteNB_ID->selected_TAI.tAC.size = %d " + "(expected %d)", + (int)targeteNB_ID->selected_TAI.tAC.size, + (int)sizeof(target_tac)); + r = s1ap_send_error_indication(enb, NULL, NULL, + S1AP_Cause_PR_radioNetwork, + S1AP_CauseRadioNetwork_unknown_targetID); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&source_tac, sourceeNB_ID->selected_TAI.tAC.buf, sizeof(source_tac)); source_tac = be16toh(source_tac); @@ -3208,6 +3580,17 @@ void s1ap_handle_handover_request_ack( return; } + if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) { + ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)", + (int)e_rab->gTP_TEID.size, + (int)sizeof(bearer->enb_s1u_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->target_s1u_teid, e_rab->gTP_TEID.buf, sizeof(bearer->target_s1u_teid)); bearer->target_s1u_teid = be32toh(bearer->target_s1u_teid); @@ -3225,8 +3608,17 @@ void s1ap_handle_handover_request_ack( } if (e_rab->dL_transportLayerAddress && e_rab->dL_gTP_TEID) { - ogs_assert(e_rab->dL_gTP_TEID->buf); - ogs_assert(e_rab->dL_transportLayerAddress->buf); + if (e_rab->dL_gTP_TEID->size != sizeof(bearer->enb_dl_teid)) { + ogs_error("Invalid e_rab->dL_gTP_TEID.size = %d (expected %d)", + (int)e_rab->dL_gTP_TEID->size, + (int)sizeof(bearer->enb_dl_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_dl_teid, e_rab->dL_gTP_TEID->buf, sizeof(bearer->enb_dl_teid)); bearer->enb_dl_teid = be32toh(bearer->enb_dl_teid); @@ -3245,8 +3637,17 @@ void s1ap_handle_handover_request_ack( } if (e_rab->uL_TransportLayerAddress && e_rab->uL_GTP_TEID) { - ogs_assert(e_rab->uL_GTP_TEID->buf); - ogs_assert(e_rab->uL_TransportLayerAddress->buf); + if (e_rab->uL_GTP_TEID->size != sizeof(bearer->enb_ul_teid)) { + ogs_error("Invalid e_rab->uL_GTP_TEID.size = %d (expected %d)", + (int)e_rab->uL_GTP_TEID->size, + (int)sizeof(bearer->enb_ul_teid)); + r = s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&bearer->enb_ul_teid, e_rab->uL_GTP_TEID->buf, sizeof(bearer->enb_ul_teid)); bearer->enb_ul_teid = be32toh(bearer->enb_ul_teid); @@ -3763,9 +4164,30 @@ void s1ap_handle_handover_notification( CLEAR_MME_UE_TIMER(mme_ue->t_mobile_reachable); pLMNidentity = &TAI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(target_ue->saved.tai.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(target_ue->saved.tai.plmn_id)); + r = s1ap_send_error_indication2( + mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } tAC = &TAI->tAC; - ogs_assert(tAC && tAC->size == sizeof(uint16_t)); + if (tAC->size != sizeof(target_ue->saved.tai.tac)) { + ogs_error("Invalid tAC->size = %d (expected %d)", + (int)tAC->size, (int)sizeof(target_ue->saved.tai.tac)); + r = s1ap_send_error_indication2( + mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&target_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(target_ue->saved.tai.plmn_id)); memcpy(&target_ue->saved.tai.tac, @@ -3773,9 +4195,31 @@ void s1ap_handle_handover_notification( target_ue->saved.tai.tac = be16toh(target_ue->saved.tai.tac); pLMNidentity = &EUTRAN_CGI->pLMNidentity; - ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); + if (pLMNidentity->size != sizeof(target_ue->saved.e_cgi.plmn_id)) { + ogs_error("Invalid pLMNidentity->size = %d (expected %d)", + (int)pLMNidentity->size, + (int)sizeof(target_ue->saved.e_cgi.plmn_id)); + r = s1ap_send_error_indication2( + mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } cell_ID = &EUTRAN_CGI->cell_ID; - ogs_assert(cell_ID); + if (cell_ID->size != sizeof(target_ue->saved.e_cgi.cell_id)) { + ogs_error("Invalid cell_ID->size = %d (expected %d)", + (int)cell_ID->size, + (int)sizeof(target_ue->saved.e_cgi.cell_id)); + r = s1ap_send_error_indication1( + target_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_semantic_error); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return; + } memcpy(&target_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(target_ue->saved.e_cgi.plmn_id)); memcpy(&target_ue->saved.e_cgi.cell_id, cell_ID->buf, diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index ddbdb336d..2bb7f46dd 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -879,27 +879,16 @@ int s1ap_send_error_indication( return rv; } -int s1ap_send_error_indication2( - mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause) +int s1ap_send_error_indication1( + enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause) { int rv; mme_enb_t *enb; - enb_ue_t *enb_ue; S1AP_MME_UE_S1AP_ID_t mme_ue_s1ap_id; S1AP_ENB_UE_S1AP_ID_t enb_ue_s1ap_id; - if (!mme_ue) { - ogs_error("UE(mme-ue) context has already been removed"); - return OGS_NOTFOUND; - } - - enb_ue = enb_ue_find_by_id(mme_ue->enb_ue_id); - if (!enb_ue) { - ogs_error("S1 context has already been removed"); - return OGS_NOTFOUND; - } - + ogs_assert(enb_ue); enb = mme_enb_find_by_id(enb_ue->enb_id); if (!enb) { ogs_error("eNB has already been removed"); @@ -916,6 +905,25 @@ int s1ap_send_error_indication2( return rv; } +int s1ap_send_error_indication2( + mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause) +{ + enb_ue_t *enb_ue; + + if (!mme_ue) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + enb_ue = enb_ue_find_by_id(mme_ue->enb_ue_id); + if (!enb_ue) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + + return s1ap_send_error_indication1(enb_ue, group, cause); +} + int s1ap_send_s1_reset_ack( mme_enb_t *enb, S1AP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface) diff --git a/src/mme/s1ap-path.h b/src/mme/s1ap-path.h index a23c52304..bab6039ed 100644 --- a/src/mme/s1ap-path.h +++ b/src/mme/s1ap-path.h @@ -97,6 +97,8 @@ int s1ap_send_error_indication( S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id, S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id, S1AP_Cause_PR group, long cause); +int s1ap_send_error_indication1( + enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause); int s1ap_send_error_indication2( mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause); int s1ap_send_s1_reset_ack(