IP assigned from SMF: session->paa
Static IP read from the Subscriber DB: session->ue_ip
When passing the PDP context information to the SGSN, we actually wanna
provide it with the IP address currently in use.
Try to fix the following error
"MME_Tests.ttcn:955 : no SGSN Context Response from MME"
MME_Tests.ttcn:1572 MME_Tests control part
MME_Tests.ttcn:1457 TC_ue_cell_reselect_eutran_to_geran testcase
If the UE continuously attempts to Attach while changing PDN Type,
it will cause the wrong IP to be assigned.
(e.g PDU-Type : IPv4v6 -> IPv4 -> IPv4v6)
This is because we use two variables at the same time,
one to read and store the Static IP from the Subscriber DB and
one to store the IP assigned from SMF, called session->paa.
When the UE attaches with PDN-Type set to IPv4v6,
MME saves the allocated IP in session->paa.
However, MME thinks it has been assigned a static IP based on the information
in session->paa, so changing the PDN-Type may result in the wrong IP
being assigned.
To solve this problem, I separated the variable(session->paa) that stores
the allocated IP received from SMF and the variable(session->ue_ip) that stores
the Static IP read from the Subscriber DB.
Therefore, the information read from the Subscriber DB
(session->session_type and session->ue_ip) should not be modified.
When using ogs_buffer_to_bcd(), an overflow occurs if the input buffer length
is larger than the output bcd size, causing a crash.
We adjusted the size of the input buffer length using ogs_min as follows.
```
sgwc_ue->imsi_len = ogs_min(imsi_len, OGS_MAX_IMSI_LEN);
memcpy(sgwc_ue->imsi, imsi, sgwc_ue->imsi_len);
ogs_buffer_to_bcd(sgwc_ue->imsi, sgwc_ue->imsi_len, sgwc_ue->imsi_bcd);
```
When we run the test, for example,
./tests/registration/registration simple-init,
wee get an INFO message like the one below.
```
05/17 14:24:03.933: [sbi] INFO: NF EndPoint(addr) setup [127.0.0.200:7777] (../lib/sbi/context.c:474)
```
When we run the code in Open5GS, the log level initially defaults to INFO.
However, for test code, we change the log level to ERROR
by automatically inserting the -e error option into argv.
The reason for this is to prevent WARNING and INFO messages
from appearing when the test code is run.
However, the log level to ERROR is changed at the bottom of
the initialize routine, which caused the above message
to be printed during testing.
To prevent this from being printed, I modified the code
to change that log level to ERROR a little earlier.
The validity time for NF Instances obtained through NF Discovery was
not properly implemented. Since the validity was 3600 seconds(1 hour),
which caused 5G Core to not work properly after 3600 seconds(1 hour).
There was an issue where an NF Instance should be deleted
when its validity time expired, but it was not working correctly
due to incorrect use of reference count.
Therefore, I have modified the Validity of NF Instances obtained
through NF Discovery to work properly.
I also changed the default value of valdityPeriod to 30 seconds.
Fixed not using Reference Count for adding/deleting NF Instances.
Up until now, NF Instances have been managed by referencing the Reference Count.
Initially, when an NF Instance is added, the Reference Count is incremented and
when it is deleted, the Reference Count is decremented.
If a UE discovers another NF Instance through the NF Discovery function,
the Reference Count is incremented. And if a UE de-registers,
the Reference Count of the discovered NF is decremented.
However, there's a problem with this approach.
When other NF is de-registered,
there is no guarantee that it will be 100% notified.
For example, if a UDM is de-registered, but an SCP is de-registered before it,
the AMF will not be notified that the UDM has been de-registered.
In situations where this is not clear, Reference Count cannot be used.
Therefore, we have modified it to not use the Reference Count method.
Also, when a UE connects, it is modified to always search
whether an NF Instance exists by NF Instance ID whenever it is discovered.
To do this, we modified lib/sbi/path.c as shown below.
```diff
@@ -281,13 +281,15 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
}
/* Target NF-Instance */
- nf_instance = sbi_object->service_type_array[service_type].nf_instance;
+ nf_instance = ogs_sbi_nf_instance_find(
+ sbi_object->service_type_array[service_type].nf_instance_id);
if (!nf_instance) {
nf_instance = ogs_sbi_nf_instance_find_by_discovery_param(
target_nf_type, requester_nf_type, discovery_option);
- if (nf_instance)
- OGS_SBI_SETUP_NF_INSTANCE(
- sbi_object->service_type_array[service_type], nf_instance);
+ if (nf_instance) {
+ OGS_SBI_SETUP_NF_INSTANCE_ID(
+ sbi_object->service_type_array[service_type], nf_instance->id);
+ }
}
```
An assert shall be triggered.
The vulnerable code path is in src/mme/mme-fd-path.c:
```
/* s6a process Subscription-Data from avp */
static int mme_s6a_subscription_data_from_avp(struct avp *avp,
ogs_subscription_data_t *subscription_data,
mme_ue_t *mme_ue, uint32_t *subdatamask)
{
...
/* AVP: 'MSISDN'( 701 )
* The MSISDN AVP is of type OctetString. This AVP contains an MSISDN,
* in international number format as described in ITU-T Rec E.164 [8],
* encoded as a TBCD-string, i.e. digits from 0 through 9 are encoded
* 0000 to 1001; 1111 is used as a filler when there is an odd number
* of digits; bits 8 to 5 of octet n encode digit 2n; bits 4 to 1 of
* octet n encode digit 2(n-1)+1.
* Reference: 3GPP TS 29.329
*/
ret = fd_avp_search_avp(avp, ogs_diam_s6a_msisdn, &avpch1);
ogs_assert(ret == 0);
if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0);
if (hdr->avp_value->os.data && hdr->avp_value->os.len) {
mme_ue->msisdn_len = hdr->avp_value->os.len; /* 1 */
memcpy(mme_ue->msisdn, hdr->avp_value->os.data,
ogs_min(mme_ue->msisdn_len, OGS_MAX_MSISDN_LEN)); /* 2 */
ogs_buffer_to_bcd(mme_ue->msisdn,
mme_ue->msisdn_len, mme_ue->msisdn_bcd); /* 3 */
*subdatamask = (*subdatamask | OGS_DIAM_S6A_SUBDATA_MSISDN);
}
}
```
When NSSF was first implemented, nf-status-notify was not required.
This is because there was no need to be notified
if other NFs were registered or de-registered in the NRF.
However, this situation changed with the addition of SEPP.
NSSFs can be notified whenever a SEPP registers or de-registers an NRF.
Therefore, we added nf-status-notify,
which was not implemented when the NSSF was originally created.
When running the open5gs package with systemd network config, the 1st IP address
of the UE pool configured in open5gs-upfd config file for ogstun is
being assigned to the interface through this file.
That was discussed as being a desirable default setup.
However, in the event a user wants a setup where no IP address is
assigned to the tundev, then it's not enough removing the IP address,
because then the implicit routing rules regarding the subnet of the IP
address added automatically by the kernel are also removed.
This patch adds config sections to set up the routing explicitly, with
the aim to get the routing still applied if the user decides to comment
out the IP address, so that packets are still forwarded properly in that
case.
Related: https://osmocom.org/issues/6361
A friend in the community was trying to connect an SMF made by another
manufacturer with an SBI interface and found a big problem with Open5GS.
All of the code in the part that generates the Resource URI
from HTTP.location is invalid.
For example, suppose we create a Resource URI with SMContext as below.
{apiRoot}/nsmf-pdusession/<apiVersion>/sm-contexts/{smContextRef}
In this case, Open5GS extracted the {smContextRef} part of the HTTP.location
and appended it to the beginning
{apiRoot}/nsmf-pdusession/<apiVersion>/sm-contexts/.
This implementation may not work properly if the apiRoot changes.
Consider a different port number as shown below.
<HTTP.location>
127.0.0.4:9999/nsmf-pdusession/v1/sm-contexts/1
The SMF may send an apiRoot to the AMF with a changed port number,
in which case the AMF must honor it.
Therefore, instead of extracting only the smContextRef from HTTP.location,
we modified it to use the whole thing to create a Resource URI.
We modified all NFs that use HTTP.location in the same way, not just SMFs.
Add an option to disable printing the timestamp. This is useful to not
have duplicate timestamps, when stderr is piped into a logging system
that adds timestamps on its own. For example with systemd's journald:
$ journalctl -u open5gs-smfd
Apr 10 13:25:18 hostname open5gs-smfd[1582]: 04/10 13:25:18.274: [app] INFO: Configuration: '/etc/open5gs/smf.yaml' (../lib/app/ogs-init.c:130)
Configuration change:
```
<OLD Format>
logger:
file: /var/log/open5gs/smf.log
<NEW Format>
logger:
file:
path: /var/log/open5gs/smf.log
```
Example config, to have no timestamps on stderr:
```
logger:
default:
timestamp: false
file:
path: /var/log/open5gs/smf.log
timestamp: true
```
The way subnet is set up has changed as shown below.
```
<OLD Format>
smf:
session:
- subnet: 10.45.0.1/16
<NEW Format>
smf:
session:
- subnet: 10.45.0.0/16
gateway: 10.45.0.1
```
For more information, please refer to Pull Request #2975.
In InitialUEMessage, send a NAS message with a message type
other than Registration Request, Deregistration Request, or Service Request,
the following messages from UE will not be accepted.
We found this issue in not only the initial state but multiple states.
We believe if an attacker has the ability to inject a NAS message to the core,
it can perform a DoS attack on the victim UE.
So, I've fixed that The MME/AMF deletes MME_UE_S1AP_ID/AMF_UE_NGAP_ID,
and will not accept any following messages from the UE.
The AMF will crash on the following locations when it receives a sequence
of NAS messages from a UE.
- ogs_nas_encrypt: Assertion `pkbuf->len' failed. (../lib/nas/common/security.c:86)
- gmm_state_authentication: Assertion `r != OGS_ERROR' failed. (../src/amf/gmm-sm.c:1561)
Besides the crashes found above, an incorrect protocol transition
is identified in Open5GS. Without any Registration/Attach Request message,
when the Identity Response message sent, the Core Network responds
with an Authentication Request message. According to the standard,
only the Registration/Attach Request message can start a state transition
from the 5GMM/EMM-DEREGISTERED state to the 5GMM/EMM-COMMON-PROCEDURE-INITIATED.
So I've modified the relevant code to address these issues.
If a Create Bearer Response occurs after a Delete Bearer Response,
SGW-C crashes.
The execution is stopped by the following ASSERT
because it tries to access the UL Tunnel
deleted by the Delete Bearer Response.
```
03/28 17:28:41.229: [gtp] DEBUG: [7] LOCAL Find GTPv2 peer [172.22.0.9]:2123 (../lib/gtp/xact.c:949)
03/28 17:28:41.229: [gtp] DEBUG: [7] LOCAL Receive peer [172.22.0.9]:2123 (../lib/gtp/xact.c:966)
03/28 17:28:41.229: [gtp] DEBUG: [7] LOCAL UPD RX-96 peer [172.22.0.9]:2123 (../lib/gtp/xact.c:448)
03/28 17:28:41.229: [sgwc] DEBUG: Create Bearer Response (../src/sgwc/s11-handler.c:707)
03/28 17:28:41.229: [gtp] DEBUG: [7] LOCAL Commit peer [172.22.0.9]:2123 (../lib/gtp/xact.c:629)
03/28 17:28:41.230: [gtp] DEBUG: [7] LOCAL Delete peer [172.22.0.9]:2123 (../lib/gtp/xact.c:1149)
03/28 17:28:41.230: [sgwc] FATAL: sgwc_s11_handle_create_bearer_response: Assertion `ul_tunnel' failed. (../src/sgwc/s11-handler.c:802)
03/28 17:28:41.231: [core] FATAL: backtrace() returned 8 addresses (../lib/core/ogs-abort.c:37)
./open5gs-sgwcd(+0x189b7) [0x5b3c92cf09b7]
./open5gs-sgwcd(+0x13c6d) [0x5b3c92cebc6d]
/open5gs/install/lib/x86_64-linux-gnu/libogscore.so.2(ogs_fsm_dispatch+0x113) [0x70600ed63402]
./open5gs-sgwcd(+0x629d) [0x5b3c92cde29d]
/open5gs/install/lib/x86_64-linux-gnu/libogscore.so.2(+0x11754) [0x70600ed54754]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x70600ecfc609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x70600ec21353]
```
To solve this problem, I have modified to handle the exception appropriately,
display the error situation in the Cause of the Create Bearer Response,
and proceed with the execution.
AS shown in 3GPP TS 29.244 C.2.1.1 diagram, the meaning of Threshold
value is different in Diameter Gy and in PFCP interfaces.
In Diameter Gy the value sets the trigger for the "remaining credit",
while in PFCP the value sets the trigger for the "used credit".
ThresholdPFCP = Quota - ThresholdGy
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed),
and a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse,
and needs to rely on its own timeout timer to figure out
that specific request failed.
To address this issue, I modified the GTP Response message to check
the Sender F-TEID and send it accordingly, setting the destination TEID
to the value of the Sender F-TEID.
I've made this modification only for SMF, but MME and SGW-C have not done so;
if you need to, you can work from the examples in SMF.
Similarly, the same situation can happen with PFCP. If anyone needs to do this
in the future, I think you can work on it this way.
This is the continuation of commit
12158eebb8, which only checked the code in
CCA[Update], but not in CCA[Initial].
The handling in CCA[Initial] is a bit more complex since depending on
the outcome, we may end up with a Result-Code != SUCCESS in MSCC but the
session may still be created at the OCS because the message Result-Code
= SUCCESS. In that scenario, we want to abort setting up the PDN session
but we still need to make sure we terminate the Gy session that was just
created.
Cause is set according to particular NF standard.
Additionally:
- OGS_SBI_HTTP_STATUS_MEHTOD_NOT_ALLOWED typo fixed.
- [PCF] Fixed SM Policy establishment error handling
First of all, it crashes when creating a Dedicated Bearer
on the default Session that is created for the first time.
This behavior should be possible, so the related ASSERT is removed.
Next, the InitialContextRequest is modified
during the Attach Request to include the first Bearer.
Finally, there was an issue where trying to create a Dedicated Bearer
with SGsAP enabled resulted in an InitialContextSetupRequest message
with a PTI of zero. This is because MME initializes the PTI to 0
upon receiving the Create Bearer Request while processing SGsAP.
All of these issues has been fixed.
Do not attempt to run "systemctl reload" on the open5gs services, unless
they are running. This fixes the logrotate service failing on this
postrotate script, if units are not running or not installed.
1. According to ETSI TS 129 118 4.1, if the Network Access Mode (NAM) is set
to "Packet only," no SGs association should be established.
2. If the NAM is set to "Packet and Circuit," and the SGs association is
rejected by the CS core, this rejection should only impact
the SGs association itself and not result in a UE attach rejection
for a UE with a valid HSS account.
a cryptographic vulnerability in the SUCI decryption routines
of Open5GS 5G—specifically Profile B, which uses P-256 (secp256r1)
for its elliptic curve routines.
If a mobile device user passes a public key within its SUCI
that does not correspond to a valid point on the P-256 elliptic curve,
the Open5GS UDM will not check the point
before running elliptic curve operations with it and returning a response
to the mobile device user.
If the public key is not checked to be a valid point, an attacker can leverage
this behavior to extract the Profile B private key from the UDM,
as has been done in other domains
(https://owasp.org/www-pdf-archive/Practical_Invalid_Curve_Attacks_on_TLS-ECDH_-_Juraj_Somorovsky.pdf).
Note that Profile A is not similarly vulnerable to this, as it is impossible
to construct an invalid point on a curve25519 elliptic curve.
There was some work that went into developing a practical proof of concept
of this kind of attack against free5gc last year; it can be found here:
https://www.gsma.com/security/wp-content/uploads/2023/10/0073-invalid_curve.pdf
And here is the free5gc security advisory:
https://github.com/advisories/GHSA-cqvv-r3g3-26rf
To mitigate this issue in Open5GS, the public key of the UE must be validated
by the UDM prior to use. Adding a validation function such as the following
should work:
I designed this code based on information from https://crypto.stackexchange.com/questions/90151/verify-that-a-point-belongs-to-secp256r1.
'node_timeout' and some other functions can remove a smf_sess_t
while that session is still waiting for a PFCP reply
and has an active PFCP xact.
In this case, xact->data points to the deleted session
and xact's timeout function (sess_5gc_timeout for example)
eventually refers to this already freed session.
This fix prevents duplicate deletes from occurring by checking to see
if the session context has already been deleted when the timeout occurs.
Additionally, it moves session deletions out of timer callbacks into
state machine by reselect_upf().
Due to the way 'ogs_timer_mgr_expire' calls timer callbacks,
one must not stop or expire timers from within a timer callback.
And now one must not remove sessions from within a timer callback.
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
When we try to send an SBI message to SMF to release a session,
sometimes ran_ue is NULL. This happens when the Mobile Reachable Timer expires
and Implicit Deregistration is triggered.
To account for this case, we added the `ran_ue` parameter to the SBI interface
and made it work even if it is NULL.
This AVP is optional and was added in later releases of the 3GPP TS
32.299 spec. For instance, it shows up in Release 16 (V16.2.0), but
doesn't show up in Release 12 (V12.7.0).
Some OCS, like PortaOne OCS, implement older versions of the release
(V12.14.0), and hence fail when receiving the 3GPP-RAT-Type inside
Multiple-Services-Credit-Control AVP.
Since nowadays we also send the 3GPP-RAT-Type in PS-Information AVP,
which has been specified for longer time (it already shows up in
V12.7.0), drop it from Multiple-Services-Credit-Control to have greater
compatibility with other vendors.
* [SBI] Handle and store AMF info
* [SBI] Add "target GUAMI" discovery option
* [SBI] Handle UeContextTransfer request and response messages
* [AMF] Handle NF discovery from AMF to AMF
* [AMF] Add UE Context Transfer Request/Response from AMF to AMF
* [SCP] Handle UeContextTransfer
* Follow-up on #3052
* [AMF] force authentication after 'Ue context transfer' for now
* [AMF] force authentication after 'Ue context transfer' for now
---------
Co-authored-by: Sukchan Lee <acetcom@gmail.com>
This happens for instance when the session is terminated due to a
rejection coming from the OCS, hence no originating GTP xact producing
the tear down.
The xact may well be NULL, eg. when tearin down the session
(send_ccr_termination_req_gx_gy_s6b()) because OCS rejected an update:
Hence there's no GTP xact originating the tear down, aka e->gtp-xact
passed to the function is NULL.
smf_gx_send_ccr() is already handling this case properly, contrary to smf_gf_send_ccr().
When building the MIME Multipart Media Encapsulation format
within an SBI message in the NF of a third-party product,
Open5GS does not parse properly if it contains a Preamble CRLF.
For example,
```
TCP/HTTP2
Stream: Data, Stream ID: 1, Length 841
MIME Multipart Media Encapsulation, Type: multipart/related, Boundary: "gc0pJq08jU534c"
--->Preamble: 0d0a
First boundary: --gc0pJq08jU534c\r\n
Encapsulated multipart part: (application/json)
Boundary: \r\n--gc0pJq08jU534c\r\n
Encapsulated multipart part: (application/vnd.3gpp.5gnas)
Boundary: \r\n--gc0pJq08jU534c\r\n
Encapsulated multipart part: (application/vnd.3gpp.ngap)
Last Boundary: \r\n--gc0pJq08jU534c--\r\n
```
Assume the UE has Attached, the session has been created,
and is in the IDLE state with the UEContextRelease process.
This could result in the following call flow.
1. TAU request without Integrity Protected
2. Authentication request/response
3. Security-mode command/complete
MME can be performed simultaneously by the HSS(S6A) and UE(S1AP).
Update-Location-Request
Service request
Service reject
Delete Session Request
Delete Session Response
Update-Location-Answer
UEContextReleaseCommand for Service reject
TAU reject
UEContextReleaseCommand for TAU reject
UEContextReleaseComplete
UEContextReleaseComplete
MME crashes when UE sends a service request(S1AP) during ULR/ULA(S6A) with HSS,
which has been fixed.
Transaction Identity doesn't map 1-to-1 with Procedure Transaction
Identity: The value ranges change, and PTI cannot use value 0 8which
means unused).
Hence, for now let's simply set the PTI to a valid default value instead
of asserting during mme_sess_add:
Assertion `pti != OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED'
Related: https://github.com/open5gs/open5gs/issues/3020
1. HandoverRequired
2. HandoverRequest
3. HandoverFailure
4. UEContextReleaseCommand
5. HandoverPreparationFailure
If UEContextReleaseComplete is not received,
the Source-UE will have the Target-UE.
6. HandoverRequired
There may be cases where the Source UE has a Target UE
from a previous HandoverRequired process. In this case,
it is recommended to force the deletion of the Target UE information
when receiving a new HandoverRequired.
7. HandoverRequest
8. HandoverFailure
9. UEContextReleaseCommand
10. UEContextReleaseComplete
11. HandoverPreparationFailure
... Crashed ...
For bi-directions, the rules are created in the same form as for downlink
as shown below, so to apply them for uplink, we need to swap the rules
according to the interface.
RX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
RX : permit in from <UE_IP> <UE_PORT> to <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
APER encoding fails when using the asn_uint642INTEGER function on a 32-bit machine as shown below.
```C
asn_uint642INTEGER(AMF_UE_NGAP_ID, 0xffffffff);
...
aper_encode_to_buffer(...)
```
INTEGER APER encode/decode functions seem to be operating internally with long variables instead of intmax_t.
That is probably the reason of the failure.
@v0-e fixed this issues in the mouse07410/asn1c pull request.
https://github.com/mouse07410/asn1c/pull/176https://github.com/mouse07410/asn1c/pull/177
When there is no MME-UE Context, going to cleanup without setting
s6a_message could cause a segmentation fault.
We fixed the problem by moving the location of setting s6a_message
to before cleanup.
The UPF is sending Session Report Request after the Session was Deleted,
when the Gy interface is active.
UPF is sending PFCP session report request after the session has been deleted
when the Gy interface is active. This is because some of the timers related to
the report are not deleted when the session is deleted.
We have fixed it to delete all the timers in the session
when the SESSION is deleted.
Problems with Purge-UE-Request/Answer can occur in the following situations
1. Attach Request
2. Authentication request
3. Authentication reject
4. UEContextReleaseCommand
5. UEContextReleaseComplete
6. Purge-UE-Request
7. Attach Request
8. Purge-UE-Answer
9. (UE Context Remove)
To resolve this issue, we have changed to delete the UE-Context
via mme_ue_remove() immediately upon receiving UEContextReleaseComplete()
without calling mme_s6a_send_pur().
1. Reachable assertion in ogs_nas_5gmm_decode
Location: lib/nas/5gs/decoder.c:4445
```c
int ogs_nas_5gmm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf)
{
int size = 0;
int decoded = 0;
ogs_assert(pkbuf);
ogs_assert(pkbuf->data);
ogs_assert(pkbuf->len);
```
When a NAS payload is received over `src/amf/context.c:1675`NGAP that has no data, the ogs_assert(pkbuf->len) assertion will be triggered.
2.Reachable assertion in ogs_nas_emm_decode
```
int ogs_nas_emm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *pkbuf)
{
int size = 0;
int decoded = 0;
ogs_assert(pkbuf);
ogs_assert(pkbuf->data);
ogs_assert(pkbuf->len);
```
Nearly identical to (1), but for LTE.
3. Reachable assertion in nas_eps_send_emm_to_esm
```
int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue,
ogs_nas_esm_message_container_t *esm_message_container)
{
int rv;
ogs_pkbuf_t *esmbuf = NULL;
if (!mme_ue_cycle(mme_ue)) {
ogs_error("UE(mme-ue) context has already been removed");
return OGS_NOTFOUND;
}
ogs_assert(esm_message_container);
ogs_assert(esm_message_container->length);
```
The ESM message payload may be 0-length, as the length is determined by a field in the NAS payload (which can be chosen arbitrarily by an attacker). This leads to the length assertion above being triggered.
5. Reachable assertion and incorrect hash calculation in ogs_kdf_hash_mme
```
void ogs_kdf_hash_mme(const uint8_t *message, uint8_t message_len, uint8_t *hash_mme)
{
uint8_t key[32];
uint8_t output[OGS_SHA256_DIGEST_SIZE];
ogs_assert(message);
ogs_assert(message_len);
ogs_assert(hash_mme);
memset(key, 0, 32);
ogs_hmac_sha256(key, 32, message, message_len,
output, OGS_SHA256_DIGEST_SIZE);
memcpy(hash_mme, output+24, OGS_HASH_MME_LEN);
}
```
When handling NAS attach requests or TAU requests, the ogs_kdf_hash_mme function is passed the NAS payload. However, the length field is represented as an unsigned 8-bit integer, which the passed length of the packet may overflow. This leads to the passed value being truncated.
When the passed value is a multiple of 256, the above assertion (ogs_assert(message_len)) is triggered. Otherwise, the hash is computed on only the first n bits of the message (where n = actual_message_len % 256).
There is an issue with SESSION RELEASE not working properly
depending on the PDU session release complete order
in the PDUSessionResourceReleaseResponse.
If the AMF receives PDUSessionResourceReleaseResponse
followed by PDU session release complete, it works correctly.
However, if it receives PDU session release complete
followed by PDUSessionResourceReleaseResponse, it does not work correctly
and sends an Error Indication to the UE/gNB.
To fix this issue, we added pdu_session_release_complete_received and
pdu_session_resource_release_response_received to the content
so that CLEAR_SM_CONTEXT_REF() is executed when both are received.
Because a race condition can occur between S6A Diameter and S1AP message,
the following error handling code has been added.
1. InitialUEMessage + Attach Request + PDN Connectivity request
2. Authentication-Information-Request/Authentication-Information-Answer
3. Authentication Request/Response
4. Security-mode command/complete
5. Update-Location-Request/Update-Location-Answer
6. Detach request/accept
In the ULR/ULA process in step 6, the PDN Connectivity request is
pushed to the queue as an ESM_MESSAGE because the NAS-Type is still
an Attach Request.
See the code below in 'mme-s6a-handler.c' for where the queue is pushed.
if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) {
rv = nas_eps_send_emm_to_esm(mme_ue,
&mme_ue->pdn_connectivity_request);
if (rv != OGS_OK) {
ogs_error("nas_eps_send_emm_to_esm() failed");
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
}
} else if (mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) {
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_error("Invalid Type[%d]", mme_ue->nas_eps.type);
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
}
If you perform step 7 Detach request/accept here,
the NAS-Type becomes Detach Request and the EMM state changes
to emm_state_de_registered().
Since the PDN, which is an ESM message that was previously queued,
should not be processed in de_registered, the message is ignored
through error handling below.
Otherwise, MME will crash because there is no active bearer
in the initial_context_setup_request build process.
See the code below in 's1ap-build.c' for where the crash occurs.
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
...
if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) {
} else if (OGS_FSM_CHECK(&bearer->sm, esm_state_inactive)) {
ogs_warn("No active EPS bearer [%d]", bearer->ebi);
ogs_warn(" IMSI[%s] NAS-EPS Type[%d] "
"ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
mme_ue->imsi_bcd, mme_ue->nas_eps.type,
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
continue;
}
...
}
}
As mentioned in the sgwu.yaml configuration file, it is possible to configure multiple addresses with different source_interface values for the gtpu interface.
Following the this section, I defined two addresses, one with source_interface set to 0 and another with source_interface set to 1. My expectation was to see different addresses for the two PDRs in the Session Establishment Response message during session establishment. However, both addresses were the same, and it was the address I had set for source_interface = 0.
When I looked into the code, I found the reason for the issue. In the lib/pfcp/context.c file, on line 1185, the function that determines the address is called as follows:
...
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
...
In the last parameter of this function, a constant value, OGS_PFCP_INTERFACE_ACCESS, is used. This causes every PDR with any source_interface to be considered as "access," and the value 0 is used for its interface.
I replaced the value with pdr->src_if, and the bug was resolved.
@ -8,6 +8,16 @@ Please follow the [documentation](https://open5gs.org/open5gs/docs/) at [open5gs
If you find Open5GS useful for work, please consider supporting this Open Source project by [Becoming a sponsor](https://github.com/sponsors/acetcom). To manage the funding transactions transparently, you can donate through [OpenCollective](https://opencollective.com/open5gs).
@ -147,7 +147,7 @@ If there is a need to change the Core Network component configuration, then corr
- Provision SIM details in open5gs HSS
Open (http://<DOCKER_HOST_IP>:3000) in a web browser, where <DOCKER_HOST_IP> is the IP of the machine/VM running the open5gs containers. Login with following credentials
Open (http://<DOCKER_HOST_IP>:9999) in a web browser, where <DOCKER_HOST_IP> is the IP of the machine/VM running the open5gs containers. Login with following credentials