Skip to content

Commit d76311d

Browse files
author
Amar Padmanabhan
authored
[lte][agw] Fix T3489 handling (magma#3818)
* Add T3489 tests Introduce a new test to validate T3489 expiry. Credit to ulaskozat for the diff Testing done: Verified that an ASAN use after free occurs on timer expiry =7031==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000093460 at pc 0x555807545462 bp 0x7f87093fd2b0 sp 0x7f87093fd2a8 WRITE of size 8 at 0x603000093460 thread T16 #0 0x555807545461 in nas_stop_T3489 /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/esm_data_context.c:101 #1 0x5558075c47c5 in esm_proc_esm_information_response /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/esm_information.c:119 #2 0x55580759339b in esm_recv_information_response /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/sap/esm_recv.c:575 #3 0x555807551fba in _esm_sap_recv /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/sap/esm_sap.c:679 #4 0x555807550f33 in esm_sap_send /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/sap/esm_sap.c:283 #5 0x5558075195a0 in lowerlayer_data_ind /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/emm/LowerLayer.c:276 #6 0x55580757848f in _emm_as_data_ind /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/emm/sap/emm_as.c:688 #7 0x555807574ec4 in emm_as_send /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/emm/sap/emm_as.c:180 #8 0x55580753147f in emm_sap_send /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/emm/sap/emm_sap.c:105 #9 0x5558074d74fc in nas_proc_ul_transfer_ind /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/nas_proc.c:326 #10 0x5558071bd634 in handle_message /home/vagrant/magma/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c:97 #11 0x7f871bb277bd in zloop_start (/usr/lib/x86_64-linux-gnu/libczmq.so.4+0x287bd) #12 0x5558071bf169 in mme_app_thread /home/vagrant/magma/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c:447 #13 0x7f871e11f4a3 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x74a3) #14 0x7f871a494d0e in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xe8d0e) 0x603000093460 is located 0 bytes inside of 32-byte region [0x603000093460,0x603000093480) freed by thread T16 here: #0 0x7f871e602a10 in free (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc1a10) #1 0x5558070dc054 in free_wrapper /home/vagrant/magma/lte/gateway/c/oai/common/dynamic_memory_check.c:47 #2 0x555807545496 in nas_stop_T3489 /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/esm_data_context.c:103 #3 0x5558075c517a in _esm_information /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/esm_information.c:269 #4 0x5558075c4e15 in _esm_information_t3489_handler /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/esm/esm_information.c:199 #5 0x5558074e2e8a in mme_app_nas_timer_handle_signal_expiry /home/vagrant/magma/lte/gateway/c/oai/tasks/nas/util/nas_timer.c:100 #6 0x5558071be2d2 in handle_message /home/vagrant/magma/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c:235 #7 0x7f871bb277bd in zloop_start (/usr/lib/x86_64-linux-gnu/libczmq.so.4+0x287bd) Signed-off-by: Amar Padmanabhan <[email protected]> * Invalidate the T3849 timer id while processing esm information retransmit The _esm_information function stops the existing T3849 timer as referenced by the esm_ctxt datastructure timer before rescheduling a new T3849 timer when it requests for the esm info from a UE. Stopping the timer has a side effect of freeing up the UE related retransmission data associated with it. This causes issues during the T3849 timer expiry handling as the cancelled timer and the rescheduled one reuse the same retransmission data datastructure. Fix this by unsetting the T3849 timer in the handling of the timer expiry as the esm_ctxt is not associated with any valid timers anymore. Further as the timer is a oneshot timer it will be cleaned up after the processing of the timer callback. Signed-off-by: Amar Padmanabhan <[email protected]>
1 parent f299075 commit d76311d

File tree

2 files changed

+162
-8
lines changed

2 files changed

+162
-8
lines changed

lte/gateway/c/oai/tasks/nas/esm/esm_information.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ static void _esm_information_t3489_handler(void* args, imsi64_t* imsi64) {
193193

194194
*imsi64 = esm_ebr_timer_data->ctx->_imsi64;
195195
if (esm_ebr_timer_data->count < ESM_INFORMATION_COUNTER_MAX) {
196+
// Unset the timer id maintained in the esm_ctx, as the timer is no
197+
// longer valid.
198+
esm_ebr_timer_data->ctx->esm_ctx.T3489.id = NAS_TIMER_INACTIVE_ID;
196199
/*
197200
* Re-send deactivate EPS bearer context request message to the UE
198201
*/
@@ -228,19 +231,21 @@ static void _esm_information_t3489_handler(void* args, imsi64_t* imsi64) {
228231

229232
/****************************************************************************
230233
** **
231-
** Name: _esm_information() **
234+
** Name: _esm_information() **
232235
** **
233236
** Description: Sends DEACTIVATE EPS BEREAR CONTEXT REQUEST message and **
234-
** starts timer T3489 **
237+
** starts timer T3489. **
238+
** Function also clearns out any existing T3489 timers referenced **
239+
** by the esm_ctx datastructure. **
235240
** **
236-
** Inputs: ue_id: UE local identifier **
237-
** ebi: EPS bearer identity **
238-
** msg: Encoded ESM message to be sent **
239-
** Others: None **
241+
** Inputs: ue_id: UE local identifier **
242+
** ebi: EPS bearer identity **
243+
** msg: Encoded ESM message to be sent **
244+
** Others: None **
240245
** **
241246
** Outputs: None **
242-
** Return: RETURNok, RETURNerror **
243-
** Others: T3489 **
247+
** Return: RETURNok, RETURNerror **
248+
** Others: T3489 **
244249
** **
245250
***************************************************************************/
246251
static int _esm_information(
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
"""
2+
Copyright 2020 The Magma Authors.
3+
4+
This source code is licensed under the BSD-style license found in the
5+
LICENSE file in the root directory of this source tree.
6+
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
"""
13+
14+
import unittest
15+
16+
import s1ap_types
17+
import time
18+
19+
from integ_tests.s1aptests import s1ap_wrapper
20+
import ctypes
21+
22+
23+
class TestEsmInformation(unittest.TestCase):
24+
def setUp(self):
25+
self._s1ap_wrapper = s1ap_wrapper.TestWrapper()
26+
27+
def tearDown(self):
28+
self._s1ap_wrapper.cleanup()
29+
30+
def test_esm_information_timerexpiration(self):
31+
""" Testing of sending Esm Information procedure """
32+
num_ues = 1
33+
num_of_expires = 2
34+
35+
self._s1ap_wrapper.configUEDevice(num_ues)
36+
print("************************* sending Attach Request for ue-id : 1")
37+
attach_req = s1ap_types.ueAttachRequest_t()
38+
attach_req.ue_Id = 1
39+
sec_ctxt = s1ap_types.TFW_CREATE_NEW_SECURITY_CONTEXT
40+
id_type = s1ap_types.TFW_MID_TYPE_IMSI
41+
eps_type = s1ap_types.TFW_EPS_ATTACH_TYPE_EPS_ATTACH
42+
attach_req.mIdType = id_type
43+
attach_req.epsAttachType = eps_type
44+
attach_req.useOldSecCtxt = sec_ctxt
45+
46+
# enabling ESM Information transfer flag
47+
attach_req.eti.pres = 1
48+
attach_req.eti.esm_info_transfer_flag = 1
49+
50+
print("Sending Attach Request ue-id", attach_req.ue_Id)
51+
self._s1ap_wrapper._s1_util.issue_cmd(
52+
s1ap_types.tfwCmd.UE_ATTACH_REQUEST, attach_req
53+
)
54+
55+
response = self._s1ap_wrapper.s1_util.get_response()
56+
self.assertEqual(
57+
response.msg_type, s1ap_types.tfwCmd.UE_AUTH_REQ_IND.value
58+
)
59+
print("Received auth req ind ")
60+
61+
auth_res = s1ap_types.ueAuthResp_t()
62+
auth_res.ue_Id = 1
63+
sqn_recvd = s1ap_types.ueSqnRcvd_t()
64+
sqn_recvd.pres = 0
65+
auth_res.sqnRcvd = sqn_recvd
66+
print("Sending Auth Response ue-id", auth_res.ue_Id)
67+
self._s1ap_wrapper._s1_util.issue_cmd(
68+
s1ap_types.tfwCmd.UE_AUTH_RESP, auth_res
69+
)
70+
71+
response = self._s1ap_wrapper.s1_util.get_response()
72+
self.assertEqual(
73+
response.msg_type, s1ap_types.tfwCmd.UE_SEC_MOD_CMD_IND.value
74+
)
75+
print("Received Security Mode Command ue-id", auth_res.ue_Id)
76+
77+
time.sleep(1)
78+
79+
sec_mode_complete = s1ap_types.ueSecModeComplete_t()
80+
sec_mode_complete.ue_Id = 1
81+
self._s1ap_wrapper._s1_util.issue_cmd(
82+
s1ap_types.tfwCmd.UE_SEC_MOD_COMPLETE, sec_mode_complete
83+
)
84+
85+
for i in range(num_of_expires):
86+
# Esm Information Request indication
87+
print(
88+
"Received Esm Information Request ue-id", sec_mode_complete.ue_Id
89+
)
90+
response = self._s1ap_wrapper.s1_util.get_response()
91+
self.assertEqual(
92+
response.msg_type, s1ap_types.tfwCmd.UE_ESM_INFORMATION_REQ.value
93+
)
94+
esm_info_req = response.cast(s1ap_types.ueEsmInformationReq_t)
95+
96+
# Sending Esm Information Response
97+
print(
98+
"Sending Esm Information Response ue-id", sec_mode_complete.ue_Id
99+
)
100+
esm_info_response = s1ap_types.ueEsmInformationRsp_t()
101+
esm_info_response.ue_Id = 1
102+
esm_info_response.tId = esm_info_req.tId
103+
esm_info_response.pdnAPN_pr.pres = 1
104+
s = "magma.ipv4"
105+
esm_info_response.pdnAPN_pr.len = len(s)
106+
esm_info_response.pdnAPN_pr.pdn_apn = (ctypes.c_ubyte * 100)(
107+
*[ctypes.c_ubyte(ord(c)) for c in s[:100]]
108+
)
109+
self._s1ap_wrapper._s1_util.issue_cmd(
110+
s1ap_types.tfwCmd.UE_ESM_INFORMATION_RSP, esm_info_response
111+
)
112+
113+
response = self._s1ap_wrapper.s1_util.get_response()
114+
self.assertEqual(
115+
response.msg_type, s1ap_types.tfwCmd.INT_CTX_SETUP_IND.value
116+
)
117+
response = self._s1ap_wrapper.s1_util.get_response()
118+
self.assertEqual(
119+
response.msg_type, s1ap_types.tfwCmd.UE_ATTACH_ACCEPT_IND.value
120+
)
121+
122+
# Trigger Attach Complete
123+
attach_complete = s1ap_types.ueAttachComplete_t()
124+
attach_complete.ue_Id = 1
125+
self._s1ap_wrapper._s1_util.issue_cmd(
126+
s1ap_types.tfwCmd.UE_ATTACH_COMPLETE, attach_complete
127+
)
128+
# Wait on EMM Information from MME
129+
self._s1ap_wrapper._s1_util.receive_emm_info()
130+
131+
print("*** Running UE detach ***")
132+
# Now detach the UE
133+
detach_req = s1ap_types.uedetachReq_t()
134+
detach_req.ue_Id = 1
135+
detach_req.ueDetType = (
136+
s1ap_types.ueDetachType_t.UE_SWITCHOFF_DETACH.value
137+
)
138+
self._s1ap_wrapper._s1_util.issue_cmd(
139+
s1ap_types.tfwCmd.UE_DETACH_REQUEST, detach_req
140+
)
141+
# Wait for UE context release command
142+
response = self._s1ap_wrapper.s1_util.get_response()
143+
self.assertEqual(
144+
response.msg_type, s1ap_types.tfwCmd.UE_CTX_REL_IND.value
145+
)
146+
147+
148+
if __name__ == "__main__":
149+
unittest.main()

0 commit comments

Comments
 (0)