* [PATCH BlueZ 2/7] client/bluetoothctl: make admin.allow controller-aware
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 3/7] doc: document admin.allow optional controller argument Frédéric Danis
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Teach admin.allow to target the selected default controller when no
controller is provided, and to accept an explicit [ctrl] argument.
Replace single cached AdminPolicy proxies with per-controller proxy
lookup keyed by controller object path, so controller selection changes
are respected.
Export controller lookup/default helpers and shared controller
completion from main.c for reuse by admin.c.
Assisted-by: GPT:GPT-5.3-Codex
---
client/admin.c | 114 ++++++++++++++++++++++++++++++++++++++-----------
client/admin.h | 4 ++
client/main.c | 25 +++++++++--
3 files changed, 116 insertions(+), 27 deletions(-)
diff --git a/client/admin.c b/client/admin.c
index dc218ed2c..584d4630b 100644
--- a/client/admin.c
+++ b/client/admin.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <stdlib.h>
+#include "bluetooth/bluetooth.h"
#include "gdbus/gdbus.h"
#include "src/shared/shell.h"
@@ -23,27 +24,79 @@
#define _GNU_SOURCE
static DBusConnection *dbus_conn;
-static GList *admin_proxies;
-static GDBusProxy *set_proxy;
-static GDBusProxy *status_proxy;
+static GList *set_proxies;
+static GList *status_proxies;
static void admin_menu_pre_run(const struct bt_shell_menu *menu);
-static void admin_policy_set_set_proxy(GDBusProxy *proxy)
+static GDBusProxy *admin_policy_find_proxy(GList *proxies,
+ const char *path)
{
- set_proxy = proxy;
+ GList *list;
+
+ for (list = g_list_first(proxies); list; list = g_list_next(list)) {
+ GDBusProxy *proxy = list->data;
+
+ if (!strcmp(g_dbus_proxy_get_path(proxy), path))
+ return proxy;
+ }
+
+ return NULL;
+}
+
+static GDBusProxy *admin_policy_get_status_proxy(const char *controller_path)
+{
+ if (!controller_path)
+ return NULL;
+
+ return admin_policy_find_proxy(status_proxies, controller_path);
+}
+
+static GDBusProxy *admin_policy_get_set_proxy(const char *controller_path)
+{
+ if (!controller_path)
+ return NULL;
+
+ return admin_policy_find_proxy(set_proxies, controller_path);
}
-static void admin_policy_set_status_proxy(GDBusProxy *proxy)
+static GDBusProxy *admin_policy_get_controller(int argc, char *argv[],
+ int *arg_index)
{
- status_proxy = proxy;
+ GDBusProxy *controller;
+
+ *arg_index = 1;
+
+ if (argc > 1 && strlen(argv[1])) {
+ controller = bluetoothctl_find_controller(argv[1]);
+ if (controller) {
+ *arg_index = 2;
+ return controller;
+ }
+
+ if (bachk(argv[1]) == 0) {
+ bt_shell_printf("Controller %s not available\n",
+ argv[1]);
+ return NULL;
+ }
+ }
+
+ controller = bluetoothctl_get_default_controller();
+ if (controller)
+ return controller;
+
+ bt_shell_printf("No default controller available\n");
+ return NULL;
}
-static void admin_policy_read_service_allowlist(DBusConnection *dbus_conn)
+static void admin_policy_read_service_allowlist(GDBusProxy *controller)
{
DBusMessageIter iter, subiter;
+ GDBusProxy *status_proxy;
char *uuid = NULL;
+ const char *controller_path = g_dbus_proxy_get_path(controller);
+ status_proxy = admin_policy_get_status_proxy(controller_path);
if (!status_proxy || !g_dbus_proxy_get_property(status_proxy,
"ServiceAllowList", &iter)) {
bt_shell_printf("Failed to get property\n");
@@ -106,10 +159,14 @@ static void set_service_reply(DBusMessage *message, void *user_data)
return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
-static void admin_policy_set_service_allowlist(int argc, char *argv[])
+static void admin_policy_set_service_allowlist(GDBusProxy *controller,
+ int argc, char *argv[])
{
struct uuid_list_data data;
+ GDBusProxy *set_proxy;
+ const char *controller_path = g_dbus_proxy_get_path(controller);
+ set_proxy = admin_policy_get_set_proxy(controller_path);
if (!set_proxy) {
bt_shell_printf("Set proxy not ready\n");
return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -128,15 +185,23 @@ static void admin_policy_set_service_allowlist(int argc, char *argv[])
static void cmd_admin_allow(int argc, char *argv[])
{
- if (argc <= 1) {
- admin_policy_read_service_allowlist(dbus_conn);
+ GDBusProxy *controller;
+ int arg_index;
+
+ controller = admin_policy_get_controller(argc, argv, &arg_index);
+ if (!controller)
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ if (argc <= arg_index) {
+ admin_policy_read_service_allowlist(controller);
return;
}
- if (strcmp(argv[1], "clear") == 0)
- argc--;
+ if (strcmp(argv[arg_index], "clear") == 0)
+ arg_index++;
- admin_policy_set_service_allowlist(argc - 1, argv + 1);
+ admin_policy_set_service_allowlist(controller, argc - arg_index,
+ argv + arg_index);
}
static const struct bt_shell_menu admin_menu = {
@@ -144,15 +209,15 @@ static const struct bt_shell_menu admin_menu = {
.desc = "Admin Policy Submenu",
.pre_run = admin_menu_pre_run,
.entries = {
- { "allow", "[clear/uuid1 uuid2 ...]", cmd_admin_allow,
- "Allow service UUIDs and block rest of them"},
+ { "allow", "[ctrl] [clear/uuid1 uuid2 ...]", cmd_admin_allow,
+ "Allow service UUIDs and block rest of them",
+ bluetoothctl_controller_generator},
{} },
};
static void admin_policy_status_added(GDBusProxy *proxy)
{
- admin_proxies = g_list_append(admin_proxies, proxy);
- admin_policy_set_status_proxy(proxy);
+ status_proxies = g_list_append(status_proxies, proxy);
}
static void proxy_added(GDBusProxy *proxy, void *user_data)
@@ -162,15 +227,14 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
interface = g_dbus_proxy_get_interface(proxy);
if (!strcmp(interface, "org.bluez.AdminPolicySet1"))
- admin_policy_set_set_proxy(proxy);
+ set_proxies = g_list_append(set_proxies, proxy);
else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1"))
admin_policy_status_added(proxy);
}
static void admin_policy_status_removed(GDBusProxy *proxy)
{
- admin_proxies = g_list_remove(admin_proxies, proxy);
- admin_policy_set_status_proxy(NULL);
+ status_proxies = g_list_remove(status_proxies, proxy);
}
static void proxy_removed(GDBusProxy *proxy, void *user_data)
@@ -180,7 +244,7 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
interface = g_dbus_proxy_get_interface(proxy);
if (!strcmp(interface, "org.bluez.AdminPolicySet1"))
- admin_policy_set_set_proxy(NULL);
+ set_proxies = g_list_remove(set_proxies, proxy);
else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1"))
admin_policy_status_removed(proxy);
}
@@ -189,8 +253,10 @@ static GDBusClient *client;
static void disconnect_handler(DBusConnection *connection, void *user_data)
{
- g_list_free_full(admin_proxies, NULL);
- admin_proxies = NULL;
+ g_list_free_full(set_proxies, NULL);
+ set_proxies = NULL;
+ g_list_free_full(status_proxies, NULL);
+ status_proxies = NULL;
}
void admin_add_submenu(void)
diff --git a/client/admin.h b/client/admin.h
index 0047770dc..be58fb2fa 100644
--- a/client/admin.h
+++ b/client/admin.h
@@ -10,3 +10,7 @@
void admin_add_submenu(void);
void admin_remove_submenu(void);
+
+GDBusProxy *bluetoothctl_get_default_controller(void);
+GDBusProxy *bluetoothctl_find_controller(const char *address);
+char *bluetoothctl_controller_generator(const char *text, int state);
diff --git a/client/main.c b/client/main.c
index 9d9ac8b14..5e9f2eeb5 100644
--- a/client/main.c
+++ b/client/main.c
@@ -881,6 +881,25 @@ static struct adapter *find_ctrl_by_address(GList *source, const char *address)
return NULL;
}
+GDBusProxy *bluetoothctl_get_default_controller(void)
+{
+ if (!default_ctrl)
+ return NULL;
+
+ return default_ctrl->proxy;
+}
+
+GDBusProxy *bluetoothctl_find_controller(const char *address)
+{
+ struct adapter *adapter;
+
+ adapter = find_ctrl_by_address(ctrl_list, address);
+ if (!adapter)
+ return NULL;
+
+ return adapter->proxy;
+}
+
static GDBusProxy *find_proxies_by_iface(GList *source, const char *path,
const char *iface)
{
@@ -2788,7 +2807,7 @@ static char *generic_generator(const char *text, int state,
return NULL;
}
-static char *ctrl_generator(const char *text, int state)
+char *bluetoothctl_controller_generator(const char *text, int state)
{
static int index = 0;
static int len = 0;
@@ -3876,9 +3895,9 @@ static const struct bt_shell_menu main_menu = {
.entries = {
{ "list", NULL, cmd_list, "List available controllers" },
{ "show", "[ctrl]", cmd_show, "Controller information",
- ctrl_generator },
+ bluetoothctl_controller_generator },
{ "select", "<ctrl>", cmd_select, "Select default controller",
- ctrl_generator },
+ bluetoothctl_controller_generator },
{ "devices", "[Paired/Bonded/Trusted/Connected]", cmd_devices,
"List available devices, with an "
"optional property as the filter" },
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 3/7] doc: document admin.allow optional controller argument
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 2/7] client/bluetoothctl: make admin.allow controller-aware Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 4/7] src/adapter: enforce allowlist for local services Frédéric Danis
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Update bluetoothctl usage to 'admin.allow [ctrl] [clear/uuid1 uuid2 ...]'
and add explicit controller examples.
Refresh AdminPolicySet examples to include the controller-qualified
admin.allow form.
Assisted-by: GPT:GPT-5.3-Codex
---
doc/bluetoothctl-admin.rst | 13 +++++++++++--
doc/org.bluez.AdminPolicySet.rst | 1 +
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/doc/bluetoothctl-admin.rst b/doc/bluetoothctl-admin.rst
index d4446ce95..ce15b8728 100644
--- a/doc/bluetoothctl-admin.rst
+++ b/doc/bluetoothctl-admin.rst
@@ -9,7 +9,7 @@ Admin Policy Submenu
:Version: BlueZ
:Copyright: Free use of this software is granted under the terms of the GNU
Lesser General Public Licenses (LGPL).
-:Date: November 2022
+:Date: June 2026
:Manual section: 1
:Manual group: Linux System Administration
@@ -30,15 +30,22 @@ allow
Allow service UUIDs and block rest of them.
-:Usage: **> allow [clear/uuid1 uuid2 ...]**
+:Usage: **> allow [ctrl] [clear/uuid1 uuid2 ...]**
+:[ctrl]: Bluetooth controller address (optional; defaults to the selected controller)
:Uses: **org.bluez.AdminPolicySet(5)** property **ServiceAllowList**
:[clear/uuid1 uuid2 ...]: List of service UUIDs to allow, or "clear" to remove all restrictions
:Example Get current allowed UUIDs list:
| **> allow**
+:Example Get current allowed UUIDs list for a specific controller:
+ | **> allow 00:11:22:33:44:55**
:Example Allow Serial Port Profile only:
| **> allow 0x1101**
+:Example Allow Serial Port Profile on a specific controller:
+ | **> allow 00:11:22:33:44:55 0x1101**
:Example Allow Serial Port Profile and LAN Access Profile:
| **> allow 0x1101 0x1102**
+:Example Allow Serial Port Profile and LAN Access Profile on a specific controller:
+ | **> allow 00:11:22:33:44:55 0x1101 0x1102**
:Example Allow Serial Port Profile, LAN Access Profile, and Dialup Networking Profile:
| **> allow 0x1101 0x1102 0x1103**
:Example Allow Advanced Audio Distribution Profile only:
@@ -51,6 +58,8 @@ Allow service UUIDs and block rest of them.
| **> allow 00001101-0000-1000-8000-00805f9b34fb 00001102-0000-1000-8000-00805f9b34fb**
:Example Remove all UUID restrictions:
| **> allow clear**
+:Example Remove all UUID restrictions on a specific controller:
+ | **> allow 00:11:22:33:44:55 clear**
:Example Allow SPP, LAP, and DUN using mixed UUID formats:
| **> allow 0x1101 00001102-0000-1000-8000-00805f9b34fb 0x1103**
diff --git a/doc/org.bluez.AdminPolicySet.rst b/doc/org.bluez.AdminPolicySet.rst
index db132b7de..29fe3bdf7 100644
--- a/doc/org.bluez.AdminPolicySet.rst
+++ b/doc/org.bluez.AdminPolicySet.rst
@@ -55,3 +55,4 @@ Possible errors:
Examples:
:bluetoothctl: > admin.allow [clear/uuid1 uuid2 ...]
+:bluetoothctl: > admin.allow [ctrl] [clear/uuid1 uuid2 ...]
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 4/7] src/adapter: enforce allowlist for local services
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 2/7] client/bluetoothctl: make admin.allow controller-aware Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 3/7] doc: document admin.allow optional controller argument Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 5/7] plugins/admin: reapply allowlist on policy updates Frédéric Danis
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Apply admin allowlist to adapter/server service startup and
registration, and reapply policy dynamically when allowlist changes.
- Gate adapter profile probe by allowlist-derived UUID policy
- Reapply active adapter profiles on allowlist updates (stop
disallowed, start newly allowed)
- Block SDP service registration when UUID is not allowed
- Reapply existing local SDP registrations at runtime by removing
services that become disallowed
Assisted-by: GPT:GPT-5.3-Codex
---
src/adapter.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/adapter.h | 1 +
2 files changed, 140 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index 538f63e0a..5a293b3f3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1346,6 +1346,7 @@ done:
int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec)
{
+ char *svc_uuid;
int ret;
/*
@@ -1357,6 +1358,18 @@ int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec)
DBG("%s", adapter->path);
+ svc_uuid = bt_uuid2string(&rec->svclass);
+ if (!svc_uuid)
+ return -ENOMEM;
+
+ if (!btd_adapter_is_uuid_allowed(adapter, svc_uuid)) {
+ DBG("Service %s blocked by admin allowlist", svc_uuid);
+ free(svc_uuid);
+ return -EPERM;
+ }
+
+ free(svc_uuid);
+
ret = add_record_to_server(&adapter->bdaddr, rec);
if (ret < 0)
return ret;
@@ -5201,6 +5214,70 @@ 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 where adapter-side server behavior
+ * needs a different UUID source (e.g. A2DP source/sink role inversion) or
+ * where server policy is derived from the profile remote_uuid.
+ */
+static const struct profile_allowlist_map profile_allowlist_map[] = {
+ { "a2dp-source", A2DP_SINK_UUID, false },
+ { "a2dp-sink", A2DP_SOURCE_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;
+}
+
+static bool adapter_profile_is_allowed(struct btd_adapter *adapter,
+ const struct btd_profile *profile)
+{
+ const char *uuid = profile_allowlist_uuid(profile);
+
+ if (!uuid)
+ return true;
+
+ return btd_adapter_is_uuid_allowed(adapter, uuid);
+}
+
static void probe_profile(struct btd_profile *profile, void *data)
{
struct btd_adapter *adapter = data;
@@ -5209,6 +5286,11 @@ static void probe_profile(struct btd_profile *profile, void *data)
if (profile->adapter_probe == NULL)
return;
+ if (!adapter_profile_is_allowed(adapter, profile)) {
+ DBG("%s blocked by admin allowlist", profile->name);
+ return;
+ }
+
err = profile->adapter_probe(profile, adapter);
if (err < 0) {
btd_error(adapter->dev_id, "%s: %s (%d)", profile->name,
@@ -5219,6 +5301,63 @@ static void probe_profile(struct btd_profile *profile, void *data)
adapter->profiles = g_slist_prepend(adapter->profiles, profile);
}
+static void reapply_profile(struct btd_profile *profile, void *data)
+{
+ struct btd_adapter *adapter = data;
+ bool active;
+
+ if (profile->adapter_probe == NULL)
+ return;
+
+ active = g_slist_find(adapter->profiles, profile) != NULL;
+
+ if (adapter_profile_is_allowed(adapter, profile)) {
+ if (!active)
+ probe_profile(profile, adapter);
+ return;
+ }
+
+ if (!active)
+ return;
+
+ adapter->profiles = g_slist_remove(adapter->profiles, profile);
+
+ if (profile->adapter_remove)
+ profile->adapter_remove(profile, adapter);
+}
+
+static void reapply_adapter_services(struct btd_adapter *adapter)
+{
+ sdp_list_t *l;
+
+ for (l = adapter->services; l != NULL;) {
+ sdp_list_t *next = l->next;
+ sdp_record_t *rec = l->data;
+ char *svc_uuid;
+
+ svc_uuid = bt_uuid2string(&rec->svclass);
+ if (!svc_uuid) {
+ l = next;
+ continue;
+ }
+
+ if (!btd_adapter_is_uuid_allowed(adapter, svc_uuid))
+ adapter_service_remove(adapter, rec->handle);
+
+ free(svc_uuid);
+ l = next;
+ }
+}
+
+void btd_adapter_reapply_allowed_uuids(struct btd_adapter *adapter)
+{
+ if (!adapter || !adapter->initialized)
+ return;
+
+ btd_profile_foreach(reapply_profile, adapter);
+ reapply_adapter_services(adapter);
+}
+
void adapter_add_profile(struct btd_adapter *adapter, gpointer p)
{
struct btd_profile *profile = p;
diff --git a/src/adapter.h b/src/adapter.h
index 4e07f71ad..cec528c56 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -295,6 +295,7 @@ bool btd_adapter_set_allowed_uuids(struct btd_adapter *adapter,
struct queue *uuids);
bool btd_adapter_is_uuid_allowed(struct btd_adapter *adapter,
const char *uuid_str);
+void btd_adapter_reapply_allowed_uuids(struct btd_adapter *adapter);
void btd_adapter_load_conn_param(struct btd_adapter *adapter,
const bdaddr_t *peer, uint8_t bdaddr_type,
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 5/7] plugins/admin: reapply allowlist on policy updates
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
` (2 preceding siblings ...)
2026-07-02 8:36 ` [PATCH BlueZ 4/7] src/adapter: enforce allowlist for local services Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 6/7] doc: describe admin allowlist runtime enforcement Frédéric Danis
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Invoke adapter allowlist reapply after SetServiceAllowList updates
so runtime state follows policy changes immediately.
Assisted-by: GPT:GPT-5.3-Codex
---
plugins/admin.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/admin.c b/plugins/admin.c
index 6c5c8d97f..07bd0bf3d 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -203,6 +203,7 @@ static bool service_allowlist_set(struct btd_admin_policy *admin_policy,
free_service_allowlist(admin_policy->service_allowlist);
admin_policy->service_allowlist = uuid_list;
+ btd_adapter_reapply_allowed_uuids(adapter);
return true;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 6/7] doc: describe admin allowlist runtime enforcement
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
` (3 preceding siblings ...)
2026-07-02 8:36 ` [PATCH BlueZ 5/7] plugins/admin: reapply allowlist on policy updates Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 8:36 ` [PATCH BlueZ 7/7] profiles/audio: fix UAF on external media service teardown Frédéric Danis
2026-07-02 11:57 ` [BlueZ,1/7] plugins/admin: make AdminPolicy state per-adapter bluez.test.bot
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Document that ServiceAllowList now also governs local adapter/server
startup and registration, and that allowlist updates are applied
immediately on initialized adapters.
Clarify ServiceAllowList status semantics for both remote profile
connection policy and local server policy.
Assisted-by: GPT:GPT-5.3-Codex
---
doc/org.bluez.AdminPolicySet.rst | 11 +++++++++++
doc/org.bluez.AdminPolicyStatus.rst | 5 +++++
2 files changed, 16 insertions(+)
diff --git a/doc/org.bluez.AdminPolicySet.rst b/doc/org.bluez.AdminPolicySet.rst
index 29fe3bdf7..9ac0aa76f 100644
--- a/doc/org.bluez.AdminPolicySet.rst
+++ b/doc/org.bluez.AdminPolicySet.rst
@@ -41,6 +41,17 @@ Sets the service allowlist by specifying service UUIDs.
When called, **bluetoothd(8)** will block incoming and outgoing connections to
the service not in UUIDs for all of the clients.
+The allowlist also applies to local adapter/server services. When an allowlist
+exists, only adapter/server services whose policy UUID is in UUIDs are started
+or registered.
+
+Updating the allowlist is applied immediately on initialized adapters:
+
+- services that become disallowed are stopped/removed
+- services that become allowed are started/registered
+
+This does not require restarting **bluetoothd(8)** or power-cycling adapters.
+
Any subsequent calls to this method will supersede any previously set allowlist
values. Calling this method with an empty array will allow any service UUIDs to
be used.
diff --git a/doc/org.bluez.AdminPolicyStatus.rst b/doc/org.bluez.AdminPolicyStatus.rst
index 702e020aa..d44ab9361 100644
--- a/doc/org.bluez.AdminPolicyStatus.rst
+++ b/doc/org.bluez.AdminPolicyStatus.rst
@@ -43,6 +43,11 @@ array{string} ServiceAllowList [readonly, adapter-only]
Current value of service allow list.
+When non-empty, this list controls both:
+
+- remote service connection policy for device profiles
+- local adapter/server service startup and registration policy
+
bool IsAffectedByPolicy [readonly, device-only]
```````````````````````````````````````````````
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 7/7] profiles/audio: fix UAF on external media service teardown
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
` (4 preceding siblings ...)
2026-07-02 8:36 ` [PATCH BlueZ 6/7] doc: describe admin allowlist runtime enforcement Frédéric Danis
@ 2026-07-02 8:36 ` Frédéric Danis
2026-07-02 11:57 ` [BlueZ,1/7] plugins/admin: make AdminPolicy state per-adapter bluez.test.bot
6 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-07-02 8:36 UTC (permalink / raw)
To: linux-bluetooth
Keep media_app endpoint/player queues in sync with object lifetime to
avoid stale pointers during proxy removal.
When admin allowlist reapply removes audio services, endpoint/player
objects may be destroyed through non-proxy paths first.
Later proxy_removed_cb calls queue_remove_if() and matching by path
can dereference freed endpoint/player memory.
Fix by:
- adding media_app back-references in media_endpoint/local_player
- unlinking from app queues inside media_endpoint_remove or
local_player_remove
- setting ownership when app-registering endpoint/player objects
This prevents heap-use-after-free in match_endpoint_by_path or
match_player_by_path during service disconnect.
Assisted-by: GPT:GPT-5.3-Codex
---
profiles/audio/media.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 5d9ea2cbc..95f9580b0 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -136,12 +136,14 @@ struct media_endpoint {
guint watch;
GSList *requests;
struct media_adapter *adapter;
+ struct media_app *app;
GSList *transports;
struct endpoint_features features;
};
struct local_player {
struct media_adapter *adapter;
+ struct media_app *app;
char *sender; /* Player DBus bus id */
char *path; /* Player object path */
GHashTable *settings; /* Player settings */
@@ -305,6 +307,11 @@ static void media_endpoint_remove(void *data)
}
#endif
+ if (endpoint->app) {
+ queue_remove(endpoint->app->endpoints, endpoint);
+ endpoint->app = NULL;
+ }
+
info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
endpoint->path);
@@ -2076,6 +2083,11 @@ static void local_player_remove(void *data)
{
struct local_player *mp = data;
+ if (mp->app) {
+ queue_remove(mp->app->players, mp);
+ mp->app = NULL;
+ }
+
info("Player unregistered: sender=%s path=%s", mp->sender, mp->path);
local_player_destroy(mp);
@@ -3168,6 +3180,8 @@ static void app_register_endpoint(void *data, void *user_data)
return;
}
+ endpoint->app = app;
+
queue_push_tail(app->endpoints, endpoint);
return;
@@ -3196,6 +3210,8 @@ static void app_register_player(void *data, void *user_data)
if (!player)
return;
+ player->app = app;
+
if (g_dbus_proxy_get_property(proxy, "PlaybackStatus", &iter)) {
if (!set_status(player, &iter))
goto fail;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* RE: [BlueZ,1/7] plugins/admin: make AdminPolicy state per-adapter
2026-07-02 8:36 [PATCH BlueZ 1/7] plugins/admin: make AdminPolicy state per-adapter Frédéric Danis
` (5 preceding siblings ...)
2026-07-02 8:36 ` [PATCH BlueZ 7/7] profiles/audio: fix UAF on external media service teardown Frédéric Danis
@ 2026-07-02 11:57 ` bluez.test.bot
6 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-07-02 11:57 UTC (permalink / raw)
To: linux-bluetooth, frederic.danis
[-- Attachment #1: Type: text/plain, Size: 7217 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1120331
---Test result---
Test Summary:
CheckPatch FAIL 2.63 seconds
GitLint PASS 1.64 seconds
BuildEll PASS 20.98 seconds
BluezMake PASS 546.48 seconds
MakeCheck PASS 19.10 seconds
MakeDistcheck PASS 160.21 seconds
CheckValgrind PASS 229.85 seconds
CheckSmatch PASS 315.68 seconds
bluezmakeextell PASS 102.92 seconds
IncrementalBuild PASS 585.69 seconds
ScanBuild PASS 973.73 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,1/7] plugins/admin: make AdminPolicy state per-adapter
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#80:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#80:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658608.patch total: 1 errors, 1 warnings, 259 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658608.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,2/7] client/bluetoothctl: make admin.allow controller-aware
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#81:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#81:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658607.patch total: 1 errors, 1 warnings, 244 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658607.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,3/7] doc: document admin.allow optional controller argument
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#77:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#77:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658606.patch total: 1 errors, 1 warnings, 43 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658606.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,4/7] src/adapter: enforce allowlist for local services
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#80:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#80:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658613.patch total: 1 errors, 1 warnings, 176 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658613.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,5/7] plugins/admin: reapply allowlist on policy updates
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#73:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#73:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658605.patch total: 1 errors, 1 warnings, 7 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658605.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,6/7] doc: describe admin allowlist runtime enforcement
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#77:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#77:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658609.patch total: 1 errors, 1 warnings, 28 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658609.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[BlueZ,7/7] profiles/audio: fix UAF on external media service teardown
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#88:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#88:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14658610.patch total: 1 errors, 1 warnings, 52 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14658610.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
https://github.com/bluez/bluez/pull/2262
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 8+ messages in thread