]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_followme.c: Grab reference on nativeformats before using it
authorMatthew Fredrickson <matt@fredricknet.net>
Thu, 26 Oct 2023 02:14:48 +0000 (21:14 -0500)
committerAsterisk Development Team <asteriskteam@digium.com>
Fri, 12 Jan 2024 18:32:13 +0000 (18:32 +0000)
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 b5c31b55c9812036a41d21de8fc89a2bc6500865)

apps/app_chanisavail.c
apps/app_followme.c
main/bridge.c
main/bridge_basic.c

index c75bb792089fc1453793bd40581719e52e5d24a4..910e7146246198d5b2b0ab4647c4e90a7134b0ff 100644 (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_channel *tempchan;
        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_APP_ARG(reqchans);
                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);
 
+       ao2_lock(chan);
+       caps = ao2_bump(ast_channel_nativeformats(chan));
+       ao2_unlock(chan);
+
        if (args.options) {
                if (strchr(args.options, 'a')) {
                        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);
                        status = inuse = ast_device_state(trychan);
                }
-               ast_str_append(&tmp_availstat, 0, "%s%d",
-                       ast_str_strlen(tmp_availstat) ? "&" : "", status);
+               ast_str_append(&tmp_availstat, 0, "%s%d", ast_str_strlen(tmp_availstat) ? "&" : "", status);
+
                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_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
 
@@ -199,8 +205,11 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
                                break;
                        }
                }
+
        }
 
+       ao2_cleanup(caps);
+
        pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
        /* Store the originally used channel too */
        pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig));
index 31ba9b8a56585b737e04c9ff50da7d18495041c3..abc68aef207adc3b8aa642249b1dadf115c8e2d5 100644 (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));
                for (number = num; number; number = rest) {
                        struct ast_channel *outbound;
+                       struct ast_format_cap *caps;
 
                        rest = strchr(number, '&');
                        if (rest) {
@@ -1097,8 +1098,15 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel
                                                ? "/n" : "/m");
                        }
 
-                       outbound = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller,
-                               tmpuser->dialarg, &dg);
+                       /* Capture nativeformats reference in case it gets changed */
+                       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) {
                                ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n",
                                        tmpuser->dialarg, ast_cause2str(dg));
index 112b621b43b5bdd15dd52d74e0344c8973c5449e..8299a1967acaa015dfecf48f37498b4ed2e03409 100644 (file)
@@ -4118,10 +4118,18 @@ static enum ast_transfer_result blind_transfer_bridge(int is_external,
        struct ast_channel *local;
        char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
        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);
-       local = ast_request("Local", ast_channel_nativeformats(transferer), NULL, transferer,
+       local = ast_request("Local", caps, NULL, transferer,
                        chan_name, &cause);
+
+       ao2_cleanup(caps);
+
        if (!local) {
                return AST_BRIDGE_TRANSFER_FAIL;
        }
@@ -4228,9 +4236,16 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
        int cause;
        int res;
        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) {
                return AST_BRIDGE_TRANSFER_FAIL;
        }
index 96d38e59e9dc20adb94796d807d9099b42bc1402..952ac9f3804a1865eafda96fffef68ebee40954f 100644 (file)
@@ -3288,10 +3288,17 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
 {
        struct ast_channel *chan;
        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 */
-       chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination,
-               &cause);
+       chan = ast_request("Local", caps, NULL, caller, destination, &cause);
+
+       ao2_cleanup(caps);
+
        if (!chan) {
                return NULL;
        }