* [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* Re: [PATCH BlueZ] device: Limit the number of retries on auth failures
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
1 sibling, 1 reply; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2025-11-11 22:14 UTC (permalink / raw)
To: Andrey Smirnov; +Cc: linux-bluetooth, Luiz Augusto von Dentz
Hi Andrey,
On Tue, Nov 11, 2025 at 4:25 PM Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
>
> 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.
Ok, but then it won't auto connect ever again, so we would have to
somehow inform application auto-connect is disabled, we can't really
remove the pairing either since this could be an impersonation attack.
> ---
>
> 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
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH BlueZ] device: Limit the number of retries on auth failures
2025-11-11 22:14 ` Luiz Augusto von Dentz
@ 2025-11-11 22:23 ` Andrey Smirnov
0 siblings, 0 replies; 4+ messages in thread
From: Andrey Smirnov @ 2025-11-11 22:23 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Luiz Augusto von Dentz
On Tue, Nov 11, 2025 at 2:14 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Andrey,
>
> On Tue, Nov 11, 2025 at 4:25 PM Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
> >
> > 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.
>
> Ok, but then it won't auto connect ever again, so we would have to
> somehow inform application auto-connect is disabled,
>
Do you have suggestions/preferences for how this should be
implemented? Probably a D-Bus signal?
> we can't really
> remove the pairing either since this could be an impersonation attack.
I see, it makes sense. Haven't considered that. Disregard #2 from my
questions list.
> > ---
> >
> > 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
> >
>
>
> --
> Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [BlueZ] device: Limit the number of retries on auth failures
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:50 ` bluez.test.bot
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2025-11-11 22:50 UTC (permalink / raw)
To: linux-bluetooth, andrew.smirnov
[-- Attachment #1: Type: text/plain, Size: 1262 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=1022224
---Test result---
Test Summary:
CheckPatch PENDING 0.35 seconds
GitLint PENDING 0.26 seconds
BuildEll PASS 20.71 seconds
BluezMake PASS 2792.93 seconds
MakeCheck PASS 19.90 seconds
MakeDistcheck PASS 187.75 seconds
CheckValgrind PASS 239.11 seconds
CheckSmatch PASS 313.06 seconds
bluezmakeextell PASS 129.94 seconds
IncrementalBuild PENDING 0.28 seconds
ScanBuild PASS 949.01 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [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.