osmo-sip-connector/src/app.c

114 lines
2.8 KiB
C
Raw Normal View History

/*
* (C) 2016 by Holger Hans Peter Freyther
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "app.h"
#include "call.h"
#include "logging.h"
#include "mncc.h"
#include "mncc_protocol.h"
void app_mncc_disconnected(struct mncc_connection *conn)
{
struct call *call, *tmp;
llist_for_each_entry_safe(call, tmp, &g_call_list, entry) {
mncc: Fix use after free on mncc socket disconnection When the MNCC socket breaks down we would release all callds but when there is no remote call the call would be released before if (call->remote) ... is being executed leading to a use after free. Fix it by copying the legs first and assuming the call will be gone after that. ==3618== Invalid read of size 4 ==3618== at 0x804A18A: app_mncc_disconnected (app.c:49) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Address 0x47f3258 is 64 bytes inside a block of size 76 free'd ==3618== at 0x402A3A8: free (vg_replace_malloc.c:473) ==3618== by 0x42E7FD1: ??? (in /usr/lib/i386-linux-gnu/libtalloc.so.2.1.5) ==3618== by 0x804A3FD: call_leg_release (call.c:87) ==3618== by 0x804A186: app_mncc_disconnected (app.c:48) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Change-Id: I1889013ed315f896e4295358f6daf76ce523dc2a
2017-03-06 09:02:37 +00:00
struct call_leg *initial, *remote;
int has_mncc = 0;
if (call->initial && call->initial->type == CALL_TYPE_MNCC)
has_mncc = 1;
if (call->remote && call->remote->type == CALL_TYPE_MNCC)
has_mncc = 1;
if (!has_mncc)
continue;
/*
mncc: Fix use after free on mncc socket disconnection When the MNCC socket breaks down we would release all callds but when there is no remote call the call would be released before if (call->remote) ... is being executed leading to a use after free. Fix it by copying the legs first and assuming the call will be gone after that. ==3618== Invalid read of size 4 ==3618== at 0x804A18A: app_mncc_disconnected (app.c:49) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Address 0x47f3258 is 64 bytes inside a block of size 76 free'd ==3618== at 0x402A3A8: free (vg_replace_malloc.c:473) ==3618== by 0x42E7FD1: ??? (in /usr/lib/i386-linux-gnu/libtalloc.so.2.1.5) ==3618== by 0x804A3FD: call_leg_release (call.c:87) ==3618== by 0x804A186: app_mncc_disconnected (app.c:48) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Change-Id: I1889013ed315f896e4295358f6daf76ce523dc2a
2017-03-06 09:02:37 +00:00
* this call has a MNCC component and we will release it now.
* There might be no remote so on the release of the initial
* leg the call might be gone. We may not touch call beyond
* that point.
*/
LOGP(DAPP, LOGL_NOTICE,
"Going to release call(%u) due MNCC.\n", call->id);
mncc: Fix use after free on mncc socket disconnection When the MNCC socket breaks down we would release all callds but when there is no remote call the call would be released before if (call->remote) ... is being executed leading to a use after free. Fix it by copying the legs first and assuming the call will be gone after that. ==3618== Invalid read of size 4 ==3618== at 0x804A18A: app_mncc_disconnected (app.c:49) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Address 0x47f3258 is 64 bytes inside a block of size 76 free'd ==3618== at 0x402A3A8: free (vg_replace_malloc.c:473) ==3618== by 0x42E7FD1: ??? (in /usr/lib/i386-linux-gnu/libtalloc.so.2.1.5) ==3618== by 0x804A3FD: call_leg_release (call.c:87) ==3618== by 0x804A186: app_mncc_disconnected (app.c:48) ==3618== by 0x804B52D: close_connection (mncc.c:255) ==3618== by 0x804BCFA: mncc_rtp_send.constprop.13 (mncc.c:145) ==3618== by 0x804CC86: check_setup (mncc.c:435) ==3618== by 0x804CC86: mncc_data (mncc.c:795) ==3618== by 0x42FCF94: osmo_fd_disp_fds (select.c:167) ==3618== by 0x804D1F2: evpoll (evpoll.c:92) ==3618== by 0x4205053: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x4205478: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1) ==3618== by 0x8049AA6: main (main.c:171) ==3618== Change-Id: I1889013ed315f896e4295358f6daf76ce523dc2a
2017-03-06 09:02:37 +00:00
initial = call->initial;
remote = call->remote;
call = NULL;
if (initial)
initial->release_call(initial);
if (remote)
remote->release_call(remote);
}
}
/*
* I hook SIP and MNCC together.
*/
void app_setup(struct app_config *cfg)
{
cfg->mncc.conn.on_disconnect = app_mncc_disconnected;
}
static void route_to_sip(struct call *call)
{
if (sip_create_remote_leg(&g_app.sip.agent, call) != 0)
call->initial->release_call(call->initial);
}
static void route_to_mncc(struct call *call)
{
if (mncc_create_remote_leg(&g_app.mncc.conn, call) != 0)
call->initial->release_call(call->initial);
}
void app_route_call(struct call *call, const char *source, const char *dest)
{
if (!source || !dest) {
LOGP(DAPP, LOGL_ERROR, "call(%u) missing source(%p)/dest(%p)\n",
call->id, source, dest);
call->initial->release_call(call->initial);
return;
}
call->source = source;
call->dest = dest;
if (call->initial->type == CALL_TYPE_MNCC)
route_to_sip(call);
else
route_to_mncc(call);
}
const char *app_media_name(int ptmsg)
{
if (ptmsg == GSM_TCHF_FRAME)
return "GSM";
if (ptmsg == GSM_TCHF_FRAME_EFR)
return "GSM-EFR";
if (ptmsg == GSM_TCHH_FRAME)
return "GSM-HR-08";
if (ptmsg == GSM_TCH_FRAME_AMR)
return "AMR";
LOGP(DAPP, LOGL_ERROR, "Unknown ptmsg(%d). call broken\n", ptmsg);
return "unknown";
}