shared/gatt-server: Fix crash on read multiple 37/204937/1
authorSzymon Janc <szymon.janc@codecoup.pl>
Tue, 13 Mar 2018 07:47:27 +0000 (08:47 +0100)
committerAmit Purwar <amit.purwar@samsung.com>
Fri, 26 Apr 2019 10:44:14 +0000 (16:14 +0530)
When read multiple includes external characteristic, call to
gatt_db_attribute_read's complete callback is asynchronous.

Fix following crash:
Use of uninitialised value of size 8
   at 0x49718A: read_multiple_complete_cb (gatt-server.c:994)
   by 0x498999: pending_read_result (gatt-db.c:136)
   by 0x49A84B: gatt_db_attribute_read_result (gatt-db.c:1787)
   by 0x451F4C: read_reply_cb (gatt-database.c:1712)
   by 0x48B221: method_call_reply (client.c:972)
   by 0x53AB601: ??? (in /usr/lib64/libdbus-1.so.3.19.3)
   by 0x53AEF7E: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.3)
   by 0x486FEF: message_dispatch (mainloop.c:72)
   by 0x50CB576: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CEB76: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CEF1F: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CF231: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.5400.3)

Invalid read of size 8
   at 0x49718A: read_multiple_complete_cb (gatt-server.c:994)
   by 0x498999: pending_read_result (gatt-db.c:136)
   by 0x49A84B: gatt_db_attribute_read_result (gatt-db.c:1787)
   by 0x451F4C: read_reply_cb (gatt-database.c:1712)
   by 0x48B221: method_call_reply (client.c:972)
   by 0x53AB601: ??? (in /usr/lib64/libdbus-1.so.3.19.3)
   by 0x53AEF7E: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.3)
   by 0x486FEF: message_dispatch (mainloop.c:72)
   by 0x50CB576: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CEB76: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CEF1F: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
   by 0x50CF231: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.5400.3)
 Address 0x8 is not stack'd, malloc'd or (recently) free'd

Change-Id: Id0aca942b2c5229e798c2d4fb9d9d8c3ac86cdde
Signed-off-by: Amit Purwar <amit.purwar@samsung.com>
src/shared/gatt-server.c

index 640ac29..d22e06b 100755 (executable)
@@ -1004,10 +1004,8 @@ struct read_multiple_resp_data {
 static void read_multiple_resp_data_free(struct read_multiple_resp_data *data)
 {
        free(data->handles);
-       data->handles = NULL;
-
        free(data->rsp_data);
-       data->rsp_data = NULL;
+       free(data);
 }
 
 static void read_multiple_complete_cb(struct gatt_db_attribute *attr, int err,
@@ -1084,38 +1082,38 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu,
 {
        struct bt_gatt_server *server = user_data;
        struct gatt_db_attribute *attr;
-       struct read_multiple_resp_data data;
+       struct read_multiple_resp_data *data = NULL;
        uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
        size_t i = 0;
 
-       data.handles = NULL;
-       data.rsp_data = NULL;
-
        if (length < 4) {
                ecode = BT_ATT_ERROR_INVALID_PDU;
                goto error;
        }
 
-       data.server = server;
-       data.num_handles = length / 2;
-       data.cur_handle = 0;
-       data.mtu = bt_att_get_mtu(server->att);
-       data.length = 0;
-       data.rsp_data = malloc(data.mtu - 1);
-
-       if (!data.rsp_data)
+       data = new0(struct read_multiple_resp_data, 1);
+       data->handles = NULL;
+       data->rsp_data = NULL;
+       data->server = server;
+       data->num_handles = length / 2;
+       data->cur_handle = 0;
+       data->mtu = bt_att_get_mtu(server->att);
+       data->length = 0;
+       data->rsp_data = malloc(data->mtu - 1);
+
+       if (!data->rsp_data)
                goto error;
 
-       data.handles = new0(uint16_t, data.num_handles);
+       data->handles = new0(uint16_t, data->num_handles);
 
-       for (i = 0; i < data.num_handles; i++)
-               data.handles[i] = get_le16(pdu + i * 2);
+       for (i = 0; i < data->num_handles; i++)
+               data->handles[i] = get_le16(pdu + i * 2);
 
        util_debug(server->debug_callback, server->debug_data,
                        "Read Multiple Req - %zu handles, 1st: 0x%04x",
-                       data.num_handles, data.handles[0]);
+                       data->num_handles, data->handles[0]);
 
-       attr = gatt_db_get_attribute(server->db, data.handles[0]);
+       attr = gatt_db_get_attribute(server->db, data->handles[0]);
 
        if (!attr) {
                ecode = BT_ATT_ERROR_INVALID_HANDLE;
@@ -1123,11 +1121,13 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu,
        }
 
        if (gatt_db_attribute_read(attr, 0, opcode, server->att,
-                                       read_multiple_complete_cb, &data))
+                                       read_multiple_complete_cb, data))
                return;
 
 error:
-       read_multiple_resp_data_free(&data);
+       if (data)
+               read_multiple_resp_data_free(data);
+
        bt_att_send_error_rsp(server->att, opcode, 0, ecode);
 }