]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
json: Audit ast_json_* usage for thread safety. 28/1828/1
authorJoshua Colp <jcolp@digium.com>
Mon, 14 Dec 2015 18:04:15 +0000 (14:04 -0400)
committerJoshua Colp <jcolp@digium.com>
Wed, 16 Dec 2015 21:17:30 +0000 (17:17 -0400)
The JSON library Asterisk uses, jansson, is not thread
safe for us in a few ways. To help with this wrappers for JSON
object reference count increasing and decreasing were added
which use a global lock to ensure they don't clobber over
each other. This does not extend to reference count manipulation
within the jansson library itself. This means you can't safely
use the object borrowing specifier (O) in ast_json_pack and
you can't share JSON instances between objects.

This change removes uses of the O specifier and replaces them
with the o specifier and an explicit ast_json_ref. Some cases
of instance sharing have also been removed.

ASTERISK-25601 #close

Change-Id: I06550d8b0cc1bfeb56cab580a4e608ae4f1ec7d1

main/aoc.c
main/loader.c
main/rtp_engine.c
main/stasis.c
main/stasis_channels.c
res/res_fax.c
res/res_stasis.c
res/res_stasis_playback.c
res/res_stasis_recording.c
res/stasis/app.c

index 5bce0665155e776da6601ff7b179165a78605e81..29c5e87b61ff172b9c64dadd769fa49fdf25f15f 100644 (file)
@@ -1667,11 +1667,11 @@ static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded)
        }
 
        return ast_json_pack(
-               "{s:s, s:s, s:s, s:O}",
+               "{s:s, s:s, s:s, s:o}",
                "Type", aoc_charge_type_str(decoded->charge_type),
                "BillingID", aoc_billingid_str(decoded->billing_id),
                "TotalType", aoc_type_of_totaling_str(decoded->total_type),
-               obj_type, obj);
+               obj_type, ast_json_ref(obj));
 }
 
 static struct ast_json *association_to_json(const struct ast_aoc_decoded *decoded)
@@ -1738,10 +1738,10 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                        "Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale);
                        }
 
-                       type = ast_json_pack("{s:O, s:s, s:O, s:O}", "Currency", currency, "ChargingType",
+                       type = ast_json_pack("{s:o, s:s, s:o, s:o}", "Currency", ast_json_ref(currency), "ChargingType",
                                             decoded->aoc_s_entries[i].rate.duration.charging_type ?
-                                            "StepFunction" : "ContinuousCharging", "Time", time,
-                                            "Granularity", granularity ? granularity : ast_json_null());
+                                            "StepFunction" : "ContinuousCharging", "Time", ast_json_ref(time),
+                                            "Granularity", granularity ? ast_json_ref(granularity) : ast_json_ref(ast_json_null()));
 
                        break;
                }
@@ -1751,7 +1751,7 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                decoded->aoc_s_entries[i].rate.flat.amount,
                                decoded->aoc_s_entries[i].rate.flat.multiplier);
 
-                       type = ast_json_pack("{s:O}", "Currency", currency);
+                       type = ast_json_pack("{s:o}", "Currency", ast_json_ref(currency));
                        break;
                case AST_AOC_RATE_TYPE_VOLUME:
                        currency = currency_to_json(
@@ -1760,9 +1760,9 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                decoded->aoc_s_entries[i].rate.volume.multiplier);
 
                        type = ast_json_pack(
-                               "{s:s, s:O}", "Unit", aoc_volume_unit_str(
+                               "{s:s, s:o}", "Unit", aoc_volume_unit_str(
                                        decoded->aoc_s_entries[i].rate.volume.volume_unit),
-                               "Currency", currency);
+                               "Currency", ast_json_ref(currency));
                        break;
                case AST_AOC_RATE_TYPE_SPECIAL_CODE:
                        type = ast_json_pack("{s:i}", "SpecialCode",
@@ -1772,8 +1772,8 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                        break;
                }
 
-               rate = ast_json_pack("{s:s, s:O}", "Chargeable", charge_item,
-                                    aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), type);
+               rate = ast_json_pack("{s:s, s:o}", "Chargeable", charge_item,
+                                    aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), ast_json_ref(type));
                if (ast_json_array_append(rates, rate)) {
                        break;
                }
index 940b53edb904f83ce74fcc62638fc9ab1137b373..2b3bd1fba5050aad7759e661945976eaf7d2f406 100644 (file)
@@ -852,10 +852,10 @@ static void publish_reload_message(const char *name, enum ast_module_reload_resu
        event_object = ast_json_pack("{s: s, s: s}",
                        "Module", S_OR(name, "All"),
                        "Status", res_buffer);
-       json_object = ast_json_pack("{s: s, s: i, s: O}",
+       json_object = ast_json_pack("{s: s, s: i, s: o}",
                        "type", "Reload",
                        "class_type", EVENT_FLAG_SYSTEM,
-                       "event", event_object);
+                       "event", ast_json_ref(event_object));
 
        if (!json_object) {
                return;
index beda8cd745651d0ae67531ca5935446853973211..d659b980972a00d70d3e7dc8d1b922f45462bdef 100644 (file)
@@ -2008,12 +2008,12 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
                }
        }
 
