[MME] Crash due to a race condition

A race condition can occur in the following situations.
In conclusion, we can use this situation to determine
whether or not the UE Context has been removed and avoiding a crash.

For example, suppose a UE Context is removed in the followings.

1. Attach Request
2. Authentication-Information-Request
3. Authentication-Information-Answer
4. Authentication Request
5. Authentication Response(MAC Failed)
6. Authentication Reject
7. UEContextReleaseCommand
8. UEContextReleaseComplete

The MME then sends a Purge-UE-request to the HSS and deletes
the UE context as soon as it receives a Purge-UE-Answer.

Suppose an Attach Request is received from the same UE
between Purge-UE-Request/Answer, then the MME and HSS start
the Authentication-Information-Request/Answer process.

This can lead to the following situations.

1. Purge-UE-Request
2. Attach Request
3. Authentication-Information-Request
4. Purge-UE-Answer
5. [UE Context Removed]
6. Authentication-Information-Answer

Since the UE Context has already been deleted
when the Authentication-Information-Answer is received,
it cannot be processed properly.

Therefore, mme_ue_cycle() is used to check
whether the UE Context has been deleted and
decide whether to process or
ignore the Authentication-Information-Answer as shown below.
This commit is contained in:
Sukchan Lee 2024-01-25 23:25:47 +09:00
parent 609c234f0b
commit 3886891833
3 changed files with 71 additions and 4 deletions

View File

@ -146,7 +146,6 @@ void ogs_timer_stop_debug(ogs_timer_t *timer, const char *file_line)
manager = timer->manager;
ogs_assert(manager);
timer = ogs_timer_cycle(manager, timer);
ogs_assert(timer);
if (!timer) {
ogs_fatal("ogs_timer_stop() failed in %s", file_line);
ogs_assert_if_reached();

View File

@ -407,8 +407,53 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
break;
case MME_EVENT_S6A_MESSAGE:
mme_ue = e->mme_ue;
ogs_assert(mme_ue);
/*
* A race condition can occur in the following situations.
* In conclusion, we can use this situation to determine
* whether or not the UE Context has been removed and avoiding a crash.
*
* For example, suppose a UE Context is removed in the followings.
*
* 1. Attach Request
* 2. Authentication-Information-Request
* 3. Authentication-Information-Answer
* 4. Authentication Request
* 5. Authentication Response(MAC Failed)
* 6. Authentication Reject
* 7. UEContextReleaseCommand
* 8. UEContextReleaseComplete
*
* The MME then sends a Purge-UE-request to the HSS and deletes
* the UE context as soon as it receives a Purge-UE-Answer.
*
* Suppose an Attach Request is received from the same UE
* between Purge-UE-Request/Answer, then the MME and HSS start
* the Authentication-Information-Request/Answer process.
*
* This can lead to the following situations.
*
* 1. Purge-UE-Request
* 2. Attach Request
* 3. Authentication-Information-Request
* 4. Purge-UE-Answer
* 5. [UE Context Removed]
* 6. Authentication-Information-Answer
*
* Since the UE Context has already been deleted
* when the Authentication-Information-Answer is received,
* it cannot be processed properly.
*
* Therefore, mme_ue_cycle() is used to check
* whether the UE Context has been deleted and
* decide whether to process or
* ignore the Authentication-Information-Answer as shown below.
*/
mme_ue = mme_ue_cycle(e->mme_ue);
if (!mme_ue) {
ogs_error("UE(mme-ue) context has already been removed");
goto cleanup;
}
s6a_message = e->s6a_message;
ogs_assert(s6a_message);
@ -473,6 +518,8 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_error("Invalid Type[%d]", s6a_message->cmd_code);
break;
}
cleanup:
ogs_subscription_data_free(&s6a_message->idr_message.subscription_data);
ogs_subscription_data_free(&s6a_message->ula_message.subscription_data);
ogs_free(s6a_message);

View File

@ -574,7 +574,28 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
emmbuf = NULL;
}
ogs_assert(E_RABToBeSetupListCtxtSUReq->list.count);
if (!E_RABToBeSetupListCtxtSUReq->list.count) {
ogs_error(" IMSI[%s] NAS-EPS Type[%d] "
"ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
mme_ue->imsi_bcd, mme_ue->nas_eps.type,
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_error(" APN[%s]",
sess->session ? sess->session->name : "Unknown");
ogs_list_for_each(&sess->bearer_list, bearer) {
if (OGS_FSM_CHECK(&bearer->sm, esm_state_inactive))
ogs_error(" IN-ACTIVE");
else if (OGS_FSM_CHECK(&bearer->sm, esm_state_active))
ogs_error(" ACTIVE");
else
ogs_error(" OTHER STATE");
ogs_error(" EBI[%d] QCI[%d] SGW-S1U-TEID[%d]",
bearer->ebi, bearer->qos.index, bearer->sgw_s1u_teid);
}
}
return NULL;
}
ie = CALLOC(1, sizeof(S1AP_InitialContextSetupRequestIEs_t));
ASN_SEQUENCE_ADD(&InitialContextSetupRequest->protocolIEs, ie);