[MME] Hangs on an invalid S1AP message

Within the PathSwitchRequest packet,
the E-RABToBeSwitchedDLList has two bearers.

If the E-RAB-ID of both bearers is 5, the MME's list memory is destroyed
and the MME crashes. To fix this issue, we modified the code so that
the MME can work correctly with invalid S1AP messages.
This commit is contained in:
Sukchan Lee 2024-01-17 20:17:55 +09:00
parent 52be56b839
commit 4088cdf17d
3 changed files with 292 additions and 5 deletions

View File

@ -206,6 +206,19 @@ static ogs_inline int ogs_list_count(const ogs_list_t *list)
return i;
}
static ogs_inline bool ogs_list_exists(const ogs_list_t *list, void *lnode)
{
ogs_list_t *node = (ogs_list_t *)lnode;
void *iter = NULL;
ogs_list_for_each(list, iter) {
if (node == (ogs_list_t *)iter)
return true;
}
return false;
}
#ifdef __cplusplus
}
#endif

View File

@ -1046,8 +1046,14 @@ void s1ap_handle_initial_context_setup_response(
ogs_debug(" ### ULI PRESENT ###");
uli_presence = 1;
}
ogs_list_add(&mme_ue->bearer_to_modify_list,
&bearer->to_modify_node);
if (ogs_list_exists(
&mme_ue->bearer_to_modify_list,
&bearer->to_modify_node) == false)
ogs_list_add(
&mme_ue->bearer_to_modify_list,
&bearer->to_modify_node);
else
ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID);
}
}
@ -2195,7 +2201,13 @@ void s1ap_handle_e_rab_modification_indication(
return;
}
ogs_list_add(&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
if (ogs_list_exists(
&mme_ue->bearer_to_modify_list,
&bearer->to_modify_node) == false)
ogs_list_add(
&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
else
ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID);
}
if (ogs_list_count(&mme_ue->bearer_to_modify_list)) {
@ -2623,8 +2635,13 @@ void s1ap_handle_path_switch_request(
return;
}
ogs_list_add(
&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
if (ogs_list_exists(
&mme_ue->bearer_to_modify_list,
&bearer->to_modify_node) == false)
ogs_list_add(
&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
else
ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID);
}
relocation = sgw_ue_check_if_relocated(mme_ue);

View File

@ -370,11 +370,268 @@ static void test1_func(abts_case *tc, void *data)
test_ue_remove(test_ue);
}
static void test2_func(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *s1ap1, *s1ap2;
ogs_socknode_t *gtpu1, *gtpu2;
ogs_pkbuf_t *emmbuf;
ogs_pkbuf_t *esmbuf;
ogs_pkbuf_t *sendbuf;
ogs_pkbuf_t *recvbuf;
ogs_s1ap_message_t message;
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t *test_ue = NULL;
test_sess_t *sess = NULL;
test_bearer_t *bearer = NULL;
bson_t *doc = NULL;
/* Setup Test UE & Session Context */
memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci));
mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI;
mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI;
mobile_identity_suci.routing_indicator1 = 0;
mobile_identity_suci.routing_indicator2 = 0xf;
mobile_identity_suci.routing_indicator3 = 0xf;
mobile_identity_suci.routing_indicator4 = 0xf;
mobile_identity_suci.protection_scheme_id = OGS_PROTECTION_SCHEME_NULL;
mobile_identity_suci.home_network_pki_value = 0;
test_ue = test_ue_add_by_suci(&mobile_identity_suci, "3746000006");
ogs_assert(test_ue);
test_ue->e_cgi.cell_id = 0x1234560;
test_ue->nas.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH;
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
sess = test_sess_add_by_apn(test_ue, "internet", OGS_GTP2_RAT_TYPE_EUTRAN);
ogs_assert(sess);
/* Two eNB connects to MME */
s1ap1 = tests1ap_client(AF_INET);
ABTS_PTR_NOTNULL(tc, s1ap1);
s1ap2 = tests1ap_client(AF_INET);
ABTS_PTR_NOTNULL(tc, s1ap2);
/* Two eNB connects to SGW */
gtpu1 = test_gtpu_server(1, AF_INET);
ABTS_PTR_NOTNULL(tc, gtpu1);
gtpu2 = test_gtpu_server(2, AF_INET);
ABTS_PTR_NOTNULL(tc, gtpu2);
/* S1-Setup Reqeust/Response for Source eNB */
sendbuf = test_s1ap_build_s1_setup_request(
S1AP_ENB_ID_PR_macroENB_ID, 0x54f64);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(NULL, recvbuf);
/* S1-Setup Reqeust/Response for Target eNB */
sendbuf = test_s1ap_build_s1_setup_request(
S1AP_ENB_ID_PR_macroENB_ID, 0x54f65);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(NULL, recvbuf);
/********** Insert Subscriber in Database */
doc = test_db_new_qos_flow(test_ue);
ABTS_PTR_NOTNULL(tc, doc);
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
/* Send Attach Request */
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
sess->pdn_connectivity_param.eit = 1;
sess->pdn_connectivity_param.pco = 1;
sess->pdn_connectivity_param.request_type =
OGS_NAS_EPS_REQUEST_TYPE_INITIAL;
esmbuf = testesm_build_pdn_connectivity_request(sess, false);
ABTS_PTR_NOTNULL(tc, esmbuf);
memset(&test_ue->attach_request_param,
0, sizeof(test_ue->attach_request_param));
test_ue->attach_request_param.drx_parameter = 1;
test_ue->attach_request_param.tmsi_status = 1;
test_ue->attach_request_param.mobile_station_classmark_2 = 1;
test_ue->attach_request_param.additional_update_type = 1;
test_ue->attach_request_param.ue_usage_setting = 1;
emmbuf = testemm_build_attach_request(test_ue, esmbuf, false, false);
ABTS_PTR_NOTNULL(tc, emmbuf);
memset(&test_ue->initial_ue_param, 0, sizeof(test_ue->initial_ue_param));
sendbuf = test_s1ap_build_initial_ue_message(
test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, false);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication Request */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send Authentication response */
emmbuf = testemm_build_authentication_response(test_ue);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode Command */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send Security mode complete */
test_ue->mobile_identity_imeisv_presence = true;
emmbuf = testemm_build_security_mode_complete(test_ue);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive ESM Information Request */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send ESM Information Response */
esmbuf = testesm_build_esm_information_response(sess);
ABTS_PTR_NOTNULL(tc, esmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Initial Context Setup Request +
* Attach Accept +
* Activate Default Bearer Context Request */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send UE Capability Info Indication */
sendbuf = tests1ap_build_ue_radio_capability_info_indication(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Initial Context Setup Response */
sendbuf = test_s1ap_build_initial_context_setup_response(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Attach Complete + Activate default EPS bearer cotext accept */
test_ue->nr_cgi.cell_id = 0x1234502;
bearer = test_bearer_find_by_ue_ebi(test_ue, 5);
ogs_assert(bearer);
esmbuf = testesm_build_activate_default_eps_bearer_context_accept(
bearer, false);
ABTS_PTR_NOTNULL(tc, esmbuf);
emmbuf = testemm_build_attach_complete(test_ue, esmbuf);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive EMM information */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Receive E-RAB Setup Request +
* Activate dedicated EPS bearer context request */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send E-RAB Setup Response */
bearer = test_bearer_find_by_ue_ebi(test_ue, 6);
ogs_assert(bearer);
sendbuf = test_s1ap_build_e_rab_setup_response(bearer);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Activate dedicated EPS bearer context accept */
esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer);
ABTS_PTR_NOTNULL(tc, esmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* Send Path Switch Request */
test_ue->e_cgi.cell_id = 0xabcdef0;
test_ue->enb_ue_s1ap_id++;
bearer = ogs_list_first(&sess->bearer_list);
bearer->ebi = 5;
bearer->enb_s1u_addr = test_self()->gnb2_addr;
bearer->enb_s1u_addr6 = test_self()->gnb2_addr6;
bearer = ogs_list_next(bearer);
bearer->ebi = 5; /* Invalid Bearer with same EBI = 5 */
bearer->enb_s1u_addr = test_self()->gnb2_addr;
bearer->enb_s1u_addr6 = test_self()->gnb2_addr6;
sendbuf = test_s1ap_build_path_switch_request(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Path Switch Ack */
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu1);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
ogs_msleep(300);
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
/* Two eNB disonncect from SGW */
testgnb_gtpu_close(gtpu1);
testgnb_gtpu_close(gtpu2);
/* Two eNB disonncect from MME */
testenb_s1ap_close(s1ap1);
testenb_s1ap_close(s1ap2);
test_ue_remove(test_ue);
}
abts_suite *test_epc_x2(abts_suite *suite)
{
suite = ADD_SUITE(suite)
abts_run_test(suite, test1_func, NULL);
abts_run_test(suite, test2_func, NULL);
return suite;
}