bluetooth pull request for net:
- hci_core: Disable works on hci_unregister_dev - SCO: Fix UAF on sco_sock_timeout - ISO: Fix UAF on iso_sock_timeout -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmcZB+0ZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKWcfD/4j4Q3W01y1UotsTKa1et7V r6ydZfHBwU/ND8G8t7sfg4zJ6daYcYY6ERllj92JYCHdmrwILzt3WEgCAAC1Y8dj r6RUXFapGSwE3YMIdDstcKgsfYV+zzKL+IBt0VRjhEMeoEEczzRGldk8Y8Z9ePhm 9Jyw1WDmid9DkIfIdrTKjnLH5HsjYZSvIJfkVuKKcfRshdolxfokHv9DpbPIbueO ya33a/mnHVKnLyZPT72uP2DANkP218+zHI+dCjE6279LzrXJkQKLKThf/3bTGO+o NohqGEj9NsIp8NqS/jr1yzvXOIqXkA5cG0Qrix+OyZuvBIohukTFyes1f2hcRHoh l41s+IorviUhrtEPZ2ki/AWyXTVpWJl2EQ6XPf6iUexF2PDCgTzILN4WIELBTZse cEWPVbMI+ZEq9FHX1P9Vfc+Yje4glTXcQzBSlfaljPmbW0CouxYCJ4kEj+5m4F6V xBUevpIz3dRUMST4tXaOrhso/Th2zCDDbWwp6ImEZQ8xBM5wm8sDrjkZOtWEWRNc miLEnkfqZxJmt6b8DfGzeM/p3FJ9i7OsCo6tUVEH4mGATViD8QOUaqMk/kxV5Wh0 ORB3cWk4VYTvXGuPceEH7u8yBslbUzmad/eMOK52ErP4UrORhESZYoaDy3ALcr7A 4z+9xBlOlezKTe5puR5ulw== =gOTr -----END PGP SIGNATURE----- Merge tag 'for-net-2024-10-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - hci_core: Disable works on hci_unregister_dev - SCO: Fix UAF on sco_sock_timeout - ISO: Fix UAF on iso_sock_timeout * tag 'for-net-2024-10-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: ISO: Fix UAF on iso_sock_timeout Bluetooth: SCO: Fix UAF on sco_sock_timeout Bluetooth: hci_core: Disable works on hci_unregister_dev ==================== Link: https://patch.msgid.link/20241023143005.2297694-1-luiz.dentz@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
1876479d98
@ -403,6 +403,7 @@ int bt_sock_register(int proto, const struct net_proto_family *ops);
|
||||
void bt_sock_unregister(int proto);
|
||||
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
|
||||
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
|
||||
bool bt_sock_linked(struct bt_sock_list *l, struct sock *s);
|
||||
struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
|
||||
struct proto *prot, int proto, gfp_t prio, int kern);
|
||||
int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
||||
|
@ -185,6 +185,28 @@ void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_unlink);
|
||||
|
||||
bool bt_sock_linked(struct bt_sock_list *l, struct sock *s)
|
||||
{
|
||||
struct sock *sk;
|
||||
|
||||
if (!l || !s)
|
||||
return false;
|
||||
|
||||
read_lock(&l->lock);
|
||||
|
||||
sk_for_each(sk, &l->head) {
|
||||
if (s == sk) {
|
||||
read_unlock(&l->lock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
read_unlock(&l->lock);
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_linked);
|
||||
|
||||
void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
|
@ -1644,12 +1644,12 @@ void hci_adv_instances_clear(struct hci_dev *hdev)
|
||||
struct adv_info *adv_instance, *n;
|
||||
|
||||
if (hdev->adv_instance_timeout) {
|
||||
cancel_delayed_work(&hdev->adv_instance_expire);
|
||||
disable_delayed_work(&hdev->adv_instance_expire);
|
||||
hdev->adv_instance_timeout = 0;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
|
||||
cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
|
||||
disable_delayed_work_sync(&adv_instance->rpa_expired_cb);
|
||||
list_del(&adv_instance->list);
|
||||
kfree(adv_instance);
|
||||
}
|
||||
@ -2685,11 +2685,11 @@ void hci_unregister_dev(struct hci_dev *hdev)
|
||||
list_del(&hdev->list);
|
||||
write_unlock(&hci_dev_list_lock);
|
||||
|
||||
cancel_work_sync(&hdev->rx_work);
|
||||
cancel_work_sync(&hdev->cmd_work);
|
||||
cancel_work_sync(&hdev->tx_work);
|
||||
cancel_work_sync(&hdev->power_on);
|
||||
cancel_work_sync(&hdev->error_reset);
|
||||
disable_work_sync(&hdev->rx_work);
|
||||
disable_work_sync(&hdev->cmd_work);
|
||||
disable_work_sync(&hdev->tx_work);
|
||||
disable_work_sync(&hdev->power_on);
|
||||
disable_work_sync(&hdev->error_reset);
|
||||
|
||||
hci_cmd_sync_clear(hdev);
|
||||
|
||||
@ -2796,8 +2796,14 @@ static void hci_cancel_cmd_sync(struct hci_dev *hdev, int err)
|
||||
{
|
||||
bt_dev_dbg(hdev, "err 0x%2.2x", err);
|
||||
|
||||
cancel_delayed_work_sync(&hdev->cmd_timer);
|
||||
cancel_delayed_work_sync(&hdev->ncmd_timer);
|
||||
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
|
||||
disable_delayed_work_sync(&hdev->cmd_timer);
|
||||
disable_delayed_work_sync(&hdev->ncmd_timer);
|
||||
} else {
|
||||
cancel_delayed_work_sync(&hdev->cmd_timer);
|
||||
cancel_delayed_work_sync(&hdev->ncmd_timer);
|
||||
}
|
||||
|
||||
atomic_set(&hdev->cmd_cnt, 1);
|
||||
|
||||
hci_cmd_sync_cancel_sync(hdev, err);
|
||||
|
@ -5131,9 +5131,15 @@ int hci_dev_close_sync(struct hci_dev *hdev)
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
cancel_delayed_work(&hdev->power_off);
|
||||
cancel_delayed_work(&hdev->ncmd_timer);
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
|
||||
disable_delayed_work(&hdev->power_off);
|
||||
disable_delayed_work(&hdev->ncmd_timer);
|
||||
disable_delayed_work(&hdev->le_scan_disable);
|
||||
} else {
|
||||
cancel_delayed_work(&hdev->power_off);
|
||||
cancel_delayed_work(&hdev->ncmd_timer);
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
}
|
||||
|
||||
hci_cmd_sync_cancel_sync(hdev, ENODEV);
|
||||
|
||||
|
@ -93,6 +93,16 @@ static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
|
||||
#define ISO_CONN_TIMEOUT (HZ * 40)
|
||||
#define ISO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
||||
static struct sock *iso_sock_hold(struct iso_conn *conn)
|
||||
{
|
||||
if (!conn || !bt_sock_linked(&iso_sk_list, conn->sk))
|
||||
return NULL;
|
||||
|
||||
sock_hold(conn->sk);
|
||||
|
||||
return conn->sk;
|
||||
}
|
||||
|
||||
static void iso_sock_timeout(struct work_struct *work)
|
||||
{
|
||||
struct iso_conn *conn = container_of(work, struct iso_conn,
|
||||
@ -100,9 +110,7 @@ static void iso_sock_timeout(struct work_struct *work)
|
||||
struct sock *sk;
|
||||
|
||||
iso_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
if (sk)
|
||||
sock_hold(sk);
|
||||
sk = iso_sock_hold(conn);
|
||||
iso_conn_unlock(conn);
|
||||
|
||||
if (!sk)
|
||||
@ -209,9 +217,7 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
|
||||
|
||||
/* Kill socket */
|
||||
iso_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
if (sk)
|
||||
sock_hold(sk);
|
||||
sk = iso_sock_hold(conn);
|
||||
iso_conn_unlock(conn);
|
||||
|
||||
if (sk) {
|
||||
|
@ -76,6 +76,16 @@ struct sco_pinfo {
|
||||
#define SCO_CONN_TIMEOUT (HZ * 40)
|
||||
#define SCO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
||||
static struct sock *sco_sock_hold(struct sco_conn *conn)
|
||||
{
|
||||
if (!conn || !bt_sock_linked(&sco_sk_list, conn->sk))
|
||||
return NULL;
|
||||
|
||||
sock_hold(conn->sk);
|
||||
|
||||
return conn->sk;
|
||||
}
|
||||
|
||||
static void sco_sock_timeout(struct work_struct *work)
|
||||
{
|
||||
struct sco_conn *conn = container_of(work, struct sco_conn,
|
||||
@ -87,9 +97,7 @@ static void sco_sock_timeout(struct work_struct *work)
|
||||
sco_conn_unlock(conn);
|
||||
return;
|
||||
}
|
||||
sk = conn->sk;
|
||||
if (sk)
|
||||
sock_hold(sk);
|
||||
sk = sco_sock_hold(conn);
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (!sk)
|
||||
@ -194,9 +202,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
|
||||
|
||||
/* Kill socket */
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
if (sk)
|
||||
sock_hold(sk);
|
||||
sk = sco_sock_hold(conn);
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (sk) {
|
||||
|
Loading…
Reference in New Issue
Block a user