From: Mike Ryan <mike@xxxxxxx> The first two bits of valid static addresses must both be 0 because other values are reserved for resolvable and non-resolvable private addresses (RPA and NRPA). In order to facilitate impersonation attacks against devices using RPAs, this debugfs entry allows the user to set the static address to an illegal value reserved for RPAs. Signed-off-by: Mike Ryan <mike@xxxxxxx> --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_debugfs.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 4 +++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 5bc1e30de..d1e477093 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -280,6 +280,7 @@ enum { HCI_DUT_MODE, HCI_VENDOR_DIAG, HCI_FORCE_BREDR_SMP, + HCI_ALLOW_ILLEGAL_STATIC_ADDR, HCI_FORCE_STATIC_ADDR, HCI_LL_RPA_RESOLUTION, HCI_CMD_PENDING, diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 402e2cc54..0d3006302 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -667,6 +667,47 @@ static int static_address_show(struct seq_file *f, void *p) DEFINE_SHOW_ATTRIBUTE(static_address); +static ssize_t allow_illegal_static_address_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + char buf[3]; + + buf[0] = hci_dev_test_flag(hdev, HCI_ALLOW_ILLEGAL_STATIC_ADDR) ? 'Y': 'N'; + buf[1] = '\n'; + buf[2] = '\0'; + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static ssize_t allow_illegal_static_address_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + bool enable; + int err; + + err = kstrtobool_from_user(user_buf, count, &enable); + if (err) + return err; + + if (enable == hci_dev_test_flag(hdev, HCI_ALLOW_ILLEGAL_STATIC_ADDR)) + return -EALREADY; + + hci_dev_change_flag(hdev, HCI_ALLOW_ILLEGAL_STATIC_ADDR); + + return count; + +} + +static const struct file_operations allow_illegal_static_address_fops = { + .open = simple_open, + .read = allow_illegal_static_address_read, + .write = allow_illegal_static_address_write, + .llseek = default_llseek, +}; + static ssize_t force_static_address_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1016,6 +1057,8 @@ void hci_debugfs_create_le(struct hci_dev *hdev) &random_address_fops); debugfs_create_file("static_address", 0444, hdev->debugfs, hdev, &static_address_fops); + debugfs_create_file("allow_illegal_static_address", 0644, hdev->debugfs, + hdev, &allow_illegal_static_address_fops); /* For controllers with a public address, provide a debug * option to force the usage of the configured static diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index acb7c6d56..59945b850 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4428,10 +4428,12 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev, MGMT_STATUS_INVALID_PARAMS); /* Two most significant bits shall be set */ - if ((cp->bdaddr.b[5] & 0xc0) != 0xc0) + if ((cp->bdaddr.b[5] & 0xc0) != 0xc0 && + !hci_dev_test_flag(hdev, HCI_ALLOW_ILLEGAL_STATIC_ADDR)) { return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, MGMT_STATUS_INVALID_PARAMS); + } } hci_dev_lock(hdev); -- 2.11.0