From 1a42e0b1d135749058639e2a3aba984c5f0a5d0b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 7 Apr 2021 19:27:17 +0200 Subject: [PATCH] epc,nas: add error handling for all make_byte_buffer() calls not handling the case where allocation was failing was causing a segfault. It seems that when doing high rate UDP iperf and disconnecting the UE causes the buffer pool to become empty due to the PDU buffering. Thus, causing a crash when attaching the UE again. --- srsepc/src/mme/nas.cc | 75 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 9d233da67..45f28769e 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -274,6 +274,10 @@ bool nas::handle_imsi_attach_request_unknown_ue(uint32_t // Pack NAS Authentication Request in Downlink NAS Transport msg nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_ctx->pack_authentication_request(nas_tx.get()); // Send reply to eNB @@ -383,6 +387,10 @@ bool nas::handle_guti_attach_request_unknown_ue(uint32_t // Send Identity Request nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + srslog::fetch_basic_logger("NAS").error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_ctx->pack_identity_request(nas_tx.get()); s1ap->send_downlink_nas_transport( nas_ctx->m_ecm_ctx.enb_ue_s1ap_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), nas_ctx->m_ecm_ctx.enb_sri); @@ -459,6 +467,10 @@ bool nas::handle_guti_attach_request_known_ue(nas* // Send reply nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } if (ecm_ctx->eit) { srsran::console("Secure ESM information transfer requested.\n"); nas_logger.info("Secure ESM information transfer requested."); @@ -531,7 +543,11 @@ bool nas::handle_guti_attach_request_known_ue(nas* // Restarting security context. Reseting eKSI to 0. sec_ctx->eksi = 0; - nas_tx = srsran::unique_byte_buffer_t(); + nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_ctx->pack_authentication_request(nas_tx.get()); // Send reply to eNB @@ -581,6 +597,10 @@ bool nas::handle_service_request(uint32_t m_tmsi, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_tmp.pack_service_reject(nas_tx.get(), LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), *enb_sri); return true; @@ -595,6 +615,10 @@ bool nas::handle_service_request(uint32_t m_tmsi, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_tmp.pack_service_reject(nas_tx.get(), LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), *enb_sri); return true; @@ -679,6 +703,10 @@ bool nas::handle_service_request(uint32_t m_tmsi, s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_ctx->pack_service_reject(nas_tx.get(), LIBLTE_MME_EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); s1ap->send_downlink_nas_transport(ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, nas_tx.get(), *enb_sri); @@ -783,6 +811,10 @@ bool nas::handle_tracking_area_update_request(uint32_t m_tmsi, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + nas_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } nas_tmp.pack_tracking_area_update_reject(nas_tx.get(), LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), *enb_sri); return true; @@ -886,6 +918,10 @@ bool nas::handle_attach_request(srsran::byte_buffer_t* nas_rx) // Pack NAS Authentication Request in Downlink NAS Transport msg srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } pack_authentication_request(nas_tx.get()); // Send reply to eNB @@ -903,8 +939,7 @@ bool nas::handle_attach_request(srsran::byte_buffer_t* nas_rx) bool nas::handle_authentication_response(srsran::byte_buffer_t* nas_rx) { - srsran::unique_byte_buffer_t nas_tx; - LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp = {}; bool ue_valid = true; // Get NAS authentication response @@ -927,7 +962,11 @@ bool nas::handle_authentication_response(srsran::byte_buffer_t* nas_rx) } } - nas_tx = srsran::make_byte_buffer(); + srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } if (!ue_valid) { // Authentication rejected srsran::console("UE Authentication Rejected.\n"); @@ -955,8 +994,7 @@ bool nas::handle_authentication_response(srsran::byte_buffer_t* nas_rx) bool nas::handle_security_mode_complete(srsran::byte_buffer_t* nas_rx) { - srsran::unique_byte_buffer_t nas_tx; - LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp = {}; // Get NAS security mode complete LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &sm_comp); @@ -970,7 +1008,11 @@ bool nas::handle_security_mode_complete(srsran::byte_buffer_t* nas_rx) srsran::console("Security Mode Command Complete -- IMSI: %015" PRIu64 "\n", m_emm_ctx.imsi); // Check wether secure ESM information transfer is required - nas_tx = srsran::make_byte_buffer(); + srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } if (m_ecm_ctx.eit == true) { // Secure ESM information transfer is required srsran::console("Sending ESM information request\n"); @@ -997,7 +1039,6 @@ bool nas::handle_attach_complete(srsran::byte_buffer_t* nas_rx) LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; uint8_t pd, msg_type; LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; - srsran::unique_byte_buffer_t nas_tx; // Get NAS authentication response std::memset(&attach_comp, 0, sizeof(attach_comp)); @@ -1027,7 +1068,11 @@ bool nas::handle_attach_complete(srsran::byte_buffer_t* nas_rx) m_emm_ctx.imsi, act_bearer.eps_bearer_id, &m_esm_ctx[act_bearer.eps_bearer_id].enb_fteid); // Send reply to EMM Info to UE - nas_tx = srsran::make_byte_buffer(); + srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } pack_emm_information(nas_tx.get()); m_s1ap->send_downlink_nas_transport( @@ -1117,6 +1162,10 @@ bool nas::handle_identity_response(srsran::byte_buffer_t* nas_rx) // Pack NAS Authentication Request in Downlink NAS Transport msg nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } pack_authentication_request(nas_tx.get()); // Send reply to eNB @@ -1138,6 +1187,10 @@ bool nas::handle_tracking_area_update_request(srsran::byte_buffer_t* nas_rx) /* TAU handling unsupported, therefore send TAU reject with cause IMPLICITLY DETACHED. * this will trigger full re-attach by the UE, instead of going to a TAU request loop */ nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } // TODO we could enable integrity protection in some cases, but UE should comply anyway pack_tracking_area_update_reject(nas_tx.get(), LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); // Send reply @@ -1195,6 +1248,10 @@ bool nas::handle_authentication_failure(srsran::byte_buffer_t* nas_rx) // Pack NAS Authentication Request in Downlink NAS Transport msg nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } pack_authentication_request(nas_tx.get()); // Send reply to eNB