-       json_rtcp_report = ast_json_pack("{s: i, s: i, s: i, s: O, s: O}",
+       json_rtcp_report = ast_json_pack("{s: i, s: i, s: i, s: o, s: o}",
                        "ssrc", payload->report->ssrc,
                        "type", payload->report->type,
                        "report_count", payload->report->reception_report_count,
-                       "sender_information", json_rtcp_sender_info ? json_rtcp_sender_info : ast_json_null(),
-                       "report_blocks", json_rtcp_report_blocks);
+                       "sender_information", json_rtcp_sender_info ? ast_json_ref(json_rtcp_sender_info) : ast_json_ref(ast_json_null()),
+                       "report_blocks", ast_json_ref(json_rtcp_report_blocks));
        if (!json_rtcp_report) {
                return NULL;
        }
@@ -2025,10 +2025,10 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
                }
        }
 
-       return ast_json_pack("{s: O, s: O, s: O}",
-               "channel", payload->snapshot ? json_channel : ast_json_null(),
-               "rtcp_report", json_rtcp_report,
-               "blob", payload->blob);
+       return ast_json_pack("{s: o, s: o, s: o}",
+               "channel", payload->snapshot ? ast_json_ref(json_channel) : ast_json_ref(ast_json_null()),
+               "rtcp_report", ast_json_ref(json_rtcp_report),
+               "blob", ast_json_deep_copy(payload->blob));
 }
 
 static void rtp_rtcp_report_dtor(void *obj)
index 6adbfc3b69383e4b2214fe0f66a89bc89334182a..962efc83ed05b183f95b9661cba49e5e286991e7 100644 (file)
@@ -1274,8 +1274,8 @@ static struct ast_json *multi_user_event_to_json(
 
        ast_json_object_set(out, "type", ast_json_string_create("ChannelUserevent"));
        ast_json_object_set(out, "timestamp", ast_json_timeval(*tv, NULL));
-       ast_json_object_set(out, "eventname", ast_json_ref(ast_json_object_get(blob, "eventname")));
-       ast_json_object_set(out, "userevent", ast_json_ref(blob)); /* eventname gets duplicated, that's ok */
+       ast_json_object_set(out, "eventname", ast_json_string_create(ast_json_string_get((ast_json_object_get(blob, "eventname")))));
+       ast_json_object_set(out, "userevent", ast_json_deep_copy(blob));
 
        for (type = 0; type < STASIS_UMOS_MAX; ++type) {
                for (i = 0; i < AST_VECTOR_SIZE(&multi->snapshots[type]); ++i) {
index b8efd407b578bcb8507f0fca699bc7b524afe9fb..d46a8ddcf003b0ced6cfde56bbe8520100669abf 100644 (file)
@@ -1016,6 +1016,10 @@ static struct ast_json *dtmf_end_to_json(
        struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
        const char *direction =
                ast_json_string_get(ast_json_object_get(blob, "direction"));
+       const char *digit =
+               ast_json_string_get(ast_json_object_get(blob, "digit"));
+       long duration_ms =
+               ast_json_integer_get(ast_json_object_get(blob, "duration_ms"));
        const struct timeval *tv = stasis_message_timestamp(message);
        struct ast_json *json_channel;
 
@@ -1029,11 +1033,11 @@ static struct ast_json *dtmf_end_to_json(
                return NULL;
        }
 
-       return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
+       return ast_json_pack("{s: s, s: o, s: s, s: i, s: o}",
                "type", "ChannelDtmfReceived",
                "timestamp", ast_json_timeval(*tv, NULL),
-               "digit", ast_json_object_get(blob, "digit"),
-               "duration_ms", ast_json_object_get(blob, "duration_ms"),
+               "digit", digit,
+               "duration_ms", duration_ms,
                "channel", json_channel);
 }
 
@@ -1057,6 +1061,12 @@ static struct ast_json *dial_to_json(
 {
        struct ast_multi_channel_blob *payload = stasis_message_data(message);
        struct ast_json *blob = ast_multi_channel_blob_get_json(payload);
+       const char *dialstatus =
+               ast_json_string_get(ast_json_object_get(blob, "dialstatus"));
+       const char *forward =
+               ast_json_string_get(ast_json_object_get(blob, "forward"));
+       const char *dialstring =
+               ast_json_string_get(ast_json_object_get(blob, "dialstring"));
        struct ast_json *caller_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "caller"), sanitize);
        struct ast_json *peer_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "peer"), sanitize);
        struct ast_json *forwarded_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "forwarded"), sanitize);
