Fix crash when AMI redirect action redirects two channels out of a bridge.

The two party bridging loops were changing the bridge peer pointers
without the channel locks held.  Thus when ast_channel_massquerade()
tested and used the pointer there is a small window of opportunity for the
pointers to become NULL even though the masquerade code has the channels
locked.

(closes issue ASTERISK-21356)
Reported by: William luke
Patches:
      jira_asterisk_21356_v11.patch (license #5621) patch uploaded by rmudgett
Tested by: William luke
........

Merged revisions 386256 from http://svn.asterisk.org/svn/asterisk/branches/1.8


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@386286 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2013-04-22 16:30:53 +00:00
parent a3a58d9d44
commit c1c2ae1e5f
+15
View File
@@ -7549,8 +7549,11 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
}
ast_channel_lock_both(c0, c1);
ast_channel_internal_bridged_channel_set(c0, c1);
ast_channel_internal_bridged_channel_set(c1, c0);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
}
continue;
}
@@ -7831,8 +7834,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
}
/* Keep track of bridge */
ast_channel_lock_both(c0, c1);
ast_channel_internal_bridged_channel_set(c0, c1);
ast_channel_internal_bridged_channel_set(c1, c0);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
ast_set_owners_and_peers(c0, c1);
@@ -7926,8 +7932,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
}
ast_channel_lock_both(c0, c1);
ast_channel_internal_bridged_channel_set(c0, c1);
ast_channel_internal_bridged_channel_set(c1, c0);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
ast_debug(1, "Unbridge signal received. Ending native bridge.\n");
continue;
}
@@ -7973,8 +7982,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
continue;
}
ast_channel_lock_both(c0, c1);
ast_channel_internal_bridged_channel_set(c0, NULL);
ast_channel_internal_bridged_channel_set(c1, NULL);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
ast_format_cap_destroy(o0nativeformats);
ast_format_cap_destroy(o1nativeformats);
return res;
@@ -8031,8 +8043,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
ast_indicate(c0, AST_CONTROL_SRCUPDATE);
ast_indicate(c1, AST_CONTROL_SRCUPDATE);
ast_channel_lock_both(c0, c1);
ast_channel_internal_bridged_channel_set(c0, NULL);
ast_channel_internal_bridged_channel_set(c1, NULL);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
manager_bridge_event(0, 1, c0, c1);
ast_debug(1, "Bridge stops bridging channels %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));