From 9d1f176e292a17e6cda05664fefab62c11761d05 Mon Sep 17 00:00:00 2001
From: Mark Michelson <mmichelson@digium.com>
Date: Thu, 10 Sep 2015 09:49:45 -0500
Subject: [PATCH] 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
---
 include/asterisk/res_pjsip.h  |  6 ++++--
 res/res_pjsip.c               |  4 +++-
 res/res_pjsip/config_global.c | 13 +++++--------
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 4f3fadcd87..a36935dd33 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -2046,9 +2046,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()				\
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 7afcb70c44..46edd31505 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2342,9 +2342,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 */
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index b348896c8f..ef706f0b35 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -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;
 }
 
 /*!
-- 
GitLab