mme: Prevent crash when inactive bearer exists during handover

Inactive or PDN-disconnecting EPS bearers do not have valid SGW S1U
tunnel information. When s1ap_build_handover_request() attempted to
encode those bearers, ogs_asn_ip_to_BIT_STRING() failed, resulting in
a fatal assertion and MME crash.

This patch skips all non-active EPS bearers (esm_state_inactive or
esm_state_pdn_will_disconnect) when building the E-RAB list for
Handover Request. Active bearers are guaranteed to have valid
SGW S1U TEID/IP, ensuring safe encoding.

- Skip non-active bearers before E-RAB item construction
- Add state logging for debugging and verification
- Prevent "No IPv4 or IPv6" fatal error triggered by invalid TEID/IP

Fixes: #4131
This commit is contained in:
Sukchan Lee
2025-11-02 18:30:20 +09:00
parent 7d83313a57
commit 2d61aaf671
2 changed files with 59 additions and 1 deletions

View File

@@ -581,7 +581,7 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
*/
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
if (OGS_FSM_CHECK(&bearer->sm, esm_state_inactive)) {
if (!OGS_FSM_CHECK(&bearer->sm, esm_state_active)) {
ogs_warn("No active EPS bearer [%d]", bearer->ebi);
ogs_warn(" IMSI[%s] NAS-EPS Type[%d] "
"ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
@@ -636,6 +636,9 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
ogs_error(" IN-ACTIVE");
else if (OGS_FSM_CHECK(&bearer->sm, esm_state_active))
ogs_error(" ACTIVE");
else if (OGS_FSM_CHECK(&bearer->sm,
esm_state_pdn_will_disconnect))
ogs_error(" PDN will disconnect");
else
ogs_error(" OTHER STATE");
@@ -643,6 +646,9 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
bearer->ebi, bearer->qos.index, bearer->sgw_s1u_teid);
}
}
ogs_error("Before ogs_s1ap_free()");
ogs_s1ap_free(&pdu);
ogs_error("After ogs_s1ap_free()");
return NULL;
}
@@ -2349,6 +2355,15 @@ ogs_pkbuf_t *s1ap_build_handover_request(
S1AP_E_RABToBeSetupItemHOReq_t *e_rab = NULL;
S1AP_GBR_QosInformation_t *gbrQosInformation = NULL;
if (!OGS_FSM_CHECK(&bearer->sm, esm_state_active)) {
ogs_warn("No active EPS bearer [%d]", bearer->ebi);
ogs_warn(" 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,
target_ue->enb_ue_s1ap_id, target_ue->mme_ue_s1ap_id);
continue;
}
item = CALLOC(1, sizeof(S1AP_E_RABToBeSetupItemHOReqIEs_t));
ASN_SEQUENCE_ADD(&E_RABToBeSetupListHOReq->list, item);
@@ -2401,6 +2416,31 @@ ogs_pkbuf_t *s1ap_build_handover_request(
}
}
if (!E_RABToBeSetupListHOReq->list.count) {
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 if (OGS_FSM_CHECK(&bearer->sm,
esm_state_pdn_will_disconnect))
ogs_error(" PDN will disconnect");
else
ogs_error(" OTHER STATE");
ogs_error(" EBI[%d] QCI[%d] SGW-S1U-TEID[%d]",
bearer->ebi, bearer->qos.index, bearer->sgw_s1u_teid);
}
}
ogs_error("Before ogs_s1ap_free()");
ogs_s1ap_free(&pdu);
ogs_error("After ogs_s1ap_free()");
return NULL;
}
ogs_s1ap_buffer_to_OCTET_STRING(
source_totarget_transparentContainer->buf,
source_totarget_transparentContainer->size,

View File

@@ -3286,6 +3286,24 @@ static void s1ap_handle_handover_required_intralte(enb_ue_t *source_ue,
return;
}
if (!SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
ogs_error("No Session Context : IMSI[%s]", mme_ue->imsi_bcd);
r = s1ap_send_handover_preparation_failure(source_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_authentication_failure);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (!ACTIVE_EPS_BEARERS_IS_AVAIABLE(mme_ue)) {
ogs_error("No active EPS bearers : IMSI[%s]", mme_ue->imsi_bcd);
r = s1ap_send_handover_preparation_failure(source_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_authentication_failure);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
source_ue->handover_type = S1AP_HandoverType_intralte;
mme_ue->nhcc++;