From 0956ca15dc36609dd99287e10467642dfb3bc8d3 Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Mon, 13 Feb 2017 11:05:51 +0000 Subject: [PATCH] channel: Protect flags in ast_waitfor_nandfds operation. The ast_waitfor_nandfds operation will manipulate the flags of channels passed in. This was previously done without the channel lock being held. This could result in incorrect values existing for the flags if another thread manipulated the flags at the same time. This change locks the channel during flag manipulation. ASTERISK-26788 Change-Id: I2c5c8edec17c9bdad4a93291576838cb552ca5ed --- main/channel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/channel.c b/main/channel.c index 92763f9113..ac3e960a1f 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3130,7 +3130,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, fdmap[max].chan = x; /* channel x is linked to this pfds */ max += ast_add_fd(&pfds[max], ast_channel_fd(c[x], y)); } + ast_channel_lock(c[x]); CHECK_BLOCKING(c[x]); + ast_channel_unlock(c[x]); } /* Add the individual fds */ for (x = 0; x < nfds; x++) { @@ -3157,7 +3159,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, res = ast_poll(pfds, max, rms); } for (x = 0; x < n; x++) { + ast_channel_lock(c[x]); ast_clear_flag(ast_channel_flags(c[x]), AST_FLAG_BLOCKING); + ast_channel_unlock(c[x]); } if (res < 0) { /* Simulate a timeout if we were interrupted */ if (errno != EINTR) { @@ -3193,12 +3197,14 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, } if (fdmap[x].chan >= 0) { /* this is a channel */ winner = c[fdmap[x].chan]; /* override previous winners */ + ast_channel_lock(winner); if (res & POLLPRI) { ast_set_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION); } else { ast_clear_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION); } ast_channel_fdno_set(winner, fdmap[x].fdno); + ast_channel_unlock(winner); } else { /* this is an fd */ if (outfd) { *outfd = pfds[x].fd; -- 2.47.2