sbi/nrf: This patch improves robustness of SBI client creation, HTTP parsing,

and NRF NFProfile validation by adding defensive checks and safer
memory handling.

Key changes:

1) Prevent client creation without endpoint information
   - Added error logging when NF instance lacks FQDN/IP endpoint data.
   - Avoids creating invalid SBI clients with incomplete connectivity info.

2) Enforce query parameter limits
   - Added explicit bounds check against MAX_NUM_OF_PARAM_IN_QUERY.
   - Returns HTTP 400 instead of triggering fatal assertion.
   - Prevents potential DoS via excessive query parameters.

3) Safer HTTP body memory handling
   - Introduced temporary buffer for malloc/realloc results.
   - Prevents loss of original pointer on realloc failure.
   - Returns NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE on overflow.
   - Improves resilience against large/fragmented payload attacks.

4) Validate NFProfile endpoint presence during registration
   - Rejects NFProfile lacking FQDN, IPv4, and IPv6 addresses.
   - Returns HTTP 400 with explicit error message.
   - Prevents NRF from storing unreachable NF instances.

Overall, this patch strengthens SBI stability and protects against
resource exhaustion, malformed requests, and invalid NF registrations.

Issues: #4243, #4244, #4245
This commit is contained in:
Sukchan Lee 2026-02-13 10:27:39 +09:00
parent b3169c8ee9
commit 2575c49803
3 changed files with 37 additions and 11 deletions

View file

@ -2052,7 +2052,8 @@ static ogs_sbi_client_t *nf_instance_find_client(
return NULL;
}
}
}
} else
ogs_error("No endpoint info, skip client creation");
return client;
}

View file

@ -1397,6 +1397,21 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
j = 0;
while(params[j].key && params[j].val) {
if (j >= MAX_NUM_OF_PARAM_IN_QUERY) {
ogs_error("Too many query params (max=%d)",
MAX_NUM_OF_PARAM_IN_QUERY);
ogs_sbi_server_send_error(stream,
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL,
"Too many query parameters", NULL, NULL);
ogs_free(query);
ogs_free(namestr);
ogs_free(valuestr);
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if (strlen(params[j].key))
ogs_sbi_header_set(request->http.params,
params[j].key, params[j].val);
@ -1406,12 +1421,6 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
j++;
}
if (j >= MAX_NUM_OF_PARAM_IN_QUERY+1) {
ogs_fatal("Maximum number(%d) of query params reached",
MAX_NUM_OF_PARAM_IN_QUERY);
ogs_assert_if_reached();
}
ogs_free(query);
} else if (namebuf.len == sizeof(METHOD) - 1 &&
@ -1439,6 +1448,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
{
ogs_sbi_stream_t *stream = NULL;
ogs_sbi_request_t *request = NULL;
char *content = NULL;
size_t offset = 0;
@ -1460,24 +1470,26 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
ogs_assert(request->http.content_length == 0);
ogs_assert(offset == 0);
request->http.content = (char*)ogs_malloc(len + 1);
content = (char*)ogs_malloc(len + 1);
} else {
ogs_assert(request->http.content_length != 0);
request->http.content = (char*)ogs_realloc(
content = (char*)ogs_realloc(
request->http.content, request->http.content_length + len + 1);
}
if (!request->http.content) {
if (!content) {
stream->memory_overflow = true;
ogs_error("Overflow : Content-Length[%d], len[%d]",
(int)request->http.content_length, (int)len);
ogs_log_hexdump(OGS_LOG_ERROR, data, len);
return 0;
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
request->http.content = content;
offset = request->http.content_length;
request->http.content_length += len;

View file

@ -86,6 +86,19 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance,
return false;
}
if (!NFProfile->fqdn &&
(!NFProfile->ipv4_addresses || !NFProfile->ipv4_addresses->first) &&
(!NFProfile->ipv6_addresses || !NFProfile->ipv6_addresses->first)) {
ogs_error("NFProfile missing endpoint: id=%s type=%s",
nf_instance->id,
OpenAPI_nf_type_ToString(NFProfile->nf_type));
ogs_assert(true ==
ogs_sbi_server_send_error(
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
recvmsg, "NFProfile missing endpoint", nf_instance->id, NULL));
return false;
}
/* Validate the PLMN-ID against configured serving PLMN-IDs */
if (NFProfile->plmn_list) {
/* Set PLMN status to invalid */