smf: prevent crash when receiving CCA with unknown Diameter session

In smf_gx_cca_cb(), smf_gy_cca_cb(), and S6b CCA callbacks, the code
assumed that a Diameter session always exists when processing a CCA
message and enforced this invariant with:

    ogs_assert(new == 0);

However, if a malicious or misbehaving Diameter peer sends a
Credit-Control-Answer containing an unknown or mismatched Session-Id,
fd_msg_sess_get() returns new=1, indicating that the session does not
exist locally. The assertion then triggers ogs_abort(), terminating
the entire SMF process.

This allows a single malformed CCA message to cause a denial-of-service
by crashing the SMF and dropping all active UE sessions.

Replace the assertion with a runtime check. If the session does not
exist (new != 0), the message is logged and discarded via the existing
cleanup path instead of aborting the process.

Affected callbacks:
  - smf_gx_cca_cb()
  - smf_gy_cca_cb()
  - smf_s6b_aaa_cb()
  - smf_s6b_sta_cb()

This ensures that unexpected or malicious Diameter answers do not
terminate the SMF process and are handled gracefully.

Issues: #4343
This commit is contained in:
Sukchan Lee 2026-03-11 07:55:44 +09:00
parent c36a322a39
commit 80eb484a6a
3 changed files with 19 additions and 7 deletions

View file

@ -1,5 +1,5 @@
/* Gx Interface, 3GPP TS 29.212 section 4
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2026 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -776,7 +776,10 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
/* Search the session, retrieve its data */
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
ogs_assert(ret == 0);
ogs_assert(new == 0);
if (new != 0) {
ogs_error("Session should already exist, but new session flag is set");
goto cleanup;
}
ogs_debug(" Search the session");

View file

@ -1,7 +1,7 @@
/* Gy Interface, 3GPP TS 32.299
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2025 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2025-2026 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -1006,7 +1006,10 @@ static void smf_gy_cca_cb(void *data, struct msg **msg)
/* Search the session, retrieve its data */
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
ogs_assert(ret == 0);
ogs_assert(new == 0);
if (new != 0) {
ogs_error("Session should already exist, but new session flag is set");
goto cleanup;
}
ogs_debug(" Search the Gy session");

View file

@ -1,5 +1,5 @@
/* 3GPP TS 29.273 section 9
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2026 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -387,7 +387,10 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
/* Search the session, retrieve its data */
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
ogs_assert(ret == 0);
ogs_assert(new == 0);
if (new != 0) {
ogs_error("Session should already exist, but new session flag is set");
goto cleanup;
}
ogs_debug(" Search the session");
@ -730,7 +733,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
/* Search the session, retrieve its data */
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
ogs_assert(ret == 0);
ogs_assert(new == 0);
if (new != 0) {
ogs_error("Session should already exist, but new session flag is set");
goto cleanup;
}
ogs_debug(" Search the session");