diff options
author | Richard Mudgett <rmudgett@digium.com> | 2015-01-20 16:46:16 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2015-01-20 16:46:16 +0000 |
commit | 6af6a216a1fcfb1dcefbfa6dc657d3781f3a24d9 (patch) | |
tree | 19b0d1bba2257ce3f7acf523dba76c14fa3c6a7c /res | |
parent | 072db5e1b9201b3d7219a12ed559a9e856d535b6 (diff) |
CHANNEL(peer), chan_iax2, res_fax, SNMP agent: Fix deadlock from reaching across a bridge.
Calling ast_channel_bridge_peer() cannot be done while holding any channel
locks. The reported issue hit the deadlock in chan_iax2, but an audit of
the ast_channel_bridge_peer() calls found three more locations where the
same deadlock can occur.
* Made CHANNEL(peer), res_fax, and the SNMP agent not call
ast_channel_bridge_peer() with any channel locked. For CHANNEL(peer) I
had to rework the logic to not hold the channel lock.
* Made chan_iax2 no longer call ast_channel_bridge_peer(). It was done
for legacy reasons that no longer apply.
* Removed the iax.conf forcejitterbuffer option. It is now always enabled
when the jitterbuffer option is enabled. If you put a jitter buffer on a
channel it will be on the channel.
ASTERISK-24600 #close
Reported by: Jeff Collell
Review: https://reviewboard.asterisk.org/r/4342/
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@430817 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res')
-rw-r--r-- | res/res_fax.c | 6 | ||||
-rw-r--r-- | res/snmp/agent.c | 10 |
2 files changed, 13 insertions, 3 deletions
diff --git a/res/res_fax.c b/res/res_fax.c index cb282e5bc..18811063e 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -2888,6 +2888,7 @@ static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan) { struct ast_fax_session *s; + int start_res; /* create the FAX session */ if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) { @@ -2908,7 +2909,10 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session gateway->s = s; gateway->token = NULL; - if (gateway->s->tech->start_session(gateway->s) < 0) { + ast_channel_unlock(chan); + start_res = gateway->s->tech->start_session(gateway->s); + ast_channel_lock(chan); + if (start_res < 0) { ast_string_field_set(details, result, "FAILED"); ast_string_field_set(details, resultstr, "error starting gateway session"); ast_string_field_set(details, error, "INIT_ERROR"); diff --git a/res/snmp/agent.c b/res/snmp/agent.c index abaf37224..9d1528dde 100644 --- a/res/snmp/agent.c +++ b/res/snmp/agent.c @@ -298,12 +298,18 @@ static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *le } break; case ASTCHANBRIDGE: - if ((bridge = ast_channel_bridge_peer(chan)) != NULL) { + ast_channel_unlock(chan); + bridge = ast_channel_bridge_peer(chan); + if (bridge) { + ast_channel_lock(bridge); ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret)); + ast_channel_unlock(bridge); + ast_channel_unref(bridge); + *var_len = strlen(string_ret); ret = (u_char *)string_ret; - ast_channel_unref(bridge); } + ast_channel_lock(chan); break; case ASTCHANMASQ: if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) { |