CVE-2024-40130 (published 2024-07-16T19:15Z)

open5gs v2.6.4 is vulnerable to Buffer Overflow. via /lib/core/abts.c.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/open5gs/open5gs
commit_details: repo_url: https://github.com/open5gs/open5gs
author: Sukchan Lee
author_date: 2023-09-05 21:56:53+09:00
msg: Fixed dynamic-stack-buffer-overflow (#2578, #2577)
repository: repo_url: https://github.com/open5gs/open5gs
repo_name: open5gs/open5gs
description: Open5GS is a C-language Open Source implementation for 5G Core and EPC, i.e. the core network of LTE/NR network (Release-17)
repo_language: C
owner: open5gs
file_changes: filename: main.c
change_type: ModificationType.MODIFY
diff: @@ -111,7 +111,7 @@ int main(int argc, const char *const argv[])
         bool enable_debug;
         bool enable_trace;
     } optarg;
-    const char *argv_out[argc];
+    const char *argv_out[argc+1];
 
     memset(&optarg, 0, sizeof(optarg));
 

programming_language: C++
filename: 5gc-init.c
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,7 @@ int app_initialize(const char *const argv[])
     bool user_config = false;
     int i = 0;
 
-    for (i = 0; argv[i]; i++) {
+    for (i = 0; argv[i] && i < OGS_ARG_MAX-3; i++) {
         if (strcmp("-c", argv[i]) == 0) {
             user_config = true; 
         }

programming_language: C
filename: app-init.c
change_type: ModificationType.MODIFY
diff: @@ -42,7 +42,7 @@ int app_initialize(const char *const argv[])
     bool user_config = false;
     int i = 0;
 
-    for (i = 0; argv[i]; i++) {
+    for (i = 0; argv[i] && i < OGS_ARG_MAX-3; i++) {
         if (strcmp("-c", argv[i]) == 0) {
             user_config = true;
         }

programming_language: C
filename: epc-init.c
change_type: ModificationType.MODIFY
diff: @@ -33,7 +33,7 @@ int app_initialize(const char *const argv[])
     bool user_config = false;
     int i = 0;
 
-    for (i = 0; argv[i]; i++) {
+    for (i = 0; argv[i] && i < OGS_ARG_MAX-3; i++) {
         if (strcmp("-c", argv[i]) == 0) {
             user_config = true; 
         }

programming_language: C
filename: application.c
change_type: ModificationType.MODIFY
diff: @@ -27,7 +27,7 @@ static void run(int argc, const char *const argv[],
     bool user_config;
 
     /* '-f sample-XXXX.conf -e error' is always added */
-    const char *argv_out[argc+4], *new_argv[argc+4];
+    const char *argv_out[argc+5], *new_argv[argc+5];
     int argc_out;
 
     char conf_file[OGS_MAX_FILEPATH_LEN];

programming_language: C
filename: context.c
change_type: ModificationType.MODIFY
diff: @@ -127,7 +127,8 @@ static int test_context_validation(void)
 
     if (test_self()->nr_served_tai[index].list2.num) {
         memcpy(&test_self()->nr_tai,
-            &test_self()->nr_served_tai[index].list2.tai[0], sizeof(ogs_5gs_tai_t));
+            &test_self()->nr_served_tai[index].list2.tai[0],
+            sizeof(ogs_5gs_tai_t));
     } else if (test_self()->nr_served_tai[index].list1.tai[0].num) {
         test_self()->nr_tai.tac =
             test_self()->nr_served_tai[index].list1.tai[0].tac;

programming_language: C
filename: context.h
change_type: ModificationType.MODIFY
diff: @@ -477,6 +477,13 @@ typedef struct test_bearer_s {
 
     uint32_t        sgw_s1u_teid;   /* SGW-S1U TEID */
     ogs_ip_t        sgw_s1u_ip;     /* SGW-S1U IPv4/IPv6 */
+    struct {
+        /* Indirect Forwarding */
+        uint32_t dl_teid;
+        ogs_ip_t dl_ip;
+        uint32_t ul_teid;
+        ogs_ip_t ul_ip;
+    } handover;
 
     uint32_t        enb_s1u_teid;   /* eNB-S1U TEID */
     ogs_sockaddr_t  *enb_s1u_addr;  /* eNB-S1U IPv4 */

programming_language: C
filename: gtpu.c
change_type: ModificationType.MODIFY
diff: @@ -535,9 +535,7 @@ int test_gtpu_send_indirect_data_forwarding(
         ext_hdesc.qos_flow_identifier = bearer->qfi;
 
     } else if (bearer->ebi) {
-
-        ogs_fatal("Not implmented EPC Indirect Tunnel");
-        ogs_assert_if_reached();
+        gtp_hdesc.teid = bearer->handover.ul_teid;
 
     } else {
         ogs_fatal("No QFI[%d] and EBI[%d]", bearer->qfi, bearer->ebi);

programming_language: C
filename: ngap-build.c
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,7 @@ static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
 ogs_pkbuf_t *testngap_build_ng_setup_request(uint32_t gnb_id, uint8_t bitsize)
 {
     ogs_pkbuf_t *pkbuf = NULL;
-    int i, j;
+    int i, j, k, num = 0;
     ogs_plmn_id_t *plmn_id = NULL;
     const char *ran_node_name = "5G gNB-CU";
 
@@ -118,48 +118,58 @@ ogs_pkbuf_t *testngap_build_ng_setup_request(uint32_t gnb_id, uint8_t bitsize)
     ogs_asn_buffer_to_OCTET_STRING((char*)ran_node_name,
             strlen(ran_node_name), RANNodeName);
 
-    SupportedTAItem = CALLOC(1, sizeof(NGAP_SupportedTAItem_t));
     if (test_self()->nr_served_tai[0].list2.num)
-        ogs_asn_uint24_to_OCTET_STRING(
-            test_self()->nr_served_tai[0].list2.tai[0].tac,
-            &SupportedTAItem->tAC);
+        num = test_self()->nr_served_tai[0].list2.num;
     else if (test_self()->nr_served_tai[0].list0.tai[0].num)
-        ogs_asn_uint24_to_OCTET_STRING(
-            test_self()->nr_served_tai[0].list0.tai[0].tac[0],
-                &SupportedTAItem->tAC);
+        num = test_self()->nr_served_tai[0].list0.tai[0].num;
     else
         ogs_assert_if_reached();
 
-    for (i = 0; i < test_self()->num_of_plmn_support; i++) {
-        plmn_id = &test_self()->plmn_support[i].plmn_id;
+    for (i = 0; i < num; i++) {
+        SupportedTAItem = CALLOC(1, sizeof(NGAP_SupportedTAItem_t));
+        if (test_self()->nr_served_tai[0].list2.num)
+            ogs_asn_uint24_to_OCTET_STRING(
+                test_self()->nr_served_tai[0].list2.tai[i].tac,
+                &SupportedTAItem->tAC);
+        else if (test_self()->nr_served_tai[0].list0.tai[0].num)
+            ogs_asn_uint24_to_OCTET_STRING(
+                test_self()->nr_served_tai[0].list0.tai[0].tac[i],
+                    &SupportedTAItem->tAC);
+        else
+            ogs_assert_if_reached();
 
-        BroadcastPLMNItem = CALLOC(1, sizeof(NGAP_BroadcastPLMNItem_t));
+        for (j = 0; j < test_self()->num_of_plmn_support; j++) {
+            plmn_id = &test_self()->plmn_support[j].plmn_id;
 
-        ogs_asn_buffer_to_OCTET_STRING(
-                plmn_id, OGS_PLMN_ID_LEN, &BroadcastPLMNItem->pLMNIdentity);
+            BroadcastPLMNItem = CALLOC(1, sizeof(NGAP_BroadcastPLMNItem_t));
 
-        for (j = 0; j < test_self()->plmn_support[i].num_of_s_nssai; j++) {
-            ogs_s_nssai_t *s_nssai = &test_self()->plmn_support[i].s_nssai[j];
+            ogs_asn_buffer_to_OCTET_STRING(
+                    plmn_id, OGS_PLMN_ID_LEN, &BroadcastPLMNItem->pLMNIdentity);
 
-            SliceSupportItem = CALLOC(1, sizeof(NGAP_SliceSupportItem_t));
-            ogs_asn_uint8_to_OCTET_STRING(s_nssai->sst,
-                    &SliceSupportItem->s_NSSAI.sST);
-            if (s_nssai->sd.v != OGS_S_NSSAI_NO_SD_VALUE) {
-                SliceSupportItem->s_NSSAI.sD = CALLOC(1, sizeof(NGAP_SD_t));
-                ogs_asn_uint24_to_OCTET_STRING(
-                        s_nssai->sd, SliceSupportItem->s_NSSAI.sD);
+            for (k = 0; k < test_self()->plmn_support[j].num_of_s_nssai; k++) {
+                ogs_s_nssai_t *s_nssai =
+                    &test_self()->plmn_support[j].s_nssai[k];
+
+                SliceSupportItem = CALLOC(1, sizeof(NGAP_SliceSupportItem_t));
+                ogs_asn_uint8_to_OCTET_STRING(s_nssai->sst,
+                        &SliceSupportItem->s_NSSAI.sST);
+                if (s_nssai->sd.v != OGS_S_NSSAI_NO_SD_VALUE) {
+                    SliceSupportItem->s_NSSAI.sD = CALLOC(1, sizeof(NGAP_SD_t));
+                    ogs_asn_uint24_to_OCTET_STRING(
+                            s_nssai->sd, SliceSupportItem->s_NSSAI.sD);
+                }
+
+                ASN_SEQUENCE_ADD(&BroadcastPLMNItem->tAISliceSupportList.list,
+                                SliceSupportItem);
             }
 
-            ASN_SEQUENCE_ADD(&BroadcastPLMNItem->tAISliceSupportList.list,
-                            SliceSupportItem);
+            ASN_SEQUENCE_ADD(&SupportedTAItem->broadcastPLMNList.list,
+                    BroadcastPLMNItem);
         }
 
-        ASN_SEQUENCE_ADD(&SupportedTAItem->broadcastPLMNList.list,
-                BroadcastPLMNItem);
+        ASN_SEQUENCE_ADD(&SupportedTAList->list, SupportedTAItem);
     }
 
-    ASN_SEQUENCE_ADD(&SupportedTAList->list, SupportedTAItem);
-
     *PagingDRX = NGAP_PagingDRX_v32;
 
     return ogs_ngap_encode(&pdu);
@@ -168,7 +178,7 @@ ogs_pkbuf_t *testngap_build_ng_setup_request(uint32_t gnb_id, uint8_t bitsize)
 ogs_pkbuf_t *testngap_build_ran_configuration_update(bool supported_ta_list)
 {
     ogs_pkbuf_t *pkbuf = NULL;
-    int i, j;
+    int i, j, k, num;
     ogs_plmn_id_t *plmn_id = NULL;
 
     NGAP_NGAP_PDU_t pdu;
@@ -210,48 +220,62 @@ ogs_pkbuf_t *testngap_build_ran_configuration_update(bool supported_ta_list)
 
         SupportedTAList = &ie->value.choice.SupportedTAList;
 
-        SupportedTAItem = CALLOC(1, sizeof(NGAP_SupportedTAItem_t));
         if (test_self()->nr_served_tai[0].list2.num)
-            ogs_asn_uint24_to_OCTET_STRING(
-                test_self()->nr_served_tai[0].list2.tai[0].tac,
-                &SupportedTAItem->tAC);
+            num = test_self()->nr_served_tai[0].list2.num;
         else if (test_self()->nr_served_tai[0].list0.tai[0].num)
-            ogs_asn_uint24_to_OCTET_STRING(
-                test_self()->nr_served_tai[0].list0.tai[0].tac[0],
-                    &SupportedTAItem->tAC);
+            num = test_self()->nr_served_tai[0].list0.tai[0].num;
         else
             ogs_assert_if_reached();
 
-        for (i = 0; i < test_self()->num_of_plmn_support; i++) {
-            plmn_id = &test_self()->plmn_support[i].plmn_id;
-
-            BroadcastPLMNItem = CALLOC(1, sizeof(NGAP_BroadcastPLMNItem_t));
-
-            ogs_asn_buffer_to_OCTET_STRING(
-                    plmn_id, OGS_PLMN_ID_LEN, &BroadcastPLMNItem->pLMNIdentity);
-
-            for (j = 0; j < test_self()->plmn_support[i].num_of_s_nssai; j++) {
-                ogs_s_nssai_t *s_nssai =
-                    &test_self()->plmn_support[i].s_nssai[j];
-
-                SliceSupportItem = CALLOC(1, sizeof(NGAP_SliceSupportItem_t));
-                ogs_asn_uint8_to_OCTET_STRING(s_nssai->sst,
-                        &SliceSupportItem->s_NSSAI.sST);
-                if (s_nssai->sd.v != OGS_S_NSSAI_NO_SD_VALUE) {
-                    SliceSupportItem->s_NSSAI.sD = CALLOC(1, sizeof(NGAP_SD_t));
-                    ogs_asn_uint24_to_OCTET_STRING(
-                            s_nssai->sd, SliceSupportItem->s_NSSAI.sD);
+        for (i = 0; i < num; i++) {
+            SupportedTAItem = CALLOC(1, sizeof(NGAP_SupportedTAItem_t));
+            if (test_self()->nr_served_tai[0].list2.num)
+                ogs_asn_uint24_to_OCTET_STRING(
+                    test_self()->nr_served_tai[0].list2.tai[i].tac,
+                    &SupportedTAItem->tAC);
+            else if (test_self()->nr_served_tai[0].list0.tai[0].num)
+                ogs_asn_uint24_to_OCTET_STRING(
+                    test_self()->nr_served_tai[0].list0.tai[0].tac[i],
+                        &SupportedTAItem->tAC);
+            else
+                ogs_assert_if_reached();
+
+            for (j = 0; j < test_self()->num_of_plmn_support; j++) {
+                plmn_id = &test_self()->plmn_support[j].plmn_id;
+
+                BroadcastPLMNItem = CALLOC(1, sizeof(NGAP_BroadcastPLMNItem_t));
+
+                ogs_asn_buffer_to_OCTET_STRING(
+                        plmn_id, OGS_PLMN_ID_LEN,
+                        &BroadcastPLMNItem->pLMNIdentity);
+
+                for (k = 0; k < test_self()->plmn_support[j].num_of_s_nssai;
+                        k++) {
+                    ogs_s_nssai_t *s_nssai =
+                        &test_self()->plmn_support[j].s_nssai[k];
+
+                    SliceSupportItem = CALLOC(1,
+                            sizeof(NGAP_SliceSupportItem_t));
+                    ogs_asn_uint8_to_OCTET_STRING(s_nssai->sst,
+                            &SliceSupportItem->s_NSSAI.sST);
+                    if (s_nssai->sd.v != OGS_S_NSSAI_NO_SD_VALUE) {
+                        SliceSupportItem->s_NSSAI.sD = CALLOC(
+                                1, sizeof(NGAP_SD_t));
+                        ogs_asn_uint24_to_OCTET_STRING(
+                                s_nssai->sd, SliceSupportItem->s_NSSAI.sD);
+                    }
+
+                    ASN_SEQUENCE_ADD(
+                            &BroadcastPLMNItem->tAISliceSupportList.list,
+                            SliceSupportItem);
                 }
 
-                ASN_SEQUENCE_ADD(&BroadcastPLMNItem->tAISliceSupportList.list,
-                                SliceSupportItem);
+                ASN_SEQUENCE_ADD(&SupportedTAItem->broadcastPLMNList.list,
+                        BroadcastPLMNItem);
             }
 
-            ASN_SEQUENCE_ADD(&SupportedTAItem->broadcastPLMNList.list,
-                    BroadcastPLMNItem);
+            ASN_SEQUENCE_ADD(&SupportedTAList->list, SupportedTAItem);
         }
-
-        ASN_SEQUENCE_ADD(&SupportedTAList->list, SupportedTAItem);
     }
 
     return ogs_ngap_encode(&pdu);

programming_language: C
filename: s1ap-handler.c
change_type: ModificationType.MODIFY
diff: @@ -479,6 +479,7 @@ void tests1ap_handle_handover_command(
     char buf[OGS_ADDRSTRLEN];
 
     test_sess_t *sess = NULL;
+    test_bearer_t *bearer = NULL;
 
     S1AP_S1AP_PDU_t pdu;
     S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
@@ -487,6 +488,8 @@ void tests1ap_handle_handover_command(
     S1AP_HandoverCommandIEs_t *ie = NULL;
     S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
     S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
+    S1AP_E_RABSubjecttoDataForwardingList_t
+        *E_RABSubjecttoDataForwardingList = NULL;
 
     ogs_assert(test_ue);
     ogs_assert(message);
@@ -505,6 +508,10 @@ void tests1ap_handle_handover_command(
         case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
             ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
             break;
+        case S1AP_ProtocolIE_ID_id_E_RABSubjecttoDataForwardingList:
+            E_RABSubjecttoDataForwardingList =
+                &ie->value.choice.E_RABSubjecttoDataForwardingList;
+            break;
         default:
             break;
         }
@@ -514,6 +521,44 @@ void tests1ap_handle_handover_command(
         test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
     if (ENB_UE_S1AP_ID)
         test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
+
+    if (E_RABSubjecttoDataForwardingList) {
+        for (i = 0; i < E_RABSubjecttoDataForwardingList->list.count; i++) {
+            S1AP_E_RABDataForwardingItemIEs_t *ie = NULL;
+            S1AP_E_RABDataForwardingItem_t *e_rab = NULL;
+
+            ie = (S1AP_E_RABDataForwardingItemIEs_t *)
+                    E_RABSubjecttoDataForwardingList->list.array[i];
+            ogs_assert(ie);
+            e_rab = &ie->value.choice.E_RABDataForwardingItem;
+
+            bearer = test_bearer_find_by_ue_ebi(test_ue, e_rab->e_RAB_ID);
+            ogs_assert(bearer);
+
+            if (e_rab->dL_gTP_TEID) {
+                memcpy(&bearer->handover.dl_teid, e_rab->dL_gTP_TEID->buf,
+                        sizeof(bearer->handover.dl_teid));
+                bearer->handover.dl_teid = be32toh(bearer->handover.dl_teid);
+            }
+            if (e_rab->dL_transportLayerAddress) {
+                ogs_assert(OGS_OK ==
+                        ogs_asn_BIT_STRING_to_ip(
+                            e_rab->dL_transportLayerAddress,
+                            &bearer->handover.dl_ip));
+            }
+            if (e_rab->uL_GTP_TEID) {
+                memcpy(&bearer->handover.ul_teid, e_rab->uL_GTP_TEID->buf,
+                        sizeof(bearer->handover.ul_teid));
+                bearer->handover.ul_teid = be32toh(bearer->handover.ul_teid);
+            }
+            if (e_rab->uL_TransportLayerAddress) {
+                ogs_assert(OGS_OK ==
+                        ogs_asn_BIT_STRING_to_ip(
+                            e_rab->uL_TransportLayerAddress,
+                            &bearer->handover.ul_ip));
+            }
+        }
+    }
 }
 
 void tests1ap_handle_handover_preparation_failure(

programming_language: C
filename: abts-main.c
change_type: ModificationType.MODIFY
diff: @@ -77,7 +77,7 @@ int main(int argc, const char *const argv[])
         char *log_level;
         char *domain_mask;
     } optarg;
-    const char *argv_out[argc+2]; /* '-e error' is always added */
+    const char *argv_out[argc+3]; /* '-e error' is always added */
     
     abts_suite *suite = NULL;
     ogs_pkbuf_config_t config;

programming_language: C
filename: abts-main.c
change_type: ModificationType.MODIFY
diff: @@ -50,7 +50,7 @@ int main(int argc, const char *const argv[])
         char *log_level;
         char *domain_mask;
     } optarg;
-    const char *argv_out[argc+2]; /* '-e error' is always added */
+    const char *argv_out[argc+3]; /* '-e error' is always added */
     
     abts_suite *suite = NULL;
     ogs_pkbuf_config_t config;

programming_language: C
filename: epc-s1-test.c
change_type: ModificationType.MODIFY
diff: @@ -28,6 +28,7 @@ static void test1_func(abts_case *tc, void *data)
     ogs_pkbuf_t *esmbuf;
     ogs_pkbuf_t *sendbuf;
     ogs_pkbuf_t *recvbuf;
+    ogs_pkbuf_t *pkbuf;
     ogs_s1ap_message_t message;
 
     ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
@@ -329,6 +330,35 @@ static void test1_func(abts_case *tc, void *data)
     ABTS_PTR_NOTNULL(tc, recvbuf);
     tests1ap_recv(test_ue, recvbuf);
 
+    /* Send GTP-U ICMP Packet */
+    bearer = test_bearer_find_by_ue_ebi(test_ue, 5);
+    ogs_assert(bearer);
+    rv = test_gtpu_send_ping(gtpu1, bearer, TEST_PING_IPV4);
+    ABTS_INT_EQUAL(tc, OGS_OK, rv);
+
+    /* Receive GTP-U ICMP Packet */
+    recvbuf = test_gtpu_read(gtpu1);
+    ABTS_PTR_NOTNULL(tc, recvbuf);
+
+    /* Copy ICMP Packet */
+    pkbuf = ogs_pkbuf_alloc(NULL, 200);
+    ogs_assert(pkbuf);
+    ogs_pkbuf_reserve(pkbuf, OGS_GTPV1U_5GC_HEADER_LEN);
+    ogs_pkbuf_put(pkbuf, 200-OGS_GTPV1U_5GC_HEADER_LEN);
+    memset(pkbuf->data, 0, pkbuf->len);
+    memcpy(pkbuf->data, recvbuf->data + 8, recvbuf->len - 8);
+
+    ogs_pkbuf_free(recvbuf);
+
+    /* Send GTP-U Packet with Indirect Data Forwarding */
+    rv = test_gtpu_send_indirect_data_forwarding(gtpu1, bearer, pkbuf);
+    ABTS_INT_EQUAL(tc, OGS_OK, rv);
+
+    /* Receive GTP-U ICMP Packet */
+    recvbuf = testgnb_gtpu_read(gtpu2);
+    ABTS_PTR_NOTNULL(tc, recvbuf);
+    ogs_pkbuf_free(recvbuf);
+
     /* Send eNB Status Transfer */
     sendbuf = test_s1ap_build_enb_status_transfer(test_ue);
     ABTS_PTR_NOTNULL(tc, sendbuf);

programming_language: C
filename: abts-main.c
change_type: ModificationType.MODIFY
diff: @@ -45,7 +45,7 @@ int main(int argc, const char *const argv[])
         char *log_level;
         char *domain_mask;
     } optarg;
-    const char *argv_out[argc+2]; /* '-e error' is always added */
+    const char *argv_out[argc+3]; /* '-e error' is always added */
     
     abts_suite *suite = NULL;
     ogs_pkbuf_config_t config;

programming_language: C
filename: abts-main.c
change_type: ModificationType.MODIFY
diff: @@ -67,7 +67,7 @@ int main(int argc, const char *const argv[])
         char *log_level;
         char *domain_mask;
     } optarg;
-    const char *argv_out[argc+2]; /* '-e error' is always added */
+    const char *argv_out[argc+3]; /* '-e error' is always added */
     
     abts_suite *suite = NULL;
     ogs_pkbuf_config_t config;

programming_language: C