app_followme.c: Grab reference on nativeformats before using it

Fixes a crash due to a lack of proper reference on the nativeformats
object before passing it into ast_request().  Also found potentially
similar use case bugs in app_chanisavail.c, bridge.c, and bridge_basic.c

Fixes: #388
(cherry picked from commit 275f7911b5)
This commit is contained in:
Matthew Fredrickson
2023-10-25 21:14:48 -05:00
committed by Asterisk Development Team
parent 52388f11f8
commit eac9ad69a8
4 changed files with 49 additions and 10 deletions

View File

@@ -117,6 +117,7 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
struct ast_str *tmp_availcause = ast_str_alloca(2048); struct ast_str *tmp_availcause = ast_str_alloca(2048);
struct ast_channel *tempchan; struct ast_channel *tempchan;
struct ast_custom_function *cdr_prop_func = ast_custom_function_find("CDR_PROP"); struct ast_custom_function *cdr_prop_func = ast_custom_function_find("CDR_PROP");
struct ast_format_cap *caps = NULL;
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(reqchans); AST_APP_ARG(reqchans);
AST_APP_ARG(options); AST_APP_ARG(options);
@@ -126,6 +127,10 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
AST_STANDARD_APP_ARGS(args, info); AST_STANDARD_APP_ARGS(args, info);
ao2_lock(chan);
caps = ao2_bump(ast_channel_nativeformats(chan));
ao2_unlock(chan);
if (args.options) { if (args.options) {
if (strchr(args.options, 'a')) { if (strchr(args.options, 'a')) {
option_all_avail = 1; option_all_avail = 1;
@@ -174,10 +179,11 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
snprintf(trychan, sizeof(trychan), "%s/%s", tech, number); snprintf(trychan, sizeof(trychan), "%s/%s", tech, number);
status = inuse = ast_device_state(trychan); status = inuse = ast_device_state(trychan);
} }
ast_str_append(&tmp_availstat, 0, "%s%d", ast_str_append(&tmp_availstat, 0, "%s%d", ast_str_strlen(tmp_availstat) ? "&" : "", status);
ast_str_strlen(tmp_availstat) ? "&" : "", status);
if ((inuse <= (int) AST_DEVICE_NOT_INUSE) if ((inuse <= (int) AST_DEVICE_NOT_INUSE)
&& (tempchan = ast_request(tech, ast_channel_nativeformats(chan), NULL, chan, number, &status))) { && (tempchan = ast_request(tech, caps, NULL, chan, number, &status))) {
ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_append(&tmp_availchan, 0, "%s%s",
ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan)); ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
@@ -199,8 +205,11 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
break; break;
} }
} }
} }
ao2_cleanup(caps);
pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan)); pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
/* Store the originally used channel too */ /* Store the originally used channel too */
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig)); pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig));

View File

@@ -1068,6 +1068,7 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel
ast_copy_string(num, nm->number, sizeof(num)); ast_copy_string(num, nm->number, sizeof(num));
for (number = num; number; number = rest) { for (number = num; number; number = rest) {
struct ast_channel *outbound; struct ast_channel *outbound;
struct ast_format_cap *caps;
rest = strchr(number, '&'); rest = strchr(number, '&');
if (rest) { if (rest) {
@@ -1097,8 +1098,15 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel
? "/n" : "/m"); ? "/n" : "/m");
} }
outbound = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, /* Capture nativeformats reference in case it gets changed */
tmpuser->dialarg, &dg); ast_channel_lock(caller);
caps = ao2_bump(ast_channel_nativeformats(caller));
ast_channel_unlock(caller);
outbound = ast_request("Local", caps, NULL, caller, tmpuser->dialarg, &dg);
ao2_cleanup(caps);
if (!outbound) { if (!outbound) {
ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n",
tmpuser->dialarg, ast_cause2str(dg)); tmpuser->dialarg, ast_cause2str(dg));

View File

@@ -4118,10 +4118,18 @@ static enum ast_transfer_result blind_transfer_bridge(int is_external,
struct ast_channel *local; struct ast_channel *local;
char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2]; char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
int cause; int cause;
struct ast_format_cap *caps;
ast_channel_lock(transferer);
caps = ao2_bump(ast_channel_nativeformats(transferer));
ast_channel_unlock(transferer);
snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context); snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context);
local = ast_request("Local", ast_channel_nativeformats(transferer), NULL, transferer, local = ast_request("Local", caps, NULL, transferer,
chan_name, &cause); chan_name, &cause);
ao2_cleanup(caps);
if (!local) { if (!local) {
return AST_BRIDGE_TRANSFER_FAIL; return AST_BRIDGE_TRANSFER_FAIL;
} }
@@ -4228,9 +4236,16 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
int cause; int cause;
int res; int res;
const char *app = NULL; const char *app = NULL;
struct ast_format_cap *caps;
ast_channel_lock(chan1);
caps = ao2_bump(ast_channel_nativeformats(chan1));
ast_channel_unlock(chan1);
local_chan = ast_request("Local", caps, NULL, chan1, dest, &cause);
ao2_cleanup(caps);
local_chan = ast_request("Local", ast_channel_nativeformats(chan1), NULL, chan1,
dest, &cause);
if (!local_chan) { if (!local_chan) {
return AST_BRIDGE_TRANSFER_FAIL; return AST_BRIDGE_TRANSFER_FAIL;
} }

View File

@@ -3293,10 +3293,17 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
{ {
struct ast_channel *chan; struct ast_channel *chan;
int cause; int cause;
struct ast_format_cap *caps;
ast_channel_lock(caller);
caps = ao2_bump(ast_channel_nativeformats(caller));
ast_channel_unlock(caller);
/* Now we request a local channel to prepare to call the destination */ /* Now we request a local channel to prepare to call the destination */
chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination, chan = ast_request("Local", caps, NULL, caller, destination, &cause);
&cause);
ao2_cleanup(caps);
if (!chan) { if (!chan) {
return NULL; return NULL;
} }