shared/gatt-db: Fix crash when generating hash
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tue, 14 May 2019 07:39:27 +0000 (10:39 +0300)
committerhimanshu <h.himanshu@samsung.com>
Tue, 11 Feb 2020 08:57:47 +0000 (14:27 +0530)
The following crash can be observed when handles are not contiguous:

Invalid write of size 8
   at 0x452697: gen_hash_m (gatt-db.c:314)
   by 0x453FE8: gatt_db_service_foreach (gatt-db.c:1395)
   by 0x45408C: service_gen_hash_m (gatt-db.c:322)
   by 0x4548F1: foreach_service_in_range (gatt-db.c:1284)
   by 0x4548F1: foreach_in_range (gatt-db.c:1307)
   by 0x457470: queue_foreach (queue.c:220)
   by 0x453B75: gatt_db_foreach_service_in_range (gatt-db.c:1349)
   by 0x453BAC: gatt_db_foreach_service (gatt-db.c:1254)
   by 0x453C46: db_hash_update (gatt-db.c:340)
   by 0x4567B4: timeout_callback (timeout-glib.c:34)

Change-Id: Idc0456441e2b94935e7475e25b62428277180797
Signed-off-by: himanshu <h.himanshu@samsung.com>
src/shared/gatt-db.c

index 0c3627e..412fae1 100644 (file)
@@ -277,9 +277,14 @@ static void handle_notify(void *data, void *user_data)
                notify->service_removed(notify_data->attr, notify->user_data);
 }
 
+struct hash_data {
+       struct iovec *iov;
+       uint16_t i;
+};
+
 static void gen_hash_m(struct gatt_db_attribute *attr, void *user_data)
 {
-       struct iovec *iov = user_data;
+       struct hash_data *hash = user_data;
        uint8_t *data;
        size_t len;
 
@@ -313,8 +318,10 @@ static void gen_hash_m(struct gatt_db_attribute *attr, void *user_data)
                return;
        }
 
-       iov[attr->handle].iov_base = data;
-       iov[attr->handle].iov_len = len;
+       hash->iov[hash->i].iov_base = data;
+       hash->iov[hash->i].iov_len = len;
+
+       hash->i++;
 
        return;
 }
@@ -327,7 +334,7 @@ static void service_gen_hash_m(struct gatt_db_attribute *attr, void *user_data)
 static bool db_hash_update(void *user_data)
 {
        struct gatt_db *db = user_data;
-       struct iovec *iov;
+       struct hash_data hash;
        uint16_t i;
 
        db->hash_id = 0;
@@ -335,15 +342,16 @@ static bool db_hash_update(void *user_data)
        if (!db->next_handle)
                return false;
 
-       iov = new0(struct iovec, db->next_handle);
+       hash.iov = new0(struct iovec, db->next_handle);
+       hash.i = 0;
 
-       gatt_db_foreach_service(db, NULL, service_gen_hash_m, iov);
-       bt_crypto_gatt_hash(db->crypto, iov, db->next_handle, db->hash);
+       gatt_db_foreach_service(db, NULL, service_gen_hash_m, &hash);
+       bt_crypto_gatt_hash(db->crypto, hash.iov, db->next_handle, db->hash);
 
-       for (i = 0; i < db->next_handle; i++)
-               free(iov[i].iov_base);
+       for (i = 0; i < hash.i; i++)
+               free(hash.iov[i].iov_base);
 
-       free(iov);
+       free(hash.iov);
 
        return false;
 }