From: Greg Kroah-Hartman Date: Mon, 20 Jul 2026 12:49:21 +0000 (+0200) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec90aa31081d2acd874966cc4848f07cbb06d77b;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch --- diff --git a/queue-6.6/bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch b/queue-6.6/bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch new file mode 100644 index 0000000000..ae13673e0f --- /dev/null +++ b/queue-6.6/bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch @@ -0,0 +1,74 @@ +From b819db93d73f4593636299e229914052b89e3ef2 Mon Sep 17 00:00:00 2001 +From: Pauli Virtanen +Date: Sun, 12 Apr 2026 21:47:42 +0300 +Subject: Bluetooth: SCO: fix sleeping under spinlock in sco_conn_ready + +From: Pauli Virtanen + +commit b819db93d73f4593636299e229914052b89e3ef2 upstream. + +sco_conn_ready calls sleeping functions under conn->lock spinlock. + +The critical section can be reduced: conn->hcon is modified only with +hdev->lock held. It is guaranteed to be held in sco_conn_ready, so +conn->lock is not needed to guard it. + +Move taking conn->lock after lock_sock(parent). This also follows the +lock ordering lock_sock() > conn->lock elsewhere in the file. + +Fixes: 27c24fda62b60 ("Bluetooth: switch to lock_sock in SCO") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/sco.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -1314,26 +1314,24 @@ static void sco_conn_ready(struct sco_co + sk->sk_state_change(sk); + release_sock(sk); + } else { +- sco_conn_lock(conn); +- +- if (!conn->hcon) { +- sco_conn_unlock(conn); ++ if (!conn->hcon) + return; +- } ++ ++ lockdep_assert_held(&conn->hcon->hdev->lock); + + parent = sco_get_sock_listen(&conn->hcon->src); +- if (!parent) { +- sco_conn_unlock(conn); ++ if (!parent) + return; +- } + + lock_sock(parent); + ++ sco_conn_lock(conn); ++ + sk = sco_sock_alloc(sock_net(parent), NULL, + BTPROTO_SCO, GFP_ATOMIC, 0); + if (!sk) { +- release_sock(parent); + sco_conn_unlock(conn); ++ release_sock(parent); + return; + } + +@@ -1353,9 +1351,9 @@ static void sco_conn_ready(struct sco_co + /* Wake up parent */ + parent->sk_data_ready(parent); + +- release_sock(parent); +- + sco_conn_unlock(conn); ++ ++ release_sock(parent); + } + } + diff --git a/queue-6.6/bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch b/queue-6.6/bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch new file mode 100644 index 0000000000..5cb5d8738b --- /dev/null +++ b/queue-6.6/bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch @@ -0,0 +1,137 @@ +From 4e37f6452d586b95c346a9abdd2fb80b67794f39 Mon Sep 17 00:00:00 2001 +From: Pauli Virtanen +Date: Sat, 18 Apr 2026 18:41:12 +0300 +Subject: Bluetooth: SCO: hold sk properly in sco_conn_ready + +From: Pauli Virtanen + +commit 4e37f6452d586b95c346a9abdd2fb80b67794f39 upstream. + +sk deref in sco_conn_ready must be done either under conn->lock, or +holding a refcount, to avoid concurrent close. conn->sk and parent sk is +currently accessed without either, and without checking parent->sk_state: + + [Task 1] [Task 2] + sco_sock_release + sco_conn_ready + sk = conn->sk + lock_sock(sk) + conn->sk = NULL + lock_sock(sk) + release_sock(sk) + sco_sock_kill(sk) + UAF on sk deref + +and similarly for access to sco_get_sock_listen() return value. + +Fix possible UAF by holding sk refcount in sco_conn_ready() and making +sco_get_sock_listen() increase refcount. Also recheck after lock_sock +that the socket is still valid. Adjust conn->sk locking so it's +protected also by lock_sock() of the associated socket if any. + +Fixes: 27c24fda62b60 ("Bluetooth: switch to lock_sock in SCO") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/sco.c | 44 ++++++++++++++++++++++++++++++++------------ + 1 file changed, 32 insertions(+), 12 deletions(-) + +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -409,9 +409,13 @@ static struct sock *sco_get_sock_listen( + sk1 = sk; + } + ++ sk = sk ? sk : sk1; ++ if (sk) ++ sock_hold(sk); ++ + read_unlock(&sco_sk_list.lock); + +- return sk ? sk : sk1; ++ return sk; + } + + static void sco_sock_destruct(struct sock *sk) +@@ -451,11 +455,13 @@ static void sco_sock_kill(struct sock *s + BT_DBG("sk %p state %d", sk, sk->sk_state); + + /* Sock is dead, so set conn->sk to NULL to avoid possible UAF */ ++ lock_sock(sk); + if (sco_pi(sk)->conn) { + sco_conn_lock(sco_pi(sk)->conn); + sco_pi(sk)->conn->sk = NULL; + sco_conn_unlock(sco_pi(sk)->conn); + } ++ release_sock(sk); + + /* Kill poor orphan */ + bt_sock_unlink(&sco_sk_list, sk); +@@ -1302,17 +1308,28 @@ static int sco_sock_release(struct socke + + static void sco_conn_ready(struct sco_conn *conn) + { +- struct sock *parent; +- struct sock *sk = conn->sk; ++ struct sock *parent, *sk; ++ ++ sco_conn_lock(conn); ++ sk = sco_sock_hold(conn); ++ sco_conn_unlock(conn); + + BT_DBG("conn %p", conn); + + if (sk) { + lock_sock(sk); +- sco_sock_clear_timer(sk); +- sk->sk_state = BT_CONNECTED; +- sk->sk_state_change(sk); ++ ++ /* conn->sk may have become NULL if racing with sk close, but ++ * due to held hdev->lock, it can't become different sk. ++ */ ++ if (conn->sk) { ++ sco_sock_clear_timer(sk); ++ sk->sk_state = BT_CONNECTED; ++ sk->sk_state_change(sk); ++ } ++ + release_sock(sk); ++ sock_put(sk); + } else { + if (!conn->hcon) + return; +@@ -1327,13 +1344,15 @@ static void sco_conn_ready(struct sco_co + + sco_conn_lock(conn); + ++ /* hdev->lock guarantees conn->sk == NULL still here */ ++ ++ if (parent->sk_state != BT_LISTEN) ++ goto release; ++ + sk = sco_sock_alloc(sock_net(parent), NULL, + BTPROTO_SCO, GFP_ATOMIC, 0); +- if (!sk) { +- sco_conn_unlock(conn); +- release_sock(parent); +- return; +- } ++ if (!sk) ++ goto release; + + sco_sock_init(sk, parent); + +@@ -1351,9 +1370,10 @@ static void sco_conn_ready(struct sco_co + /* Wake up parent */ + parent->sk_data_ready(parent); + ++release: + sco_conn_unlock(conn); +- + release_sock(parent); ++ sock_put(parent); + } + } + diff --git a/queue-6.6/hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch b/queue-6.6/hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch new file mode 100644 index 0000000000..966691c2a8 --- /dev/null +++ b/queue-6.6/hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch @@ -0,0 +1,59 @@ +From 82a4fc46330910b4c1d9b189561439d468e3ff11 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Beno=C3=AEt=20Sevens?= +Date: Mon, 23 Mar 2026 12:47:37 +0000 +Subject: HID: playstation: validate num_touch_reports in DualShock 4 reports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Benoît Sevens + +commit 82a4fc46330910b4c1d9b189561439d468e3ff11 upstream. + +The DualShock 4 HID driver fails to validate the num_touch_reports field +received from the device in both USB and Bluetooth input reports. +A malicious device could set this field to a value larger than the +allocated size of the touch_reports array (3 for USB, 4 for Bluetooth), +leading to an out-of-bounds read in dualshock4_parse_report(). + +This can result in kernel memory disclosure when processing malicious +HID reports. + +Validate num_touch_reports against the array size for the respective +connection types before processing the touch data. + +Signed-off-by: Benoît Sevens +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-playstation.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/hid/hid-playstation.c ++++ b/drivers/hid/hid-playstation.c +@@ -2199,6 +2199,12 @@ static int dualshock4_parse_report(struc + size == DS4_INPUT_REPORT_USB_SIZE) { + struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; + ++ if (usb->num_touch_reports > ARRAY_SIZE(usb->touch_reports)) { ++ hid_err(hdev, "DualShock4 USB input report has invalid num_touch_reports=%d\n", ++ usb->num_touch_reports); ++ return -EINVAL; ++ } ++ + ds4_report = &usb->common; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); +@@ -2214,6 +2220,12 @@ static int dualshock4_parse_report(struc + return -EILSEQ; + } + ++ if (bt->num_touch_reports > ARRAY_SIZE(bt->touch_reports)) { ++ hid_err(hdev, "DualShock4 BT input report has invalid num_touch_reports=%d\n", ++ bt->num_touch_reports); ++ return -EINVAL; ++ } ++ + ds4_report = &bt->common; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); diff --git a/queue-6.6/series b/queue-6.6/series index cfa1a91f38..4baac5d379 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -957,3 +957,6 @@ batman-adv-frag-fix-primary_if-leak-on-failed-linearization.patch batman-adv-tt-prevent-tvlv-oob-check-overflow.patch cifs-invalidate-cfid-on-unlink-rename-rmdir.patch mfd-tps6586x-fix-of-node-refcount.patch +hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch +bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch +bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch