res_pjsip: Copy default_from_user to avoid crash.

The default_from_user retrieval function was pulling the
default_from_user from the global configuration struct in an unsafe way.
If using a database as a backend configuration store, the global
configuration struct is short-lived, so grabbing a pointer from it
results in referencing freed memory.

The fix here is to copy the default_from_user value out of the global
configuration struct.

Thanks go to John Hardin for discovering this problem and proposing the
patch on which this fix is based.

ASTERISK-25390 #close
Reported by Mark Michelson

Change-Id: I6b96067a495c1259da768f4012d44e03e7c6148c
This commit is contained in:
Mark Michelson
2015-09-10 09:49:45 -05:00
parent be3f52a122
commit f1a2e82d49
3 changed files with 12 additions and 11 deletions

View File

@@ -2025,9 +2025,11 @@ char *ast_sip_get_endpoint_identifier_order(void);
* is no better option (such as an endpoint-configured from_user or
* caller ID number).
*
* \retval The global default_from_user value.
* \param[out] from_user The default from user
* \param size The buffer size of from_user
* \return nothing
*/
const char *ast_sip_get_default_from_user(void);
void ast_sip_get_default_from_user(char *from_user, size_t size);
/*! \brief Determines whether the res_pjsip module is loaded */
#define CHECK_PJSIP_MODULE_LOADED() \

View File

@@ -2338,9 +2338,11 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
pjsip_sip_uri *sip_uri;
pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
int local_port;
char default_user[PJSIP_MAX_URL_SIZE];
if (ast_strlen_zero(user)) {
user = ast_sip_get_default_from_user();
ast_sip_get_default_from_user(default_user, sizeof(default_user));
user = default_user;
}
/* Parse the provided target URI so we can determine what transport it will end up using */

View File

@@ -182,20 +182,17 @@ unsigned int ast_sip_get_max_initial_qualify_time(void)
return time;
}
const char *ast_sip_get_default_from_user(void)
void ast_sip_get_default_from_user(char *from_user, size_t size)
{
const char *from_user;
struct global_config *cfg;
cfg = get_global_cfg();
if (!cfg) {
return DEFAULT_FROM_USER;
ast_copy_string(from_user, DEFAULT_FROM_USER, size);
} else {
ast_copy_string(from_user, cfg->default_from_user, size);
ao2_ref(cfg, -1);
}
from_user = cfg->default_from_user;
ao2_ref(cfg, -1);
return from_user;
}
/*!