mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
I am fighting deadlocks in chan_iax2. I have tracked them down to a single
core issue. You can not call find_callno() while holding a pvt lock as this function has to lock another (every) other pvt lock. Doing so can lead to a classic deadlock. So, I am tracking down all of the code paths where this can happen and fixing them. The fix I committed earlier today was along the same theme. This patch fixes some code down the path of authenticate_reply. git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@79272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1244,6 +1244,9 @@ static int make_trunk(unsigned short callno, int locked)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \note Calling this function while holding another pvt lock can cause a deadlock.
|
||||
*/
|
||||
static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int lockpeer, int sockfd)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -2502,6 +2505,10 @@ static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newcha
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \note This function calls reg_source_db -> iax2_poke_peer -> find_callno,
|
||||
* so do not call this with a pvt lock held.
|
||||
*/
|
||||
static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
|
||||
{
|
||||
struct ast_variable *var;
|
||||
@@ -5219,6 +5226,10 @@ static int authenticate(const char *challenge, const char *secret, const char *k
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \note This function calls realtime_peer -> reg_source_db -> iax2_poke_peer -> find_callno,
|
||||
* so do not call this function with a pvt lock held.
|
||||
*/
|
||||
static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey)
|
||||
{
|
||||
struct iax2_peer *peer = NULL;
|
||||
@@ -5226,7 +5237,8 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin,
|
||||
int res = -1;
|
||||
int authmethods = 0;
|
||||
struct iax_ie_data ied;
|
||||
|
||||
uint16_t callno = p->callno;
|
||||
|
||||
memset(&ied, 0, sizeof(ied));
|
||||
|
||||
if (ies->username)
|
||||
@@ -5263,11 +5275,21 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin,
|
||||
if (!peer) {
|
||||
/* We checked our list and didn't find one. It's unlikely, but possible,
|
||||
that we're trying to authenticate *to* a realtime peer */
|
||||
if ((peer = realtime_peer(p->peer, NULL))) {
|
||||
const char *peer_name = ast_strdupa(p->peer);
|
||||
ast_mutex_unlock(&iaxsl[callno]);
|
||||
if ((peer = realtime_peer(peer_name, NULL))) {
|
||||
ast_mutex_lock(&iaxsl[callno]);
|
||||
if (!(p = iaxs[callno]))
|
||||
return -1;
|
||||
res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
|
||||
if (ast_test_flag(peer, IAX_TEMPONLY))
|
||||
destroy_peer(peer);
|
||||
}
|
||||
if (!peer) {
|
||||
ast_mutex_lock(&iaxsl[callno]);
|
||||
if (!(p = iaxs[callno]))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ies->encmethods)
|
||||
@@ -7384,6 +7406,10 @@ retryowner2:
|
||||
"I don't know how to authenticate %s to %s\n",
|
||||
ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
|
||||
}
|
||||
if (!iaxs[fr->callno]) {
|
||||
ast_mutex_unlock(&iaxsl[fr->callno]);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case IAX_COMMAND_AUTHREP:
|
||||
/* For security, always ack immediately */
|
||||
|
Reference in New Issue
Block a user