[PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping
flat view
COLD26d
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2026-09-10 18:42:30
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Luiz Augusto von Dentz <redacted> The allowlist enforcement added across the adapter, device and A2DP layers ended up using three different UUIDs for the same two profiles: adapter.c mapped both a2dp-source and a2dp-sink to ADVANCED_AUDIO_UUID (0x110d), while device.c and a2dp.c mapped them to the local role UUIDs 0x110a and 0x110b. An allowlist containing only 0x110a therefore blocked the a2dp-sink adapter probe outright, so the finer grained SEP checks in a2dp.c never ran. Add btd_profile_get_policy_uuid() as the single place resolving a profile to the UUID of the local service it provides. btd_profile names and remote_uuid describe the remote role, so the A2DP profiles are inverted there: "a2dp-source" registers the local Sink server and "a2dp-sink" registers the local Source server. This matches what device.c and a2dp.c already do. Note that allowlisting 0x110d alone no longer enables A2DP; the local role UUIDs 0x110a and/or 0x110b have to be listed. This also drops the hardcoded profile name table in adapter.c. Every entry but the two A2DP ones just returned profile->remote_uuid, and any profile without a local_uuid that was missing from the table resolved to NULL, i.e. was allowed unconditionally regardless of the allowlist. Assisted-by: opencode:claude-opus-5 --- src/adapter.c | 49 +------------------------------------------------ src/device.c | 25 ++----------------------- src/profile.c | 24 ++++++++++++++++++++++++ src/profile.h | 7 +++++++ 4 files changed, 34 insertions(+), 71 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 157d7392d32c..fc734424be07 100644
--- a/src/adapter.c
+++ b/src/adapter.c@@ -5353,59 +5353,12 @@ static void load_drivers(struct btd_adapter *adapter) probe_driver(adapter, l->data); } -struct profile_allowlist_map { - const char *name; - const char *uuid; - bool use_remote_uuid; -}; - -/* - * Adapter server policy UUID defaults to local_uuid when available. - * Profiles listed below are exceptions. - * - * A2DP profiles map to ADVANCED_AUDIO_UUID so profile probe gating matches - * the A2DP profile class (0x110d), while adapter service registration/removal - * still filters specific Source/Sink records by their own UUIDs. - */ -static const struct profile_allowlist_map profile_allowlist_map[] = { - { "a2dp-source", ADVANCED_AUDIO_UUID, false }, - { "a2dp-sink", ADVANCED_AUDIO_UUID, false }, - { "audio-avrcp-target", NULL, true }, - { "avrcp-controller", NULL, true }, - { "vcp", NULL, true }, - { "micp", NULL, true }, - { "ccp", NULL, true }, - { "gmap", NULL, true }, - { "tmap", NULL, true }, - { "bass", NULL, true }, - { "bap", NULL, true }, - { "mcp-gmcs", NULL, true }, -}; - static const char *profile_allowlist_uuid(const struct btd_profile *profile) { - size_t i; - if (profile->local_uuid) return profile->local_uuid; - if (!profile->name) - return NULL; - - for (i = 0; i < ARRAY_SIZE(profile_allowlist_map); i++) { - const struct profile_allowlist_map *entry = - &profile_allowlist_map[i]; - - if (strcmp(profile->name, entry->name)) - continue; - - if (entry->use_remote_uuid) - return profile->remote_uuid; - - return entry->uuid; - } - - return NULL; + return btd_profile_get_policy_uuid(profile); } bool btd_adapter_is_profile_allowed(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index 8da576ec5932..ec74c44ac4aa 100644
--- a/src/device.c
+++ b/src/device.c@@ -2547,27 +2547,6 @@ static struct btd_service *find_connectable_service(struct btd_device *dev, return NULL; } -static const char *service_policy_uuid(const struct btd_profile *profile) -{ - if (!profile) - return NULL; - - /* - * For A2DP device services, apply admin policy by local role UUID: - * - a2dp-sink profile is local source role (110a) - * - a2dp-source profile is local sink role (110b) - */ - if (profile->name) { - if (!strcmp(profile->name, "a2dp-sink")) - return A2DP_SOURCE_UUID; - - if (!strcmp(profile->name, "a2dp-source")) - return A2DP_SINK_UUID; - } - - return profile->remote_uuid; -} - bool btd_device_all_services_allowed(struct btd_device *dev) { GSList *l;
@@ -2579,7 +2558,7 @@ bool btd_device_all_services_allowed(struct btd_device *dev) for (l = dev->services; l != NULL; l = g_slist_next(l)) { service = l->data; profile = btd_service_get_profile(service); - uuid = service_policy_uuid(profile); + uuid = btd_profile_get_policy_uuid(profile); if (!profile || !profile->auto_connect || !uuid) continue;
@@ -2614,7 +2593,7 @@ void btd_device_update_allowed_services(struct btd_device *dev) for (l = dev->services; l != NULL; l = g_slist_next(l)) { service = l->data; profile = btd_service_get_profile(service); - uuid = service_policy_uuid(profile); + uuid = btd_profile_get_policy_uuid(profile); if (!profile || !uuid) continue;
diff --git a/src/profile.c b/src/profile.c
index 97fffe9b4d5c..e5b1cdfc5d33 100644
--- a/src/profile.c
+++ b/src/profile.c@@ -16,6 +16,7 @@ #include <stdbool.h> #include <stdint.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <glib.h>
@@ -753,6 +754,29 @@ void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data), } } +const char *btd_profile_get_policy_uuid(const struct btd_profile *profile) +{ + if (!profile) + return NULL; + + /* + * The admin allowlist is expressed in terms of the services the local + * adapter exposes, while btd_profile names and remote_uuid describe + * the remote role. The A2DP profiles therefore have to be inverted: + * the "a2dp-source" profile drives the local Sink server and the + * "a2dp-sink" profile drives the local Source server. + */ + if (profile->name) { + if (!strcmp(profile->name, "a2dp-source")) + return A2DP_SINK_UUID; + + if (!strcmp(profile->name, "a2dp-sink")) + return A2DP_SOURCE_UUID; + } + + return profile->remote_uuid; +} + static struct btd_profile *btd_profile_find_uuid(const char *uuid) { GSList *l, *next;
diff --git a/src/profile.h b/src/profile.h
index 04a99528b4be..270f09ea2b96 100644
--- a/src/profile.h
+++ b/src/profile.h@@ -84,6 +84,13 @@ struct btd_profile { void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data), void *data); +/* + * Return the UUID of the local service a profile provides, for use by the + * admin policy allowlist. Returns NULL when the profile has no service to + * match against. + */ +const char *btd_profile_get_policy_uuid(const struct btd_profile *profile); + int btd_profile_register(struct btd_profile *profile); void btd_profile_unregister(struct btd_profile *profile);
--
2.55.0