mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
bluetooth pull request for net:
- Fix handling of duplicate connection handle - Fix handling of HCI vendor opcode - Fix suspend performance regression - Fix build errors - Fix not handling shutdown condition on ISO sockets - Fix double free issue -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmMICQwZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKYu5D/sEgAU3vGtX5b0eGDinlfxw /PfWLceaAJavVfI3MrPEi4OZuYX7TVNRIEUauOvj0zB+278QIHWKcuHzS4PLWdgM AjHJ0YdTcX2t3mcBiSpS1ZMUvUHaHrWIQ9boFW6JffaFwEUGyVZDHBv8fSt8Esq1 lPlBLzDkxLGIY19QHOi+KnnFFf2wrTFbkijBJrSu/Egk0URBJbZH7Ih8jVeC7KnA U6kdyW10LIHcMVbIGm0dKXEe35BqCbRkV2iIqmHg8g/2tkD0qauBgivYXPtEc04l DwUx4T/tO+/rYMoYoe3pKf2mKY9ctm5croAhzFGdRcdplWTLOD1xPnNAKuQvk5Qt sL2Nu4J+XAm+ccgK1XJs0nJBEA118bCEtpxpig3B3DqsKUMEx42y7RMWy6LMsSn1 l8d6RS2bEE0Kz6G9LdT5KtTHJhR7yw2lTYjIF/xub7meFBpuggB4Ib2qOF75MIVk RUpaHyceAz1g+Kb7oXFjm9hB5CmOc4l5uEieTkRn9WgGm2c4yJsTfwWVJo3BjRUt seC9VFCkDfO9QgxHdJqZTMlMdNjcUIGUj9bz/KMHproK89UliDRHjzB5suryhj/L zwoCfQVzVyHLCFqg6xjYZhi9NiTqnTkagHVOXWEG+BEOs2ve0/UZKzZiZZFig7Xw wzmIuuuU11iMX0O8iGUrSQ== =7AHt -----END PGP SIGNATURE----- Merge tag 'for-net-2022-08-25' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - Fix handling of duplicate connection handle - Fix handling of HCI vendor opcode - Fix suspend performance regression - Fix build errors - Fix not handling shutdown condition on ISO sockets - Fix double free issue * tag 'for-net-2022-08-25' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: hci_sync: hold hdev->lock when cleanup hci_conn Bluetooth: move from strlcpy with unused retval to strscpy Bluetooth: hci_event: Fix checking conn for le_conn_complete_evt Bluetooth: ISO: Fix not handling shutdown condition Bluetooth: hci_sync: fix double mgmt_pending_free() in remove_adv_monitor() Bluetooth: MGMT: Fix Get Device Flags Bluetooth: L2CAP: Fix build errors in some archs Bluetooth: hci_sync: Fix suspend performance regression Bluetooth: hci_event: Fix vendor (unknown) opcode status handling ==================== Link: https://lore.kernel.org/r/20220825234559.1837409-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
037c97b288
@ -4179,6 +4179,17 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(hci_cc_table)) {
|
||||
/* Unknown opcode, assume byte 0 contains the status, so
|
||||
* that e.g. __hci_cmd_sync() properly returns errors
|
||||
* for vendor specific commands send by HCI drivers.
|
||||
* If a vendor doesn't actually follow this convention we may
|
||||
* need to introduce a vendor CC table in order to properly set
|
||||
* the status.
|
||||
*/
|
||||
*status = skb->data[0];
|
||||
}
|
||||
|
||||
handle_cmd_cnt_and_timer(hdev, ev->ncmd);
|
||||
|
||||
hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
|
||||
@ -5790,7 +5801,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
||||
*/
|
||||
hci_dev_clear_flag(hdev, HCI_LE_ADV);
|
||||
|
||||
conn = hci_lookup_le_connect(hdev);
|
||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
|
||||
if (!conn) {
|
||||
/* In case of error status and there is no connection pending
|
||||
* just unlock as there is nothing to cleanup.
|
||||
|
@ -4773,9 +4773,11 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason)
|
||||
/* Cleanup hci_conn object if it cannot be cancelled as it
|
||||
* likelly means the controller and host stack are out of sync.
|
||||
*/
|
||||
if (err)
|
||||
if (err) {
|
||||
hci_dev_lock(hdev);
|
||||
hci_conn_failed(conn, err);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
return err;
|
||||
case BT_CONNECT2:
|
||||
return hci_reject_conn_sync(hdev, conn, reason);
|
||||
@ -5288,17 +5290,21 @@ int hci_suspend_sync(struct hci_dev *hdev)
|
||||
/* Prevent disconnects from causing scanning to be re-enabled */
|
||||
hci_pause_scan_sync(hdev);
|
||||
|
||||
/* Soft disconnect everything (power off) */
|
||||
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
|
||||
if (err) {
|
||||
/* Set state to BT_RUNNING so resume doesn't notify */
|
||||
hdev->suspend_state = BT_RUNNING;
|
||||
hci_resume_sync(hdev);
|
||||
return err;
|
||||
}
|
||||
if (hci_conn_count(hdev)) {
|
||||
/* Soft disconnect everything (power off) */
|
||||
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
|
||||
if (err) {
|
||||
/* Set state to BT_RUNNING so resume doesn't notify */
|
||||
hdev->suspend_state = BT_RUNNING;
|
||||
hci_resume_sync(hdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Update event mask so only the allowed event can wakeup the host */
|
||||
hci_set_event_mask_sync(hdev);
|
||||
/* Update event mask so only the allowed event can wakeup the
|
||||
* host.
|
||||
*/
|
||||
hci_set_event_mask_sync(hdev);
|
||||
}
|
||||
|
||||
/* Only configure accept list if disconnect succeeded and wake
|
||||
* isn't being prevented.
|
||||
|
@ -83,14 +83,14 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo
|
||||
ci->product = session->input->id.product;
|
||||
ci->version = session->input->id.version;
|
||||
if (session->input->name)
|
||||
strlcpy(ci->name, session->input->name, 128);
|
||||
strscpy(ci->name, session->input->name, 128);
|
||||
else
|
||||
strlcpy(ci->name, "HID Boot Device", 128);
|
||||
strscpy(ci->name, "HID Boot Device", 128);
|
||||
} else if (session->hid) {
|
||||
ci->vendor = session->hid->vendor;
|
||||
ci->product = session->hid->product;
|
||||
ci->version = session->hid->version;
|
||||
strlcpy(ci->name, session->hid->name, 128);
|
||||
strscpy(ci->name, session->hid->name, 128);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1309,7 +1309,7 @@ static int iso_sock_shutdown(struct socket *sock, int how)
|
||||
struct sock *sk = sock->sk;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
|
||||
|
||||
if (!sk)
|
||||
return 0;
|
||||
@ -1317,17 +1317,32 @@ static int iso_sock_shutdown(struct socket *sock, int how)
|
||||
sock_hold(sk);
|
||||
lock_sock(sk);
|
||||
|
||||
if (!sk->sk_shutdown) {
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
iso_sock_clear_timer(sk);
|
||||
__iso_sock_close(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING))
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED,
|
||||
sk->sk_lingertime);
|
||||
switch (how) {
|
||||
case SHUT_RD:
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
goto unlock;
|
||||
sk->sk_shutdown |= RCV_SHUTDOWN;
|
||||
break;
|
||||
case SHUT_WR:
|
||||
if (sk->sk_shutdown & SEND_SHUTDOWN)
|
||||
goto unlock;
|
||||
sk->sk_shutdown |= SEND_SHUTDOWN;
|
||||
break;
|
||||
case SHUT_RDWR:
|
||||
if (sk->sk_shutdown & SHUTDOWN_MASK)
|
||||
goto unlock;
|
||||
sk->sk_shutdown |= SHUTDOWN_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
iso_sock_clear_timer(sk);
|
||||
__iso_sock_close(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING))
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
||||
|
||||
unlock:
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
|
||||
|
@ -1992,11 +1992,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
|
||||
src_match = !bacmp(&c->src, src);
|
||||
dst_match = !bacmp(&c->dst, dst);
|
||||
if (src_match && dst_match) {
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
if (c) {
|
||||
read_unlock(&chan_list_lock);
|
||||
return c;
|
||||
}
|
||||
if (!l2cap_chan_hold_unless_zero(c))
|
||||
continue;
|
||||
|
||||
read_unlock(&chan_list_lock);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Closest match */
|
||||
|
@ -4547,6 +4547,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, ¶ms->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)
|
||||
{
|
||||
@ -4578,10 +4594,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;
|
||||
}
|
||||
|
||||
@ -4649,38 +4665,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, ¶ms->addr,
|
||||
params->addr_type)) {
|
||||
bt_dev_warn(hdev,
|
||||
"Cannot set wakeable for RPA");
|
||||
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);
|
||||
} else {
|
||||
bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
|
||||
&cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
}
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -5054,7 +5067,6 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
|
||||
else
|
||||
status = MGMT_STATUS_FAILED;
|
||||
|
||||
mgmt_pending_remove(cmd);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user