Commit 455d691d0e for asterisk.org
commit 455d691d0ea10c603f63248a8327abcdbf29b626
Author: phoneben <3232963@gmail.com>
Date: Tue Oct 13 13:33:01 2026 +0300
res_pjsip_caller_id: Avoid channel access outside session serializer
res_pjsip_caller_id: Avoid channel access outside session serializer
**Issue:**
During SIP response retransmissions, `caller_id_outgoing_response()` may execute on the PJSIP monitor thread, outside the session serializer.
If a channel masquerade changes `session->channel` between the lock and unlock operations, the original channel mutex may remain locked, potentially causing a deadlock during `PickupChan()`.
**Fix:**
Add a serializer check using `ast_taskpool_serializer_get_current()` to prevent accessing `session->channel` outside its session serializer, following the existing pattern in `res_pjsip_rfc3326.c`.
**AI assistance:** ChatGPT assisted with identifying the issue and drafting the PR description.
Resolves: #2224
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 2289ab4db1..72a347f879 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -34,6 +34,7 @@
#include "asterisk/module.h"
#include "asterisk/callerid.h"
#include "asterisk/conversions.h"
+#include "asterisk/taskpool.h"
static int extract_oli(const pjsip_param *param_list, char *buf, size_t len)
{
@@ -590,7 +591,18 @@ static void caller_id_outgoing_response(struct ast_sip_session *session, pjsip_t
struct ast_party_id effective_id;
struct ast_party_id connected_id;
- if (!session->channel
+ /*
+ * Outgoing response callbacks may execute on the PJSIP monitor
+ * thread during retransmissions, outside the session serializer.
+ * The channel pointer can change during a masquerade, potentially
+ * causing a channel mutex to remain locked.
+ *
+ * Retransmitted responses already contain the caller ID information
+ * added when the response was first sent, so skipping this callback
+ * outside the serializer does not change the response contents.
+ */
+ if (session->serializer != ast_taskpool_serializer_get_current()
+ || !session->channel
|| (!session->endpoint->id.send_connected_line
&& session->inv_session
&& session->inv_session->state >= PJSIP_INV_STATE_EARLY)) {