Skip to content

Commit

Permalink
Bluetooth: MGMT: Fix Get Device Flags
Browse files Browse the repository at this point in the history
Get Device Flags don't check if device does actually use an RPA in which
case it shall only set HCI_CONN_FLAG_REMOTE_WAKEUP if LL Privacy is
enabled.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Luiz Augusto von Dentz committed Aug 25, 2022
1 parent fc5ae5b commit 529d449
Showing 1 changed file with 42 additions and 29 deletions.
71 changes: 42 additions & 29 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4546,6 +4546,22 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
MGMT_STATUS_NOT_SUPPORTED);
}

static u32 get_params_flags(struct hci_dev *hdev,
struct hci_conn_params *params)
{
u32 flags = hdev->conn_flags;

/* Devices using RPAs can only be programmed in the acceptlist if
* LL Privacy has been enable otherwise they cannot mark
* HCI_CONN_FLAG_REMOTE_WAKEUP.
*/
if ((flags & HCI_CONN_FLAG_REMOTE_WAKEUP) && !use_ll_privacy(hdev) &&
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type))
flags &= ~HCI_CONN_FLAG_REMOTE_WAKEUP;

return flags;
}

static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
Expand Down Expand Up @@ -4577,10 +4593,10 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
} else {
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));

if (!params)
goto done;

supported_flags = get_params_flags(hdev, params);
current_flags = params->flags;
}

Expand Down Expand Up @@ -4648,38 +4664,35 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
&cp->addr.bdaddr, cp->addr.type);
}
} else {
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (params) {
/* Devices using RPAs can only be programmed in the
* acceptlist LL Privacy has been enable otherwise they
* cannot mark HCI_CONN_FLAG_REMOTE_WAKEUP.
*/
if ((current_flags & HCI_CONN_FLAG_REMOTE_WAKEUP) &&
!use_ll_privacy(hdev) &&
hci_find_irk_by_addr(hdev, &params->addr,
params->addr_type)) {
bt_dev_warn(hdev,
"Cannot set wakeable for RPA");
goto unlock;
}

params->flags = current_flags;
status = MGMT_STATUS_SUCCESS;
goto unlock;
}

/* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
* has been set.
*/
if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
hci_update_passive_scan(hdev);
} else {
bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
&cp->addr.bdaddr,
le_addr_type(cp->addr.type));
}
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!params) {
bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
&cp->addr.bdaddr, le_addr_type(cp->addr.type));
goto unlock;
}

supported_flags = get_params_flags(hdev, params);

if ((supported_flags | current_flags) != supported_flags) {
bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
current_flags, supported_flags);
goto unlock;
}

params->flags = current_flags;
status = MGMT_STATUS_SUCCESS;

/* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
* has been set.
*/
if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
hci_update_passive_scan(hdev);

unlock:
hci_dev_unlock(hdev);

Expand Down

0 comments on commit 529d449

Please sign in to comment.