[PATCH v3 1/2] Bluetooth: forget a peer's RPA once it advertises its identity address
From: Radek Podgorny <hidden>
Date: 2026-09-08 22:30:07
Also in:
lkml
Subsystem:
bluetooth subsystem, the rest · Maintainers:
Marcel Holtmann, Luiz Augusto von Dentz, Linus Torvalds
hci_connect_le() dials the RPA cached in the peer's IRK whenever one is set, on the assumption that a peer holding an IRK is on air with a resolvable private address. A peer that stops using privacy breaks that assumption: it advertises its identity address, the cached RPA keeps the value it had before the change, and the host aims at an address the peer has abandoned. Nothing clears the cache. hci_find_irk_by_rpa() refreshes irk->rpa each time an advertisement resolves, so it tracks rotation, but a peer that stops sending RPAs stops producing the reports that would update it, and the stale address then survives until the adapter is powered off. On the path that creates the connection object this is currently masked: __hci_conn_add() resolves the cached RPA back to the identity address, so that is what goes on air. It is not masked on the reuse branch, which copies the swapped address straight into an existing conn->dst, and the next patch removes the conversion for the case where the controller cannot translate an identity address, so the stale RPA would be dialled there too. Clear the cached RPA when the peer is seen on its identity address. hci_find_irk_by_addr() only matches public and static random addresses, so an unresolved RPA belonging to some other device cannot reach this path. Assisted-by: Claude:claude-opus-5 Signed-off-by: Radek Podgorny <redacted> --- net/bluetooth/hci_event.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2f5e21ff9752..03b805207ab0 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c@@ -6311,6 +6311,15 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, if (irk) { bdaddr = &irk->bdaddr; bdaddr_type = irk->addr_type; + } else { + /* The peer is on air with its identity address, so whatever + * RPA is cached for it has been abandoned. Drop it, or + * hci_connect_le() would swap it back in and dial an address + * the peer no longer answers. + */ + irk = hci_find_irk_by_addr(hdev, bdaddr, bdaddr_type); + if (irk) + bacpy(&irk->rpa, BDADDR_ANY); } bdaddr_type = ev_bdaddr_type(hdev, bdaddr_type, &bdaddr_resolved);
--
2.55.0