a2dp: Fix crash when SEP codec has not been initialized
authorFrédéric Danis <frederic.danis@collabora.com>
Wed, 30 Mar 2022 09:28:44 +0000 (11:28 +0200)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 15 May 2023 09:25:54 +0000 (14:55 +0530)
If SEP has not been properly discovered avdtp_get_codec may return NULL
thus causing crashes such as when running AVRCP/TG/VLH/BI-01-C after
AVRCP/TG/RCR/BV-04-C.

Prevent remote endpoint registration if its codec is not available.

Remove queue_isempty check from store_remote_seps since that prevents
cleaning up if no seps could be registered.

Signed-off-by: Manika Shrivastava <manika.sh@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/audio/a2dp.c

index 94bde3d..afcd0f2 100644 (file)
@@ -883,9 +883,6 @@ static void store_remote_seps(struct a2dp_channel *chan)
        char *data;
        gsize length = 0;
 
-       if (queue_isempty(chan->seps))
-               return;
-
        ba2str(device_get_address(device), dst_addr);
 
        snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
@@ -2177,6 +2174,11 @@ static struct a2dp_remote_sep *register_remote_sep(void *data, void *user_data)
        if (sep)
                return sep;
 
+       if (!avdtp_get_codec(rsep)) {
+               error("Unable to get remote sep codec");
+               return NULL;
+       }
+
        sep = new0(struct a2dp_remote_sep, 1);
        sep->chan = chan;
        sep->sep = rsep;
@@ -2251,6 +2253,7 @@ static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
        struct avdtp_remote_sep *rsep;
        uint8_t lseid, rseid;
        char *value;
+       bool update = false;
 
        if (!seids)
                return;
@@ -2309,10 +2312,19 @@ static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
                }
 
                sep = register_remote_sep(rsep, chan);
-               if (sep)
-                       sep->from_cache = true;
+               if (!sep) {
+                       avdtp_unregister_remote_sep(chan->session, rsep);
+                       update = true;
+                       continue;
+               }
+
+               sep->from_cache = true;
        }
 
+       /* Update cache */
+       if (update)
+               store_remote_seps(chan);
+
        value = g_key_file_get_string(key_file, "Endpoints", "LastUsed", NULL);
        if (!value)
                return;