All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] device: Limit the number of retries on auth failures
@ 2025-11-11 21:22 Andrey Smirnov
  2025-11-11 22:14 ` Luiz Augusto von Dentz
  2025-11-11 22:50 ` [BlueZ] " bluez.test.bot
  0 siblings, 2 replies; 4+ messages in thread
From: Andrey Smirnov @ 2025-11-11 21:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrey Smirnov, Luiz Augusto von Dentz

Currently BlueZ has no retry limit on reconnection attempts in case of
authentication failures. This leads to a very unpleasant user
experince with, for example, XBox controller. The scenario is as
follows:

1. Host A is running BlueZ and XBox controller is paired and connected
   to it.
2. Host A shuts down (for example)
3. XBox controller is put into pairing mode and is paired to a Host B
4. Host B is powered down
5. Host A is powered on
6. XBox controller is powered on
7. Host A/BlueZ will start spamming XBox controller with connection
   attempts in an endless loop

What happens under the hood is:

1. BlueZ starts up, sees that there's LTK saved for XBox controller,
   so it adds it to kernels autoconnect list
2. Once XBox controller is on and advertising, kernel connects to it
3. BlueZ tries to elevate the security level, but is rejected by the
   controller with "Key or PIN missing" because the controller is already
   paired to another host.
4. Controller disconnects, controller goes back to advertising, goto 2

To avoid this, let's add a simple auth failure counter and disable
autoconnect for the device once we go past the failure threshold.
---

I don't really expect this to be the final form of this change, so
this is more of an RFC to get some feedback from upstream.

I'd also love to get some feedback on the following:

1. Ideally I'd also want to add an exponential backoff to the retries,
but I'm not familiar enough with BlueZ code to know how to go about
that. Anyone has any advise what would be the best way to implement
it? Assuming there's no objection to that.

2. It seems like another imporvement on this front would be for BlueZ
to get the "Key or PIN is missing" error code and react to that by
removing the stored LTK info. Does that seem reasonable? If yes, it
looks like the kernel actually doesn't pass that error code to the
userspace. Is that right? Does anyone know why and what's the best way
to go about fixing that?

Thanks!


 src/device.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/device.c b/src/device.c
index 91b6cc0c6..434bdf721 100644
--- a/src/device.c
+++ b/src/device.c
@@ -77,6 +77,7 @@
 #endif

 #define RSSI_THRESHOLD		8
+#define AUTH_FAILURES_THRESHOLD	5

 static DBusConnection *dbus_conn = NULL;
 static unsigned service_state_cb_id;
@@ -306,6 +307,8 @@ struct btd_device {
 	time_t		name_resolve_failed_time;

 	int8_t		volume;
+
+	uint32_t	auth_failures;
 };

 static const uint16_t uuid_list[] = {
@@ -7113,9 +7116,15 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
 			btd_device_set_temporary(device, true);

 		device_bonding_failed(device, status);
+
+		if (device->auth_failures > AUTH_FAILURES_THRESHOLD)
+			device_set_auto_connect(device, FALSE);
+
 		return;
 	}

+	device->auth_failures = 0;
+
 	device_auth_req_free(device);

 	/* Enable the wake_allowed property if required */
@@ -7320,6 +7329,8 @@ void device_bonding_failed(struct btd_device *device, uint8_t status)
 	struct bonding_req *bonding = device->bonding;
 	DBusMessage *reply;

+	device->auth_failures++;
+
 	DBG("status %u", status);

 	if (!bonding)
--
2.34.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-11-11 22:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-11 21:22 [PATCH BlueZ] device: Limit the number of retries on auth failures Andrey Smirnov
2025-11-11 22:14 ` Luiz Augusto von Dentz
2025-11-11 22:23   ` Andrey Smirnov
2025-11-11 22:50 ` [BlueZ] " bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.