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:
George Joseph
2022-10-10 08:35:54 -06:00
committed by Friendly Automation
parent 81f10e847e
commit 7684c9e907
4 changed files with 307 additions and 43 deletions

View File

@@ -87,6 +87,26 @@
#define AST_STIR_SHAKEN_RESPONSE_STR_UNSUPPORTED_CREDENTIAL "Unsupported Credential"
#define AST_STIR_SHAKEN_RESPONSE_STR_INVALID_IDENTITY_HEADER "Invalid Identity Header"
/* ":12345" */
#define COLON_PORT_STRLEN 6
/*
* "<ipaddr>:<port>"
* PJ_INET6_ADDRSTRLEN includes the NULL terminator
*/
#define IP6ADDR_COLON_PORT_BUFLEN (PJ_INET6_ADDRSTRLEN + COLON_PORT_STRLEN)
/*!
* \brief Fill a buffer with a pjsip transport's remote ip address and port
*
* \param transport The pjsip_transport to use
* \param dest The destination buffer of at least IP6ADDR_COLON_PORT_BUFLEN bytes
*/
#define AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(_transport, _dest) \
snprintf(_dest, IP6ADDR_COLON_PORT_BUFLEN, \
PJSTR_PRINTF_SPEC ":%d", \
PJSTR_PRINTF_VAR(_transport->remote_name.host), \
_transport->remote_name.port);
/* Forward declarations of PJSIP stuff */
struct pjsip_rx_data;
struct pjsip_module;
@@ -3745,6 +3765,7 @@ enum ast_transport_monitor_reg {
/*!
* \brief Register a reliable transport shutdown monitor callback.
* \deprecated Replaced with ast_sip_transport_monitor_register_key().
* \since 13.20.0
*
* \param transport Transport to monitor for shutdown.
@@ -3762,8 +3783,29 @@ enum ast_transport_monitor_reg {
enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport,
ast_transport_monitor_shutdown_cb cb, void *ao2_data);
/*!
* \brief Register a reliable transport shutdown monitor callback.
*
* \param transport_key Key for the transport to monitor for shutdown.
* Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.
* \param cb Who to call when transport is shutdown.
* \param ao2_data Data to pass with the callback.
*
* \note The data object passed will have its reference count automatically
* incremented by this call and automatically decremented after the callback
* runs or when the callback is unregistered.
*
* There is no checking for duplicate registrations.
*
* \return enum ast_transport_monitor_reg
*/
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_key(
const char *transport_key, ast_transport_monitor_shutdown_cb cb,
void *ao2_data);
/*!
* \brief Register a reliable transport shutdown monitor callback replacing any duplicate.
* \deprecated Replaced with ast_sip_transport_monitor_register_replace_key().
* \since 13.26.0
* \since 16.3.0
*
@@ -3785,8 +3827,32 @@ enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transpor
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport,
ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches);
/*!
* \brief Register a reliable transport shutdown monitor callback replacing any duplicate.
*
* \param transport_key Key for the transport to monitor for shutdown.
* Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.
* \param cb Who to call when transport is shutdown.
* \param ao2_data Data to pass with the callback.
* \param matches Matcher function that returns true if data matches a previously
* registered data object
*
* \note The data object passed will have its reference count automatically
* incremented by this call and automatically decremented after the callback
* runs or when the callback is unregistered.
*
* This function checks for duplicates, and overwrites/replaces the old monitor
* with the given one.
*
* \return enum ast_transport_monitor_reg
*/
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace_key(
const char *transport_key, ast_transport_monitor_shutdown_cb cb,
void *ao2_data, ast_transport_monitor_data_matcher matches);
/*!
* \brief Unregister a reliable transport shutdown monitor
* \deprecated Replaced with ast_sip_transport_monitor_unregister_key().
* \since 13.20.0
*
* \param transport Transport to monitor for shutdown.
@@ -3802,6 +3868,23 @@ enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_
void ast_sip_transport_monitor_unregister(pjsip_transport *transport,
ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches);
/*!
* \brief Unregister a reliable transport shutdown monitor
*
* \param transport_key Key for the transport to monitor for shutdown.
* Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.
* \param cb The callback that was used for the original register.
* \param data Data to pass to the matcher. May be NULL and does NOT need to be an ao2 object.
* If NULL, all monitors with the provided callback are unregistered.
* \param matches Matcher function that returns true if data matches the previously
* registered data object. If NULL, a simple pointer comparison is done.
*
* \note The data object passed into the original register will have its reference count
* automatically decremented.
*/
void ast_sip_transport_monitor_unregister_key(const char *transport_key,
ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches);
/*!
* \brief Unregister a transport shutdown monitor from all reliable transports
* \since 13.20.0