@@ -1064,12 +1074,12 @@ static struct ast_json *dial_to_json(
        const struct timeval *tv = stasis_message_timestamp(message);
        int res = 0;
 
-       json = ast_json_pack("{s: s, s: o, s: O, s: O, s: O}",
+       json = ast_json_pack("{s: s, s: o, s: s, s: s, s: s}",
                "type", "Dial",
                "timestamp", ast_json_timeval(*tv, NULL),
-               "dialstatus", ast_json_object_get(blob, "dialstatus"),
-               "forward", ast_json_object_get(blob, "forward"),
-               "dialstring", ast_json_object_get(blob, "dialstring"));
+               "dialstatus", dialstatus,
+               "forward", forward,
+               "dialstring", dialstring);
        if (!json) {
                ast_json_unref(caller_json);
                ast_json_unref(peer_json);
index e947c91c18ccf9e3480195ee9c97e6dc7b8dca60..ef0e27696ad13525a8535e8635aa996155aa8953 100644 (file)
@@ -2028,14 +2028,14 @@ static int report_receive_fax_status(struct ast_channel *chan, const char *filen
                        fax_bitrate = ast_strdupa(fax_bitrate);
                }
 
-               json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: O}",
+               json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
                                "type", "receive",
                                "remote_station_id", S_OR(remote_station_id, ""),
                                "local_station_id", S_OR(local_station_id, ""),
                                "fax_pages", S_OR(fax_pages, ""),
                                "fax_resolution", S_OR(fax_resolution, ""),
                                "fax_bitrate", S_OR(fax_bitrate, ""),
-                               "filenames", json_array);
+                               "filenames", ast_json_ref(json_array));
                if (!json_object) {
                        return -1;
                }
index 1cab8c389b1fd0d83532b6685ed47e8429e474c7..94b037e69c6a190352d4cc20f884d5f915f1880d 100644 (file)
@@ -150,10 +150,10 @@ static struct ast_json *stasis_start_to_json(struct stasis_message *message,
                return NULL;
        }
 
-       msg = ast_json_pack("{s: s, s: O, s: O, s: o}",
+       msg = ast_json_pack("{s: s, s: o, s: o, s: o}",
                "type", "StasisStart",
-               "timestamp", ast_json_object_get(payload->blob, "timestamp"),
-               "args", ast_json_object_get(payload->blob, "args"),
+               "timestamp", ast_json_copy(ast_json_object_get(payload->blob, "timestamp")),
+               "args", ast_json_deep_copy(ast_json_object_get(payload->blob, "args")),
                "channel", ast_channel_snapshot_to_json(payload->channel, NULL));
        if (!msg) {
                ast_log(LOG_ERROR, "Failed to pack JSON for StasisStart message\n");
index dc6e8f2b8b4982e7c9f4d5bf1af2445943518ebd..779dd77550698079323661200659690d2a880608 100644 (file)
@@ -105,9 +105,9 @@ static struct ast_json *playback_to_json(struct stasis_message *message,
                return NULL;
        }
 
-       return ast_json_pack("{s: s, s: O}",
+       return ast_json_pack("{s: s, s: o}",
                "type", type,
-               "playback", blob);
+               "playback", ast_json_deep_copy(blob));
 }
 
 STASIS_MESSAGE_TYPE_DEFN(stasis_app_playback_snapshot_type,
index 50e0697b1821d230e391d53c8dd5cab37e164aa9..392d92c8e54056d50a62feb69427e55194804fd4 100644 (file)
@@ -91,9 +91,9 @@ static struct ast_json *recording_to_json(struct stasis_message *message,
                return NULL;
        }
 
-       return ast_json_pack("{s: s, s: O}",
+       return ast_json_pack("{s: s, s: o}",
                "type", type,
-               "recording", blob);
+               "recording", ast_json_deep_copy(blob));
 }
 
 STASIS_MESSAGE_TYPE_DEFN(stasis_app_recording_snapshot_type,
index 3539182410adcfb98b113b0d25f0a690280be429..4e18aa5ae72023f743c34aed3721f38c131b5101 100644 (file)
@@ -610,11 +610,11 @@ static int message_received_handler(const char *endpoint_id, struct ast_json *js
                return -1;
        }
 
-       app_send(app, ast_json_pack("{s: s, s: o, s: o, s: O}",
+       app_send(app, ast_json_pack("{s: s, s: o, s: o, s: o}",
                "type", "TextMessageReceived",
                "timestamp", ast_json_timeval(ast_tvnow(), NULL),
                "endpoint", json_endpoint,
-               "message", json_msg));
+               "message", ast_json_ref(json_msg)));
 
        return 0;
 }