mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
pjsip_transport_events: Fix possible use after free on transport
It was possible for a module that registered for transport monitor events to pass in a pjsip_transport that had already been freed. This caused pjsip_transport_events to crash when looking up the monitor for the transport. The fix is a two pronged approach. 1. We now increment the reference count on pjsip_transports when we create monitors for them, then decrement the count when the transport is going to be destroyed. 2. There are now APIs to register and unregister monitor callbacks by "transport key" which is a string concatenation of the remote ip address and port. This way the module needing to monitor the transport doesn't have to hold on to the transport object itself to unregister. It just has to save the transport_key. * Added the pjsip_transport reference increment and decrement. * Changed the internal transport monitor container key from the transport->obj_name (which may not be unique anyway) to the transport_key. * Added a helper macro AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR() that fills a buffer with the transport_key using a passed-in pjsip_transport. * Added the following functions: ast_sip_transport_monitor_register_key ast_sip_transport_monitor_register_replace_key ast_sip_transport_monitor_unregister_key and marked their non-key counterparts as deprecated. * Updated res_pjsip_pubsub and res_pjsip_outbound_register to use the new "key" monitor functions. NOTE: res_pjsip_registrar also uses the transport monitor functionality but doesn't have a persistent object other than contact to store a transport key. At this time, it continues to use the non-key monitor functions. ASTERISK-30244 Change-Id: I1a20baf2a8643c272dcf819871d6c395f148f00b
This commit is contained in:
committed by
Friendly Automation
parent
81f10e847e
commit
7684c9e907
@@ -389,8 +389,8 @@ struct subscription_persistence {
|
||||
char src_name[PJ_INET6_ADDRSTRLEN];
|
||||
/*! Source port of the message */
|
||||
int src_port;
|
||||
/*! Local transport key type */
|
||||
char transport_key[32];
|
||||
/*! Local transport type (UDP,TCP,TLS)*/
|
||||
char transport_type[32];
|
||||
/*! Local transport address */
|
||||
char local_name[PJ_INET6_ADDRSTRLEN];
|
||||
/*! Local transport port */
|
||||
@@ -474,7 +474,7 @@ struct sip_subscription_tree {
|
||||
/*! The transport the subscription was received on.
|
||||
* Only used for reliable transports.
|
||||
*/
|
||||
pjsip_transport *transport;
|
||||
char transport_key[IP6ADDR_COLON_PORT_BUFLEN];
|
||||
/*! Indicator if initial notify should be generated.
|
||||
* Used to refresh modified RLS.
|
||||
*/
|
||||
@@ -711,8 +711,9 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
|
||||
rdata->tp_info.transport->obj_name,
|
||||
sub_tree->persistence->endpoint, sub_tree->root->resource,
|
||||
sub_tree->persistence->prune_on_boot);
|
||||
sub_tree->transport = rdata->tp_info.transport;
|
||||
ast_sip_transport_monitor_register(rdata->tp_info.transport,
|
||||
AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(rdata->tp_info.transport,
|
||||
sub_tree->transport_key);
|
||||
ast_sip_transport_monitor_register_key(sub_tree->transport_key,
|
||||
sub_tree_transport_cb, sub_tree);
|
||||
/*
|
||||
* FYI: ast_sip_transport_monitor_register holds a reference to the sub_tree
|
||||
@@ -746,8 +747,8 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
|
||||
ast_copy_string(sub_tree->persistence->src_name, rdata->pkt_info.src_name,
|
||||
sizeof(sub_tree->persistence->src_name));
|
||||
sub_tree->persistence->src_port = rdata->pkt_info.src_port;
|
||||
ast_copy_string(sub_tree->persistence->transport_key, rdata->tp_info.transport->type_name,
|
||||
sizeof(sub_tree->persistence->transport_key));
|
||||
ast_copy_string(sub_tree->persistence->transport_type, rdata->tp_info.transport->type_name,
|
||||
sizeof(sub_tree->persistence->transport_type));
|
||||
ast_copy_pj_str(sub_tree->persistence->local_name, &rdata->tp_info.transport->local_name.host,
|
||||
sizeof(sub_tree->persistence->local_name));
|
||||
sub_tree->persistence->local_port = rdata->tp_info.transport->local_name.port;
|
||||
@@ -763,12 +764,12 @@ static void subscription_persistence_remove(struct sip_subscription_tree *sub_tr
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub_tree->persistence->prune_on_boot && sub_tree->transport) {
|
||||
if (sub_tree->persistence->prune_on_boot && !ast_strlen_zero(sub_tree->transport_key)) {
|
||||
ast_debug(3, "Unregistering transport monitor on %s '%s->%s'\n",
|
||||
sub_tree->transport->obj_name,
|
||||
sub_tree->transport_key,
|
||||
sub_tree->endpoint ? ast_sorcery_object_get_id(sub_tree->endpoint) : "Unknown",
|
||||
sub_tree->root ? sub_tree->root->resource : "Unknown");
|
||||
ast_sip_transport_monitor_unregister(sub_tree->transport,
|
||||
ast_sip_transport_monitor_unregister_key(sub_tree->transport_key,
|
||||
sub_tree_transport_cb, sub_tree, NULL);
|
||||
}
|
||||
|
||||
@@ -1743,7 +1744,7 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
|
||||
rdata.tp_info.pool = pool;
|
||||
|
||||
if (ast_sip_create_rdata_with_contact(&rdata, persistence->packet, persistence->src_name,
|
||||
persistence->src_port, persistence->transport_key, persistence->local_name,
|
||||
persistence->src_port, persistence->transport_type, persistence->local_name,
|
||||
persistence->local_port, persistence->contact_uri)) {
|
||||
ast_log(LOG_WARNING, "Failed recreating '%s' subscription: The message could not be parsed\n",
|
||||
persistence->endpoint);
|
||||
@@ -5759,7 +5760,7 @@ static int load_module(void)
|
||||
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "src_port", "0", OPT_UINT_T, 0,
|
||||
FLDSET(struct subscription_persistence, src_port));
|
||||
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "transport_key", "0", OPT_CHAR_ARRAY_T, 0,
|
||||
CHARFLDSET(struct subscription_persistence, transport_key));
|
||||
CHARFLDSET(struct subscription_persistence, transport_type));
|
||||
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "local_name", "", OPT_CHAR_ARRAY_T, 0,
|
||||
CHARFLDSET(struct subscription_persistence, local_name));
|
||||
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "local_port", "0", OPT_UINT_T, 0,
|
||||
|
Reference in New Issue
Block a user