From d82f338246af961bb69f959971bc362e25df4e3b Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 27 Nov 2022 00:03:56 +0900 Subject: [PATCH] Fixed alpine stack overflow (#1911) --- lib/pfcp/message.c | 51 +++++++++++++++++++++++++++++++----- lib/pfcp/message.h | 5 ++-- lib/pfcp/support/pfcp-tlv.py | 30 ++++++++++++++++----- src/sgwc/sgwc-sm.c | 17 +++++++++--- src/sgwu/sgwu-sm.c | 17 +++++++++--- src/smf/smf-sm.c | 17 +++++++++--- src/upf/upf-sm.c | 17 +++++++++--- 7 files changed, 124 insertions(+), 30 deletions(-) diff --git a/lib/pfcp/message.c b/lib/pfcp/message.c index 58a37ec1b..d23b45cf1 100644 --- a/lib/pfcp/message.c +++ b/lib/pfcp/message.c @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by pfcp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2022-06-29 14:29:16.181253 by acetcom + * Created on: 2022-11-26 23:47:22.086824 by acetcom * from 29244-g91-modified.docx ******************************************************************************/ @@ -3977,20 +3977,25 @@ ogs_tlv_desc_t ogs_pfcp_msg_desc_pfcp_session_report_response = }}; -int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t *pkbuf) +ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf) { int rv = OGS_ERROR; ogs_pfcp_header_t *h = NULL; uint16_t size = 0; - ogs_assert(pfcp_message); + ogs_pfcp_message_t *pfcp_message = NULL; + ogs_assert(pkbuf); ogs_assert(pkbuf->len); h = (ogs_pfcp_header_t *)pkbuf->data; ogs_assert(h); - memset(pfcp_message, 0, sizeof(ogs_pfcp_message_t)); + pfcp_message = ogs_calloc(1, sizeof(*pfcp_message)); + if (!pfcp_message) { + ogs_error("No memory"); + return NULL; + } if (h->seid_presence) size = OGS_PFCP_HEADER_LEN; @@ -4007,108 +4012,142 @@ int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t *pkbuf) } if (pkbuf->len == 0) - return OGS_OK; + return pfcp_message; switch(pfcp_message->h.type) { case OGS_PFCP_HEARTBEAT_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_heartbeat_request, &ogs_pfcp_msg_desc_pfcp_heartbeat_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_heartbeat_response, &ogs_pfcp_msg_desc_pfcp_heartbeat_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_PFD_MANAGEMENT_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_pfd_management_request, &ogs_pfcp_msg_desc_pfcp_pfd_management_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_PFD_MANAGEMENT_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_pfd_management_response, &ogs_pfcp_msg_desc_pfcp_pfd_management_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_setup_request, &ogs_pfcp_msg_desc_pfcp_association_setup_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_setup_response, &ogs_pfcp_msg_desc_pfcp_association_setup_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_UPDATE_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_update_request, &ogs_pfcp_msg_desc_pfcp_association_update_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_UPDATE_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_update_response, &ogs_pfcp_msg_desc_pfcp_association_update_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_RELEASE_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_release_request, &ogs_pfcp_msg_desc_pfcp_association_release_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_ASSOCIATION_RELEASE_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_association_release_response, &ogs_pfcp_msg_desc_pfcp_association_release_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_version_not_supported_response, &ogs_pfcp_msg_desc_pfcp_version_not_supported_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_NODE_REPORT_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_node_report_request, &ogs_pfcp_msg_desc_pfcp_node_report_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_NODE_REPORT_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_node_report_response, &ogs_pfcp_msg_desc_pfcp_node_report_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_SET_DELETION_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_set_deletion_request, &ogs_pfcp_msg_desc_pfcp_session_set_deletion_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_SET_DELETION_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_set_deletion_response, &ogs_pfcp_msg_desc_pfcp_session_set_deletion_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_establishment_request, &ogs_pfcp_msg_desc_pfcp_session_establishment_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_establishment_response, &ogs_pfcp_msg_desc_pfcp_session_establishment_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_modification_request, &ogs_pfcp_msg_desc_pfcp_session_modification_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_modification_response, &ogs_pfcp_msg_desc_pfcp_session_modification_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_deletion_request, &ogs_pfcp_msg_desc_pfcp_session_deletion_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_deletion_response, &ogs_pfcp_msg_desc_pfcp_session_deletion_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_report_request, &ogs_pfcp_msg_desc_pfcp_session_report_request, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; case OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE: rv = ogs_tlv_parse_msg(&pfcp_message->pfcp_session_report_response, &ogs_pfcp_msg_desc_pfcp_session_report_response, pkbuf, OGS_TLV_MODE_T2_L2); + ogs_expect(rv == OGS_OK); break; default: ogs_warn("Not implemented(type:%d)", pfcp_message->h.type); break; } - return rv; + if (rv != OGS_OK) { + ogs_pfcp_message_free(pfcp_message); + return NULL; + } + + return pfcp_message; +} + +void ogs_pfcp_message_free(ogs_pfcp_message_t *pfcp_message) +{ + ogs_assert(pfcp_message); + ogs_free(pfcp_message); } ogs_pkbuf_t *ogs_pfcp_build_msg(ogs_pfcp_message_t *pfcp_message) diff --git a/lib/pfcp/message.h b/lib/pfcp/message.h index 281f54d47..bd999f81b 100644 --- a/lib/pfcp/message.h +++ b/lib/pfcp/message.h @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by pfcp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2022-06-29 14:29:16.169884 by acetcom + * Created on: 2022-11-26 23:47:22.074293 by acetcom * from 29244-g91-modified.docx ******************************************************************************/ @@ -1870,7 +1870,8 @@ typedef struct ogs_pfcp_message_s { }; } ogs_pfcp_message_t; -int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t *pkbuf); +ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf); +void ogs_pfcp_message_free(ogs_pfcp_message_t *pfcp_message); ogs_pkbuf_t *ogs_pfcp_build_msg(ogs_pfcp_message_t *pfcp_message); #ifdef __cplusplus diff --git a/lib/pfcp/support/pfcp-tlv.py b/lib/pfcp/support/pfcp-tlv.py index f0d04963d..7beb763b0 100644 --- a/lib/pfcp/support/pfcp-tlv.py +++ b/lib/pfcp/support/pfcp-tlv.py @@ -682,7 +682,8 @@ for (k, v) in sorted_msg_list: f.write(" };\n"); f.write("} ogs_pfcp_message_t;\n\n") -f.write("""int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t *pkbuf); +f.write("""ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf); +void ogs_pfcp_message_free(ogs_pfcp_message_t *pfcp_message); ogs_pkbuf_t *ogs_pfcp_build_msg(ogs_pfcp_message_t *pfcp_message); #ifdef __cplusplus @@ -761,20 +762,25 @@ for (k, v) in sorted_msg_list: f.write("}};\n\n") f.write("\n") -f.write("""int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t *pkbuf) +f.write("""ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf) { int rv = OGS_ERROR; ogs_pfcp_header_t *h = NULL; uint16_t size = 0; - ogs_assert(pfcp_message); + ogs_pfcp_message_t *pfcp_message = NULL; + ogs_assert(pkbuf); ogs_assert(pkbuf->len); h = (ogs_pfcp_header_t *)pkbuf->data; ogs_assert(h); - memset(pfcp_message, 0, sizeof(ogs_pfcp_message_t)); + pfcp_message = ogs_calloc(1, sizeof(*pfcp_message)); + if (!pfcp_message) { + ogs_error("No memory"); + return NULL; + } if (h->seid_presence) size = OGS_PFCP_HEADER_LEN; @@ -791,7 +797,7 @@ f.write("""int ogs_pfcp_parse_msg(ogs_pfcp_message_t *pfcp_message, ogs_pkbuf_t } if (pkbuf->len == 0) - return OGS_OK; + return pfcp_message; switch(pfcp_message->h.type) { @@ -801,13 +807,25 @@ for (k, v) in sorted_msg_list: f.write(" case OGS_%s_TYPE:\n" % v_upper(k)) f.write(" rv = ogs_tlv_parse_msg(&pfcp_message->%s,\n" % v_lower(k)) f.write(" &ogs_pfcp_msg_desc_%s, pkbuf, OGS_TLV_MODE_T2_L2);\n" % v_lower(k)) + f.write(" ogs_expect(rv == OGS_OK);\n") f.write(" break;\n") f.write(""" default: ogs_warn("Not implemented(type:%d)", pfcp_message->h.type); break; } - return rv; + if (rv != OGS_OK) { + ogs_pfcp_message_free(pfcp_message); + return NULL; + } + + return pfcp_message; +} + +void ogs_pfcp_message_free(ogs_pfcp_message_t *pfcp_message) +{ + ogs_assert(pfcp_message); + ogs_free(pfcp_message); } """) diff --git a/src/sgwc/sgwc-sm.c b/src/sgwc/sgwc-sm.c index 670c33881..e174ccdc8 100644 --- a/src/sgwc/sgwc-sm.c +++ b/src/sgwc/sgwc-sm.c @@ -72,7 +72,7 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) ogs_pfcp_node_t *pfcp_node = NULL; ogs_pfcp_xact_t *pfcp_xact = NULL; - ogs_pfcp_message_t pfcp_message; + ogs_pfcp_message_t *pfcp_message = NULL; sgwc_sm_debug(e); @@ -93,19 +93,27 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) ogs_assert(pfcp_node); ogs_assert(OGS_FSM_STATE(&pfcp_node->sm)); - if (ogs_pfcp_parse_msg(&pfcp_message, recvbuf) != OGS_OK) { + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { ogs_error("ogs_pfcp_parse_msg() failed"); ogs_pkbuf_free(recvbuf); break; } - rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message.h, &pfcp_xact); + rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; } - e->pfcp_message = &pfcp_message; + e->pfcp_message = pfcp_message; e->pfcp_xact = pfcp_xact; e->gtp_message = NULL; @@ -122,6 +130,7 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) if (pfcp_xact->gtpbuf) ogs_pkbuf_free(pfcp_xact->gtpbuf); ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; case SGWC_EVT_SXA_TIMER: diff --git a/src/sgwu/sgwu-sm.c b/src/sgwu/sgwu-sm.c index 6f8a29aee..e58760c3b 100644 --- a/src/sgwu/sgwu-sm.c +++ b/src/sgwu/sgwu-sm.c @@ -41,7 +41,7 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e) int rv; ogs_pkbuf_t *recvbuf = NULL; - ogs_pfcp_message_t pfcp_message; + ogs_pfcp_message_t *pfcp_message = NULL; ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; @@ -61,19 +61,27 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e) node = e->pfcp_node; ogs_assert(node); - if (ogs_pfcp_parse_msg(&pfcp_message, recvbuf) != OGS_OK) { + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { ogs_error("ogs_pfcp_parse_msg() failed"); ogs_pkbuf_free(recvbuf); break; } - rv = ogs_pfcp_xact_receive(node, &pfcp_message.h, &xact); + rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; } - e->pfcp_message = &pfcp_message; + e->pfcp_message = pfcp_message; e->pfcp_xact = xact; ogs_fsm_dispatch(&node->sm, e); if (OGS_FSM_CHECK(&node->sm, sgwu_pfcp_state_exception)) { @@ -82,6 +90,7 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e) } ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; case SGWU_EVT_SXA_TIMER: case SGWU_EVT_SXA_NO_HEARTBEAT: diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index e088028a2..34e77f01e 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -66,7 +66,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_pfcp_node_t *pfcp_node = NULL; ogs_pfcp_xact_t *pfcp_xact = NULL; - ogs_pfcp_message_t pfcp_message; + ogs_pfcp_message_t *pfcp_message = NULL; ogs_sbi_stream_t *stream = NULL; ogs_sbi_request_t *sbi_request = NULL; @@ -384,19 +384,27 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(pfcp_node); ogs_assert(OGS_FSM_STATE(&pfcp_node->sm)); - if (ogs_pfcp_parse_msg(&pfcp_message, recvbuf) != OGS_OK) { + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { ogs_error("ogs_pfcp_parse_msg() failed"); ogs_pkbuf_free(recvbuf); break; } - rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message.h, &pfcp_xact); + rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; } - e->pfcp_message = &pfcp_message; + e->pfcp_message = pfcp_message; e->pfcp_xact = pfcp_xact; e->gtp2_message = NULL; @@ -412,6 +420,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) } ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; case SMF_EVT_N4_TIMER: case SMF_EVT_N4_NO_HEARTBEAT: diff --git a/src/upf/upf-sm.c b/src/upf/upf-sm.c index 3e080408d..71f55881a 100644 --- a/src/upf/upf-sm.c +++ b/src/upf/upf-sm.c @@ -44,7 +44,7 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e) int rv; ogs_pkbuf_t *recvbuf = NULL; - ogs_pfcp_message_t pfcp_message; + ogs_pfcp_message_t *pfcp_message = NULL; ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; @@ -66,19 +66,27 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e) node = e->pfcp_node; ogs_assert(node); - if (ogs_pfcp_parse_msg(&pfcp_message, recvbuf) != OGS_OK) { + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { ogs_error("ogs_pfcp_parse_msg() failed"); ogs_pkbuf_free(recvbuf); break; } - rv = ogs_pfcp_xact_receive(node, &pfcp_message.h, &xact); + rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; } - e->pfcp_message = &pfcp_message; + e->pfcp_message = pfcp_message; e->pfcp_xact = xact; ogs_fsm_dispatch(&node->sm, e); if (OGS_FSM_CHECK(&node->sm, upf_pfcp_state_exception)) { @@ -87,6 +95,7 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e) } ogs_pkbuf_free(recvbuf); + ogs_pfcp_message_free(pfcp_message); break; case UPF_EVT_N4_TIMER: case UPF_EVT_N4_NO_HEARTBEAT: