From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v2 2/2] core: Fix not resolving addresses
Date: Wed, 1 Oct 2025 10:27:38 -0400 [thread overview]
Message-ID: <20251001142738.17892-2-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20251001142738.17892-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
When using the likes of btd_adapter_get_device the address can sometimes
be the so called RPA which needs to be resolved in order to avoid
creating duplicated objects of the same device.
Note that normally the RPA are resolved in the kernel but there are
instances like BASS Add Source that may attempt to add a device direcly,
bypassing the GAP layer.
---
src/adapter.c | 4 ++--
src/device.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++---
src/device.h | 5 +++--
3 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3afcb9277129..1ee2f3a08164 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5091,7 +5091,7 @@ static void load_devices(struct btd_adapter *adapter)
goto free;
if (irk_info)
- device_set_privacy(device, true);
+ device_set_privacy(device, true, irk_info->val);
btd_device_set_temporary(device, false);
adapter_add_device(adapter, device);
@@ -9024,7 +9024,7 @@ static void new_irk_callback(uint16_t index, uint16_t length,
return;
}
- device_update_addr(device, &addr->bdaddr, addr->type);
+ device_update_addr(device, &addr->bdaddr, addr->type, irk->val);
if (duplicate)
device_merge_duplicate(device, duplicate);
diff --git a/src/device.c b/src/device.c
index 9f0e8e673529..8d74ae0ea0ff 100644
--- a/src/device.c
+++ b/src/device.c
@@ -205,6 +205,7 @@ struct btd_device {
bdaddr_t bdaddr;
uint8_t bdaddr_type;
bool privacy;
+ uint8_t *irk;
char *path;
struct btd_bearer *bredr;
struct btd_bearer *le;
@@ -4995,9 +4996,17 @@ void device_set_class(struct btd_device *device, uint32_t class)
DEVICE_INTERFACE, "Icon");
}
-void device_set_privacy(struct btd_device *device, bool value)
+void device_set_privacy(struct btd_device *device, bool value,
+ const uint8_t *irk)
{
device->privacy = value;
+
+ free(device->irk);
+
+ if (irk)
+ device->irk = util_memdup(irk, 16);
+ else
+ device->irk = NULL;
}
bool device_get_privacy(struct btd_device *device)
@@ -5009,11 +5018,11 @@ bool device_get_privacy(struct btd_device *device)
}
void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
- uint8_t bdaddr_type)
+ uint8_t bdaddr_type, const uint8_t *irk)
{
bool auto_connect = device->auto_connect;
- device_set_privacy(device, true);
+ device_set_privacy(device, true, irk);
if (!bacmp(bdaddr, &device->bdaddr) &&
bdaddr_type == device->bdaddr_type)
@@ -5347,6 +5356,39 @@ static bool addr_is_public(uint8_t addr_type)
return false;
}
+static bool addr_is_resolvable(const bdaddr_t *bdaddr, uint8_t addr_type)
+{
+ if (addr_type != BDADDR_LE_RANDOM)
+ return false;
+
+ switch (bdaddr->b[5] >> 6) {
+ case 0x01: /* Private resolvable */
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool device_irk_cmp(const struct btd_device *device,
+ const struct device_addr_type *addr)
+{
+ struct bt_crypto *crypto;
+ uint8_t hash[3];
+
+ if (!device->irk)
+ return false;
+
+ crypto = bt_crypto_new();
+ if (!crypto)
+ return false;
+
+ bt_crypto_ah(crypto, device->irk, addr->bdaddr.b + 3, hash);
+
+ bt_crypto_unref(crypto);
+
+ return !memcmp(addr, hash, 3);
+}
+
int device_addr_type_cmp(gconstpointer a, gconstpointer b)
{
const struct btd_device *dev = a;
@@ -5375,8 +5417,13 @@ int device_addr_type_cmp(gconstpointer a, gconstpointer b)
return -1;
if (addr->bdaddr_type != dev->bdaddr_type) {
+ if (dev->privacy && addr_is_resolvable(&addr->bdaddr,
+ addr->bdaddr_type))
+ return device_irk_cmp(dev, addr);
+
if (addr->bdaddr_type == dev->conn_bdaddr_type)
return bacmp(&dev->conn_bdaddr, &addr->bdaddr);
+
return -1;
}
diff --git a/src/device.h b/src/device.h
index 6fbbdb1f2d28..9ff9cdfefc28 100644
--- a/src/device.h
+++ b/src/device.h
@@ -29,10 +29,11 @@ bool device_is_name_resolve_allowed(struct btd_device *device);
void device_name_resolve_fail(struct btd_device *device);
void device_set_class(struct btd_device *device, uint32_t class);
bool device_address_is_private(struct btd_device *dev);
-void device_set_privacy(struct btd_device *device, bool value);
+void device_set_privacy(struct btd_device *device, bool value,
+ const uint8_t *irk);
bool device_get_privacy(struct btd_device *device);
void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
- uint8_t bdaddr_type);
+ uint8_t bdaddr_type, const uint8_t *irk);
void device_set_bredr_support(struct btd_device *device);
void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type);
void device_update_last_seen(struct btd_device *device, uint8_t bdaddr_type,
--
2.51.0
next prev parent reply other threads:[~2025-10-01 14:27 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-01 14:27 [PATCH BlueZ v2 1/2] device: Fix privacy Luiz Augusto von Dentz
2025-10-01 14:27 ` Luiz Augusto von Dentz [this message]
2025-10-01 15:52 ` [BlueZ,v2,1/2] " bluez.test.bot
2025-10-02 19:40 ` [PATCH BlueZ v2 1/2] " patchwork-bot+bluetooth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251001142738.17892-2-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox