diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index ce0d65f51..cf576a64c 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -483,35 +483,59 @@ int ogs_nas_parse_qos_flow_descriptions( ogs_assert(description); ogs_assert(descriptions); - ogs_assert(descriptions->length); + + if (descriptions->length == 0) { + ogs_error("Length is 0"); + goto cleanup; + } + if (descriptions->buffer == NULL) { + ogs_error("Buffer is NULL"); + goto cleanup; + } + length = descriptions->length; - ogs_assert(descriptions->buffer); buffer = descriptions->buffer; size = 0; while (size < length) { memset(description, 0, sizeof(*description)); - ogs_assert(size+3 <= length); + if (size+3 > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(description, buffer+size, 3); size += 3; for (i = 0; i < description->num_of_parameter && i < OGS_NAS_MAX_NUM_OF_QOS_FLOW_PARAMETER; i++) { - ogs_assert(size+sizeof(description->param[i].identifier) <= length); + if (size+sizeof(description->param[i].identifier) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&description->param[i].identifier, buffer+size, sizeof(description->param[i].identifier)); size += sizeof(description->param[i].identifier); - ogs_assert(size+sizeof(description->param[i].len) <= length); + if (size+sizeof(description->param[i].len) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&description->param[i].len, buffer+size, sizeof(description->param[i].len)); size += sizeof(description->param[i].len); switch(description->param[i].identifier) { case OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI: - ogs_assert(description->param[i].len == 1); - ogs_assert(size+description->param[i].len <= length); + if (description->param[i].len != 1) { + ogs_error("Invalid len[%d]", description->param[i].len); + goto cleanup; + } + if (size+description->param[i].len > length) { + ogs_error("Overflow: len[%d] length[%d]", + description->param[i].len, length); + goto cleanup; + } memcpy(&description->param[i].qos_index, buffer+size, description->param[i].len); size += description->param[i].len; @@ -521,8 +545,15 @@ int ogs_nas_parse_qos_flow_descriptions( case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK: case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK: case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK: - ogs_assert(description->param[i].len == 3); - ogs_assert(size+description->param[i].len <= length); + if (description->param[i].len != 3) { + ogs_error("Invalid len[%d]", description->param[i].len); + goto cleanup; + } + if (size+description->param[i].len > length) { + ogs_error("Overflow: len[%d] length[%d]", + description->param[i].len, length); + goto cleanup; + } memcpy(&description->param[i].br, buffer+size, description->param[i].len); description->param[i].br.value = @@ -530,15 +561,17 @@ int ogs_nas_parse_qos_flow_descriptions( size += description->param[i].len; break; default: - ogs_fatal("Unknown qos_flow parameter identifier [%d]", + ogs_error("Unknown qos_flow parameter identifier [%d]", description->param[i].identifier); - ogs_assert_if_reached(); + goto cleanup; } } description++; } +cleanup: + return (int)(description-first); } @@ -777,28 +810,50 @@ int ogs_nas_parse_qos_rules( ogs_assert(rule); ogs_assert(rules); - ogs_assert(rules->length); + + if (rules->length == 0) { + ogs_error("Length is 0"); + goto cleanup; + } + if (rules->buffer == NULL) { + ogs_error("Buffer is NULL"); + goto cleanup; + } + length = rules->length; - ogs_assert(rules->buffer); buffer = rules->buffer; size = 0; while (size < length) { memset(rule, 0, sizeof(*rule)); - ogs_assert(size+sizeof(rule->identifier) <= length); + if (size+sizeof(rule->identifier) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->identifier, buffer+size, sizeof(rule->identifier)); size += sizeof(rule->identifier); - ogs_assert(size+sizeof(rule->length) <= length); + if (size+sizeof(rule->length) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->length, buffer+size, sizeof(rule->length)); rule->length = be16toh(rule->length); size += sizeof(rule->length); - ogs_assert(size+sizeof(rule->flags) <= length); + if (size+sizeof(rule->flags) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->flags, buffer+size, sizeof(rule->flags)); size += sizeof(rule->flags); + if (rule->code == 0 || rule->code == 7) { /* Reserved */ + ogs_error("Reserved Rule Code [%d]", rule->code); + goto cleanup; + } + if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE || rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { if (rule->num_of_packet_filter != 0) { @@ -806,12 +861,16 @@ int ogs_nas_parse_qos_rules( "and number of packet filter[%d]", rule->code, rule->num_of_packet_filter); rule->num_of_packet_filter = 0; + goto cleanup; } } for (i = 0; i < rule->num_of_packet_filter && i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { - ogs_assert(size+sizeof(rule->pf[i].flags) <= length); + if (size+sizeof(rule->pf[i].flags) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->pf[i].flags, buffer+size, sizeof(rule->pf[i].flags)); size += sizeof(rule->pf[i].flags); @@ -819,24 +878,35 @@ int ogs_nas_parse_qos_rules( OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) continue; - ogs_assert(size+sizeof(rule->pf[i].content.length) <= length); + if (size+sizeof(rule->pf[i].content.length) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->pf[i].content.length, buffer+size, sizeof(rule->pf[i].content.length)); size += sizeof(rule->pf[i].content.length); j = 0; len = 0; while(len < rule->pf[i].content.length) { - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].type) <= length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].type) > length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].type, buffer+size+len, sizeof(rule->pf[i].content.component[j].type)); len += sizeof(rule->pf[i].content.component[j].type); switch(rule->pf[i].content.component[j].type) { case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE: - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].proto) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].proto) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].proto, buffer+size+len, sizeof(rule->pf[i].content.component[j].proto)); @@ -844,17 +914,25 @@ int ogs_nas_parse_qos_rules( break; case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE: case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE: - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].ipv4.addr) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].ipv4.addr) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv4.addr, buffer+size+len, sizeof(rule->pf[i].content.component[j].ipv4.addr)); len += sizeof(rule->pf[i].content.component[j].ipv4.addr); - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].ipv4.mask) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].ipv4.mask) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv4.mask, buffer+size+len, sizeof(rule->pf[i].content.component[j].ipv4.mask)); @@ -862,18 +940,26 @@ int ogs_nas_parse_qos_rules( break; case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE: case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE: - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].ipv6.addr) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].ipv6.addr) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv6.addr, buffer+size+len, sizeof(rule->pf[i].content.component[j].ipv6.addr)); len += sizeof(rule->pf[i].content.component[j].ipv6.addr); - ogs_assert(size+len+ + if (size+len+ sizeof( - rule->pf[i].content.component[j].ipv6.prefixlen) <= - length); + rule->pf[i].content.component[j].ipv6.prefixlen) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv6.prefixlen, buffer+size+len, sizeof( @@ -883,10 +969,14 @@ int ogs_nas_parse_qos_rules( break; case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE: case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE: - ogs_assert(size+len+ + if (size+len+ sizeof( - rule->pf[i].content.component[j].ipv6_mask.addr) <= - length); + rule->pf[i].content.component[j].ipv6_mask.addr) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv6_mask.addr, buffer+size+len, sizeof( @@ -894,10 +984,14 @@ int ogs_nas_parse_qos_rules( len += sizeof( rule->pf[i].content.component[j].ipv6_mask.addr); - ogs_assert(size+len+ + if (size+len+ sizeof( - rule->pf[i].content.component[j].ipv6_mask.mask) <= - length); + rule->pf[i].content.component[j].ipv6_mask.mask) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].ipv6_mask.mask, buffer+size+len, sizeof( @@ -907,9 +1001,13 @@ int ogs_nas_parse_qos_rules( break; case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE: case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE: - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].port.low) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].port.low) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].port.low, buffer+size+len, sizeof(rule->pf[i].content.component[j].port.low)); @@ -919,9 +1017,13 @@ int ogs_nas_parse_qos_rules( break; case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE: case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE: - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].port.low) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].port.low) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].port.low, buffer+size+len, sizeof(rule->pf[i].content.component[j].port.low)); @@ -929,9 +1031,13 @@ int ogs_nas_parse_qos_rules( be16toh(rule->pf[i].content.component[j].port.low); len += sizeof(rule->pf[i].content.component[j].port.low); - ogs_assert(size+len+ - sizeof(rule->pf[i].content.component[j].port.high) <= - length); + if (size+len+ + sizeof(rule->pf[i].content.component[j].port.high) > + length) { + ogs_error("Overflow : size[%d] len[%d] length[%d]", + size, len, length); + goto cleanup; + } memcpy(&rule->pf[i].content.component[j].port.high, buffer+size+len, sizeof(rule->pf[i].content.component[j].port.high)); @@ -942,7 +1048,7 @@ int ogs_nas_parse_qos_rules( default: ogs_error("Unknown Packet Filter Type(%d)", rule->pf[i].content.component[j].type); - return -1; + goto cleanup; } j++; } @@ -954,11 +1060,17 @@ int ogs_nas_parse_qos_rules( rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS && rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { - ogs_assert(size+sizeof(rule->precedence) <= length); + if (size+sizeof(rule->precedence) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->precedence, buffer+size, sizeof(rule->precedence)); size += sizeof(rule->precedence); - ogs_assert(size+sizeof(rule->flow.flags) <= length); + if (size+sizeof(rule->flow.flags) > length) { + ogs_error("Overflow : size[%d] length[%d]", size, length); + goto cleanup; + } memcpy(&rule->flow.flags, buffer+size, sizeof(rule->flow.flags)); size += sizeof(rule->flow.flags); } @@ -966,6 +1078,8 @@ int ogs_nas_parse_qos_rules( rule++; } +cleanup: + return (int)(rule-first); } diff --git a/src/smf/gsm-handler.c b/src/smf/gsm-handler.c index d01252611..48bd5ce83 100644 --- a/src/smf/gsm-handler.c +++ b/src/smf/gsm-handler.c @@ -229,7 +229,11 @@ int gsm_handle_pdu_session_modification_request( int num_of_rule = 0; num_of_rule = ogs_nas_parse_qos_rules(qos_rule, requested_qos_rules); - ogs_assert(num_of_rule > 0); + if (!num_of_rule) { + ogs_error("[%s:%d] Invalid modification request", + smf_ue->supi, sess->psi); + goto cleanup; + } for (i = 0; i < num_of_rule; i++) { qos_flow = smf_qos_flow_find_by_qfi( @@ -430,7 +434,11 @@ int gsm_handle_pdu_session_modification_request( num_of_description = ogs_nas_parse_qos_flow_descriptions( qos_flow_description, requested_qos_flow_descriptions); - ogs_assert(num_of_description > 0); + if (!num_of_description) { + ogs_error("[%s:%d] Invalid modification request", + smf_ue->supi, sess->psi); + goto cleanup; + } for (i = 0; i < num_of_description; i++) { qos_flow = smf_qos_flow_find_by_qfi( @@ -478,16 +486,7 @@ int gsm_handle_pdu_session_modification_request( ogs_error("[%s:%d] Invalid modification request [modify:%d]", smf_ue->supi, sess->psi, ogs_list_count(&sess->qos_flow_to_modify_list)); - - n1smbuf = gsm_build_pdu_session_modification_reject(sess, - OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); - ogs_assert(n1smbuf); - - smf_sbi_send_sm_context_update_error_n1_n2_message( - stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - n1smbuf, OpenAPI_n2_sm_info_type_NULL, NULL); - - return OGS_ERROR; + goto cleanup; } if (pfcp_flags & OGS_PFCP_MODIFY_REMOVE) { @@ -522,4 +521,15 @@ int gsm_handle_pdu_session_modification_request( OGS_PFCP_MODIFY_UE_REQUESTED|pfcp_flags, 0)); return OGS_OK; + +cleanup: + n1smbuf = gsm_build_pdu_session_modification_reject(sess, + OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); + ogs_assert(n1smbuf); + + smf_sbi_send_sm_context_update_error_n1_n2_message( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + n1smbuf, OpenAPI_n2_sm_info_type_NULL, NULL); + + return OGS_ERROR; }