[Asterisk-code-review] res_pjsip: prevent crash on websocket disconnect (asterisk[certified/18.9])

Friendly Automation asteriskteam at digium.com
Mon Oct 31 12:31:20 CDT 2022


Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/19516 )

Change subject: res_pjsip: prevent crash on websocket disconnect
......................................................................

res_pjsip: prevent crash on websocket disconnect

When a websocket (or potentially any stateful connection) is quickly
created then destroyed, it is possible that the qualify thread will
destroy the transaction before the initialzing thread is finished
with it.

Depending on the timing, this can cause an assertion within pjsip.

To prevent this, ast_send_stateful_response will now create the group
lock and add a reference to it before creating the transaction.

While this should resolve the crash, there is still the potential that
the contact will not be cleaned up properly, see:ASTERISK~29286. As a
result, the contact has to 'time out' before it will be removed.

ASTERISK-28689

Change-Id: Id050fded2247a04d8f0fc5b8a2cf3e5482cb8cee
---
M res/res_pjsip.c
1 file changed, 64 insertions(+), 8 deletions(-)

Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit




diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 72d8e0e..e400b38 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2258,31 +2258,62 @@
 	return status == PJ_SUCCESS ? 0 : -1;
 }
 
+static void pool_destroy_callback(void *arg)
+{
+	pj_pool_t *pool = (pj_pool_t *)arg;
+	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+}
+
+static void clean_contact_from_tdata(pjsip_tx_data *tdata)
+{
+	struct ast_sip_contact *contact;
+	contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
+	ao2_cleanup(contact);
+	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
+	pjsip_tx_data_dec_ref(tdata);
+}
+
 int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
 {
 	pjsip_transaction *tsx;
+	pj_grp_lock_t *tsx_glock;
+	pj_pool_t *pool;
 
-	if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) {
-		struct ast_sip_contact *contact;
-
+	/* Create and initialize global lock pool */
+	pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "stateful response", PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC);
+	if (!pool){
 		/* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
 		 * We'll leak that reference if we don't get rid of it here.
 		 */
-		contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
-		ao2_cleanup(contact);
-		ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
-		pjsip_tx_data_dec_ref(tdata);
+		clean_contact_from_tdata(tdata);
 		return -1;
 	}
-	pjsip_tsx_recv_msg(tsx, rdata);
+	/* Create with handler so that we can release the pool once the glock derefs out */
+	if(pj_grp_lock_create_w_handler(pool, NULL, pool, &pool_destroy_callback, &tsx_glock) != PJ_SUCCESS) {
+		clean_contact_from_tdata(tdata);
+		pool_destroy_callback((void *) pool);
+		return -1;
+	}
+	/* We need an additional reference as the qualify thread may destroy this out
+	 * from under us. Add it now before it gets added to the tsx. */
+	pj_grp_lock_add_ref(tsx_glock);
 
+	if (pjsip_tsx_create_uas2(NULL, rdata, tsx_glock, &tsx) != PJ_SUCCESS) {
+		clean_contact_from_tdata(tdata);
+		pj_grp_lock_dec_ref(tsx_glock);
+		return -1;
+	}
+
+	pjsip_tsx_recv_msg(tsx, rdata);
 	supplement_outgoing_response(tdata, sip_endpoint);
 
 	if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
+		pj_grp_lock_dec_ref(tsx_glock);
 		pjsip_tx_data_dec_ref(tdata);
 		return -1;
 	}
 
+	pj_grp_lock_dec_ref(tsx_glock);
 	return 0;
 }
 

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/19516
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: certified/18.9
Gerrit-Change-Id: Id050fded2247a04d8f0fc5b8a2cf3e5482cb8cee
Gerrit-Change-Number: 19516
Gerrit-PatchSet: 1
Gerrit-Owner: Michael Bradeen <mbradeen at sangoma.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20221031/7b873ac3/attachment.html>


More information about the asterisk-code-review mailing list