From 9be7ae65c01005a75cdfad910ffd73f554f379c8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 5 Jun 2026 15:37:14 -0400 Subject: [PATCH] Fixes for all trees Signed-off-by: Sasha Levin --- ...ore-fix-use-after-free-in-vhci_flush.patch | 253 ++++++++++++++ queue-5.10/series | 4 + ...ss_m8-fix-memory-corruption-with-sma.patch | 46 +++ ...acceleport-fix-memory-corruption-wit.patch | 67 ++++ ...host-usb-device-on-dual-role-port-un.patch | 188 ++++++++++ ...ntk_ratelimited-variants-to-hid_warn.patch | 43 +++ ...e_t-specifier-in-hid_report_raw_even.patch | 67 ++++ ...-buffer-size-to-hid_report_raw_event.patch | 269 +++++++++++++++ queue-5.15/series | 6 + ...ss_m8-fix-memory-corruption-with-sma.patch | 46 +++ ...acceleport-fix-memory-corruption-wit.patch | 67 ++++ ...host-usb-device-on-dual-role-port-un.patch | 188 ++++++++++ ...ntk_ratelimited-variants-to-hid_warn.patch | 42 +++ ...e_t-specifier-in-hid_report_raw_even.patch | 66 ++++ ...-buffer-size-to-hid_report_raw_event.patch | 276 +++++++++++++++ ...les-restore-set-elements-when-delete.patch | 324 ++++++++++++++++++ ...mplete-the-rxe_cleanup_task-backport.patch | 62 ++++ queue-6.1/series | 8 + ...ss_m8-fix-memory-corruption-with-sma.patch | 46 +++ ...acceleport-fix-memory-corruption-wit.patch | 67 ++++ ...host-usb-device-on-dual-role-port-un.patch | 188 ++++++++++ queue-6.12/series | 3 + ...ss_m8-fix-memory-corruption-with-sma.patch | 46 +++ ...acceleport-fix-memory-corruption-wit.patch | 67 ++++ ...host-usb-device-on-dual-role-port-un.patch | 197 +++++++++++ ...micrel-fix-lan8814-qsgmii-soft-reset.patch | 68 ++++ queue-6.18/series | 2 + ...host-usb-device-on-dual-role-port-un.patch | 197 +++++++++++ ...nc-fix-uaf-in-hci_le_create_cis_sync.patch | 84 +++++ ...handling-of-disconnected-directories.patch | 172 ++++++++++ queue-6.6/series | 6 + ...ss_m8-fix-memory-corruption-with-sma.patch | 46 +++ ...acceleport-fix-memory-corruption-wit.patch | 67 ++++ ...e-kcov-instrumentation-after-load_se.patch | 92 +++++ ...host-usb-device-on-dual-role-port-un.patch | 197 +++++++++++ ...micrel-fix-lan8814-qsgmii-soft-reset.patch | 68 ++++ queue-7.0/series | 2 + ...host-usb-device-on-dual-role-port-un.patch | 194 +++++++++++ 38 files changed, 3831 insertions(+) create mode 100644 queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch create mode 100644 queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch create mode 100644 queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch create mode 100644 queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch create mode 100644 queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch create mode 100644 queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch create mode 100644 queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch create mode 100644 queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch create mode 100644 queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch create mode 100644 queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch create mode 100644 queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch create mode 100644 queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch create mode 100644 queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch create mode 100644 queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch create mode 100644 queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch create mode 100644 queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch create mode 100644 queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch create mode 100644 queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch create mode 100644 queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch create mode 100644 queue-6.6/landlock-fix-handling-of-disconnected-directories.patch create mode 100644 queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch create mode 100644 queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch create mode 100644 queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch create mode 100644 queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch create mode 100644 queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch create mode 100644 queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch b/queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch new file mode 100644 index 0000000000..aa17e5d4d5 --- /dev/null +++ b/queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch @@ -0,0 +1,253 @@ +From 860fa1e6ed52a6a96da778319b84d7d917664094 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 02:43:39 +0300 +Subject: Bluetooth: hci_core: Fix use-after-free in vhci_flush() + +From: Kuniyuki Iwashima + +commit 1d6123102e9fbedc8d25bf4731da6d513173e49e upstream. + +syzbot reported use-after-free in vhci_flush() without repro. [0] + +>From the splat, a thread close()d a vhci file descriptor while +its device was being used by iotcl() on another thread. + +Once the last fd refcnt is released, vhci_release() calls +hci_unregister_dev(), hci_free_dev(), and kfree() for struct +vhci_data, which is set to hci_dev->dev->driver_data. + +The problem is that there is no synchronisation after unlinking +hdev from hci_dev_list in hci_unregister_dev(). There might be +another thread still accessing the hdev which was fetched before +the unlink operation. + +We can use SRCU for such synchronisation. + +Let's run hci_dev_reset() under SRCU and wait for its completion +in hci_unregister_dev(). + +Another option would be to restore hci_dev->destruct(), which was +removed in commit 587ae086f6e4 ("Bluetooth: Remove unused +hci-destruct cb"). However, this would not be a good solution, as +we should not run hci_unregister_dev() while there are in-flight +ioctl() requests, which could lead to another data-race KCSAN splat. + +Note that other drivers seem to have the same problem, for exmaple, +virtbt_remove(). + +[0]: +BUG: KASAN: slab-use-after-free in skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] +BUG: KASAN: slab-use-after-free in skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937 +Read of size 8 at addr ffff88807cb8d858 by task syz.1.219/6718 + +CPU: 1 UID: 0 PID: 6718 Comm: syz.1.219 Not tainted 6.16.0-rc1-syzkaller-00196-g08207f42d3ff #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:408 [inline] + print_report+0xd2/0x2b0 mm/kasan/report.c:521 + kasan_report+0x118/0x150 mm/kasan/report.c:634 + skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] + skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937 + skb_queue_purge include/linux/skbuff.h:3368 [inline] + vhci_flush+0x44/0x50 drivers/bluetooth/hci_vhci.c:69 + hci_dev_do_reset net/bluetooth/hci_core.c:552 [inline] + hci_dev_reset+0x420/0x5c0 net/bluetooth/hci_core.c:592 + sock_do_ioctl+0xd9/0x300 net/socket.c:1190 + sock_ioctl+0x576/0x790 net/socket.c:1311 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:907 [inline] + __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7fcf5b98e929 +Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007fcf5c7b9038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +RAX: ffffffffffffffda RBX: 00007fcf5bbb6160 RCX: 00007fcf5b98e929 +RDX: 0000000000000000 RSI: 00000000400448cb RDI: 0000000000000009 +RBP: 00007fcf5ba10b39 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 +R13: 0000000000000000 R14: 00007fcf5bbb6160 R15: 00007ffd6353d528 + + +Allocated by task 6535: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:377 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4359 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + vhci_open+0x57/0x360 drivers/bluetooth/hci_vhci.c:635 + misc_open+0x2bc/0x330 drivers/char/misc.c:161 + chrdev_open+0x4c9/0x5e0 fs/char_dev.c:414 + do_dentry_open+0xdf0/0x1970 fs/open.c:964 + vfs_open+0x3b/0x340 fs/open.c:1094 + do_open fs/namei.c:3887 [inline] + path_openat+0x2ee5/0x3830 fs/namei.c:4046 + do_filp_open+0x1fa/0x410 fs/namei.c:4073 + do_sys_openat2+0x121/0x1c0 fs/open.c:1437 + do_sys_open fs/open.c:1452 [inline] + __do_sys_openat fs/open.c:1468 [inline] + __se_sys_openat fs/open.c:1463 [inline] + __x64_sys_openat+0x138/0x170 fs/open.c:1463 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6535: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:247 [inline] + __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2381 [inline] + slab_free mm/slub.c:4643 [inline] + kfree+0x18e/0x440 mm/slub.c:4842 + vhci_release+0xbc/0xd0 drivers/bluetooth/hci_vhci.c:671 + __fput+0x44c/0xa70 fs/file_table.c:465 + task_work_run+0x1d1/0x260 kernel/task_work.c:227 + exit_task_work include/linux/task_work.h:40 [inline] + do_exit+0x6ad/0x22e0 kernel/exit.c:955 + do_group_exit+0x21c/0x2d0 kernel/exit.c:1104 + __do_sys_exit_group kernel/exit.c:1115 [inline] + __se_sys_exit_group kernel/exit.c:1113 [inline] + __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1113 + x64_sys_call+0x21ba/0x21c0 arch/x86/include/generated/asm/syscalls_64.h:232 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +The buggy address belongs to the object at ffff88807cb8d800 + which belongs to the cache kmalloc-1k of size 1024 +The buggy address is located 88 bytes inside of + freed 1024-byte region [ffff88807cb8d800, ffff88807cb8dc00) + +Fixes: bf18c7118cf8 ("Bluetooth: vhci: Free driver_data on file release") +Reported-by: syzbot+2faa4825e556199361f9@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=f62d64848fc4c7c30cd6 +Signed-off-by: Kuniyuki Iwashima +Acked-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Vladislav Nikolaev +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_core.h | 2 ++ + net/bluetooth/hci_core.c | 34 ++++++++++++++++++++++++++++---- + 2 files changed, 32 insertions(+), 4 deletions(-) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index fe62943a35ddc9..bc4e2856f23567 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -285,6 +286,7 @@ struct amp_assoc { + + struct hci_dev { + struct list_head list; ++ struct srcu_struct srcu; + struct mutex lock; + + const char *name; +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 9787a4c551138d..a718e38f3da31a 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -1040,7 +1040,7 @@ static int hci_linkpol_req(struct hci_request *req, unsigned long opt) + + /* Get HCI device by index. + * Device is held on return. */ +-struct hci_dev *hci_dev_get(int index) ++static struct hci_dev *__hci_dev_get(int index, int *srcu_index) + { + struct hci_dev *hdev = NULL, *d; + +@@ -1053,6 +1053,8 @@ struct hci_dev *hci_dev_get(int index) + list_for_each_entry(d, &hci_dev_list, list) { + if (d->id == index) { + hdev = hci_dev_hold(d); ++ if (srcu_index) ++ *srcu_index = srcu_read_lock(&d->srcu); + break; + } + } +@@ -1060,6 +1062,22 @@ struct hci_dev *hci_dev_get(int index) + return hdev; + } + ++struct hci_dev *hci_dev_get(int index) ++{ ++ return __hci_dev_get(index, NULL); ++} ++ ++static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index) ++{ ++ return __hci_dev_get(index, srcu_index); ++} ++ ++static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index) ++{ ++ srcu_read_unlock(&hdev->srcu, srcu_index); ++ hci_dev_put(hdev); ++} ++ + /* ---- Inquiry support ---- */ + + bool hci_discovery_active(struct hci_dev *hdev) +@@ -1906,9 +1924,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev) + int hci_dev_reset(__u16 dev) + { + struct hci_dev *hdev; +- int err; ++ int err, srcu_index; + +- hdev = hci_dev_get(dev); ++ hdev = hci_dev_get_srcu(dev, &srcu_index); + if (!hdev) + return -ENODEV; + +@@ -1930,7 +1948,7 @@ int hci_dev_reset(__u16 dev) + err = hci_dev_do_reset(hdev); + + done: +- hci_dev_put(hdev); ++ hci_dev_put_srcu(hdev, srcu_index); + return err; + } + +@@ -3596,6 +3614,11 @@ struct hci_dev *hci_alloc_dev(void) + if (!hdev) + return NULL; + ++ if (init_srcu_struct(&hdev->srcu)) { ++ kfree(hdev); ++ return NULL; ++ } ++ + hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); + hdev->esco_type = (ESCO_HV1); + hdev->link_mode = (HCI_LM_ACCEPT); +@@ -3839,6 +3862,9 @@ void hci_unregister_dev(struct hci_dev *hdev) + list_del(&hdev->list); + write_unlock(&hci_dev_list_lock); + ++ synchronize_srcu(&hdev->srcu); ++ cleanup_srcu_struct(&hdev->srcu); ++ + cancel_work_sync(&hdev->rx_work); + cancel_work_sync(&hdev->cmd_work); + cancel_work_sync(&hdev->tx_work); +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index c2ae51e021..fba3779f74 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -113,3 +113,7 @@ serial-fsl_lpuart-fix-rx-buffer-and-dma-map-leaks-in-start_rx_dma.patch serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch serial-zs-fix-bootconsole-handover-lockup.patch serial-zs-switch-to-using-channel-reset.patch +bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch +usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch +usb-serial-digi_acceleport-fix-memory-corruption-wit.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch new file mode 100644 index 0000000000..3b47f07d9c --- /dev/null +++ b/queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch @@ -0,0 +1,46 @@ +From 0b0395e2c8c678a2ebba1acd157be548eb6bdad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:36:36 +0200 +Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint + +From: Johan Hovold + +commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream. + +Make sure that the interrupt-out endpoint max packet size is at least +eight bytes to avoid user-controlled slab corruption or NULL-pointer +dereference should a malicious device report a smaller size. + +Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size") +Cc: stable@vger.kernel.org # 2.6.26 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ johan: adjust context for 6.18 ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 82d2e076ea9a09..e924fb212f5b24 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -447,6 +447,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + return -ENODEV; + } + ++ /* ++ * The buffer must be large enough for the one or two-byte header (and ++ * following data), but assume anything smaller than eight bytes is ++ * broken. ++ */ ++ if (port->interrupt_out_size < 8) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch new file mode 100644 index 0000000000..e21a4028c5 --- /dev/null +++ b/queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch @@ -0,0 +1,67 @@ +From e85c58daa923c1c46806d3f58a9f584b0d16196a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 14:07:58 +0200 +Subject: USB: serial: digi_acceleport: fix memory corruption with small + endpoints + +From: Johan Hovold + +commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream. + +Add the missing bulk-out buffer size sanity checks to avoid +out-of-bounds memory accesses or slab corruption should a malicious +device report smaller buffers than expected. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index 0d606fa9fdca1a..d03bba38d802d2 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1229,15 +1229,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + static int digi_startup(struct usb_serial *serial) + { + struct digi_serial *serial_priv; ++ int oob_port_num; + int ret; ++ int i; ++ ++ /* ++ * The port bulk-out buffers must be large enough for header and ++ * buffered data. ++ */ ++ for (i = 0; i < serial->type->num_ports; i++) { ++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2) ++ return -EINVAL; ++ } ++ ++ /* ++ * The OOB port bulk-out buffer must be large enough for the two ++ * commands in digi_set_modem_signals(). ++ */ ++ oob_port_num = serial->type->num_ports; ++ if (serial->port[oob_port_num]->bulk_out_size < 8) ++ return -EINVAL; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; + + spin_lock_init(&serial_priv->ds_serial_lock); +- serial_priv->ds_oob_port_num = serial->type->num_ports; +- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; ++ serial_priv->ds_oob_port_num = oob_port_num; ++ serial_priv->ds_oob_port = serial->port[oob_port_num]; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); +-- +2.53.0 + diff --git a/queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..c4a34bd2fe --- /dev/null +++ b/queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,188 @@ +From 05777def7e2d578f109046104d883053f1fd0fbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:18 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 5.10.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, and omit the newer Tegra234 entry. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index e2cd145ed495a1..8b4a6eb8f0b11f 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -208,6 +208,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + }; + + struct tegra_xusb_context { +@@ -1161,14 +1162,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off"); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1179,42 +1183,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -1925,6 +1931,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -1961,6 +1968,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2002,6 +2010,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2033,6 +2042,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .mbox = { + .cmd = 0x68, + .data_in = 0x6c, +-- +2.53.0 + diff --git a/queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch b/queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch new file mode 100644 index 0000000000..32f26f70c8 --- /dev/null +++ b/queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch @@ -0,0 +1,43 @@ +From 20edc38963a0a2e5ba72028747b2f11bab44b3a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:26:50 +0100 +Subject: HID: core: Add printk_ratelimited variants to hid_warn() etc + +From: Vicki Pfau + +[ Upstream commit 1d64624243af8329b4b219d8c39e28ea448f9929 ] + +hid_warn_ratelimited() is needed. Add the others as part of the block. + +Signed-off-by: Vicki Pfau +Signed-off-by: Jiri Kosina +Signed-off-by: Lee Jones +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + include/linux/hid.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 671403f208c91d..3968fa039c260b 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -1248,4 +1248,15 @@ do { \ + #define hid_dbg_once(hid, fmt, ...) \ + dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__) + ++#define hid_err_ratelimited(hid, fmt, ...) \ ++ dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_notice_ratelimited(hid, fmt, ...) \ ++ dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_warn_ratelimited(hid, fmt, ...) \ ++ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_info_ratelimited(hid, fmt, ...) \ ++ dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_dbg_ratelimited(hid, fmt, ...) \ ++ dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++ + #endif +-- +2.53.0 + diff --git a/queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch b/queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch new file mode 100644 index 0000000000..332dad6aa0 --- /dev/null +++ b/queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch @@ -0,0 +1,67 @@ +From e43275056059158360d4d476ce4bc7e3974d0c53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:26:52 +0100 +Subject: HID: core: Fix size_t specifier in hid_report_raw_event() + +From: Nathan Chancellor + +[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ] + +When building for 32-bit platforms, for which 'size_t' is +'unsigned int', there are warnings around using the incorrect format +specifier to print bsize in hid_report_raw_event(): + + drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat] + 2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", + | ~~~ + | %zu + 2054 | report->id, csize, bsize); + | ^~~~~ + drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat] + 2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", + | ~~~ + | %zu + 2076 | report->id, rsize, bsize); + | ^~~~~ + +Use the proper 'size_t' format specifier, '%zu', to clear up the +warnings. + +Cc: stable@vger.kernel.org +Fixes: 2c85c61d1332 ("HID: pass the buffer size to hid_report_raw_event") +Reported-by: Miguel Ojeda +Closes: https://lore.kernel.org/20260516020430.110135-1-ojeda@kernel.org/ +Signed-off-by: Nathan Chancellor +Signed-off-by: Linus Torvalds +Signed-off-by: Lee Jones +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index a8d4673c7b8e13..e106b59b55da2d 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1793,7 +1793,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, + return 0; + + if (unlikely(bsize < csize)) { +- hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", ++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n", + report->id, csize, bsize); + return -EINVAL; + } +@@ -1815,7 +1815,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, + rsize = max_buffer_size; + + if (bsize < rsize) { +- hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", ++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n", + report->id, rsize, bsize); + return -EINVAL; + } +-- +2.53.0 + diff --git a/queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch new file mode 100644 index 0000000000..06f55229ff --- /dev/null +++ b/queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch @@ -0,0 +1,269 @@ +From 51914eb2df20b1114553d7bd48ea305f58b867ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:26:51 +0100 +Subject: HID: pass the buffer size to hid_report_raw_event + +From: Benjamin Tissoires + +[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ] + +commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing +bogus memset()") enforced the provided data to be at least the size of +the declared buffer in the report descriptor to prevent a buffer +overflow. However, we can try to be smarter by providing both the buffer +size and the data size, meaning that hid_report_raw_event() can make +better decision whether we should plaining reject the buffer (buffer +overflow attempt) or if we can safely memset it to 0 and pass it to the +rest of the stack. + +Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()") +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +Acked-by: Johan Hovold +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Jiri Kosina +Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()") +[Lee: Backported to linux-6.12.y and beyond] +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-core.c | 29 ++++++++++++++++++++++------- + drivers/hid/hid-gfrm.c | 4 ++-- + drivers/hid/hid-logitech-hidpp.c | 2 +- + drivers/hid/hid-multitouch.c | 2 +- + drivers/hid/hid-primax.c | 2 +- + drivers/hid/hid-vivaldi.c | 2 +- + drivers/hid/wacom_sys.c | 6 +++--- + drivers/staging/greybus/hid.c | 2 +- + include/linux/hid.h | 4 ++-- + 9 files changed, 34 insertions(+), 19 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 4fb573ee31b2ca..a8d4673c7b8e13 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1775,8 +1775,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, + } + EXPORT_SYMBOL_GPL(__hid_request); + +-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, +- int interrupt) ++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, ++ size_t bufsize, u32 size, int interrupt) + { + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; +@@ -1784,16 +1784,24 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + int max_buffer_size = HID_MAX_BUFFER_SIZE; + unsigned int a; + u32 rsize, csize = size; ++ size_t bsize = bufsize; + u8 *cdata = data; + int ret = 0; + + report = hid_get_report(report_enum, data); + if (!report) +- goto out; ++ return 0; ++ ++ if (unlikely(bsize < csize)) { ++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", ++ report->id, csize, bsize); ++ return -EINVAL; ++ } + + if (report_enum->numbered) { + cdata++; + csize--; ++ bsize--; + } + + rsize = hid_compute_report_size(report); +@@ -1806,9 +1814,15 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + else if (rsize > max_buffer_size) + rsize = max_buffer_size; + ++ if (bsize < rsize) { ++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", ++ report->id, rsize, bsize); ++ return -EINVAL; ++ } ++ + if (csize < rsize) { + dbg_hid("report %d is too short, (%d < %d)\n", report->id, +- csize, rsize); ++ csize, rsize); + memset(cdata + csize, 0, rsize - csize); + } + +@@ -1817,7 +1831,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + if (hid->claimed & HID_CLAIMED_HIDRAW) { + ret = hidraw_report_event(hid, data, size); + if (ret) +- goto out; ++ return ret; + } + + if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { +@@ -1830,7 +1844,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_report_event(hid, report); +-out: ++ + return ret; + } + EXPORT_SYMBOL_GPL(hid_report_raw_event); +@@ -1851,6 +1865,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i + struct hid_report_enum *report_enum; + struct hid_driver *hdrv; + struct hid_report *report; ++ size_t bufsize = size; + int ret = 0; + + if (!hid) +@@ -1889,7 +1904,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i + goto unlock; + } + +- ret = hid_report_raw_event(hid, type, data, size, interrupt); ++ ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt); + + unlock: + up(&hid->driver_input_lock); +diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c +index 699186ff2349e9..d2a56bf92b416e 100644 +--- a/drivers/hid/hid-gfrm.c ++++ b/drivers/hid/hid-gfrm.c +@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report, + switch (data[1]) { + case GFRM100_SEARCH_KEY_DOWN: + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn, +- sizeof(search_key_dn), 1); ++ sizeof(search_key_dn), sizeof(search_key_dn), 1); + break; + + case GFRM100_SEARCH_KEY_AUDIO_DATA: +@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report, + + case GFRM100_SEARCH_KEY_UP: + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up, +- sizeof(search_key_up), 1); ++ sizeof(search_key_up), sizeof(search_key_up), 1); + break; + + default: +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index 7ed851bf5bc81f..812ed660c55575 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -3440,7 +3440,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp, + memcpy(&consumer_report[1], &data[3], 4); + /* We are called from atomic context */ + hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT, +- consumer_report, 5, 1); ++ consumer_report, sizeof(consumer_report), 5, 1); + + return 1; + } +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 7a092a2a1bf004..df87d7ae94c462 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -479,7 +479,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) + } + + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, +- size, 0); ++ size, size, 0); + if (ret) + dev_warn(&hdev->dev, "failed to report feature\n"); + } +diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c +index 1e6413d07cae21..16e2a811eda9f0 100644 +--- a/drivers/hid/hid-primax.c ++++ b/drivers/hid/hid-primax.c +@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report, + data[0] |= (1 << (data[idx] - 0xE0)); + data[idx] = 0; + } +- hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0); ++ hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0); + return 1; + + default: /* unknown report */ +diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c +index d57ec17670379c..fdfea1355ee782 100644 +--- a/drivers/hid/hid-vivaldi.c ++++ b/drivers/hid/hid-vivaldi.c +@@ -126,7 +126,7 @@ static void vivaldi_feature_mapping(struct hid_device *hdev, + } + + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data, +- report_len, 0); ++ report_len, report_len, 0); + if (ret) { + dev_warn(&hdev->dev, "failed to report feature %d\n", + field->report->id); +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 9065a41336f9ba..07de763a4ee330 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -79,7 +79,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, + int err; + + size = kfifo_out(fifo, buf, sizeof(buf)); +- err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false); ++ err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false); + if (err) { + hid_warn(hdev, "%s: unable to flush event due to error %d\n", + __func__, err); +@@ -324,7 +324,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, + data, n, WAC_CMD_RETRIES); + if (ret == n && features->type == HID_GENERIC) { + ret = hid_report_raw_event(hdev, +- HID_FEATURE_REPORT, data, n, 0); ++ HID_FEATURE_REPORT, data, n, n, 0); + } else if (ret == 2 && features->type != HID_GENERIC) { + features->touch_max = data[1]; + } else { +@@ -386,7 +386,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, + data, n, WAC_CMD_RETRIES); + if (ret == n) { + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, +- data, n, 0); ++ data, n, n, 0); + } else { + hid_warn(hdev, "%s: could not retrieve sensor offsets\n", + __func__); +diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c +index adb91286803a91..49b42c0ab078ec 100644 +--- a/drivers/staging/greybus/hid.c ++++ b/drivers/staging/greybus/hid.c +@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report) + * we just need to setup the input fields, so using + * hid_report_raw_event is safe. + */ +- hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1); ++ hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1); + } + + static void gb_hid_init_reports(struct gb_hid *ghid) +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 3968fa039c260b..c92c5e2ae24f3b 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -1206,8 +1206,8 @@ static inline u32 hid_report_len(struct hid_report *report) + return DIV_ROUND_UP(report->size, 8) + (report->id > 0); + } + +-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, +- int interrupt); ++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, ++ size_t bufsize, u32 size, int interrupt); + + /* HID quirks API */ + unsigned long hid_lookup_quirk(const struct hid_device *hdev); +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index ca649ea222..5bc0113b3d 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -133,3 +133,9 @@ serial-fsl_lpuart-fix-rx-buffer-and-dma-map-leaks-in-start_rx_dma.patch serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch serial-zs-fix-bootconsole-handover-lockup.patch serial-zs-switch-to-using-channel-reset.patch +usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch +hid-core-add-printk_ratelimited-variants-to-hid_warn.patch +hid-pass-the-buffer-size-to-hid_report_raw_event.patch +hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch +usb-serial-digi_acceleport-fix-memory-corruption-wit.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch new file mode 100644 index 0000000000..7d334568ec --- /dev/null +++ b/queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch @@ -0,0 +1,46 @@ +From 76d74666c3bccf6fae8dd8783b37b09194c37b73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:36:36 +0200 +Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint + +From: Johan Hovold + +commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream. + +Make sure that the interrupt-out endpoint max packet size is at least +eight bytes to avoid user-controlled slab corruption or NULL-pointer +dereference should a malicious device report a smaller size. + +Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size") +Cc: stable@vger.kernel.org # 2.6.26 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ johan: adjust context for 6.18 ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 115e2df92132d3..2ca7e7af714fdb 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -447,6 +447,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + return -ENODEV; + } + ++ /* ++ * The buffer must be large enough for the one or two-byte header (and ++ * following data), but assume anything smaller than eight bytes is ++ * broken. ++ */ ++ if (port->interrupt_out_size < 8) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch new file mode 100644 index 0000000000..8149b0dbe3 --- /dev/null +++ b/queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch @@ -0,0 +1,67 @@ +From 8127d1b7d83a94d840b7e94feb60d2788f816eaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 14:07:58 +0200 +Subject: USB: serial: digi_acceleport: fix memory corruption with small + endpoints + +From: Johan Hovold + +commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream. + +Add the missing bulk-out buffer size sanity checks to avoid +out-of-bounds memory accesses or slab corruption should a malicious +device report smaller buffers than expected. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index af65eb863d70d4..6edc1b50a364f1 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1228,15 +1228,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + static int digi_startup(struct usb_serial *serial) + { + struct digi_serial *serial_priv; ++ int oob_port_num; + int ret; ++ int i; ++ ++ /* ++ * The port bulk-out buffers must be large enough for header and ++ * buffered data. ++ */ ++ for (i = 0; i < serial->type->num_ports; i++) { ++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2) ++ return -EINVAL; ++ } ++ ++ /* ++ * The OOB port bulk-out buffer must be large enough for the two ++ * commands in digi_set_modem_signals(). ++ */ ++ oob_port_num = serial->type->num_ports; ++ if (serial->port[oob_port_num]->bulk_out_size < 8) ++ return -EINVAL; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; + + spin_lock_init(&serial_priv->ds_serial_lock); +- serial_priv->ds_oob_port_num = serial->type->num_ports; +- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; ++ serial_priv->ds_oob_port_num = oob_port_num; ++ serial_priv->ds_oob_port = serial->port[oob_port_num]; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); +-- +2.53.0 + diff --git a/queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..3baf88b53d --- /dev/null +++ b/queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,188 @@ +From 85b22d504abe5ef887c2e5e20679e8a3a0950b56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:16 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 5.15.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, and omit the newer Tegra234 entry. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 14a772feab7946..0f936aeb88d064 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -210,6 +210,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + }; + + struct tegra_xusb_context { +@@ -1211,14 +1212,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off"); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1229,42 +1233,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2289,6 +2295,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2325,6 +2332,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2366,6 +2374,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2397,6 +2406,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .mbox = { + .cmd = 0x68, + .data_in = 0x6c, +-- +2.53.0 + diff --git a/queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch b/queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch new file mode 100644 index 0000000000..dc665d06cf --- /dev/null +++ b/queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch @@ -0,0 +1,42 @@ +From c91ad06cc5fe268b524276f59ad6df47b5d050d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 17:30:12 +0100 +Subject: HID: core: Add printk_ratelimited variants to hid_warn() etc + +From: Vicki Pfau + +[ Upstream commit 1d64624243af8329b4b219d8c39e28ea448f9929 ] + +hid_warn_ratelimited() is needed. Add the others as part of the block. + +Signed-off-by: Vicki Pfau +Signed-off-by: Jiri Kosina +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + include/linux/hid.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 6c3dc24acefc2d..058ba486fdcf87 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -1230,4 +1230,15 @@ do { \ + #define hid_dbg_once(hid, fmt, ...) \ + dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__) + ++#define hid_err_ratelimited(hid, fmt, ...) \ ++ dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_notice_ratelimited(hid, fmt, ...) \ ++ dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_warn_ratelimited(hid, fmt, ...) \ ++ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_info_ratelimited(hid, fmt, ...) \ ++ dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++#define hid_dbg_ratelimited(hid, fmt, ...) \ ++ dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) ++ + #endif +-- +2.53.0 + diff --git a/queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch b/queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch new file mode 100644 index 0000000000..2c1c211407 --- /dev/null +++ b/queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch @@ -0,0 +1,66 @@ +From 22eabda3a3fc2045c46ba27e3da5d3703305fef8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 17:30:14 +0100 +Subject: HID: core: Fix size_t specifier in hid_report_raw_event() + +From: Nathan Chancellor + +[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ] + +When building for 32-bit platforms, for which 'size_t' is +'unsigned int', there are warnings around using the incorrect format +specifier to print bsize in hid_report_raw_event(): + + drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat] + 2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", + | ~~~ + | %zu + 2054 | report->id, csize, bsize); + | ^~~~~ + drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat] + 2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", + | ~~~ + | %zu + 2076 | report->id, rsize, bsize); + | ^~~~~ + +Use the proper 'size_t' format specifier, '%zu', to clear up the +warnings. + +Cc: stable@vger.kernel.org +Fixes: 2c85c61d1332 ("HID: pass the buffer size to hid_report_raw_event") +Reported-by: Miguel Ojeda +Closes: https://lore.kernel.org/20260516020430.110135-1-ojeda@kernel.org/ +Signed-off-by: Nathan Chancellor +Signed-off-by: Linus Torvalds +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 2be5823002a3a4..2191205ce5b0bf 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2006,7 +2006,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * + return 0; + + if (unlikely(bsize < csize)) { +- hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", ++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n", + report->id, csize, bsize); + return -EINVAL; + } +@@ -2028,7 +2028,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * + rsize = max_buffer_size; + + if (bsize < rsize) { +- hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", ++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n", + report->id, rsize, bsize); + return -EINVAL; + } +-- +2.53.0 + diff --git a/queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch new file mode 100644 index 0000000000..63179d66a0 --- /dev/null +++ b/queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch @@ -0,0 +1,276 @@ +From c63ea6201204fccc17441da6a08a9321360368e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 17:30:13 +0100 +Subject: HID: pass the buffer size to hid_report_raw_event + +From: Benjamin Tissoires + +[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ] + +commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing +bogus memset()") enforced the provided data to be at least the size of +the declared buffer in the report descriptor to prevent a buffer +overflow. However, we can try to be smarter by providing both the buffer +size and the data size, meaning that hid_report_raw_event() can make +better decision whether we should plaining reject the buffer (buffer +overflow attempt) or if we can safely memset it to 0 and pass it to the +rest of the stack. + +Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()") +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +Acked-by: Johan Hovold +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Jiri Kosina +Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()") +[Lee: Backported to linux-6.12.y and beyond] +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-core.c | 33 +++++++++++++++++++++++--------- + drivers/hid/hid-gfrm.c | 4 ++-- + drivers/hid/hid-logitech-hidpp.c | 2 +- + drivers/hid/hid-multitouch.c | 2 +- + drivers/hid/hid-primax.c | 2 +- + drivers/hid/hid-vivaldi-common.c | 2 +- + drivers/hid/wacom_sys.c | 6 +++--- + drivers/staging/greybus/hid.c | 2 +- + include/linux/hid.h | 4 ++-- + 9 files changed, 36 insertions(+), 21 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 3f3de08969b55c..2be5823002a3a4 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1989,24 +1989,32 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, + } + EXPORT_SYMBOL_GPL(__hid_request); + +-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, +- int interrupt) ++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, ++ size_t bufsize, u32 size, int interrupt) + { + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; + struct hid_driver *hdrv; + int max_buffer_size = HID_MAX_BUFFER_SIZE; + u32 rsize, csize = size; ++ size_t bsize = bufsize; + u8 *cdata = data; + int ret = 0; + + report = hid_get_report(report_enum, data); + if (!report) +- goto out; ++ return 0; ++ ++ if (unlikely(bsize < csize)) { ++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n", ++ report->id, csize, bsize); ++ return -EINVAL; ++ } + + if (report_enum->numbered) { + cdata++; + csize--; ++ bsize--; + } + + rsize = hid_compute_report_size(report); +@@ -2019,9 +2027,15 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * + else if (rsize > max_buffer_size) + rsize = max_buffer_size; + ++ if (bsize < rsize) { ++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n", ++ report->id, rsize, bsize); ++ return -EINVAL; ++ } ++ + if (csize < rsize) { + dbg_hid("report %d is too short, (%d < %d)\n", report->id, +- csize, rsize); ++ csize, rsize); + memset(cdata + csize, 0, rsize - csize); + } + +@@ -2030,7 +2044,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * + if (hid->claimed & HID_CLAIMED_HIDRAW) { + ret = hidraw_report_event(hid, data, size); + if (ret) +- goto out; ++ return ret; + } + + if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { +@@ -2042,7 +2056,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * + + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_report_event(hid, report); +-out: ++ + return ret; + } + EXPORT_SYMBOL_GPL(hid_report_raw_event); +@@ -2058,12 +2072,13 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event); + * + * This is data entry for lower layers. + */ +-int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, +- int interrupt) ++int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, ++ u32 size, int interrupt) + { + struct hid_report_enum *report_enum; + struct hid_driver *hdrv; + struct hid_report *report; ++ size_t bufsize = size; + int ret = 0; + + if (!hid) +@@ -2102,7 +2117,7 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data + goto unlock; + } + +- ret = hid_report_raw_event(hid, type, data, size, interrupt); ++ ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt); + + unlock: + up(&hid->driver_input_lock); +diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c +index 699186ff2349e9..d2a56bf92b416e 100644 +--- a/drivers/hid/hid-gfrm.c ++++ b/drivers/hid/hid-gfrm.c +@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report, + switch (data[1]) { + case GFRM100_SEARCH_KEY_DOWN: + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn, +- sizeof(search_key_dn), 1); ++ sizeof(search_key_dn), sizeof(search_key_dn), 1); + break; + + case GFRM100_SEARCH_KEY_AUDIO_DATA: +@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report, + + case GFRM100_SEARCH_KEY_UP: + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up, +- sizeof(search_key_up), 1); ++ sizeof(search_key_up), sizeof(search_key_up), 1); + break; + + default: +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index c65b5f004bac57..89b0374bb9a851 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -3451,7 +3451,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp, + memcpy(&consumer_report[1], &data[3], 4); + /* We are called from atomic context */ + hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT, +- consumer_report, 5, 1); ++ consumer_report, sizeof(consumer_report), 5, 1); + + return 1; + } +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 0039508943626d..6c04eed0a46464 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -479,7 +479,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) + } + + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, +- size, 0); ++ size, size, 0); + if (ret) + dev_warn(&hdev->dev, "failed to report feature\n"); + } +diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c +index 1e6413d07cae21..16e2a811eda9f0 100644 +--- a/drivers/hid/hid-primax.c ++++ b/drivers/hid/hid-primax.c +@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report, + data[0] |= (1 << (data[idx] - 0xE0)); + data[idx] = 0; + } +- hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0); ++ hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0); + return 1; + + default: /* unknown report */ +diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c +index b0af2be948952c..7fb986615768f7 100644 +--- a/drivers/hid/hid-vivaldi-common.c ++++ b/drivers/hid/hid-vivaldi-common.c +@@ -85,7 +85,7 @@ void vivaldi_feature_mapping(struct hid_device *hdev, + } + + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data, +- report_len, 0); ++ report_len, report_len, 0); + if (ret) { + dev_warn(&hdev->dev, "failed to report feature %d\n", + field->report->id); +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 9106f16e42df23..9d2a54451b0b5f 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -74,7 +74,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, + int err; + + size = kfifo_out(fifo, buf, sizeof(buf)); +- err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false); ++ err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false); + if (err) { + hid_warn(hdev, "%s: unable to flush event due to error %d\n", + __func__, err); +@@ -319,7 +319,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, + data, n, WAC_CMD_RETRIES); + if (ret == n && features->type == HID_GENERIC) { + ret = hid_report_raw_event(hdev, +- HID_FEATURE_REPORT, data, n, 0); ++ HID_FEATURE_REPORT, data, n, n, 0); + } else if (ret == 2 && features->type != HID_GENERIC) { + features->touch_max = data[1]; + } else { +@@ -381,7 +381,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, + data, n, WAC_CMD_RETRIES); + if (ret == n) { + ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, +- data, n, 0); ++ data, n, n, 0); + } else { + hid_warn(hdev, "%s: could not retrieve sensor offsets\n", + __func__); +diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c +index adb91286803a91..49b42c0ab078ec 100644 +--- a/drivers/staging/greybus/hid.c ++++ b/drivers/staging/greybus/hid.c +@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report) + * we just need to setup the input fields, so using + * hid_report_raw_event is safe. + */ +- hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1); ++ hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1); + } + + static void gb_hid_init_reports(struct gb_hid *ghid) +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 058ba486fdcf87..c57fc6a918c030 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -1188,8 +1188,8 @@ static inline u32 hid_report_len(struct hid_report *report) + return DIV_ROUND_UP(report->size, 8) + (report->id > 0); + } + +-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, +- int interrupt); ++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, ++ size_t bufsize, u32 size, int interrupt); + + /* HID quirks API */ + unsigned long hid_lookup_quirk(const struct hid_device *hdev); +-- +2.53.0 + diff --git a/queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch b/queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch new file mode 100644 index 0000000000..13702320f1 --- /dev/null +++ b/queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch @@ -0,0 +1,324 @@ +From 0c2113155aab5f8b42a34c4826eb5ba91fdd139a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 08:32:45 +0000 +Subject: netfilter: nf_tables: restore set elements when delete set fails + +From: Pablo Neira Ayuso + +[ Upstream commit e79b47a8615d42c68aaeb68971593333667382ed ] + +>From abort path, nft_mapelem_activate() needs to restore refcounters to +the original state. Currently, it uses the set->ops->walk() to iterate +over these set elements. The existing set iterator skips inactive +elements in the next generation, this does not work from the abort path +to restore the original state since it has to skip active elements +instead (not inactive ones). + +This patch moves the check for inactive elements to the set iterator +callback, then it reverses the logic for the .activate case which +needs to skip active elements. + +Toggle next generation bit for elements when delete set command is +invoked and call nft_clear() from .activate (abort) path to restore the +next generation bit. + +The splat below shows an object in mappings memleak: + +[43929.457523] ------------[ cut here ]------------ +[43929.457532] WARNING: CPU: 0 PID: 1139 at include/net/netfilter/nf_tables.h:1237 nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] +[...] +[43929.458014] RIP: 0010:nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] +[43929.458076] Code: 83 f8 01 77 ab 49 8d 7c 24 08 e8 37 5e d0 de 49 8b 6c 24 08 48 8d 7d 50 e8 e9 5c d0 de 8b 45 50 8d 50 ff 89 55 50 85 c0 75 86 <0f> 0b eb 82 0f 0b eb b3 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 +[43929.458081] RSP: 0018:ffff888140f9f4b0 EFLAGS: 00010246 +[43929.458086] RAX: 0000000000000000 RBX: ffff8881434f5288 RCX: dffffc0000000000 +[43929.458090] RDX: 00000000ffffffff RSI: ffffffffa26d28a7 RDI: ffff88810ecc9550 +[43929.458093] RBP: ffff88810ecc9500 R08: 0000000000000001 R09: ffffed10281f3e8f +[43929.458096] R10: 0000000000000003 R11: ffff0000ffff0000 R12: ffff8881434f52a0 +[43929.458100] R13: ffff888140f9f5f4 R14: ffff888151c7a800 R15: 0000000000000002 +[43929.458103] FS: 00007f0c687c4740(0000) GS:ffff888390800000(0000) knlGS:0000000000000000 +[43929.458107] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[43929.458111] CR2: 00007f58dbe5b008 CR3: 0000000123602005 CR4: 00000000001706f0 +[43929.458114] Call Trace: +[43929.458118] +[43929.458121] ? __warn+0x9f/0x1a0 +[43929.458127] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] +[43929.458188] ? report_bug+0x1b1/0x1e0 +[43929.458196] ? handle_bug+0x3c/0x70 +[43929.458200] ? exc_invalid_op+0x17/0x40 +[43929.458211] ? nft_setelem_data_deactivate+0xd7/0xf0 [nf_tables] +[43929.458271] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] +[43929.458332] nft_mapelem_deactivate+0x24/0x30 [nf_tables] +[43929.458392] nft_rhash_walk+0xdd/0x180 [nf_tables] +[43929.458453] ? __pfx_nft_rhash_walk+0x10/0x10 [nf_tables] +[43929.458512] ? rb_insert_color+0x2e/0x280 +[43929.458520] nft_map_deactivate+0xdc/0x1e0 [nf_tables] +[43929.458582] ? __pfx_nft_map_deactivate+0x10/0x10 [nf_tables] +[43929.458642] ? __pfx_nft_mapelem_deactivate+0x10/0x10 [nf_tables] +[43929.458701] ? __rcu_read_unlock+0x46/0x70 +[43929.458709] nft_delset+0xff/0x110 [nf_tables] +[43929.458769] nft_flush_table+0x16f/0x460 [nf_tables] +[43929.458830] nf_tables_deltable+0x501/0x580 [nf_tables] + +Fixes: 628bd3e49cba ("netfilter: nf_tables: drop map element references from preparation phase") +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit e79b47a8615d42c68aaeb68971593333667382ed) +[Vegard: CVE-2024-27012; fixed conflicts due to missing commits + 0e1ea651c9717ddcd8e0648d8468477a31867b0a ("netfilter: nf_tables: shrink + memory consumption of set elements") and + 9dad402b89e81a0516bad5e0ac009b7a0a80898f ("netfilter: nf_tables: expose + opaque set element as struct nft_elem_priv") so we pass the correct types + and values to nft_setelem_data_deactivate(), nft_setelem_validate(), + nft_set_elem_ext(), etc.] +Signed-off-by: Vegard Nossum +Signed-off-by: Greg Kroah-Hartman +[acsjakub: clean cherry-pick of the commit 164936b2fc88 + ("netfilter: nf_tables: restore set elements when delete set fails") + from 6.6.y. Plus, add "[ Upstream commit .." header to the message] +Signed-off-by: Jakub Acs +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 41 ++++++++++++++++++++++++++++++---- + net/netfilter/nft_set_bitmap.c | 4 +--- + net/netfilter/nft_set_hash.c | 8 ++----- + net/netfilter/nft_set_pipapo.c | 5 +---- + net/netfilter/nft_set_rbtree.c | 4 +--- + 5 files changed, 42 insertions(+), 20 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 0c422428263873..201e2cc0453992 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) + { ++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); ++ ++ if (!nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ ++ nft_set_elem_change_active(ctx->net, set, ext); + nft_setelem_data_deactivate(ctx->net, set, elem); + + return 0; +@@ -619,6 +625,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx, + continue; + + elem.priv = catchall->elem; ++ nft_set_elem_change_active(ctx->net, set, ext); + nft_setelem_data_deactivate(ctx->net, set, &elem); + break; + } +@@ -3593,6 +3600,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, + const struct nft_data *data; + int err; + ++ if (!nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ + if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && + *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END) + return 0; +@@ -3616,19 +3626,22 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, + + int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set) + { +- u8 genmask = nft_genmask_next(ctx->net); ++ struct nft_set_iter dummy_iter = { ++ .genmask = nft_genmask_next(ctx->net), ++ }; + struct nft_set_elem_catchall *catchall; + struct nft_set_elem elem; ++ + struct nft_set_ext *ext; + int ret = 0; + + list_for_each_entry_rcu(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); +- if (!nft_set_elem_active(ext, genmask)) ++ if (!nft_set_elem_active(ext, dummy_iter.genmask)) + continue; + + elem.priv = catchall->elem; +- ret = nft_setelem_validate(ctx, set, NULL, &elem); ++ ret = nft_setelem_validate(ctx, set, &dummy_iter, &elem); + if (ret < 0) + return ret; + } +@@ -5103,6 +5116,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) + { ++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); ++ ++ if (!nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ + return nft_setelem_data_validate(ctx, set, elem); + } + +@@ -5197,6 +5215,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) + { ++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); ++ ++ /* called from abort path, reverse check to undo changes. */ ++ if (nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ ++ nft_clear(ctx->net, ext); + nft_setelem_data_activate(ctx->net, set, elem); + + return 0; +@@ -5215,6 +5240,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx, + if (nft_set_elem_active(ext, genmask)) + continue; + ++ nft_clear(ctx->net, ext); + elem.priv = catchall->elem; + nft_setelem_data_activate(ctx->net, set, &elem); + break; +@@ -5488,6 +5514,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx, + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); + struct nft_set_dump_args *args; + ++ if (!nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ + if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext)) + return 0; + +@@ -6220,7 +6249,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set, + struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); + + if (nft_setelem_is_catchall(set, elem)) { +- nft_set_elem_change_active(net, set, ext); ++ nft_clear(net, ext); + } else { + set->ops->activate(net, set, elem); + } +@@ -6902,9 +6931,13 @@ static int nft_setelem_flush(const struct nft_ctx *ctx, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) + { ++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); + struct nft_trans *trans; + int err; + ++ if (!nft_set_elem_active(ext, iter->genmask)) ++ return 0; ++ + trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM, + sizeof(struct nft_trans_elem), GFP_ATOMIC); + if (!trans) +diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c +index 1e5e7a181e0bc2..cbf7f7825f1b88 100644 +--- a/net/netfilter/nft_set_bitmap.c ++++ b/net/netfilter/nft_set_bitmap.c +@@ -171,7 +171,7 @@ static void nft_bitmap_activate(const struct net *net, + nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off); + /* Enter 11 state. */ + priv->bitmap[idx] |= (genmask << off); +- nft_set_elem_change_active(net, set, &be->ext); ++ nft_clear(net, &be->ext); + } + + static bool nft_bitmap_flush(const struct net *net, +@@ -223,8 +223,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx, + list_for_each_entry_rcu(be, &priv->list, head) { + if (iter->count < iter->skip) + goto cont; +- if (!nft_set_elem_active(&be->ext, iter->genmask)) +- goto cont; + + elem.priv = be; + +diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c +index 9ea4a09903186d..5a74ee4b7dfb35 100644 +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -196,7 +196,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set, + { + struct nft_rhash_elem *he = elem->priv; + +- nft_set_elem_change_active(net, set, &he->ext); ++ nft_clear(net, &he->ext); + } + + static bool nft_rhash_flush(const struct net *net, +@@ -285,8 +285,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, + + if (iter->count < iter->skip) + goto cont; +- if (!nft_set_elem_active(&he->ext, iter->genmask)) +- goto cont; + + elem.priv = he; + +@@ -615,7 +613,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set, + { + struct nft_hash_elem *he = elem->priv; + +- nft_set_elem_change_active(net, set, &he->ext); ++ nft_clear(net, &he->ext); + } + + static bool nft_hash_flush(const struct net *net, +@@ -669,8 +667,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set, + hlist_for_each_entry_rcu(he, &priv->table[i], node) { + if (iter->count < iter->skip) + goto cont; +- if (!nft_set_elem_active(&he->ext, iter->genmask)) +- goto cont; + + elem.priv = he; + +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index cfd0d020f3382b..11473275c6e263 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -1849,7 +1849,7 @@ static void nft_pipapo_activate(const struct net *net, + { + struct nft_pipapo_elem *e = elem->priv; + +- nft_set_elem_change_active(net, set, &e->ext); ++ nft_clear(net, &e->ext); + } + + /** +@@ -2151,9 +2151,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, + + e = f->mt[r].e; + +- if (!nft_set_elem_active(&e->ext, iter->genmask)) +- goto cont; +- + elem.priv = e; + + iter->err = iter->fn(ctx, set, iter, &elem); +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 426becaad1b94f..23e4e656f7f0cb 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -548,7 +548,7 @@ static void nft_rbtree_activate(const struct net *net, + { + struct nft_rbtree_elem *rbe = elem->priv; + +- nft_set_elem_change_active(net, set, &rbe->ext); ++ nft_clear(net, &rbe->ext); + } + + static bool nft_rbtree_flush(const struct net *net, +@@ -618,8 +618,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, + + if (iter->count < iter->skip) + goto cont; +- if (!nft_set_elem_active(&rbe->ext, iter->genmask)) +- goto cont; + + elem.priv = rbe; + +-- +2.53.0 + diff --git a/queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch b/queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch new file mode 100644 index 0000000000..acc7ab8db1 --- /dev/null +++ b/queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch @@ -0,0 +1,62 @@ +From f5a021ea66314b5bed31babffaf56d5c1df1570b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 16:27:15 +0300 +Subject: RDMA/rxe: Complete the rxe_cleanup_task backport + +From: Vladislav Nikolaev + +No upstream commit exists for this patch. + +The issue was introduced with backporting upstream commit b2b1ddc45745 +("RDMA/rxe: Fix the error "trying to register non-static key in +rxe_cleanup_task"") to the 6.1 stable tree as commit 3236221bb8e4 +("RDMA/rxe: Fix the error "trying to register non-static key in +rxe_cleanup_task""). + +The 6.1 backport guarded qp->req.task and qp->comp.task before calling +rxe_cleanup_task(), but left qp->resp.task unguarded. It also kept the +responder task cleanup before deleting the RC timers, while upstream had +already moved it after the timer shutdown by commit 960ebe97e523 +("RDMA/rxe: Remove __rxe_do_task()"). + +In the 6.1 tree, rxe_qp_from_init() calls rxe_qp_init_req() before +rxe_qp_init_resp(). Therefore, if rxe_qp_init_req() fails, cleanup can +run before qp->resp.task has been initialized by rxe_init_task(), and the +unconditional rxe_cleanup_task(&qp->resp.task) can still hit the same +uninitialized task lock problem that upstream commit b2b1ddc45745 fixed. + +Move responder task cleanup after deleting the RC timers, matching the +upstream cleanup order, and guard it with qp->resp.task.func like the +requester and completer tasks. + +Fixes: 3236221bb8e4 ("RDMA/rxe: Fix the error "trying to register non-static key in rxe_cleanup_task"") +Signed-off-by: Vladislav Nikolaev +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_qp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index 709c63e9773c5f..171c0f4dcbecfc 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -781,13 +781,15 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + + qp->valid = 0; + qp->qp_timeout_jiffies = 0; +- rxe_cleanup_task(&qp->resp.task); + + if (qp_type(qp) == IB_QPT_RC) { + del_timer_sync(&qp->retrans_timer); + del_timer_sync(&qp->rnr_nak_timer); + } + ++ if (qp->resp.task.func) ++ rxe_cleanup_task(&qp->resp.task); ++ + if (qp->req.task.func) + rxe_cleanup_task(&qp->req.task); + +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 6687d865a1..8a3815650b 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -177,3 +177,11 @@ drm-amdkfd-check-for-pdd-drm-file-first-in-criu-restore-path.patch serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch serial-zs-fix-bootconsole-handover-lockup.patch serial-zs-switch-to-using-channel-reset.patch +hid-core-add-printk_ratelimited-variants-to-hid_warn.patch +hid-pass-the-buffer-size-to-hid_report_raw_event.patch +hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch +rdma-rxe-complete-the-rxe_cleanup_task-backport.patch +usb-serial-digi_acceleport-fix-memory-corruption-wit.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch +netfilter-nf_tables-restore-set-elements-when-delete.patch +usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch diff --git a/queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch new file mode 100644 index 0000000000..fc95322f85 --- /dev/null +++ b/queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch @@ -0,0 +1,46 @@ +From b8614b05f2dfc9139fc9ee77073ef49541fe7aae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:36:36 +0200 +Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint + +From: Johan Hovold + +commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream. + +Make sure that the interrupt-out endpoint max packet size is at least +eight bytes to avoid user-controlled slab corruption or NULL-pointer +dereference should a malicious device report a smaller size. + +Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size") +Cc: stable@vger.kernel.org # 2.6.26 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ johan: adjust context for 6.18 ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 4c625e77da3a8f..f567617c8f2314 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -448,6 +448,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + return -ENODEV; + } + ++ /* ++ * The buffer must be large enough for the one or two-byte header (and ++ * following data), but assume anything smaller than eight bytes is ++ * broken. ++ */ ++ if (port->interrupt_out_size < 8) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch new file mode 100644 index 0000000000..86bf4a6a54 --- /dev/null +++ b/queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch @@ -0,0 +1,67 @@ +From a00cc119bbd9e7377e959199a8b97226e4145d56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 14:07:58 +0200 +Subject: USB: serial: digi_acceleport: fix memory corruption with small + endpoints + +From: Johan Hovold + +commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream. + +Add the missing bulk-out buffer size sanity checks to avoid +out-of-bounds memory accesses or slab corruption should a malicious +device report smaller buffers than expected. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index 45d688e9b93f68..eb23f7bb41e728 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1230,15 +1230,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + static int digi_startup(struct usb_serial *serial) + { + struct digi_serial *serial_priv; ++ int oob_port_num; + int ret; ++ int i; ++ ++ /* ++ * The port bulk-out buffers must be large enough for header and ++ * buffered data. ++ */ ++ for (i = 0; i < serial->type->num_ports; i++) { ++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2) ++ return -EINVAL; ++ } ++ ++ /* ++ * The OOB port bulk-out buffer must be large enough for the two ++ * commands in digi_set_modem_signals(). ++ */ ++ oob_port_num = serial->type->num_ports; ++ if (serial->port[oob_port_num]->bulk_out_size < 8) ++ return -EINVAL; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; + + spin_lock_init(&serial_priv->ds_serial_lock); +- serial_priv->ds_oob_port_num = serial->type->num_ports; +- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; ++ serial_priv->ds_oob_port_num = oob_port_num; ++ serial_priv->ds_oob_port = serial->port[oob_port_num]; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); +-- +2.53.0 + diff --git a/queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..3a057fb469 --- /dev/null +++ b/queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,188 @@ +From 1bf08213d392dc0615d0d32a248e4550a39ad722 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:13 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 6.1.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, and omit the newer Tegra234 entry. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 14a772feab7946..0f936aeb88d064 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -210,6 +210,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + }; + + struct tegra_xusb_context { +@@ -1211,14 +1212,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off"); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1229,42 +1233,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2289,6 +2295,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2325,6 +2332,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2366,6 +2374,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .mbox = { + .cmd = 0xe4, + .data_in = 0xe8, +@@ -2397,6 +2406,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .mbox = { + .cmd = 0x68, + .data_in = 0x6c, +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index d7cf1d2ab6..223bcd70f9 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -259,3 +259,6 @@ serial-dz-convert-to-use-a-platform-device.patch serial-zs-fix-bootconsole-handover-lockup.patch serial-zs-switch-to-using-channel-reset.patch serial-zs-convert-to-use-a-platform-device.patch +usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch +usb-serial-digi_acceleport-fix-memory-corruption-wit.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch new file mode 100644 index 0000000000..4ac4628cd7 --- /dev/null +++ b/queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch @@ -0,0 +1,46 @@ +From d9ba47331e8a007280c5aa74ae6614463406ca7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:36:36 +0200 +Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint + +From: Johan Hovold + +commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream. + +Make sure that the interrupt-out endpoint max packet size is at least +eight bytes to avoid user-controlled slab corruption or NULL-pointer +dereference should a malicious device report a smaller size. + +Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size") +Cc: stable@vger.kernel.org # 2.6.26 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ johan: adjust context for 6.18 ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index eb47f35aab0ced..905f6a560e0455 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -445,6 +445,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + return -ENODEV; + } + ++ /* ++ * The buffer must be large enough for the one or two-byte header (and ++ * following data), but assume anything smaller than eight bytes is ++ * broken. ++ */ ++ if (port->interrupt_out_size < 8) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch new file mode 100644 index 0000000000..70640c9e0e --- /dev/null +++ b/queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch @@ -0,0 +1,67 @@ +From 92801d79c243b81292c22855b7bd31a9965db8f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 14:07:58 +0200 +Subject: USB: serial: digi_acceleport: fix memory corruption with small + endpoints + +From: Johan Hovold + +commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream. + +Add the missing bulk-out buffer size sanity checks to avoid +out-of-bounds memory accesses or slab corruption should a malicious +device report smaller buffers than expected. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index a064859654121d..a876d6629b65d1 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1229,15 +1229,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + static int digi_startup(struct usb_serial *serial) + { + struct digi_serial *serial_priv; ++ int oob_port_num; + int ret; ++ int i; ++ ++ /* ++ * The port bulk-out buffers must be large enough for header and ++ * buffered data. ++ */ ++ for (i = 0; i < serial->type->num_ports; i++) { ++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2) ++ return -EINVAL; ++ } ++ ++ /* ++ * The OOB port bulk-out buffer must be large enough for the two ++ * commands in digi_set_modem_signals(). ++ */ ++ oob_port_num = serial->type->num_ports; ++ if (serial->port[oob_port_num]->bulk_out_size < 8) ++ return -EINVAL; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; + + spin_lock_init(&serial_priv->ds_serial_lock); +- serial_priv->ds_oob_port_num = serial->type->num_ports; +- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; ++ serial_priv->ds_oob_port_num = oob_port_num; ++ serial_priv->ds_oob_port = serial->port[oob_port_num]; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); +-- +2.53.0 + diff --git a/queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..e928e4f831 --- /dev/null +++ b/queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,197 @@ +From 78fd31285a78754d419d92a743c92caed3759571 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:09 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 6.12.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, and resolve context around the SoC ops/Tegra234 + entries. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++--------------- + 1 file changed, 45 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 89b3079194d7b3..2eb1aa25be1d37 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -243,6 +243,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + + bool has_bar2; + }; +@@ -1346,14 +1347,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off"); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1364,42 +1368,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2497,6 +2503,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2535,6 +2542,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2578,6 +2586,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2611,6 +2620,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0x68, +@@ -2643,6 +2653,7 @@ static const struct tegra_xusb_soc tegra234_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra234_ops, + .mbox = { + .cmd = XUSB_BAR2_ARU_MBOX_CMD, +-- +2.53.0 + diff --git a/queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch b/queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch new file mode 100644 index 0000000000..f6b7935fff --- /dev/null +++ b/queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch @@ -0,0 +1,68 @@ +From e54bf04a6ae276230f5364a9a2437c5b4696dabe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 15:41:01 +0200 +Subject: net: phy: micrel: fix LAN8814 QSGMII soft reset + +From: Robert Marko + +[ Upstream commit e027c218c482c6a0ae1948129ccda3b0a2033368 ] + +LAN8814 QSGMII soft reset was moved into the probe function to avoid +triggering it for each of 4 PHY-s in the package. + +However, that broke QSGMII link between the MAC and PHY on most LAN8814 +PHY-s, specificaly for us on the Microchip LAN969x switch. +Reading the QSGMII status registers it was visible that lanes were only +partially synced. + +It looks like the reset timing is crucial, so lets move the reset back +into the .config_init function but guard it with phy_package_init_once() +to avoid it being triggered on each of 4 PHY-s in the package. +Change the probe function to use phy_package_probe_once() for coma and PtP +setup. + +Fixes: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Robert Marko +Link: https://patch.msgid.link/20260428134138.1741253-1-robert.marko@sartura.hr +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index bc19880107ae42..e6f00aa9a99010 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -4389,6 +4389,13 @@ static int lan8814_config_init(struct phy_device *phydev) + { + struct kszphy_priv *lan8814 = phydev->priv; + ++ if (phy_package_init_once(phydev)) ++ /* Reset the PHY */ ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); ++ + /* Disable ANEG with QSGMII PCS Host side */ + lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG, +@@ -4473,13 +4480,7 @@ static int lan8814_probe(struct phy_device *phydev) + devm_phy_package_join(&phydev->mdio.dev, phydev, + addr, sizeof(struct lan8814_shared_priv)); + +- if (phy_package_init_once(phydev)) { +- /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, +- LAN8814_QSGMII_SOFT_RESET, +- LAN8814_QSGMII_SOFT_RESET_BIT, +- LAN8814_QSGMII_SOFT_RESET_BIT); +- ++ if (phy_package_probe_once(phydev)) { + err = lan8814_release_coma_mode(phydev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 5c4bf834c9..dd2be7c583 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -308,3 +308,5 @@ hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch mm-slub-hold-cpus_read_lock-around-flush_rcu_sheaves_on_cache.patch +net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..522c4288ed --- /dev/null +++ b/queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,197 @@ +From addb52fab7c2e7217a5fd8707d34e42eccd4c165 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:07 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 6.18.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, preserve str_on_off(), and resolve context around the + SoC ops/Tegra234 entries. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++--------------- + 1 file changed, 45 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 83b1766ff1521b..b0dcdede1fc8e6 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -247,6 +247,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + + bool has_bar2; + }; +@@ -1352,14 +1353,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode)); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", str_on_off(host_mode)); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1370,42 +1374,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2558,6 +2564,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2596,6 +2603,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2639,6 +2647,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2672,6 +2681,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0x68, +@@ -2705,6 +2715,7 @@ static const struct tegra_xusb_soc tegra234_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra234_ops, + .mbox = { + .cmd = XUSB_BAR2_ARU_MBOX_CMD, +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch b/queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch new file mode 100644 index 0000000000..06dafeab70 --- /dev/null +++ b/queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch @@ -0,0 +1,84 @@ +From ca8a35121e0f51f8d597f6e6abdbc5dd719851d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 11:52:29 +0200 +Subject: Bluetooth: hci_sync: fix UAF in hci_le_create_cis_sync + +From: Doruk Tan Ozturk + +[ Upstream commit bfea6091e0fffb270c20e74384b660910277eb6c ] + +hci_le_create_cis_sync() dereferences conn->conn_timeout after releasing +both rcu_read_lock() and hci_dev_lock(hdev). The conn pointer was +obtained from an RCU-protected iteration over hdev->conn_hash.list and +is not valid once these locks are dropped. A concurrent disconnect can +free the hci_conn between the unlock and the dereference, causing a +use-after-free read. + +The cancellation mechanism in hci_conn_del() cannot prevent this because +hci_le_create_cis_pending() queues hci_create_cis_sync with data=NULL: + + hci_cmd_sync_queue(hdev, hci_create_cis_sync, NULL, NULL); + +While hci_conn_del() dequeues with data=conn: + + hci_cmd_sync_dequeue(hdev, NULL, conn, NULL); + +Since NULL != conn, the lookup in _hci_cmd_sync_lookup_entry() never +matches, and the pending work item is not cancelled. + +Fix this by saving conn->conn_timeout into a local variable while the +locks are still held, so the stale conn pointer is never dereferenced +after unlock. + +This is the same class of bug as the one fixed by commit 035c25007c9e +("Bluetooth: hci_sync: Fix UAF on le_read_features_complete") which +addressed the identical pattern in a different function. + +This vulnerability was identified using 0sec.ai, an open-source +automated security auditing platform (https://github.com/0sec-labs). + +Fixes: c09b80be6ffc ("Bluetooth: hci_conn: Fix not waiting for HCI_EVT_LE_CIS_ESTABLISHED") +Cc: stable@vger.kernel.org +Reported-by: Doruk Tan Ozturk +Signed-off-by: Doruk Tan Ozturk +Signed-off-by: Luiz Augusto von Dentz +[doruk: adjust context for 6.6 \u2014 open-coded cmd struct instead of + DEFINE_FLEX, num_cis tracked via cmd.cp.num_cis] +Signed-off-by: Doruk Tan Ozturk +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index a41cfc76e98bf1..7cba461b21de4f 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -6631,6 +6631,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + struct hci_cis cis[0x1f]; + } cmd; + struct hci_conn *conn; ++ u16 timeout = 0; + u8 cig = BT_ISO_QOS_CIG_UNSET; + + /* The spec allows only one pending LE Create CIS command at a time. If +@@ -6703,6 +6704,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + set_bit(HCI_CONN_CREATE_CIS, &conn->flags); + cis->acl_handle = cpu_to_le16(conn->parent->handle); + cis->cis_handle = cpu_to_le16(conn->handle); ++ timeout = conn->conn_timeout; + cmd.cp.num_cis++; + + if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis)) +@@ -6722,7 +6724,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + sizeof(cmd.cp) + sizeof(cmd.cis[0]) * + cmd.cp.num_cis, &cmd, + HCI_EVT_LE_CIS_ESTABLISHED, +- conn->conn_timeout, NULL); ++ timeout, NULL); + } + + int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle) +-- +2.53.0 + diff --git a/queue-6.6/landlock-fix-handling-of-disconnected-directories.patch b/queue-6.6/landlock-fix-handling-of-disconnected-directories.patch new file mode 100644 index 0000000000..e82b7417ea --- /dev/null +++ b/queue-6.6/landlock-fix-handling-of-disconnected-directories.patch @@ -0,0 +1,172 @@ +From 151919186817d3f00316eafd37a81b7e2f21db03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 18:16:18 +0800 +Subject: landlock: Fix handling of disconnected directories +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mickaël Salaün + +[ Upstream commit 49c9e09d961025b22e61ef9ad56aa1c21b6ce2f1 ] + +Disconnected files or directories can appear when they are visible and +opened from a bind mount, but have been renamed or moved from the source +of the bind mount in a way that makes them inaccessible from the mount +point (i.e. out of scope). + +Previously, access rights tied to files or directories opened through a +disconnected directory were collected by walking the related hierarchy +down to the root of the filesystem, without taking into account the +mount point because it couldn't be found. This could lead to +inconsistent access results, potential access right widening, and +hard-to-debug renames, especially since such paths cannot be printed. + +For a sandboxed task to create a disconnected directory, it needs to +have write access (i.e. FS_MAKE_REG, FS_REMOVE_FILE, and FS_REFER) to +the underlying source of the bind mount, and read access to the related +mount point. Because a sandboxed task cannot acquire more access +rights than those defined by its Landlock domain, this could lead to +inconsistent access rights due to missing permissions that should be +inherited from the mount point hierarchy, while inheriting permissions +from the filesystem hierarchy hidden by this mount point instead. + +Landlock now handles files and directories opened from disconnected +directories by taking into account the filesystem hierarchy when the +mount point is not found in the hierarchy walk, and also always taking +into account the mount point from which these disconnected directories +were opened. This ensures that a rename is not allowed if it would +widen access rights [1]. + +The rationale is that, even if disconnected hierarchies might not be +visible or accessible to a sandboxed task, relying on the collected +access rights from them improves the guarantee that access rights will +not be widened during a rename because of the access right comparison +between the source and the destination (see LANDLOCK_ACCESS_FS_REFER). +It may look like this would grant more access on disconnected files and +directories, but the security policies are always enforced for all the +evaluated hierarchies. This new behavior should be less surprising to +users and safer from an access control perspective. + +Remove a wrong WARN_ON_ONCE() canary in collect_domain_accesses() and +fix the related comment. + +Because opened files have their access rights stored in the related file +security properties, there is no impact for disconnected or unlinked +files. + +Cc: Christian Brauner +Cc: Günther Noack +Cc: Song Liu +Reported-by: Tingmao Wang +Closes: https://lore.kernel.org/r/027d5190-b37a-40a8-84e9-4ccbc352bcdf@maowtm.org +Closes: https://lore.kernel.org/r/09b24128f86973a6022e6aa8338945fcfb9a33e4.1749925391.git.m@maowtm.org +Fixes: b91c3e4ea756 ("landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER") +Fixes: cb2c7d1a1776 ("landlock: Support filesystem access-control") +Link: https://lore.kernel.org/r/b0f46246-f2c5-42ca-93ce-0d629702a987@maowtm.org [1] +Reviewed-by: Tingmao Wang +Link: https://lore.kernel.org/r/20251128172200.760753-2-mic@digikod.net +Signed-off-by: Mickaël Salaün +[ Adjust context ] +Signed-off-by: Bin Lan +Signed-off-by: Sasha Levin +--- + security/landlock/errata/abi-1.h | 16 +++++++++++++ + security/landlock/fs.c | 40 +++++++++++++++++++++++--------- + 2 files changed, 45 insertions(+), 11 deletions(-) + create mode 100644 security/landlock/errata/abi-1.h + +diff --git a/security/landlock/errata/abi-1.h b/security/landlock/errata/abi-1.h +new file mode 100644 +index 00000000000000..e8a2bff2e5b6a8 +--- /dev/null ++++ b/security/landlock/errata/abi-1.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++/** ++ * DOC: erratum_3 ++ * ++ * Erratum 3: Disconnected directory handling ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * This fix addresses an issue with disconnected directories that occur when a ++ * directory is moved outside the scope of a bind mount. The change ensures ++ * that evaluated access rights include both those from the disconnected file ++ * hierarchy down to its filesystem root and those from the related mount point ++ * hierarchy. This prevents access right widening through rename or link ++ * actions. ++ */ ++LANDLOCK_ERRATUM(3) +diff --git a/security/landlock/fs.c b/security/landlock/fs.c +index fe4622d88eb15e..7145162f1e5971 100644 +--- a/security/landlock/fs.c ++++ b/security/landlock/fs.c +@@ -616,19 +616,31 @@ static bool is_access_to_paths_allowed( + break; + } + } ++ + if (unlikely(IS_ROOT(walker_path.dentry))) { ++ if (likely(walker_path.mnt->mnt_flags & MNT_INTERNAL)) { ++ /* ++ * Stops and allows access when reaching disconnected root ++ * directories that are part of internal filesystems (e.g. nsfs, ++ * which is reachable through /proc//ns/). ++ */ ++ allowed_parent1 = true; ++ allowed_parent2 = true; ++ break; ++ } ++ + /* +- * Stops at disconnected root directories. Only allows +- * access to internal filesystems (e.g. nsfs, which is +- * reachable through /proc//ns/). ++ * We reached a disconnected root directory from a bind mount. ++ * Let's continue the walk with the mount point we missed. + */ +- allowed_parent1 = allowed_parent2 = +- !!(walker_path.mnt->mnt_flags & MNT_INTERNAL); +- break; ++ dput(walker_path.dentry); ++ walker_path.dentry = walker_path.mnt->mnt_root; ++ dget(walker_path.dentry); ++ } else { ++ parent_dentry = dget_parent(walker_path.dentry); ++ dput(walker_path.dentry); ++ walker_path.dentry = parent_dentry; + } +- parent_dentry = dget_parent(walker_path.dentry); +- dput(walker_path.dentry); +- walker_path.dentry = parent_dentry; + } + path_put(&walker_path); + +@@ -705,6 +717,9 @@ static inline access_mask_t maybe_remove(const struct dentry *const dentry) + * file. While walking from @dir to @mnt_root, we record all the domain's + * allowed accesses in @layer_masks_dom. + * ++ * Because of disconnected directories, this walk may not reach @mnt_dir. In ++ * this case, the walk will continue to @mnt_dir after this call. ++ * + * This is similar to is_access_to_paths_allowed() but much simpler because it + * only handles walking on the same mount point and only checks one set of + * accesses. +@@ -744,8 +759,11 @@ static bool collect_domain_accesses( + break; + } + +- /* We should not reach a root other than @mnt_root. */ +- if (dir == mnt_root || WARN_ON_ONCE(IS_ROOT(dir))) ++ /* ++ * Stops at the mount point or the filesystem root for a disconnected ++ * directory. ++ */ ++ if (dir == mnt_root || unlikely(IS_ROOT(dir))) + break; + + parent_dentry = dget_parent(dir); +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index c84d96a748..726695120e 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -189,3 +189,9 @@ drm-amdkfd-check-for-pdd-drm-file-first-in-criu-restore-path.patch serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch serial-zs-fix-bootconsole-handover-lockup.patch serial-zs-switch-to-using-channel-reset.patch +usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch +bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch +x86-kexec-disable-kcov-instrumentation-after-load_se.patch +landlock-fix-handling-of-disconnected-directories.patch +usb-serial-digi_acceleport-fix-memory-corruption-wit.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch new file mode 100644 index 0000000000..ed656e67b1 --- /dev/null +++ b/queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch @@ -0,0 +1,46 @@ +From 3816ad8c11165edeaf9e5e5c43e4029529cd1cf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 10:36:36 +0200 +Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint + +From: Johan Hovold + +commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream. + +Make sure that the interrupt-out endpoint max packet size is at least +eight bytes to avoid user-controlled slab corruption or NULL-pointer +dereference should a malicious device report a smaller size. + +Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size") +Cc: stable@vger.kernel.org # 2.6.26 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ johan: adjust context for 6.18 ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 4c625e77da3a8f..f567617c8f2314 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -448,6 +448,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + return -ENODEV; + } + ++ /* ++ * The buffer must be large enough for the one or two-byte header (and ++ * following data), but assume anything smaller than eight bytes is ++ * broken. ++ */ ++ if (port->interrupt_out_size < 8) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch new file mode 100644 index 0000000000..6d8037c13f --- /dev/null +++ b/queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch @@ -0,0 +1,67 @@ +From a860946615a082d8fe3cd3bf70b740766b1147d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 14:07:58 +0200 +Subject: USB: serial: digi_acceleport: fix memory corruption with small + endpoints + +From: Johan Hovold + +commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream. + +Add the missing bulk-out buffer size sanity checks to avoid +out-of-bounds memory accesses or slab corruption should a malicious +device report smaller buffers than expected. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index d1dea38505762c..5eac99407c1611 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1231,15 +1231,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + static int digi_startup(struct usb_serial *serial) + { + struct digi_serial *serial_priv; ++ int oob_port_num; + int ret; ++ int i; ++ ++ /* ++ * The port bulk-out buffers must be large enough for header and ++ * buffered data. ++ */ ++ for (i = 0; i < serial->type->num_ports; i++) { ++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2) ++ return -EINVAL; ++ } ++ ++ /* ++ * The OOB port bulk-out buffer must be large enough for the two ++ * commands in digi_set_modem_signals(). ++ */ ++ oob_port_num = serial->type->num_ports; ++ if (serial->port[oob_port_num]->bulk_out_size < 8) ++ return -EINVAL; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; + + spin_lock_init(&serial_priv->ds_serial_lock); +- serial_priv->ds_oob_port_num = serial->type->num_ports; +- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; ++ serial_priv->ds_oob_port_num = oob_port_num; ++ serial_priv->ds_oob_port = serial->port[oob_port_num]; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); +-- +2.53.0 + diff --git a/queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch b/queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch new file mode 100644 index 0000000000..d0abc25dad --- /dev/null +++ b/queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch @@ -0,0 +1,92 @@ +From 0dbde02c2ae38a48c3fe38c4031ed099484e86bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 08:30:31 +0800 +Subject: x86/kexec: Disable KCOV instrumentation after load_segments() + +From: Aleksandr Nogikh + +[ Upstream commit 917e3ad3321e75ca0223d5ccf26ceda116aa51e1 ] + +The load_segments() function changes segment registers, invalidating GS base +(which KCOV relies on for per-cpu data). When CONFIG_KCOV is enabled, any +subsequent instrumented C code call (e.g. native_gdt_invalidate()) begins +crashing the kernel in an endless loop. + +To reproduce the problem, it's sufficient to do kexec on a KCOV-instrumented +kernel: + + $ kexec -l /boot/otherKernel + $ kexec -e + +The real-world context for this problem is enabling crash dump collection in +syzkaller. For this, the tool loads a panic kernel before fuzzing and then +calls makedumpfile after the panic. This workflow requires both CONFIG_KEXEC +and CONFIG_KCOV to be enabled simultaneously. + +Adding safeguards directly to the KCOV fast-path (__sanitizer_cov_trace_pc()) +is also undesirable as it would introduce an extra performance overhead. + +Disabling instrumentation for the individual functions would be too fragile, +so disable KCOV instrumentation for the entire machine_kexec_64.c and +physaddr.c. If coverage-guided fuzzing ever needs these components in the +future, other approaches should be considered. + +The problem is not relevant for 32 bit kernels as CONFIG_KCOV is not supported +there. + + [ bp: Space out comment for better readability. ] + +Fixes: 0d345996e4cb ("x86/kernel: increase kcov coverage under arch/x86/kernel folder") +Signed-off-by: Aleksandr Nogikh +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Dmitry Vyukov +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260325154825.551191-1-nogikh@google.com +Signed-off-by: Miles Wang <13621186580@139.com> +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/Makefile | 14 ++++++++++++++ + arch/x86/mm/Makefile | 2 ++ + 2 files changed, 16 insertions(+) + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 0000325ab98f4d..c1fe6c98d3f6e0 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -39,6 +39,20 @@ KMSAN_SANITIZE_nmi.o := n + KCOV_INSTRUMENT_head$(BITS).o := n + KCOV_INSTRUMENT_sev.o := n + ++# Disable KCOV to prevent crashes during kexec: load_segments() invalidates ++# the GS base, which KCOV relies on for per-CPU data. ++# ++# As KCOV and KEXEC compatibility should be preserved (e.g. syzkaller is ++# using it to collect crash dumps during kernel fuzzing), disabling ++# KCOV for KEXEC kernels is not an option. Selectively disabling KCOV ++# instrumentation for individual affected functions can be fragile, while ++# adding more checks to KCOV would slow it down. ++# ++# As a compromise solution, disable KCOV instrumentation for the whole ++# source code file. If its coverage is ever needed, other approaches ++# should be considered. ++KCOV_INSTRUMENT_machine_kexec_64.o := n ++ + CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace + + obj-y += head_$(BITS).o +diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile +index c80febc44cd2fe..dd78ec8758f17e 100644 +--- a/arch/x86/mm/Makefile ++++ b/arch/x86/mm/Makefile +@@ -5,6 +5,8 @@ KCOV_INSTRUMENT_mem_encrypt.o := n + KCOV_INSTRUMENT_mem_encrypt_amd.o := n + KCOV_INSTRUMENT_mem_encrypt_identity.o := n + KCOV_INSTRUMENT_pgprot.o := n ++# See the "Disable KCOV" comment in arch/x86/kernel/Makefile. ++KCOV_INSTRUMENT_physaddr.o := n + + KASAN_SANITIZE_mem_encrypt.o := n + KASAN_SANITIZE_mem_encrypt_amd.o := n +-- +2.53.0 + diff --git a/queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..dd6aa4980e --- /dev/null +++ b/queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,197 @@ +From d2d8ae5eaf9546e76d9dd8119511eb3b6e081ade Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:19:11 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 6.6.y: keep the host-mode snapshot in the existing + tegra->lock section, retain pm_runtime_mark_last_busy() in the host + port-power path, and resolve context around the SoC ops/Tegra234 + entries. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++--------------- + 1 file changed, 45 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 89b3079194d7b3..2eb1aa25be1d37 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -243,6 +243,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + + bool has_bar2; + }; +@@ -1346,14 +1347,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off"); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1364,42 +1368,44 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); +- pm_runtime_mark_last_busy(tegra->dev); ++ tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2497,6 +2503,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2535,6 +2542,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2578,6 +2586,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2611,6 +2620,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0x68, +@@ -2643,6 +2653,7 @@ static const struct tegra_xusb_soc tegra234_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra234_ops, + .mbox = { + .cmd = XUSB_BAR2_ARU_MBOX_CMD, +-- +2.53.0 + diff --git a/queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch b/queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch new file mode 100644 index 0000000000..ee25483c53 --- /dev/null +++ b/queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch @@ -0,0 +1,68 @@ +From 053fa58cc11c8f2a0fda1c48d4f3a410d6aa49db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 15:41:01 +0200 +Subject: net: phy: micrel: fix LAN8814 QSGMII soft reset + +From: Robert Marko + +[ Upstream commit e027c218c482c6a0ae1948129ccda3b0a2033368 ] + +LAN8814 QSGMII soft reset was moved into the probe function to avoid +triggering it for each of 4 PHY-s in the package. + +However, that broke QSGMII link between the MAC and PHY on most LAN8814 +PHY-s, specificaly for us on the Microchip LAN969x switch. +Reading the QSGMII status registers it was visible that lanes were only +partially synced. + +It looks like the reset timing is crucial, so lets move the reset back +into the .config_init function but guard it with phy_package_init_once() +to avoid it being triggered on each of 4 PHY-s in the package. +Change the probe function to use phy_package_probe_once() for coma and PtP +setup. + +Fixes: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Robert Marko +Link: https://patch.msgid.link/20260428134138.1741253-1-robert.marko@sartura.hr +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index c6b011a9d63698..23305be8c7fac7 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -4548,6 +4548,13 @@ static int lan8814_config_init(struct phy_device *phydev) + struct kszphy_priv *lan8814 = phydev->priv; + int ret; + ++ if (phy_package_init_once(phydev)) ++ /* Reset the PHY */ ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); ++ + /* Based on the interface type select how the advertise ability is + * encoded, to set as SGMII or as USGMII. + */ +@@ -4655,13 +4662,7 @@ static int lan8814_probe(struct phy_device *phydev) + priv->is_ptp_available = err == LAN8814_REV_LAN8814 || + err == LAN8814_REV_LAN8818; + +- if (phy_package_init_once(phydev)) { +- /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, +- LAN8814_QSGMII_SOFT_RESET, +- LAN8814_QSGMII_SOFT_RESET_BIT, +- LAN8814_QSGMII_SOFT_RESET_BIT); +- ++ if (phy_package_probe_once(phydev)) { + err = lan8814_release_coma_mode(phydev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-7.0/series b/queue-7.0/series index c3783d96f0..13f68c95ad 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -327,3 +327,5 @@ i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch +net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch +xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch diff --git a/queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch new file mode 100644 index 0000000000..ee9218136b --- /dev/null +++ b/queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch @@ -0,0 +1,194 @@ +From c760846a5e78bb06fd99efcbefd1293903a9c821 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:09:14 +0800 +Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug + +From: Wei-Cheng Chen + +[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ] + +When a USB device is unplugged from the dual-role port, the device-mode +path in tegra_xhci_id_work() explicitly clears both SS and HS port power +via direct hub_control ClearPortFeature(POWER) calls. This preempts the +xHCI controller's normal disconnect processing -- PORT_CSC is never +generated, the USB core never sees the disconnect, and the device remains +in its internal tree as a ghost visible in lsusb. + +Add an otg_set_port_power flag to control whether the dual-role switch +path performs explicit port power management. SoCs that need it +(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and +beyond) rely on the PHY mode change to handle disconnect naturally and +skip all port power calls. + +Within the port power path, otg_reset_sspi additionally gates the SSPI +reset sequence on host-mode entry for SoCs that require it. + +Flags set per SoC: + Tegra124, Tegra186 -> otg_set_port_power + Tegra210 -> otg_set_port_power, otg_reset_sspi + Tegra194 and later -> (none) + +[ Backport to 7.0.y: keep the host-mode snapshot in the existing + tegra->lock section, preserve str_on_off(), and resolve context around + the SoC ops/Tegra234 entries. ] + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable@vger.kernel.org +Signed-off-by: Wei-Cheng Chen +Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-tegra.c | 77 ++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 33 deletions(-) + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 3f6aa2440b05b9..ddc52d1e0edaf7 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -247,6 +247,7 @@ struct tegra_xusb_soc { + bool has_ipfs; + bool lpm_support; + bool otg_reset_sspi; ++ bool otg_set_port_power; + + bool has_bar2; + }; +@@ -1352,14 +1353,17 @@ static void tegra_xhci_id_work(struct work_struct *work) + struct tegra_xusb_mbox_msg msg; + struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", + tegra->otg_usb2_port); ++ bool host_mode; + u32 status; + int ret; + +- dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode)); +- + mutex_lock(&tegra->lock); + +- if (tegra->host_mode) ++ host_mode = tegra->host_mode; ++ ++ dev_dbg(tegra->dev, "host mode %s\n", str_on_off(host_mode)); ++ ++ if (host_mode) + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST); + else + phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE); +@@ -1370,41 +1374,43 @@ static void tegra_xhci_id_work(struct work_struct *work) + tegra->otg_usb2_port); + + pm_runtime_get_sync(tegra->dev); +- if (tegra->host_mode) { +- /* switch to host mode */ +- if (tegra->otg_usb3_port >= 0) { +- if (tegra->soc->otg_reset_sspi) { +- /* set PP=0 */ +- tegra_xhci_hc_driver.hub_control( +- xhci->shared_hcd, GetPortStatus, +- 0, tegra->otg_usb3_port+1, +- (char *) &status, sizeof(status)); +- if (status & USB_SS_PORT_STAT_POWER) +- tegra_xhci_set_port_power(tegra, false, +- false); +- +- /* reset OTG port SSPI */ +- msg.cmd = MBOX_CMD_RESET_SSPI; +- msg.data = tegra->otg_usb3_port+1; +- +- ret = tegra_xusb_mbox_send(tegra, &msg); +- if (ret < 0) { +- dev_info(tegra->dev, +- "failed to RESET_SSPI %d\n", +- ret); ++ if (tegra->soc->otg_set_port_power) { ++ if (host_mode) { ++ /* switch to host mode */ ++ if (tegra->otg_usb3_port >= 0) { ++ if (tegra->soc->otg_reset_sspi) { ++ /* set PP=0 */ ++ tegra_xhci_hc_driver.hub_control( ++ xhci->shared_hcd, GetPortStatus, ++ 0, tegra->otg_usb3_port+1, ++ (char *) &status, sizeof(status)); ++ if (status & USB_SS_PORT_STAT_POWER) ++ tegra_xhci_set_port_power(tegra, false, ++ false); ++ ++ /* reset OTG port SSPI */ ++ msg.cmd = MBOX_CMD_RESET_SSPI; ++ msg.data = tegra->otg_usb3_port+1; ++ ++ ret = tegra_xusb_mbox_send(tegra, &msg); ++ if (ret < 0) { ++ dev_info(tegra->dev, ++ "failed to RESET_SSPI %d\n", ++ ret); ++ } + } +- } + +- tegra_xhci_set_port_power(tegra, false, true); +- } ++ tegra_xhci_set_port_power(tegra, false, true); ++ } + +- tegra_xhci_set_port_power(tegra, true, true); ++ tegra_xhci_set_port_power(tegra, true, true); + +- } else { +- if (tegra->otg_usb3_port >= 0) +- tegra_xhci_set_port_power(tegra, false, false); ++ } else { ++ if (tegra->otg_usb3_port >= 0) ++ tegra_xhci_set_port_power(tegra, false, false); + +- tegra_xhci_set_port_power(tegra, true, false); ++ tegra_xhci_set_port_power(tegra, true, false); ++ } + } + pm_runtime_put_autosuspend(tegra->dev); + } +@@ -2557,6 +2563,7 @@ static const struct tegra_xusb_soc tegra124_soc = { + .scale_ss_clock = true, + .has_ipfs = true, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2595,6 +2602,7 @@ static const struct tegra_xusb_soc tegra210_soc = { + .scale_ss_clock = false, + .has_ipfs = true, + .otg_reset_sspi = true, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2638,6 +2646,7 @@ static const struct tegra_xusb_soc tegra186_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = true, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0xe4, +@@ -2671,6 +2680,7 @@ static const struct tegra_xusb_soc tegra194_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra124_ops, + .mbox = { + .cmd = 0x68, +@@ -2704,6 +2714,7 @@ static const struct tegra_xusb_soc tegra234_soc = { + .scale_ss_clock = false, + .has_ipfs = false, + .otg_reset_sspi = false, ++ .otg_set_port_power = false, + .ops = &tegra234_ops, + .mbox = { + .cmd = XUSB_BAR2_ARU_MBOX_CMD, +-- +2.53.0 + -- 2.47.3