Merge tag 'for-net-2024-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - SCO: Fix transparent voice setting - ISO: Locking fixes - hci_core: Fix sleeping function called from invalid context - hci_event: Fix using rcu_read_(un)lock while iterating - btmtk: avoid UAF in btmtk_process_coredump * tag 'for-net-2024-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: btmtk: avoid UAF in btmtk_process_coredump Bluetooth: iso: Fix circular lock in iso_conn_big_sync Bluetooth: iso: Fix circular lock in iso_listen_bis Bluetooth: SCO: Add support for 16 bits transparent voice setting Bluetooth: iso: Fix recursive locking warning Bluetooth: iso: Always release hdev at the end of iso_listen_bis Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating Bluetooth: hci_core: Fix sleeping function called from invalid context Bluetooth: Improve setsockopt() handling of malformed user input ==================== Link: https://patch.msgid.link/20241212142806.2046274-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -123,6 +123,7 @@ struct bt_voice {
|
||||
|
||||
#define BT_VOICE_TRANSPARENT 0x0003
|
||||
#define BT_VOICE_CVSD_16BIT 0x0060
|
||||
#define BT_VOICE_TRANSPARENT_16BIT 0x0063
|
||||
|
||||
#define BT_SNDMTU 12
|
||||
#define BT_RCVMTU 13
|
||||
@@ -590,15 +591,6 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
|
||||
sockptr_t src, size_t src_size)
|
||||
{
|
||||
if (dst_size > src_size)
|
||||
return -EINVAL;
|
||||
|
||||
return copy_from_sockptr(dst, src, dst_size);
|
||||
}
|
||||
|
||||
int bt_to_errno(u16 code);
|
||||
__u8 bt_status(int err);
|
||||
|
||||
|
||||
@@ -804,7 +804,6 @@ struct hci_conn_params {
|
||||
extern struct list_head hci_dev_list;
|
||||
extern struct list_head hci_cb_list;
|
||||
extern rwlock_t hci_dev_list_lock;
|
||||
extern struct mutex hci_cb_list_lock;
|
||||
|
||||
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
|
||||
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
|
||||
@@ -2017,24 +2016,47 @@ struct hci_cb {
|
||||
|
||||
char *name;
|
||||
|
||||
bool (*match) (struct hci_conn *conn);
|
||||
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
|
||||
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
|
||||
void (*security_cfm) (struct hci_conn *conn, __u8 status,
|
||||
__u8 encrypt);
|
||||
__u8 encrypt);
|
||||
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
|
||||
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
|
||||
};
|
||||
|
||||
static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
|
||||
{
|
||||
struct hci_cb *cb, *cpy;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
|
||||
if (cb->match && cb->match(conn)) {
|
||||
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
|
||||
if (!cpy)
|
||||
break;
|
||||
|
||||
*cpy = *cb;
|
||||
INIT_LIST_HEAD(&cpy->list);
|
||||
list_add_rcu(&cpy->list, list);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
struct list_head list;
|
||||
struct hci_cb *cb, *tmp;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
INIT_LIST_HEAD(&list);
|
||||
hci_cb_lookup(conn, &list);
|
||||
|
||||
list_for_each_entry_safe(cb, tmp, &list, list) {
|
||||
if (cb->connect_cfm)
|
||||
cb->connect_cfm(conn, status);
|
||||
kfree(cb);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
|
||||
if (conn->connect_cfm_cb)
|
||||
conn->connect_cfm_cb(conn, status);
|
||||
@@ -2042,22 +2064,43 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
|
||||
|
||||
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
struct list_head list;
|
||||
struct hci_cb *cb, *tmp;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
INIT_LIST_HEAD(&list);
|
||||
hci_cb_lookup(conn, &list);
|
||||
|
||||
list_for_each_entry_safe(cb, tmp, &list, list) {
|
||||
if (cb->disconn_cfm)
|
||||
cb->disconn_cfm(conn, reason);
|
||||
kfree(cb);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
|
||||
if (conn->disconn_cfm_cb)
|
||||
conn->disconn_cfm_cb(conn, reason);
|
||||
}
|
||||
|
||||
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
|
||||
__u8 encrypt)
|
||||
{
|
||||
struct list_head list;
|
||||
struct hci_cb *cb, *tmp;
|
||||
|
||||
INIT_LIST_HEAD(&list);
|
||||
hci_cb_lookup(conn, &list);
|
||||
|
||||
list_for_each_entry_safe(cb, tmp, &list, list) {
|
||||
if (cb->security_cfm)
|
||||
cb->security_cfm(conn, status, encrypt);
|
||||
kfree(cb);
|
||||
}
|
||||
|
||||
if (conn->security_cfm_cb)
|
||||
conn->security_cfm_cb(conn, status);
|
||||
}
|
||||
|
||||
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
__u8 encrypt;
|
||||
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
||||
@@ -2065,20 +2108,11 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
||||
|
||||
encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
if (cb->security_cfm)
|
||||
cb->security_cfm(conn, status, encrypt);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
|
||||
if (conn->security_cfm_cb)
|
||||
conn->security_cfm_cb(conn, status);
|
||||
hci_security_cfm(conn, status, encrypt);
|
||||
}
|
||||
|
||||
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
__u8 encrypt;
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
@@ -2105,40 +2139,38 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
||||
conn->sec_level = conn->pending_sec_level;
|
||||
}
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
if (cb->security_cfm)
|
||||
cb->security_cfm(conn, status, encrypt);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
|
||||
if (conn->security_cfm_cb)
|
||||
conn->security_cfm_cb(conn, status);
|
||||
hci_security_cfm(conn, status, encrypt);
|
||||
}
|
||||
|
||||
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
struct list_head list;
|
||||
struct hci_cb *cb, *tmp;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
INIT_LIST_HEAD(&list);
|
||||
hci_cb_lookup(conn, &list);
|
||||
|
||||
list_for_each_entry_safe(cb, tmp, &list, list) {
|
||||
if (cb->key_change_cfm)
|
||||
cb->key_change_cfm(conn, status);
|
||||
kfree(cb);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
}
|
||||
|
||||
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
|
||||
__u8 role)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
struct list_head list;
|
||||
struct hci_cb *cb, *tmp;
|
||||
|
||||
mutex_lock(&hci_cb_list_lock);
|
||||
list_for_each_entry(cb, &hci_cb_list, list) {
|
||||
INIT_LIST_HEAD(&list);
|
||||
hci_cb_lookup(conn, &list);
|
||||
|
||||
list_for_each_entry_safe(cb, tmp, &list, list) {
|
||||
if (cb->role_switch_cfm)
|
||||
cb->role_switch_cfm(conn, status, role);
|
||||
kfree(cb);
|
||||
}
|
||||
mutex_unlock(&hci_cb_list_lock);
|
||||
}
|
||||
|
||||
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
|
||||
|
||||
Reference in New Issue
Block a user