From 2a98a73be4fbd361d372e28c79a2fc2dc37709fe Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Mon, 19 Mar 2018 16:06:12 +0100 Subject: [PATCH] MSC_Tests: Test what happens when the DLCX is dropped Test the reaction of osmo-msc when the DLCX at the end of a call is not answered. Normally osmo-msc should time out and clear the connection. Change-ID osmo-msc:I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 fixes a regression that causes osmo-msc to segfault due to a use after free. This testcase provokes the situation that leads to the crash. Change-Id: Ic124ea116496209f9a1d8e74ae3e3a36cf866db0 Related OS#2881 Related OS#2882 --- msc/BSC_ConnectionHandler.ttcn | 24 +++++++++++++++----- msc/MSC_Tests.ttcn | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/msc/BSC_ConnectionHandler.ttcn b/msc/BSC_ConnectionHandler.ttcn index 1704c1816..72e2a4e77 100644 --- a/msc/BSC_ConnectionHandler.ttcn +++ b/msc/BSC_ConnectionHandler.ttcn @@ -373,6 +373,8 @@ type record CallParameters { PortNumber mgw_rtp_port_mss, /* MSS-facing MGW RTP Port */ uint7_t rtp_payload_type, /* dynamic RTP payload type */ charstring rtp_sdp_format, /* AMR/8000 or the like */ + boolean mgw_drop_dlcx optional, /* Provoke errors by not responding to DLCX + (f_mt_call and f_mt_call) */ MgcpCallId mgcp_call_id optional, /* MGCP Call ID; CallAgent allocated */ MgcpEndpoint mgcp_ep optional /* MGCP Endpoint, CallAgent or MGW allocated */, @@ -410,6 +412,7 @@ runs on BSC_ConnHdlr { var MobileIdentityLV mi; var MNCC_PDU mncc; var MgcpCommand mgcp_cmd; + var boolean respond_to_dlcx; f_bssmap_register_imsi(g_pars.imsi, g_pars.tmsi); @@ -510,6 +513,8 @@ runs on BSC_ConnHdlr { BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_REL_COMPL(cpars.transaction_id))); } + respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx)); + /* clearing of radio channel */ interleave { [] BSSAP.receive(tr_BSSMAP_ClearCommand) { @@ -517,9 +522,11 @@ runs on BSC_ConnHdlr { BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND); } [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd { - /* TODO: For one or all connections on EP? */ - MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id)); - f_create_mgcp_delete_ep(cpars.mgcp_ep); + if (respond_to_dlcx) { + /* TODO: For one or all connections on EP? */ + MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id)); + f_create_mgcp_delete_ep(cpars.mgcp_ep); + } } } setverdict(pass); @@ -531,6 +538,7 @@ runs on BSC_ConnHdlr { var MobileIdentityLV mi; var MNCC_PDU mncc; var MgcpCommand mgcp_cmd; + var boolean respond_to_dlcx; /* If we have a TMSI, use TMSI instead of IMSI */ if (ispresent(g_pars.tmsi)) { @@ -628,6 +636,8 @@ runs on BSC_ConnHdlr { BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))); BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id))); + respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx)); + /* clearing of radio channel */ interleave { [] BSSAP.receive(tr_BSSMAP_ClearCommand) { @@ -635,9 +645,11 @@ runs on BSC_ConnHdlr { BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND); } [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd { - /* TODO: For one or all connections on EP? */ - MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id)); - f_create_mgcp_delete_ep(cpars.mgcp_ep); + if (respond_to_dlcx) { + /* TODO: For one or all connections on EP? */ + MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id)); + f_create_mgcp_delete_ep(cpars.mgcp_ep); + } } } setverdict(pass); diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn index 698b34160..5ae5d60d7 100644 --- a/msc/MSC_Tests.ttcn +++ b/msc/MSC_Tests.ttcn @@ -1734,6 +1734,45 @@ testcase TC_mo_release_timeout() runs on MTC_CT { } +/* LU followed by MT call (including paging) */ +private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr { + f_init_handler(pars); + //FIXME: odd digits var CallParameters cpars := valueof(t_CallParams('12345'H, 0)); + var CallParameters cpars := valueof(t_CallParams('123456'H, 0)); + cpars.bss_rtp_port := 1110; + cpars.mgcp_connection_id_bss := '10004'H; + cpars.mgcp_connection_id_mss := '10005'H; + + /* Note: This is an optional parameter. When the call-agent (MSC) does + * supply a full endpoint name this setting will be overwritten. */ + cpars.mgcp_ep := "rtpbridge/1@mgw"; + + /* Intentionally disable the CRCX response */ + cpars.mgw_drop_dlcx := true; + + /* Perform location update and call */ + f_perform_lu(); + f_mt_call(cpars); +} +testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT { + var BSC_ConnHdlr vc_conn; + f_init(); + + /* Perform an almost normal looking locationupdate + mt-call, but do + * not respond to the DLCX at the end of the call */ + vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41); + vc_conn.done; + + /* Wait a guard period until the MGCP layer in the MSC times out, + * if the MSC is vulnerable to the use-after-free situation that is + * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should + * segfault now */ + f_sleep(6.0); + + /* Run the init procedures once more. If the MSC has crashed, this + * this will fail */ + f_init(); +} /* TODO: * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout? @@ -1791,6 +1830,7 @@ control { execute( TC_lu_imsi_auth_tmsi_encr_13_2() ); execute( TC_lu_imsi_auth_tmsi_encr_013_2() ); execute( TC_mo_release_timeout() ); + execute( TC_lu_and_mt_call_no_dlcx_resp() ); execute( TC_lu_and_mt_call() );