From 26df42f28c466a9a0a76081978b15e515ba52505 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 21 Feb 2008 21:38:49 +0000 Subject: [PATCH] more protection git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7718 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_core.h | 2 ++ src/include/switch_types.h | 1 + src/switch_channel.c | 37 +++++++++++++++++++++--- src/switch_core_io.c | 41 +++++++++++++++++++++++++-- src/switch_core_memory.c | 58 ++++++++++++++++++++------------------ src/switch_core_session.c | 15 ++++++++++ src/switch_ivr_async.c | 10 +++++-- src/switch_rtp.c | 10 ++++++- 8 files changed, 136 insertions(+), 38 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 1bcc93cf1f..26d5220452 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -350,6 +350,8 @@ SWITCH_DECLARE(int) switch_core_add_state_handler(_In_ const switch_state_handle SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(_In_ int index); ///\} +SWITCH_DECLARE(void) switch_core_memory_pool_tag(switch_memory_pool_t *pool, const char *tag); + SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(_Out_ switch_memory_pool_t **pool, _In_z_ const char *file, _In_z_ const char *func, _In_ int line); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 8083814140..5743ac4e3e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -93,6 +93,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_SEQ_CLEARSCR SWITCH_SEQ_ESC SWITCH_SEQ_CLEARSCR_CHAR SWITCH_SEQ_HOME #define SWITCH_DEFAULT_DTMF_DURATION 2000 +#define SWITCH_MAX_DTMF_DURATION 192000 #define SWITCH_DEFAULT_DIR_PERMS SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE | SWITCH_FPROT_UEXECUTE | SWITCH_FPROT_GREAD | SWITCH_FPROT_GEXECUTE #ifdef WIN32 diff --git a/src/switch_channel.c b/src/switch_channel.c index 88e2c9a3dc..47980e233c 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -210,19 +210,32 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan { switch_status_t status; void *pop; + switch_dtmf_t new_dtmf; + + switch_assert(dtmf); switch_mutex_lock(channel->dtmf_mutex); - + new_dtmf = *dtmf; + if ((status = switch_core_session_recv_dtmf(channel->session, dtmf) != SWITCH_STATUS_SUCCESS)) { goto done; } - if (is_dtmf(dtmf->digit)) { + if (is_dtmf(new_dtmf.digit)) { switch_dtmf_t *dt; int x = 0; + if (new_dtmf.duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s EXECSSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(channel), new_dtmf.digit, new_dtmf.duration); + new_dtmf.duration = SWITCH_MAX_DTMF_DURATION; + } else if (!new_dtmf.duration) { + new_dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; + } + switch_zmalloc(dt, sizeof(*dt)); - *dt = *dtmf; + *dt = new_dtmf; + while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) { switch_queue_trypop(channel->dtmf_queue, &pop); if (++x > 100) { @@ -268,6 +281,14 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_ } } + if (dtmf.duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "EXECSSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration); + dtmf.duration = SWITCH_MAX_DTMF_DURATION; + } else if (!dtmf.duration) { + dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; + } + + for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; @@ -295,9 +316,17 @@ SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *ch if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) { dt = (switch_dtmf_t *) pop; - /* TODO: Shouldn't we be doing a memcpy here? */ *dtmf = *dt; free(dt); + + if (dtmf->duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s EXECSSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(channel), dtmf->digit, dtmf->duration); + dtmf->duration = SWITCH_MAX_DTMF_DURATION; + } else if (!dtmf->duration) { + dtmf->duration = SWITCH_DEFAULT_DTMF_DURATION; + } + status = SWITCH_STATUS_SUCCESS; } switch_mutex_unlock(channel->dtmf_mutex); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index b019fa3dd7..8c7ba6a6c1 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -915,9 +915,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio { switch_io_event_hook_recv_dtmf_t *ptr; switch_status_t status; + switch_dtmf_t new_dtmf; + + switch_assert(dtmf); + + new_dtmf = *dtmf; + + if (new_dtmf.duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s EXECSSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration); + new_dtmf.duration = SWITCH_MAX_DTMF_DURATION; + } else if (!new_dtmf.duration) { + new_dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; + } for (ptr = session->event_hooks.recv_dtmf; ptr; ptr = ptr->next) { - if ((status = ptr->recv_dtmf(session, dtmf)) != SWITCH_STATUS_SUCCESS) { + if ((status = ptr->recv_dtmf(session, &new_dtmf)) != SWITCH_STATUS_SUCCESS) { return status; } } @@ -928,8 +941,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio { switch_io_event_hook_send_dtmf_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; + switch_dtmf_t new_dtmf; - + switch_assert(dtmf); + + new_dtmf = *dtmf; + + if (new_dtmf.duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s EXECSSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration); + new_dtmf.duration = SWITCH_MAX_DTMF_DURATION; + } else if (!new_dtmf.duration) { + new_dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; + } + + for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) { if ((status = ptr->send_dtmf(session, dtmf)) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_SUCCESS; @@ -942,7 +968,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio } else if (dtmf->digit == 'W') { switch_yield(1000000); } else { - status = session->endpoint_interface->io_routines->send_dtmf(session, dtmf); + status = session->endpoint_interface->io_routines->send_dtmf(session, &new_dtmf); } } return status; @@ -986,6 +1012,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core } } + + if (dtmf.duration > SWITCH_MAX_DTMF_DURATION) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s EXECSSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); + dtmf.duration = SWITCH_MAX_DTMF_DURATION; + } else if (!dtmf.duration) { + dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; + } + for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; diff --git a/src/switch_core_memory.c b/src/switch_core_memory.c index 0c535979d9..10510bacfd 100644 --- a/src/switch_core_memory.c +++ b/src/switch_core_memory.c @@ -35,7 +35,7 @@ #include #include "private/switch_core_pvt.h" /*#define LOCK_MORE*/ -/*#define PER_POOL_LOCK 1*/ +#define PER_POOL_LOCK 1 static struct { switch_mutex_t *mem_lock; @@ -246,21 +246,31 @@ SWITCH_DECLARE(char *) switch_core_strdup(switch_memory_pool_t *pool, const char return duped; } +SWITCH_DECLARE(void) switch_core_memory_pool_tag(switch_memory_pool_t *pool, const char *tag) +{ + apr_pool_tag(pool, tag); +} + SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memory_pool_t **pool, const char *file, const char *func, int line) { char *tmp; - void *pop; +#ifdef PER_POOL_LOCK + apr_allocator_t *my_allocator = NULL; + apr_thread_mutex_t *my_mutex; +#else + void *pop = NULL; +#endif switch_mutex_lock(memory_manager.mem_lock); switch_assert(pool != NULL); - if (switch_queue_trypop(memory_manager.pool_recycle_queue, &pop) == SWITCH_STATUS_SUCCESS) { +#ifndef PER_POOL_LOCK + if (switch_queue_trypop(memory_manager.pool_recycle_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { *pool = (switch_memory_pool_t *) pop; } else { -#ifdef PER_POOL_LOCK - apr_allocator_t *my_allocator = NULL; - apr_thread_mutex_t *my_mutex; +#endif +#ifdef PER_POOL_LOCK if ((apr_allocator_create(&my_allocator)) != APR_SUCCESS) { return SWITCH_STATUS_MEMERR; } @@ -280,8 +290,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor #else apr_pool_create(pool, NULL); switch_assert(*pool != NULL); -#endif } +#endif #ifdef DEBUG_ALLOC2 printf("New Pool %s %s:%d\n", file, func, line); @@ -356,9 +366,6 @@ SWITCH_DECLARE(void) switch_core_memory_reclaim(void) static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t * thread, void *obj) { - void *pop = NULL; - switch_memory_pool_t *pool; - memory_manager.pool_thread_running = 1; while (memory_manager.pool_thread_running == 1) { @@ -370,26 +377,21 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t * thread, void *obj) switch_yield(1000000); switch_mutex_lock(memory_manager.mem_lock); while (x > 0) { - if (switch_queue_pop(memory_manager.pool_queue, &pop) != SWITCH_STATUS_SUCCESS) { + void *pop = NULL; + if (switch_queue_pop(memory_manager.pool_queue, &pop) != SWITCH_STATUS_SUCCESS || !pop) { done = 1; break; } + - if (!pop) { - done = 1; - break; - } - - pool = (switch_memory_pool_t *) pop; -#if PER_POOL_LOCK - apr_pool_destroy(pool); +#if defined(PER_POOL_LOCK) || defined(DESTROY_POOLS) + apr_pool_destroy(pop); #else - apr_pool_clear(pool); - if (switch_queue_trypush(memory_manager.pool_recycle_queue, pool) != SWITCH_STATUS_SUCCESS) { - apr_pool_destroy(pool); + apr_pool_clear(pop); + if (switch_queue_trypush(memory_manager.pool_recycle_queue, pop) != SWITCH_STATUS_SUCCESS) { + apr_pool_destroy(pop); } #endif - pool = NULL; x--; } switch_mutex_unlock(memory_manager.mem_lock); @@ -404,12 +406,12 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t * thread, void *obj) done: switch_core_memory_reclaim(); - while (switch_queue_trypop(memory_manager.pool_queue, &pop) == SWITCH_STATUS_SUCCESS) { - pool = (switch_memory_pool_t *) pop; - if (!pool) { - break; + { + void *pop = NULL; + while (switch_queue_trypop(memory_manager.pool_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { + apr_pool_destroy(pop); + pop = NULL; } - apr_pool_destroy(pool); } memory_manager.pool_thread_running = 0; diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 7f80c0dea3..692c740b86 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -690,6 +690,10 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t * thread, void *obj) { switch_core_session_t *session = obj; + switch_event_t *event; + char *event_str = NULL; + const char *val; + session->thread = thread; switch_core_session_run(session); @@ -697,6 +701,17 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t * thr session->id, switch_channel_get_name(session->channel)); switch_core_session_write_lock(session); switch_set_flag(session, SSF_DESTROYED); + + if ((val = switch_channel_get_variable(session->channel, "memory_debug")) && switch_true(val)) { + if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(session->channel, event); + switch_event_serialize(event, &event_str, SWITCH_FALSE); + switch_assert(event_str); + switch_core_memory_pool_tag(switch_core_session_get_pool(session), switch_core_session_strdup(session, event_str)); + free(event_str); + } + } + switch_core_session_rwunlock(session); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Session %"SWITCH_SIZE_T_FMT" (%s) Ended\n", diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index a7521491f7..0b2e401a5d 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -979,9 +979,15 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void while (switch_queue_trypop(pvt->digit_queue, &pop) == SWITCH_STATUS_SUCCESS) { switch_dtmf_t *dtmf = (switch_dtmf_t *) pop; char buf[2] = ""; - + int duration = dtmf->duration; + buf[0] = dtmf->digit; - pvt->ts.duration = dtmf->duration; + if (duration > 8000) { + duration = 4000; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s Truncating ridiculous DTMF duration %d ms to 1/2 second.\n", + switch_channel_get_name(switch_core_session_get_channel(pvt->session)), dtmf->duration / 8); + } + pvt->ts.duration = duration; teletone_run(&pvt->ts, buf); } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 9d131774d9..ff3a9dd557 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1371,6 +1371,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_sessi if ((rdigit = malloc(sizeof(*rdigit))) != 0) { *rdigit = *dtmf; + if (rdigit->duration < SWITCH_DEFAULT_DTMF_DURATION) { + rdigit->duration = SWITCH_DEFAULT_DTMF_DURATION; + } + if ((switch_queue_trypush(rtp_session->dtmf_data.dtmf_queue, rdigit)) != SWITCH_STATUS_SUCCESS) { free(rdigit); return SWITCH_STATUS_FALSE; @@ -1389,9 +1393,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_se if (!switch_rtp_ready(rtp_session)) { return SWITCH_STATUS_FALSE; } - + if ((rdigit = malloc(sizeof(*rdigit))) != 0) { *rdigit = *dtmf; + if (rdigit->duration < SWITCH_DEFAULT_DTMF_DURATION) { + rdigit->duration = SWITCH_DEFAULT_DTMF_DURATION; + } + if ((switch_queue_trypush(rtp_session->dtmf_data.dtmf_inqueue, rdigit)) != SWITCH_STATUS_SUCCESS) { free(rdigit); return SWITCH_STATUS_FALSE;