shared/bap: Fix not unregistering disconnect callback
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tue, 6 Sep 2022 19:54:36 +0000 (12:54 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 15 May 2023 09:25:54 +0000 (14:55 +0530)
bt_bap_detach shall always unregister the disconnect callback otherwise
the session pointer may still be accessible.

Signed-off-by: Manika Shrivastava <manika.sh@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/shared/bap.c

index 150b211..c5f1134 100644 (file)
@@ -158,6 +158,7 @@ struct bt_bap {
        unsigned int cp_id;
 
        unsigned int process_id;
+       unsigned int disconn_id;
        struct queue *reqs;
        struct queue *pending;
        struct queue *notify;
@@ -623,6 +624,8 @@ static void bap_disconnected(int err, void *user_data)
 {
        struct bt_bap *bap = user_data;
 
+       bap->disconn_id = 0;
+
        DBG(bap, "bap %p disconnected err %d", bap, err);
 
        bt_bap_detach(bap);
@@ -643,8 +646,6 @@ static struct bt_bap *bap_get_session(struct bt_att *att, struct gatt_db *db)
        bap = bt_bap_new(db, NULL);
        bap->att = att;
 
-       bt_att_register_disconnect(att, bap_disconnected, bap, NULL);
-
        bt_bap_attach(bap, NULL);
 
        return bap;
@@ -3643,6 +3644,19 @@ static void bap_endpoint_foreach(void *data, void *user_data)
        bap_endpoint_attach(bap, ep);
 }
 
+static void bap_attach_att(struct bt_bap *bap, struct bt_att *att)
+{
+       if (bap->disconn_id) {
+               if (att == bt_bap_get_att(bap))
+                       return;
+               bt_att_unregister_disconnect(bap->att, bap->disconn_id);
+       }
+
+       bap->disconn_id = bt_att_register_disconnect(bap->att,
+                                                       bap_disconnected,
+                                                       bap, NULL);
+}
+
 bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
 {
        bt_uuid_t uuid;
@@ -3663,8 +3677,10 @@ bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
 
        queue_foreach(bap_cbs, bap_attached, bap);
 
-       if (!client)
+       if (!client) {
+               bap_attach_att(bap, bap->att);
                return true;
+       }
 
        if (bap->client)
                return false;
@@ -3674,6 +3690,8 @@ clone:
        if (!bap->client)
                return false;
 
+       bap_attach_att(bap, bt_gatt_client_get_att(client));
+
        if (bap->rdb->pacs) {
                uint16_t value_handle;
                struct bt_pacs *pacs = bap->rdb->pacs;
@@ -3733,6 +3751,9 @@ void bt_bap_detach(struct bt_bap *bap)
        bt_gatt_client_unref(bap->client);
        bap->client = NULL;
 
+       bt_att_unregister_disconnect(bap->att, bap->disconn_id);
+       bap->att = NULL;
+
        queue_foreach(bap->streams, stream_foreach_detach, bap);
        queue_foreach(bap_cbs, bap_detached, bap);
 }