From: Greg Kroah-Hartman Date: Mon, 13 Jul 2026 13:44:27 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0fd185ae12c40cabeeb2eb0c9fb9fddaae88702e;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: 6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holding-conn-ref.patch bluetooth-mgmt-fix-uaf-of-hci_conn_params-in-add_device_complete.patch coresight-etb10-restore-atomic_t-for-shared-reading-state.patch crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch debugobjects-plug-race-against-a-concurrent-oom-disable.patch fs-ntfs3-validate-dirty-page-table-capacity-in-log_replay-copy_lcns.patch gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch gpio-sch-use-raw_spinlock_t-in-the-irq-startup-path.patch hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch io_uring-nop-fix-file-reference-leak-with-iosqe_fixed_file.patch io_uring-rw-preserve-partial-result-for-iopoll.patch ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch ksmbd-fix-use-after-free-of-a-deferred-file_lock-on-smb2_close-then-smb2_cancel.patch media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch mm-damon-ops-common-handle-extreme-intervals-in-damon_hot_score.patch mm-shrinker-do-not-hold-rcu-lock-in-shrinker_debugfs_count_show.patch mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch mm-shrinker-fix-shrinker_info-teardown-race-with-expansion.patch mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch net-af_key-initialize-alg_key_len-for-ipcomp-states.patch net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch netpoll-fix-a-use-after-free-on-shutdown-path.patch ntb-epf-avoid-calling-pci_irq_vector-from-hardirq-context.patch smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch staging-media-ipu7-fix-double-free-and-use-after-free-in-error-paths.patch staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch staging-rtl8723bs-fix-oob-read-in-onassocrsp-ie-loop.patch staging-rtl8723bs-fix-oob-read-in-update_beacon_info-ie-loop.patch staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch staging-rtl8723bs-fix-oob-reads-in-is_ap_in_tkip-ie-loop.patch staging-rtl8723bs-fix-oob-write-in-ht_caps_handler.patch staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch staging-vme_user-bound-slave-read-write-to-the-kern_buf-size.patch staging-vme_user-fix-location-monitor-leak-in-fake-bridge.patch staging-vme_user-fix-location-monitor-leak-in-tsi148-bridge.patch tcp-restore-rcu-grace-period-in-tcp_ao_destroy_sock.patch tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch usb-dwc3-run-gadget-disconnect-from-sleepable-suspend-context.patch usb-misc-usbio-fix-disconnect-uaf-in-client-teardown.patch virtio-mmio-fix-device-release-warning-on-module-unload.patch virtio_pci-fix-vq-info-pointer-lookup-via-wrong-index.patch --- diff --git a/queue-6.18/6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch b/queue-6.18/6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch new file mode 100644 index 0000000000..0e38dc7784 --- /dev/null +++ b/queue-6.18/6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch @@ -0,0 +1,66 @@ +From 1720db928e5a58ca7d75ac1d514c3b73fd7061a7 Mon Sep 17 00:00:00 2001 +From: Yizhou Zhao +Date: Tue, 9 Jun 2026 16:00:52 +0800 +Subject: 6lowpan: fix NHC entry use-after-free on error path + +From: Yizhou Zhao + +commit 1720db928e5a58ca7d75ac1d514c3b73fd7061a7 upstream. + +lowpan_nhc_do_uncompression() looks up an NHC descriptor while holding +lowpan_nhc_lock. If the descriptor has no uncompress callback, the error +path drops the lock before printing nhc->name. + +lowpan_nhc_del() removes descriptors under the same lock and then relies +on synchronize_net() before the owning module can be unloaded. That only +waits for net RX RCU readers. lowpan_header_decompress() is also exported +and can be reached from callers that are not necessarily covered by the net +core RX critical section, for example the Bluetooth 6LoWPAN L2CAP receive +path. + +This leaves a race where one task drops lowpan_nhc_lock in the error path, +another task unregisters and frees the matching descriptor after +synchronize_net() returns, and the first task then dereferences nhc->name +for the warning. + +With the post-unlock window widened, KASAN reports: + + BUG: KASAN: slab-use-after-free in lowpan_nhc_do_uncompression+0x1f4/0x220 + Read of size 8 + lowpan_nhc_do_uncompression + lowpan_header_decompress + +Fix this by printing the warning before dropping lowpan_nhc_lock, so the +descriptor name is read while unregister is still excluded. The malformed +packet is still rejected with -ENOTSUPP. + +Fixes: 92aa7c65d295 ("6lowpan: add generic nhc layer interface") +Cc: stable@vger.kernel.org +Reported-by: Yizhou Zhao +Reported-by: Yuxiang Yang +Reported-by: Ao Wang +Reported-by: Xuewei Feng +Reported-by: Qi Li +Reported-by: Ke Xu +Signed-off-by: Yizhou Zhao +Acked-by: Alexander Aring +Link: https://patch.msgid.link/20260609080054.4541-1-zhaoyz24@mails.tsinghua.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/6lowpan/nhc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/6lowpan/nhc.c ++++ b/net/6lowpan/nhc.c +@@ -117,9 +117,9 @@ int lowpan_nhc_do_uncompression(struct s + return ret; + } + } else { +- spin_unlock_bh(&lowpan_nhc_lock); + netdev_warn(dev, "received nhc id for %s which is not implemented.\n", + nhc->name); ++ spin_unlock_bh(&lowpan_nhc_lock); + return -ENOTSUPP; + } + } else { diff --git a/queue-6.18/audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch b/queue-6.18/audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch new file mode 100644 index 0000000000..a620e8c8c4 --- /dev/null +++ b/queue-6.18/audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch @@ -0,0 +1,110 @@ +From c9a71daaecb2fb1d8c704545cc0b1c920b9bf5d7 Mon Sep 17 00:00:00 2001 +From: Chi Wang +Date: Fri, 19 Jun 2026 15:42:44 +0800 +Subject: audit: Fix data races of skb_queue_len() readers on audit_queue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chi Wang + +commit c9a71daaecb2fb1d8c704545cc0b1c920b9bf5d7 upstream. + +Multiple readers access audit_queue.qlen via skb_queue_len() without +holding the queue lock or using READ_ONCE(), while kauditd writes to +this field via the skb_dequeue() → __skb_unlink() path with WRITE_ONCE() +protected by a spinlock. This constitutes data races. + +All affected skb_queue_len(&audit_queue) call sites: + - kauditd_thread() wait_event_freezable() condition + - audit_receive_msg() AUDIT_GET handler (s.backlog assignment) + - audit_receive() backlog check + - audit_log_start() backlog check and pr_warn() + +KCSAN reports the following conflicting access pattern (one example): +================================================================== +BUG: KCSAN: data-race in audit_log_start / skb_dequeue + +write (marked) to 0xffffffff8512ee20 of 4 bytes by task 661 on cpu 57: + skb_dequeue+0x70/0xf0 + kauditd_send_queue+0x71/0x220 + kauditd_thread+0x1cb/0x430 + kthread+0x1c2/0x210 + ret_from_fork+0x162/0x1a0 + ret_from_fork_asm+0x1a/0x30 + +read to 0xffffffff8512ee20 of 4 bytes by task 36586 on cpu 1: + audit_log_start+0x2a0/0x6b0 + audit_core_dumps+0x64/0xa0 + do_coredump+0x14b/0x1260 + get_signal+0xeb2/0xf70 + arch_do_signal_or_restart+0x41/0x170 + exit_to_user_mode_loop+0xa2/0x1c0 + do_syscall_64+0x1a3/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0xe0 + +value changed: 0x00000001 -> 0x00000000 +================================================================== + +Resolve the race by switching to lockless helper skb_queue_len_lockless(), +which internally uses READ_ONCE() and properly pairs with the WRITE_ONCE() +write accesses already present on the writer side. + +Cc: stable@vger.kernel.org +Fixes: 3197542482df ("audit: rework audit_log_start()") +Signed-off-by: Chi Wang +Reviewed-by: Ricardo Robaina +[PM: line length tweak] +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + kernel/audit.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -946,7 +946,7 @@ main_queue: + * do the multicast send and rotate records from the + * main queue to the retry/hold queues */ + wait_event_freezable(kauditd_wait, +- (skb_queue_len(&audit_queue) ? 1 : 0)); ++ (skb_queue_len_lockless(&audit_queue) ? 1 : 0)); + } + + return 0; +@@ -1279,7 +1279,7 @@ static int audit_receive_msg(struct sk_b + s.rate_limit = audit_rate_limit; + s.backlog_limit = audit_backlog_limit; + s.lost = atomic_read(&audit_lost); +- s.backlog = skb_queue_len(&audit_queue); ++ s.backlog = skb_queue_len_lockless(&audit_queue); + s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; + s.backlog_wait_time = audit_backlog_wait_time; + s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual); +@@ -1622,7 +1622,7 @@ static void audit_receive(struct sk_buff + + /* can't block with the ctrl lock, so penalize the sender now */ + if (audit_backlog_limit && +- (skb_queue_len(&audit_queue) > audit_backlog_limit)) { ++ (skb_queue_len_lockless(&audit_queue) > audit_backlog_limit)) { + DECLARE_WAITQUEUE(wait, current); + + /* wake kauditd to try and flush the queue */ +@@ -1928,7 +1928,7 @@ struct audit_buffer *audit_log_start(str + long stime = audit_backlog_wait_time; + + while (audit_backlog_limit && +- (skb_queue_len(&audit_queue) > audit_backlog_limit)) { ++ (skb_queue_len_lockless(&audit_queue) > audit_backlog_limit)) { + /* wake kauditd to try and flush the queue */ + wake_up_interruptible(&kauditd_wait); + +@@ -1948,7 +1948,7 @@ struct audit_buffer *audit_log_start(str + } else { + if (audit_rate_check() && printk_ratelimit()) + pr_warn("audit_backlog=%d > audit_backlog_limit=%d\n", +- skb_queue_len(&audit_queue), ++ skb_queue_len_lockless(&audit_queue), + audit_backlog_limit); + audit_log_lost("backlog limit exceeded"); + return NULL; diff --git a/queue-6.18/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holding-conn-ref.patch b/queue-6.18/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holding-conn-ref.patch new file mode 100644 index 0000000000..96fa705fa3 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holding-conn-ref.patch @@ -0,0 +1,242 @@ +From b66774b48dd98f07254951f74ea6f513efe7ff8b Mon Sep 17 00:00:00 2001 +From: Marco Elver +Date: Fri, 5 Jun 2026 16:23:35 +0200 +Subject: Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref + +From: Marco Elver + +commit b66774b48dd98f07254951f74ea6f513efe7ff8b upstream. + +l2cap_chan_timeout() runs asynchronously and accesses chan->conn. If +the connection is torn down while the timer is running or pending, +chan->conn can be freed, leading to a use-after-free when the timer +worker attempts to lock conn->lock: + +| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| Write of size 8 at addr ffff8881298d9550 by task kworker/2:1/83 +| +| CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full) +| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 +| Workqueue: events l2cap_chan_timeout +| Call Trace: +| +| instrument_atomic_read_write include/linux/instrumented.h:112 [inline] +| atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline] +| __mutex_trylock_fast kernel/locking/mutex.c:161 [inline] +| mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318 +| l2cap_chan_timeout+0x5d/0x1b0 net/bluetooth/l2cap_core.c:422 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| +| Allocated by task 320: +| l2cap_conn_add+0xa7/0x820 net/bluetooth/l2cap_core.c:7075 +| l2cap_connect_cfm+0xdb/0xd70 net/bluetooth/l2cap_core.c:7452 +| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline] +| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760 +| hci_event_func net/bluetooth/hci_event.c:7796 [inline] +| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847 +| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040 +| process_one_work kernel/workqueue.c:3326 [inline] +| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409 +| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490 +| kthread+0x346/0x430 kernel/kthread.c:436 +| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158 +| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 +| +| Freed by task 322: +| hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline] +| hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736 +| hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405 +| hci_dev_do_close net/bluetooth/hci_core.c:502 [inline] +| hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679 +| vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690 +| __fput+0x369/0x890 fs/file_table.c:510 +| task_work_run+0x160/0x1d0 kernel/task_work.c:233 +| get_signal+0xf5b/0x1120 kernel/signal.c:2810 +| arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337 +| __exit_to_user_mode_loop kernel/entry/common.c:64 [inline] +| exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98 +| do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100 +| entry_SYSCALL_64_after_hwframe+0x77/0x7f +| +| The buggy address belongs to the object at ffff8881298d9400 +| which belongs to the cache kmalloc-512 of size 512 +| The buggy address is located 336 bytes inside of +| freed 512-byte region [ffff8881298d9400, ffff8881298d9600) + +Fix it by having chan->conn hold a reference to l2cap_conn (via +l2cap_conn_get) when the channel is added to the connection, and +releasing it in the channel destructor. This ensures the l2cap_conn +remains alive as long as the channel exists. + +A new FLAG_DEL channel flag is introduced to indicate that the channel +has been deleted from its connection. l2cap_chan_del() atomically sets +this flag using test_and_set_bit() instead of setting chan->conn to +NULL. All asynchronous workers (l2cap_chan_timeout, l2cap_ack_timeout, +l2cap_monitor_timeout, l2cap_retrans_timeout) and l2cap_chan_send() +check FLAG_DEL to determine whether the channel has been torn down, +rather than testing chan->conn for NULL. + +Fixes: 8c8e620467a7 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()") +Cc: +Cc: Siwei Zhang +Cc: Luiz Augusto von Dentz +Assisted-by: Gemini:gemini-3.1-pro-preview +Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz +Signed-off-by: Marco Elver +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + include/net/bluetooth/l2cap.h | 1 + + net/bluetooth/l2cap_core.c | 34 ++++++++++++++++++++-------------- + 2 files changed, 21 insertions(+), 14 deletions(-) + +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -748,6 +748,7 @@ enum { + FLAG_ECRED_CONN_REQ_SENT, + FLAG_PENDING_SECURITY, + FLAG_HOLD_HCI_CONN, ++ FLAG_DEL, + }; + + /* Lock nesting levels for L2CAP channels. We need these because lockdep +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -411,7 +411,7 @@ static void l2cap_chan_timeout(struct wo + + BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + +- if (!conn) { ++ if (test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_put(chan); + return; + } +@@ -422,6 +422,9 @@ static void l2cap_chan_timeout(struct wo + */ + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) + reason = ECONNREFUSED; + else if (chan->state == BT_CONNECT && +@@ -434,10 +437,10 @@ static void l2cap_chan_timeout(struct wo + + chan->ops->close(chan); + ++unlock: + l2cap_chan_unlock(chan); +- l2cap_chan_put(chan); +- + mutex_unlock(&conn->lock); ++ l2cap_chan_put(chan); + } + + struct l2cap_chan *l2cap_chan_create(void) +@@ -490,6 +493,9 @@ static void l2cap_chan_destroy(struct kr + list_del(&chan->global_l); + write_unlock(&chan_list_lock); + ++ if (chan->conn) ++ l2cap_conn_put(chan->conn); ++ + kfree(chan); + } + +@@ -593,7 +599,7 @@ void __l2cap_chan_add(struct l2cap_conn + + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; + +- chan->conn = conn; ++ chan->conn = l2cap_conn_get(conn); + + switch (chan->chan_type) { + case L2CAP_CHAN_CONN_ORIENTED: +@@ -648,30 +654,26 @@ void l2cap_chan_add(struct l2cap_conn *c + + void l2cap_chan_del(struct l2cap_chan *chan, int err) + { +- struct l2cap_conn *conn = chan->conn; +- + __clear_chan_timer(chan); + +- BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, ++ BT_DBG("chan %p, err %d, state %s", chan, err, + state_to_string(chan->state)); + + chan->ops->teardown(chan, err); + +- if (conn) { ++ if (!test_and_set_bit(FLAG_DEL, &chan->flags)) { + /* Delete from channel list */ + list_del(&chan->list); + + l2cap_chan_put(chan); + +- chan->conn = NULL; +- + /* Reference was only held for non-fixed channels or + * fixed channels that explicitly requested it using the + * FLAG_HOLD_HCI_CONN flag. + */ + if (chan->chan_type != L2CAP_CHAN_FIXED || + test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) +- hci_conn_drop(conn->hcon); ++ hci_conn_drop(chan->conn->hcon); + } + + if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) +@@ -1903,7 +1905,7 @@ static void l2cap_monitor_timeout(struct + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -1924,7 +1926,7 @@ static void l2cap_retrans_timeout(struct + + l2cap_chan_lock(chan); + +- if (!chan->conn) { ++ if (test_bit(FLAG_DEL, &chan->flags)) { + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + return; +@@ -2565,7 +2567,7 @@ int l2cap_chan_send(struct l2cap_chan *c + int err; + struct sk_buff_head seg_queue; + +- if (!chan->conn) ++ if (test_bit(FLAG_DEL, &chan->flags)) + return -ENOTCONN; + + /* Connectionless channel */ +@@ -3160,12 +3162,16 @@ static void l2cap_ack_timeout(struct wor + + l2cap_chan_lock(chan); + ++ if (test_bit(FLAG_DEL, &chan->flags)) ++ goto unlock; ++ + frames_to_ack = __seq_offset(chan, chan->buffer_seq, + chan->last_acked_seq); + + if (frames_to_ack) + l2cap_send_rr_or_rnr(chan, 0); + ++unlock: + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + } diff --git a/queue-6.18/bluetooth-mgmt-fix-uaf-of-hci_conn_params-in-add_device_complete.patch b/queue-6.18/bluetooth-mgmt-fix-uaf-of-hci_conn_params-in-add_device_complete.patch new file mode 100644 index 0000000000..1d8b962e4b --- /dev/null +++ b/queue-6.18/bluetooth-mgmt-fix-uaf-of-hci_conn_params-in-add_device_complete.patch @@ -0,0 +1,148 @@ +From fa85d985f614bc3feb343000f14a1072e99b0df1 Mon Sep 17 00:00:00 2001 +From: Samuel Page +Date: Mon, 15 Jun 2026 16:09:22 +0100 +Subject: Bluetooth: MGMT: Fix UAF of hci_conn_params in add_device_complete + +From: Samuel Page + +commit fa85d985f614bc3feb343000f14a1072e99b0df1 upstream. + +add_device_complete() runs from the hci_cmd_sync_work kworker, which +holds only hci_req_sync_lock and *not* hci_dev_lock. It calls +hci_conn_params_lookup() and then dereferences the returned object +(params->flags) without taking hci_dev_lock: + + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ... + device_flags_changed(NULL, hdev, &cp->addr.bdaddr, + cp->addr.type, hdev->conn_flags, + params ? params->flags : 0); + +hci_conn_params_lookup() walks hdev->le_conn_params and is documented to +require hdev->lock. A concurrent MGMT_OP_REMOVE_DEVICE +(remove_device()), which does run under hci_dev_lock, can call +hci_conn_params_free() to list_del() and kfree() the very object the +lookup returned, so the subsequent params->flags read touches freed +memory [0]. + +Hold hci_dev_lock() across the hci_conn_params_lookup() and the read of +params->flags (and the matching event emission) so the lookup result +cannot be freed by a concurrent remove_device() before it is used, +honouring the locking contract of hci_conn_params_lookup(). + +[0]: (trailing page/memory-state dump trimmed) +BUG: KASAN: slab-use-after-free in add_device_complete+0x358/0x3d8 net/bluetooth/mgmt.c:7671 +Read of size 1 at addr ffff000017ab26c1 by task kworker/u9:8/388 + +CPU: 1 UID: 0 PID: 388 Comm: kworker/u9:8 Not tainted 7.0.11 #20 PREEMPT +Hardware name: linux,dummy-virt (DT) +Workqueue: hci0 hci_cmd_sync_work +Call trace: + show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C) + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0xb4/0xd4 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0x118/0x5d8 mm/kasan/report.c:482 + kasan_report+0xb0/0xf4 mm/kasan/report.c:595 + __asan_report_load1_noabort+0x20/0x2c mm/kasan/report_generic.c:378 + add_device_complete+0x358/0x3d8 net/bluetooth/mgmt.c:7671 + hci_cmd_sync_work+0x14c/0x240 net/bluetooth/hci_sync.c:334 + process_one_work+0x628/0xd38 kernel/workqueue.c:3289 + process_scheduled_works kernel/workqueue.c:3372 [inline] + worker_thread+0x7a8/0xac0 kernel/workqueue.c:3453 + kthread+0x39c/0x444 kernel/kthread.c:436 + ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:860 + +Allocated by task 3401: + kasan_save_stack+0x3c/0x64 mm/kasan/common.c:57 + kasan_save_track+0x20/0x3c mm/kasan/common.c:78 + kasan_save_alloc_info+0x40/0x54 mm/kasan/generic.c:570 + poison_kmalloc_redzone mm/kasan/common.c:398 [inline] + __kasan_kmalloc+0xd4/0xd8 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 [inline] + __kmalloc_cache_noprof+0x1b0/0x458 mm/slub.c:5385 + kmalloc_noprof include/linux/slab.h:950 [inline] + kzalloc_noprof include/linux/slab.h:1188 [inline] + hci_conn_params_add+0x10c/0x4b0 net/bluetooth/hci_core.c:2279 + hci_conn_params_set net/bluetooth/mgmt.c:5162 [inline] + add_device+0x5b4/0xa54 net/bluetooth/mgmt.c:7755 + hci_mgmt_cmd net/bluetooth/hci_sock.c:1721 [inline] + hci_sock_sendmsg+0x10b4/0x1dd0 net/bluetooth/hci_sock.c:1841 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0xe0/0x128 net/socket.c:742 + sock_write_iter+0x250/0x390 net/socket.c:1195 + new_sync_write fs/read_write.c:595 [inline] + vfs_write+0x66c/0xab0 fs/read_write.c:688 + ksys_write+0x1fc/0x24c fs/read_write.c:740 + __do_sys_write fs/read_write.c:751 [inline] + __se_sys_write fs/read_write.c:748 [inline] + __arm64_sys_write+0x70/0xa4 fs/read_write.c:748 + __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] + invoke_syscall+0x84/0x2a8 arch/arm64/kernel/syscall.c:49 + el0_svc_common.constprop.0+0xe4/0x294 arch/arm64/kernel/syscall.c:132 + do_el0_svc+0x44/0x5c arch/arm64/kernel/syscall.c:151 + el0_svc+0x38/0xac arch/arm64/kernel/entry-common.c:724 + el0t_64_sync_handler+0xa0/0xe4 arch/arm64/kernel/entry-common.c:743 + el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596 + +Freed by task 3740: + kasan_save_stack+0x3c/0x64 mm/kasan/common.c:57 + kasan_save_track+0x20/0x3c mm/kasan/common.c:78 + kasan_save_free_info+0x4c/0x74 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 [inline] + __kasan_slab_free+0x88/0xb8 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 [inline] + slab_free_hook mm/slub.c:2685 [inline] + slab_free mm/slub.c:6170 [inline] + kfree+0x14c/0x458 mm/slub.c:6488 + hci_conn_params_free+0x288/0x484 net/bluetooth/hci_core.c:2312 + remove_device+0x4b0/0x968 net/bluetooth/mgmt.c:7919 + hci_mgmt_cmd net/bluetooth/hci_sock.c:1721 [inline] + hci_sock_sendmsg+0x10b4/0x1dd0 net/bluetooth/hci_sock.c:1841 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0xe0/0x128 net/socket.c:742 + sock_write_iter+0x250/0x390 net/socket.c:1195 + new_sync_write fs/read_write.c:595 [inline] + vfs_write+0x66c/0xab0 fs/read_write.c:688 + ksys_write+0x1fc/0x24c fs/read_write.c:740 + __do_sys_write fs/read_write.c:751 [inline] + __se_sys_write fs/read_write.c:748 [inline] + __arm64_sys_write+0x70/0xa4 fs/read_write.c:748 + __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] + invoke_syscall+0x84/0x2a8 arch/arm64/kernel/syscall.c:49 + el0_svc_common.constprop.0+0xe4/0x294 arch/arm64/kernel/syscall.c:132 + do_el0_svc+0x44/0x5c arch/arm64/kernel/syscall.c:151 + el0_svc+0x38/0xac arch/arm64/kernel/entry-common.c:724 + el0t_64_sync_handler+0xa0/0xe4 arch/arm64/kernel/entry-common.c:743 + el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596 + +Fixes: 1e2e3044c1bc ("Bluetooth: MGMT: Fix MGMT_OP_ADD_DEVICE invalid device flags") +Cc: stable@vger.kernel.org +Assisted-by: Bynario AI +Signed-off-by: Samuel Page +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/mgmt.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7641,6 +7641,8 @@ static void add_device_complete(struct h + if (!err) { + struct hci_conn_params *params; + ++ hci_dev_lock(hdev); ++ + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + +@@ -7649,6 +7651,7 @@ static void add_device_complete(struct h + device_flags_changed(NULL, hdev, &cp->addr.bdaddr, + cp->addr.type, hdev->conn_flags, + params ? params->flags : 0); ++ hci_dev_unlock(hdev); + } + + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE, diff --git a/queue-6.18/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch b/queue-6.18/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch new file mode 100644 index 0000000000..0327e128d8 --- /dev/null +++ b/queue-6.18/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch @@ -0,0 +1,119 @@ +From fa09f08ede3db3050ae16ae1ed92c902d0cada23 Mon Sep 17 00:00:00 2001 +From: Runyu Xiao +Date: Fri, 29 May 2026 00:52:01 +0800 +Subject: coresight: etb10: restore atomic_t for shared reading state + +From: Runyu Xiao + +commit fa09f08ede3db3050ae16ae1ed92c902d0cada23 upstream. + +The etb10 miscdevice uses drvdata->reading as a shared exclusivity gate +for userspace buffer access. etb_open() claims that gate with +local_cmpxchg(), and etb_release() clears it with local_set(). + +That gate is shared per-device state rather than CPU-local state. A +running system can reach it whenever /dev/ is opened, closed, and +reopened by different tasks while the device remains registered, so the +same drvdata->reading variable may be claimed on one CPU and later +cleared on another. + +This code used to use atomic_t for the same gate, but commit +27b10da8fff2 ("coresight: etb10: moving to local atomic operations") +changed it to local_t even though the access pattern remained cross-task +and cross-CPU. Restore atomic_t together with atomic_cmpxchg() and +atomic_set() so the exclusivity gate again uses a primitive intended +for shared state. + +The issue was found on Linux v6.18.21 by our static analysis tool while +scanning surviving local_t-on-shared-state sites, and then manually +reviewed against the live etb10 file-op path. + +It was runtime-validated with a reproducible QEMU no-device KCSAN PoC +that kept the same report-local contract: + + 1. use one shared struct etb_drvdata carrier and its + drvdata->reading gate; + 2. call etb_open() and etb_release() sequentially on that gate to + confirm the original claim/clear path; + 3. bind the open side to CPU0 and the release side to CPU1 for the + same gate to show cross-CPU ownership; + 4. run bound workers that repeatedly race etb_open() and + etb_release() on the same gate until KCSAN reports a target hit. + +The harness recorded: + + L1 passed open=1 release=1 + reading_after_open=1 reading_after_release=0 + L2 passed open_cpu=0 release_cpu=1 + cross_cpu_release=1 reading_after=0 open_ret=0 + +Representative KCSAN excerpt from the no-device validation run: + + BUG: KCSAN: data-race in etb_open.constprop.0.isra.0 [vuln_msv] + + write to 0xffffffffc0003810 of 4 bytes by task 216 on cpu 1: + etb_open.constprop.0.isra.0+0x38/0x80 [vuln_msv] + l3_worker_thread_fn+0x4f/0xf0 [vuln_msv] + kthread+0x17e/0x1c0 + ret_from_fork+0x22/0x30 + + read to 0xffffffffc0003810 of 4 bytes by task 215 on cpu 0: + etb_open.constprop.0.isra.0+0x18/0x80 [vuln_msv] + l3_worker_thread_fn+0x4f/0xf0 [vuln_msv] + kthread+0x17e/0x1c0 + ret_from_fork+0x22/0x30 + + value changed: 0x00000000 -> 0x00000001 + + Reported by Kernel Concurrency Sanitizer on: + CPU: 0 PID: 215 Comm: etb10_l3_a Tainted: G O 6.1.66 #2 + +This no-device harness is not a real ETB10 hardware end-to-end run, but +it preserves the same shared drvdata->reading gate and the same +etb_open()/etb_release() claim/clear contract. No real ETB10 hardware +was available for runtime testing. + +Build-tested with: + make olddefconfig + make -j"$(nproc)" drivers/hwtracing/coresight/coresight-etb10.o + +Fixes: 27b10da8fff2 ("coresight: etb10: moving to local atomic operations") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Reviewed-by: James Clark +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20260528165201.319452-1-runyu.xiao@seu.edu.cn +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwtracing/coresight/coresight-etb10.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/hwtracing/coresight/coresight-etb10.c ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -85,7 +85,7 @@ struct etb_drvdata { + struct coresight_device *csdev; + struct miscdevice miscdev; + raw_spinlock_t spinlock; +- local_t reading; ++ atomic_t reading; + pid_t pid; + u8 *buf; + u32 buffer_depth; +@@ -603,7 +603,7 @@ static int etb_open(struct inode *inode, + struct etb_drvdata *drvdata = container_of(file->private_data, + struct etb_drvdata, miscdev); + +- if (local_cmpxchg(&drvdata->reading, 0, 1)) ++ if (atomic_cmpxchg(&drvdata->reading, 0, 1)) + return -EBUSY; + + dev_dbg(&drvdata->csdev->dev, "%s: successfully opened\n", __func__); +@@ -641,7 +641,7 @@ static int etb_release(struct inode *ino + { + struct etb_drvdata *drvdata = container_of(file->private_data, + struct etb_drvdata, miscdev); +- local_set(&drvdata->reading, 0); ++ atomic_set(&drvdata->reading, 0); + + dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__); + return 0; diff --git a/queue-6.18/crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch b/queue-6.18/crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch new file mode 100644 index 0000000000..904b50668d --- /dev/null +++ b/queue-6.18/crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch @@ -0,0 +1,137 @@ +From 6d827ade51a24e18d81afb9f32756d339520a14c Mon Sep 17 00:00:00 2001 +From: Dawei Feng +Date: Fri, 8 May 2026 12:24:16 +0800 +Subject: crypto: amlogic - avoid double cleanup in meson_crypto_probe() + +From: Dawei Feng + +commit 6d827ade51a24e18d81afb9f32756d339520a14c upstream. + +When meson_allocate_chanlist() fails after a partial allocation, it already +unwinds the allocated chanlist state through its local error path. +meson_crypto_probe() then jump to error_flow and calls +meson_free_chanlist() again, causing the same per-flow resources to be torn +down twice. In the reproduced failure path, the second teardown +re-entered crypto_engine_exit() on an already destroyed worker and KASAN +reported a slab-use-after-free in kthread_destroy_worker(). + +Prevent double-free by handling partial allocation failures locally within +meson_allocate_chanlist() and skipping the outer cleanup path. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. + +The bug was reproduced in a QEMU x86_64 guest booted with KASAN on v7.1, +using the reproducer under tools/testing/meson_crypto_probe. The reproducer +forces the second dma_alloc_attrs() call in the gxl-crypto probe path to +return NULL, making meson_allocate_chanlist() fail after partial +initialization. On the unpatched kernel this reliably triggered a +slab-use-after-free. With this fix applied, the same reproducer no longer +emits any KASAN report and the probe fails cleanly with -ENOMEM. + + ================================================================== + BUG: KASAN: slab-use-after-free in kthread_destroy_worker+0xb2/0xd0 + Read of size 8 at addr ff1100010c057a68 by task insmod/265 + + CPU: 1 UID: 0 PID: 265 Comm: insmod Tainted: G O 7.1.0-rc2-00376-g810af9adc907-dirty #10 PREEMPT(lazy) + Tainted: [O]=OOT_MODULE + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 + Call Trace: + + dump_stack_lvl+0x68/0xa0 + print_report+0xcb/0x5e0 + ? __virt_addr_valid+0x21d/0x3f0 + ? kthread_destroy_worker+0xb2/0xd0 + ? kthread_destroy_worker+0xb2/0xd0 + kasan_report+0xca/0x100 + ? kthread_destroy_worker+0xb2/0xd0 + kthread_destroy_worker+0xb2/0xd0 + meson_crypto_probe+0x4d0/0xc10 [amlogic_gxl_crypto] + platform_probe+0x99/0x140 + really_probe+0x1c6/0x6a0 + ? __pfx___device_attach_driver+0x10/0x10 + __driver_probe_device+0x248/0x310 + ? acpi_driver_match_device+0xb0/0x100 + driver_probe_device+0x48/0x210 + ? __pfx___device_attach_driver+0x10/0x10 + __device_attach_driver+0x160/0x320 + bus_for_each_drv+0x104/0x190 + ? __pfx_bus_for_each_drv+0x10/0x10 + ? _raw_spin_unlock_irqrestore+0x2c/0x50 + __device_attach+0x19d/0x3b0 + ? __pfx___device_attach+0x10/0x10 + ? do_raw_spin_unlock+0x53/0x220 + device_initial_probe+0x78/0xa0 + bus_probe_device+0x5b/0x130 + device_add+0xcfd/0x1430 + ? __pfx_device_add+0x10/0x10 + ? insert_resource+0x34/0x50 + ? lock_release+0xc9/0x290 + platform_device_add+0x24e/0x590 + ? __pfx_meson_crypto_probe_repro_init+0x10/0x10 [meson_crypto_probe_repro] + meson_crypto_probe_repro_init+0x330/0xff0 [meson_crypto_probe_repro] + do_one_initcall+0xc0/0x450 + ? __pfx_do_one_initcall+0x10/0x10 + ? _raw_spin_unlock_irqrestore+0x2c/0x50 + ? __create_object+0x59/0x80 + ? kasan_unpoison+0x27/0x60 + do_init_module+0x27b/0x7d0 + ? __pfx_do_init_module+0x10/0x10 + ? kasan_quarantine_put+0x84/0x1d0 + ? kfree+0x32c/0x510 + ? load_module+0x561e/0x5ff0 + load_module+0x54fe/0x5ff0 + ? __pfx_load_module+0x10/0x10 + ? security_file_permission+0x20/0x40 + ? kernel_read_file+0x23d/0x6e0 + ? mmap_region+0x235/0x4a0 + ? __pfx_kernel_read_file+0x10/0x10 + ? __file_has_perm+0x2c0/0x3e0 + init_module_from_file+0x158/0x180 + ? __pfx_init_module_from_file+0x10/0x10 + ? __lock_acquire+0x45a/0x1ba0 + ? idempotent_init_module+0x315/0x610 + ? lock_release+0xc9/0x290 + ? lockdep_init_map_type+0x4b/0x220 + ? do_raw_spin_unlock+0x53/0x220 + idempotent_init_module+0x330/0x610 + ? __pfx_idempotent_init_module+0x10/0x10 + ? __pfx_cred_has_capability.isra.0+0x10/0x10 + ? ksys_mmap_pgoff+0x385/0x520 + __x64_sys_finit_module+0xbe/0x120 + do_syscall_64+0x115/0x690 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + RIP: 0033:0x7f7d6d31690d + Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 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 8b 0d f3 b4 0f 00 f7 d8 > + RSP: 002b:00007fffc027ac68 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 + RAX: ffffffffffffffda RBX: 000055f7b81967c0 RCX: 00007f7d6d31690d + RDX: 0000000000000000 RSI: 000055f79a0d6cd2 RDI: 0000000000000003 + RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000003 R11: 0000000000000246 R12: 000055f79a0d6cd2 + R13: 000055f7b8196790 R14: 000055f79a0d5888 R15: 000055f7b81968e0 + + +Fixes: 48fe583fe541 ("crypto: amlogic - Add crypto accelerator for amlogic GXL") +Cc: stable@vger.kernel.org +Signed-off-by: Zilin Guan +Signed-off-by: Dawei Feng +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/amlogic/amlogic-gxl-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/crypto/amlogic/amlogic-gxl-core.c ++++ b/drivers/crypto/amlogic/amlogic-gxl-core.c +@@ -291,8 +291,8 @@ static int meson_crypto_probe(struct pla + return 0; + error_alg: + meson_unregister_algs(mc); +-error_flow: + meson_free_chanlist(mc, MAXFLOW - 1); ++error_flow: + clk_disable_unprepare(mc->busclk); + return err; + } diff --git a/queue-6.18/crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch b/queue-6.18/crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch new file mode 100644 index 0000000000..70834250d1 --- /dev/null +++ b/queue-6.18/crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch @@ -0,0 +1,54 @@ +From 6c9dddeb582fde005360f4fe02c760d45ca05fb5 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Sun, 10 May 2026 19:24:55 -0400 +Subject: crypto: krb5 - filter out async aead implementations at alloc + +From: Michael Bommarito + +commit 6c9dddeb582fde005360f4fe02c760d45ca05fb5 upstream. + +krb5_aead_encrypt(), krb5_aead_decrypt() in rfc3961_simplified.c and +rfc8009_encrypt(), rfc8009_decrypt() in rfc8009_aes2.c set a NULL +completion callback and treat any negative return from +crypto_aead_{encrypt,decrypt}() as terminal, falling through to +kfree_sensitive(buffer). When the encrypt_name resolves to an +async AEAD instance the request returns -EINPROGRESS, the buffer +is freed while the backend's worker still holds a pointer, and the +worker dereferences the freed slab on completion. + +KASAN report under UML+SLUB with a synthetic async aead backend +bound to krb5->encrypt_name: + + BUG: KASAN: slab-use-after-free in t5_stub_complete+0x7d/0xc7 + +The helpers were written synchronously, so filter the async +instances out at allocation time instead of plumbing +crypto_wait_req() through every call site. + +Reachable via net/rxrpc/rxgk.c, fs/afs/cm_security.c and +net/ceph/crypto.c on systems with an async AEAD provider bound to +the krb5 enctype name. + +Fixes: 00244da40f78 ("crypto/krb5: Implement the Kerberos5 rfc3961 encrypt and decrypt functions") +Fixes: 6c3c0e86c2ac ("crypto/krb5: Implement the AES enctypes from rfc8009") +Cc: stable@vger.kernel.org +Suggested-by: Herbert Xu +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/krb5/krb5_api.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/crypto/krb5/krb5_api.c ++++ b/crypto/krb5/krb5_api.c +@@ -207,7 +207,7 @@ struct crypto_aead *krb5_prepare_encrypt + struct crypto_aead *ci = NULL; + int ret = -ENOMEM; + +- ci = crypto_alloc_aead(krb5->encrypt_name, 0, 0); ++ ci = crypto_alloc_aead(krb5->encrypt_name, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(ci)) { + ret = PTR_ERR(ci); + if (ret == -ENOENT) diff --git a/queue-6.18/debugobjects-plug-race-against-a-concurrent-oom-disable.patch b/queue-6.18/debugobjects-plug-race-against-a-concurrent-oom-disable.patch new file mode 100644 index 0000000000..49b8c140b2 --- /dev/null +++ b/queue-6.18/debugobjects-plug-race-against-a-concurrent-oom-disable.patch @@ -0,0 +1,111 @@ +From b81dde13cc163450dcb402dcc915ef13ba241e01 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Sun, 21 Jun 2026 16:47:44 +0200 +Subject: debugobjects: Plug race against a concurrent OOM disable + +From: Thomas Gleixner + +commit b81dde13cc163450dcb402dcc915ef13ba241e01 upstream. + +syzbot reported a puzzling splat: + + WARNING: kernel/time/hrtimer.c:443 at stub_timer+0xa/0x20 + +stub_timer() is installed as timer callback function in +hrtimer_fixup_assert_init(), which is invoked when +debug_object_assert_init() can't find a shadow object. In that case debug +objects emits a warning about it before invoking the fixup. + +Though the provided console log lacks this warning and instead has the +following a few seconds before the splat: + + ODEBUG: Out of memory. ODEBUG disabled + +So the object was looked up in debug_object_assert_init() and the lookup +failed due a concurrent out of memory situation which disabled debug +objects and freed the shadow objects: + +debug_object_assert_init() + if (!debug_objects_enabled) + return; obj = alloc(); + if (!obj) { + // Out of memory + debug_objects_enabled = false; + free_objects(); + obj = lookup_or_alloc(); + + // The lookup failed because the other side + // removed the objects, so this returns + // an error code as the object in question + // is not statically initialized + + if (!IS_ERR_OR_NULL(obj)) + return; + if (!obj) { + debug_oom(); + return; + } + + print(...) + if (!debug_objects_enabled) + return; + + fixup(...) + +The debug object splat is skipped because debug_objects_enabled is false, +but the fixup callback is invoked unconditionally, which makes the timer +disfunctional. + +This is only a problem in debug_object_assert_init() and +debug_object_activate() as both have to handle statically initialized +objects and therefore must handle the error pointer return case +gracefully. All other places only handle the found/not found case and the +NULL pointer return is a signal for OOM. Otherwise they get a valid shadow +object. + +Plug the hole by checking whether debug objects are still enabled before +invoking the print and fixup function in those two places. + +Fixes: b84d435cc228 ("debugobjects: Extend to assert that an object is initialized") +Reported-by: syzbot+5e8dda76ca21dae314b6@syzkaller.appspotmail.com +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/874iiwlzlb.ffs@fw13 +Signed-off-by: Greg Kroah-Hartman +--- + lib/debugobjects.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/lib/debugobjects.c ++++ b/lib/debugobjects.c +@@ -894,6 +894,14 @@ int debug_object_activate(void *addr, co + } + + raw_spin_unlock_irqrestore(&db->lock, flags); ++ ++ /* ++ * lookup_object_or_alloc() might have raced with a concurrent ++ * allocation failure which disabled debug objects. ++ */ ++ if (!debug_objects_enabled) ++ return 0; ++ + debug_print_object(&o, "activate"); + + switch (o.state) { +@@ -1071,6 +1079,15 @@ void debug_object_assert_init(void *addr + return; + } + ++ /* ++ * lookup_object_or_alloc() might have raced with a concurrent ++ * allocation failure which disabled debug objects. Don't run the fixup ++ * as it might turn a valid object useless. See for example ++ * hrtimer_fixup_assert_init(). ++ */ ++ if (!debug_objects_enabled) ++ return; ++ + /* Object is neither tracked nor static. It's not initialized. */ + debug_print_object(&o, "assert_init"); + debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE); diff --git a/queue-6.18/fs-ntfs3-validate-dirty-page-table-capacity-in-log_replay-copy_lcns.patch b/queue-6.18/fs-ntfs3-validate-dirty-page-table-capacity-in-log_replay-copy_lcns.patch new file mode 100644 index 0000000000..44332a4f0a --- /dev/null +++ b/queue-6.18/fs-ntfs3-validate-dirty-page-table-capacity-in-log_replay-copy_lcns.patch @@ -0,0 +1,78 @@ +From 57382ec6ac63b63dce2789e835fded28b698ae79 Mon Sep 17 00:00:00 2001 +From: Yunpeng Tian +Date: Mon, 4 May 2026 07:19:43 -0700 +Subject: fs/ntfs3: validate Dirty Page Table capacity in log_replay copy_lcns + +From: Yunpeng Tian + +commit 57382ec6ac63b63dce2789e835fded28b698ae79 upstream. + +In the analysis pass of $LogFile journal replay, log_replay() copies +LCNs from each action log record into an existing Dirty Page Table +(DPT) entry without bounding the destination index. A crafted NTFS +image with DPT entry lcns_follow=1 and an action log record with +lcns_follow=2 produces a kernel slab out-of-bounds write at mount +time: + + BUG: KASAN: slab-out-of-bounds in log_replay+0x654c/0xdb60 + Write of size 8 at addr ffff8880095e1040 by task mount + +Two attacker-controlled fields can drive j+i past the allocated +page_lcns[] array: + + 1. dp->lcns_follow (capacity) can be smaller than lrh->lcns_follow. + 2. lrh->target_vcn may be smaller than dp->vcn, making the u64 + subtraction wrap to a huge size_t. + +Validate target VCN delta and per-record LCN count against the +DPT entry capacity, bail via the existing out: cleanup label with +-EINVAL. + +This mirrors the bounds-check pattern added in commit b2bc7c44ed17 +("fs/ntfs3: Fix slab-out-of-bounds read in DeleteIndexEntryRoot") +and commit 0ca0485e4b2e ("fs/ntfs3: validate rec->used in +journal-replay file record check"). + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Reported-by: Yunpeng Tian +Reported-by: Mingda Zhang +Reported-by: Gongming Wang +Reported-by: Peiyuan Xu +Reported-by: Qinrun Dai +Cc: stable@vger.kernel.org +Signed-off-by: Yunpeng Tian +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -4546,11 +4546,21 @@ copy_lcns: + * whole routine a loop, case Lcns do not fit below. + */ + t16 = le16_to_cpu(lrh->lcns_follow); +- for (i = 0; i < t16; i++) { +- size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) - +- le64_to_cpu(dp->vcn)); +- dp->page_lcns[j + i] = lrh->page_lcns[i]; +- } ++ t32 = le32_to_cpu(dp->lcns_follow); ++ if (le64_to_cpu(lrh->target_vcn) < le64_to_cpu(dp->vcn)) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ for (i = 0; i < t16; i++) { ++ size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) - ++ le64_to_cpu(dp->vcn)); ++ if (j >= t32 || i >= t32 - j) { ++ err = -EINVAL; ++ goto out; ++ } ++ dp->page_lcns[j + i] = lrh->page_lcns[i]; ++ } + + goto next_log_record_analyze; + diff --git a/queue-6.18/gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch b/queue-6.18/gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch new file mode 100644 index 0000000000..ebe1d8af14 --- /dev/null +++ b/queue-6.18/gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch @@ -0,0 +1,84 @@ +From 90f0109019e6817eb40a486671b7722d1544ae29 Mon Sep 17 00:00:00 2001 +From: Runyu Xiao +Date: Wed, 17 Jun 2026 23:40:35 +0800 +Subject: gpio: eic-sprd: use raw_spinlock_t in the irq startup path + +From: Runyu Xiao + +commit 90f0109019e6817eb40a486671b7722d1544ae29 upstream. + +sprd_eic_irq_unmask() enables the GPIO IRQ and then updates controller +state through sprd_eic_update(), which takes sprd_eic->lock with +spin_lock_irqsave(). The callback can be reached from irq_startup() +while setting up a requested IRQ. That path is not sleepable, but on +PREEMPT_RT a regular spinlock_t becomes a sleeping lock. + +This issue was found by our static analysis tool and then manually +reviewed against the current tree. + +The grounded PoC kept the request_threaded_irq() -> __setup_irq() -> +irq_startup() -> sprd_eic_irq_unmask() -> sprd_eic_update() carrier and +used the original spin_lock_irqsave(&sprd_eic->lock) edge. Lockdep +reported: + + BUG: sleeping function called from invalid context + hardirqs last disabled at ... __setup_irq.constprop.0 ... [vuln_msv] + sprd_rt_spin_lock_irqsave+0x1c/0x30 [vuln_msv] + sprd_eic_update.constprop.0+0x48/0x90 [vuln_msv] + sprd_eic_irq_unmask.constprop.0+0x35/0x50 [vuln_msv] + __setup_irq.constprop.0+0xd/0x30 [vuln_msv] + +Convert the Spreadtrum EIC controller lock to raw_spinlock_t. The +locked section only serializes MMIO register updates and does not contain +sleepable operations, so keeping it non-sleeping is appropriate for the +irqchip callbacks. + +Fixes: 25518e024e3a ("gpio: Add Spreadtrum EIC driver support") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Reviewed-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/20260617154035.1199948-3-runyu.xiao@seu.edu.cn +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpio-eic-sprd.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpio/gpio-eic-sprd.c ++++ b/drivers/gpio/gpio-eic-sprd.c +@@ -95,7 +95,7 @@ struct sprd_eic { + struct notifier_block irq_nb; + void __iomem *base[SPRD_EIC_MAX_BANK]; + enum sprd_eic_type type; +- spinlock_t lock; ++ raw_spinlock_t lock; + int irq; + }; + +@@ -149,7 +149,7 @@ static void sprd_eic_update(struct gpio_ + unsigned long flags; + u32 tmp; + +- spin_lock_irqsave(&sprd_eic->lock, flags); ++ raw_spin_lock_irqsave(&sprd_eic->lock, flags); + tmp = readl_relaxed(base + reg); + + if (val) +@@ -158,7 +158,7 @@ static void sprd_eic_update(struct gpio_ + tmp &= ~BIT(SPRD_EIC_BIT(offset)); + + writel_relaxed(tmp, base + reg); +- spin_unlock_irqrestore(&sprd_eic->lock, flags); ++ raw_spin_unlock_irqrestore(&sprd_eic->lock, flags); + } + + static int sprd_eic_read(struct gpio_chip *chip, unsigned int offset, u16 reg) +@@ -628,7 +628,7 @@ static int sprd_eic_probe(struct platfor + if (!sprd_eic) + return -ENOMEM; + +- spin_lock_init(&sprd_eic->lock); ++ raw_spin_lock_init(&sprd_eic->lock); + sprd_eic->type = pdata->type; + + sprd_eic->irq = platform_get_irq(pdev, 0); diff --git a/queue-6.18/gpio-sch-use-raw_spinlock_t-in-the-irq-startup-path.patch b/queue-6.18/gpio-sch-use-raw_spinlock_t-in-the-irq-startup-path.patch new file mode 100644 index 0000000000..b69eebe922 --- /dev/null +++ b/queue-6.18/gpio-sch-use-raw_spinlock_t-in-the-irq-startup-path.patch @@ -0,0 +1,159 @@ +From 286533cb14a3c8a8bd39ff64ea2fc8e1aa0f638b Mon Sep 17 00:00:00 2001 +From: Runyu Xiao +Date: Wed, 17 Jun 2026 23:40:34 +0800 +Subject: gpio: sch: use raw_spinlock_t in the irq startup path + +From: Runyu Xiao + +commit 286533cb14a3c8a8bd39ff64ea2fc8e1aa0f638b upstream. + +sch_irq_unmask() enables the GPIO IRQ and then updates the controller +state through sch_irq_mask_unmask(), which takes sch->lock with +spin_lock_irqsave(). The callback can be reached from irq_startup() +while setting up a requested IRQ. That path is not sleepable, but on +PREEMPT_RT a regular spinlock_t becomes a sleeping lock. + +This issue was found by our static analysis tool and then manually +reviewed against the current tree. + +The grounded PoC kept the request_threaded_irq() -> __setup_irq() -> +irq_startup() -> sch_irq_unmask() -> sch_irq_mask_unmask() carrier and +used the original spin_lock_irqsave(&sch->lock) edge. Lockdep reported: + + BUG: sleeping function called from invalid context + hardirqs last disabled at ... __setup_irq.constprop.0 ... [vuln_msv] + sch_rt_spin_lock_irqsave+0x1c/0x30 [vuln_msv] + sch_irq_mask_unmask.constprop.0+0x31/0x70 [vuln_msv] + __setup_irq.constprop.0+0xd/0x30 [vuln_msv] + +Convert the SCH controller lock to raw_spinlock_t. The same lock is +also used by the GPIO direction and value callbacks, but those critical +sections only update MMIO-backed GPIO registers and do not contain +sleepable operations. Keeping this register lock non-sleeping is +therefore appropriate for the irqchip callbacks and does not change the +GPIO-side locking contract. + +Fixes: 7a81638485c1 ("gpio: sch: Add edge event support") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Reviewed-by: Sebastian Andrzej Siewior +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260617154035.1199948-2-runyu.xiao@seu.edu.cn +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpio-sch.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +--- a/drivers/gpio/gpio-sch.c ++++ b/drivers/gpio/gpio-sch.c +@@ -39,7 +39,7 @@ + struct sch_gpio { + struct gpio_chip chip; + void __iomem *regs; +- spinlock_t lock; ++ raw_spinlock_t lock; + unsigned short resume_base; + + /* GPE handling */ +@@ -104,9 +104,9 @@ static int sch_gpio_direction_in(struct + struct sch_gpio *sch = gpiochip_get_data(gc); + unsigned long flags; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + sch_gpio_reg_set(sch, gpio_num, GIO, 1); +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + return 0; + } + +@@ -122,9 +122,9 @@ static int sch_gpio_set(struct gpio_chip + struct sch_gpio *sch = gpiochip_get_data(gc); + unsigned long flags; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + sch_gpio_reg_set(sch, gpio_num, GLV, val); +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + + return 0; + } +@@ -135,9 +135,9 @@ static int sch_gpio_direction_out(struct + struct sch_gpio *sch = gpiochip_get_data(gc); + unsigned long flags; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + sch_gpio_reg_set(sch, gpio_num, GIO, 0); +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + + /* + * according to the datasheet, writing to the level register has no +@@ -196,14 +196,14 @@ static int sch_irq_type(struct irq_data + return -EINVAL; + } + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + + sch_gpio_reg_set(sch, gpio_num, GTPE, rising); + sch_gpio_reg_set(sch, gpio_num, GTNE, falling); + + irq_set_handler_locked(d, handle_edge_irq); + +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + + return 0; + } +@@ -215,9 +215,9 @@ static void sch_irq_ack(struct irq_data + irq_hw_number_t gpio_num = irqd_to_hwirq(d); + unsigned long flags; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + sch_gpio_reg_set(sch, gpio_num, GTS, 1); +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + } + + static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, int val) +@@ -225,9 +225,9 @@ static void sch_irq_mask_unmask(struct g + struct sch_gpio *sch = gpiochip_get_data(gc); + unsigned long flags; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + sch_gpio_reg_set(sch, gpio_num, GGPE, val); +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + } + + static void sch_irq_mask(struct irq_data *d) +@@ -268,12 +268,12 @@ static u32 sch_gpio_gpe_handler(acpi_han + int offset; + u32 ret; + +- spin_lock_irqsave(&sch->lock, flags); ++ raw_spin_lock_irqsave(&sch->lock, flags); + + core_status = ioread32(sch->regs + CORE_BANK_OFFSET + GTS); + resume_status = ioread32(sch->regs + RESUME_BANK_OFFSET + GTS); + +- spin_unlock_irqrestore(&sch->lock, flags); ++ raw_spin_unlock_irqrestore(&sch->lock, flags); + + pending = (resume_status << sch->resume_base) | core_status; + for_each_set_bit(offset, &pending, sch->chip.ngpio) +@@ -343,7 +343,7 @@ static int sch_gpio_probe(struct platfor + + sch->regs = regs; + +- spin_lock_init(&sch->lock); ++ raw_spin_lock_init(&sch->lock); + sch->chip = sch_gpio_chip; + sch->chip.label = dev_name(dev); + sch->chip.parent = dev; diff --git a/queue-6.18/hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch b/queue-6.18/hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch new file mode 100644 index 0000000000..f347fc545b --- /dev/null +++ b/queue-6.18/hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch @@ -0,0 +1,120 @@ +From e3046eeada299f917a8ad883af4434bfb86556b1 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Sun, 31 May 2026 10:22:51 -0400 +Subject: hwrng: virtio: clamp device-reported used.len at copy_data() + +From: Michael Bommarito + +commit e3046eeada299f917a8ad883af4434bfb86556b1 upstream. + +random_recv_done() stores the device-reported used.len directly into +vi->data_avail. copy_data() then indexes vi->data[] using +vi->data_idx (advanced by previous copy_data() calls) and issues a +memcpy() without re-validating either value against the posted +buffer size sizeof(vi->data) (SMP_CACHE_BYTES bytes, typically 32 +or 64). + +A malicious or buggy virtio-rng backend can set used.len beyond +sizeof(vi->data), steering the memcpy() past the end of the inline +array into adjacent kmalloc-1k slab bytes. hwrng_fillfn() mixes +those bytes into the guest RNG, and guest root can also observe +them directly via /dev/hwrng. + +Concrete impact is inside the guest: + + - Memory-safety / hardening: any virtio-rng backend that + over-reports used.len causes the driver to read past vi->data + into unrelated slab contents. hwrng_fillfn() is a kernel thread + that runs as soon as the device is probed; no guest userspace + interaction is required to first-trigger the OOB. + + - Cross-boundary leak (confidential-compute threat model): a + malicious hypervisor cooperating with a malicious or compromised + guest root userspace can use /dev/hwrng as a leak channel for + guest-kernel heap data. The host sets a large used.len, guest + root reads /dev/hwrng, and the returned bytes contain guest + kernel slab contents that were adjacent to vi->data. In + practice, confidential-compute guests (SEV-SNP, TDX) usually + disable virtio-rng entirely, so this path is narrow, but the + fix is still worth carrying because the underlying + memory-safety bug contaminates the guest RNG on any host. + +KASAN confirms the OOB on a 7.1-rc4 guest whose virtio-rng backend +has been patched to report used.len = 0x10000: + + BUG: KASAN: slab-out-of-bounds in virtio_read+0x394/0x5d0 + Read of size 64 at addr ffff88800ae0ba20 by task hwrng/52 + Call Trace: + __asan_memcpy+0x23/0x60 + virtio_read+0x394/0x5d0 + hwrng_fillfn+0xb2/0x470 + kthread+0x2cc/0x3a0 + Allocated by task 1: + probe_common+0xa5/0x660 + virtio_dev_probe+0x549/0xbc0 + The buggy address belongs to the object at ffff88800ae0b800 + which belongs to the cache kmalloc-1k of size 1024 + The buggy address is located 0 bytes to the right of + allocated 544-byte region [ffff88800ae0b800, ffff88800ae0ba20) + +Same class of bug as commit c04db81cd028 ("net/9p: Fix buffer +overflow in USB transport layer"), which hardened +usb9pfs_rx_complete() against unchecked device-reported length in +the USB 9p transport. + +With the clamp at point of use and array_index_nospec() in place, +the same harness boots cleanly: copy_data() returns zero for the +bogus report, the device-supplied bytes after data_idx are +discarded, and the driver issues a fresh request. + +Fixes: f7f510ec1957 ("virtio: An entropy device, as suggested by hpa.") +Cc: stable@vger.kernel.org +Suggested-by: Michael S. Tsirkin +Signed-off-by: Michael Bommarito +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Michael S. Tsirkin +Message-ID: <20260531142251.2792061-1-michael.bommarito@gmail.com> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/hw_random/virtio-rng.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/char/hw_random/virtio-rng.c ++++ b/drivers/char/hw_random/virtio-rng.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -66,8 +67,26 @@ static void request_entropy(struct virtr + static unsigned int copy_data(struct virtrng_info *vi, void *buf, + unsigned int size) + { +- size = min_t(unsigned int, size, vi->data_avail); +- memcpy(buf, vi->data + vi->data_idx, size); ++ unsigned int idx, avail; ++ ++ /* ++ * vi->data_avail was set from the device-reported used.len and ++ * vi->data_idx was advanced by previous copy_data() calls. A ++ * malicious or buggy virtio-rng backend can drive either past ++ * sizeof(vi->data). Clamp at point of use and harden the index ++ * with array_index_nospec() so the memcpy() below cannot be ++ * steered into adjacent slab memory, including under ++ * speculation. ++ */ ++ avail = min_t(unsigned int, vi->data_avail, sizeof(vi->data)); ++ if (vi->data_idx >= avail) { ++ vi->data_avail = 0; ++ request_entropy(vi); ++ return 0; ++ } ++ size = min_t(unsigned int, size, avail - vi->data_idx); ++ idx = array_index_nospec(vi->data_idx, sizeof(vi->data)); ++ memcpy(buf, vi->data + idx, size); + vi->data_idx += size; + vi->data_avail -= size; + if (vi->data_avail == 0) diff --git a/queue-6.18/io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch b/queue-6.18/io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch new file mode 100644 index 0000000000..05793e7c7d --- /dev/null +++ b/queue-6.18/io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch @@ -0,0 +1,54 @@ +From 29bef9934b2521f787bb15dd1985d4c0d12ae02a Mon Sep 17 00:00:00 2001 +From: Runyu Xiao +Date: Thu, 28 May 2026 01:22:03 +0800 +Subject: io_uring/io-wq: re-check IO_WQ_BIT_EXIT for each linked work item + +From: Runyu Xiao + +commit 29bef9934b2521f787bb15dd1985d4c0d12ae02a upstream. + +commit 10dc95939817 ("io_uring/io-wq: check IO_WQ_BIT_EXIT inside work +run loop") fixed the obvious case where io_worker_handle_work() took one +exit-bit snapshot before draining pending work, but the fix stops one +level too early. + +io_worker_handle_work() now re-checks IO_WQ_BIT_EXIT in its outer work +run loop, yet it still snapshots that bit once before processing a whole +dependent linked-work chain. If io_wq_exit_start() sets IO_WQ_BIT_EXIT +after the first linked item has started, the remaining linked items can +still reuse stale do_kill = false, skip IO_WQ_WORK_CANCEL, and continue +running after exit has begun. + +Move the check further inside, so it covers linked items too. Note: this +is a syzbot special as it loves setting up tons of slow linked work on +weird devices like msr that take forever to read, and immediately close +the ring. Exit then takes a long time. + +Fixes: 10dc95939817 ("io_uring/io-wq: check IO_WQ_BIT_EXIT inside work run loop") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Link: https://patch.msgid.link/20260527172203.2043962-1-runyu.xiao@seu.edu.cn +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/io-wq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -601,7 +601,6 @@ static void io_worker_handle_work(struct + struct io_wq *wq = worker->wq; + + do { +- bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state); + struct io_wq_work *work; + + /* +@@ -637,6 +636,7 @@ static void io_worker_handle_work(struct + + /* handle a whole dependent link */ + do { ++ bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state); + struct io_wq_work *next_hashed, *linked; + unsigned int work_flags = atomic_read(&work->flags); + unsigned int hash = __io_wq_is_hashed(work_flags) diff --git a/queue-6.18/io_uring-nop-fix-file-reference-leak-with-iosqe_fixed_file.patch b/queue-6.18/io_uring-nop-fix-file-reference-leak-with-iosqe_fixed_file.patch new file mode 100644 index 0000000000..95c4f8e69a --- /dev/null +++ b/queue-6.18/io_uring-nop-fix-file-reference-leak-with-iosqe_fixed_file.patch @@ -0,0 +1,72 @@ +From 2564ca2e31bd8ee8348362941af2ee4671e487ca Mon Sep 17 00:00:00 2001 +From: Vasileios Almpanis +Date: Mon, 15 Jun 2026 16:45:57 +0200 +Subject: io_uring/nop: fix file reference leak with IOSQE_FIXED_FILE + +From: Vasileios Almpanis + +commit 2564ca2e31bd8ee8348362941af2ee4671e487ca upstream. + +NOP file-acquisition support choses between a fixed (registered) file and +a normal fget()'d file based on its own IORING_NOP_FIXED_FILE flag in +sqe->nop_flags. However, a request's REQ_F_FIXED_FILE is set +independently from the generic IOSQE_FIXED_FILE sqe flag during request +init, before the issue handler runs. + +If a NOP is submitted with IOSQE_FIXED_FILE set (so REQ_F_FIXED_FILE is +set) but without IORING_NOP_FIXED_FILE, io_nop() takes the normal path +and grabs a real reference via io_file_get_normal(). On completion, +io_put_file() only drops the reference when REQ_F_FIXED_FILE is clear, +so the fget()'d file is never released and leaks: + + BUG: memory leak + unreferenced object 0xffff88800f42c240 (size 176): + kmem_cache_alloc_noprof+0x358/0x440 + alloc_empty_file+0x57/0x180 + path_openat+0x44/0x1e50 + do_file_open+0x121/0x200 + do_sys_openat2+0xa7/0x150 + __x64_sys_openat+0x82/0xf0 + +Decide between fixed and normal file acquisition from REQ_F_FIXED_FILE, +the same way io_assign_file() does for every other opcode, and fold +IORING_NOP_FIXED_FILE into REQ_F_FIXED_FILE at prep time. + +Cc: stable@vger.kernel.org +Fixes: a85f31052bce ("io_uring/nop: add support for testing registered files and buffers") +Reported-by: syzbot+2cd473471e77bda12b0e@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?id=879092631b98f73a28ea405adacfa5bb34a14a25 +Signed-off-by: Vasileios Almpanis +Link: https://patch.msgid.link/20260615144619.482749-1-vasilisalmpanis@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/nop.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/io_uring/nop.c ++++ b/io_uring/nop.c +@@ -41,6 +41,8 @@ int io_nop_prep(struct io_kiocb *req, co + nop->fd = READ_ONCE(sqe->fd); + else + nop->fd = -1; ++ if (nop->flags & IORING_NOP_FIXED_FILE) ++ req->flags |= REQ_F_FIXED_FILE; + if (nop->flags & IORING_NOP_FIXED_BUFFER) + req->buf_index = READ_ONCE(sqe->buf_index); + if (nop->flags & IORING_NOP_CQE32) { +@@ -60,12 +62,10 @@ int io_nop(struct io_kiocb *req, unsigne + int ret = nop->result; + + if (nop->flags & IORING_NOP_FILE) { +- if (nop->flags & IORING_NOP_FIXED_FILE) { ++ if (req->flags & REQ_F_FIXED_FILE) + req->file = io_file_get_fixed(req, nop->fd, issue_flags); +- req->flags |= REQ_F_FIXED_FILE; +- } else { ++ else + req->file = io_file_get_normal(req, nop->fd); +- } + if (!req->file) { + ret = -EBADF; + goto done; diff --git a/queue-6.18/io_uring-rw-preserve-partial-result-for-iopoll.patch b/queue-6.18/io_uring-rw-preserve-partial-result-for-iopoll.patch new file mode 100644 index 0000000000..91814dae0b --- /dev/null +++ b/queue-6.18/io_uring-rw-preserve-partial-result-for-iopoll.patch @@ -0,0 +1,54 @@ +From c554246ff4c68abf71b61a89c6e39d3cf94f523e Mon Sep 17 00:00:00 2001 +From: Michael Wigham +Date: Sat, 13 Jun 2026 23:52:16 +0100 +Subject: io_uring/rw: preserve partial result for iopoll + +From: Michael Wigham + +commit c554246ff4c68abf71b61a89c6e39d3cf94f523e upstream. + +A partial read will store the completed byte count in io->bytes_done. +The regular completion path applies io_fixup_rw_res() so that, when the +following operation reaches EOF, the number of bytes already read is +returned. + +The iopoll completion path does not apply this fixup to the return value +and can return zero instead. + +Use the fixup result when updating the CQE, and the raw result for the +reissue check. + +Cc: stable@vger.kernel.org +Fixes: 4d9cb92ca41d ("io_uring/rw: fix short rw error handling") +Signed-off-by: Michael Wigham +Link: https://patch.msgid.link/20260613225240.34032-1-michael@wigham.net +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/rw.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/io_uring/rw.c ++++ b/io_uring/rw.c +@@ -611,15 +611,15 @@ static void io_complete_rw_iopoll(struct + { + struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb); + struct io_kiocb *req = cmd_to_io_kiocb(rw); ++ int final_res = io_fixup_rw_res(req, res); + + if (kiocb->ki_flags & IOCB_WRITE) + io_req_end_write(req); +- if (unlikely(res != req->cqe.res)) { +- if (res == -EAGAIN && io_rw_should_reissue(req)) +- req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE; +- else +- req->cqe.res = res; +- } ++ ++ if (res == -EAGAIN && io_rw_should_reissue(req)) ++ req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE; ++ else if (unlikely(final_res != req->cqe.res)) ++ req->cqe.res = final_res; + + /* order with io_iopoll_complete() checking ->iopoll_completed */ + smp_store_release(&req->iopoll_completed, 1); diff --git a/queue-6.18/ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch b/queue-6.18/ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch new file mode 100644 index 0000000000..1897478ba1 --- /dev/null +++ b/queue-6.18/ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch @@ -0,0 +1,84 @@ +From 7993211bde166471dffac074dc965489f86531f8 Mon Sep 17 00:00:00 2001 +From: Yuyang Huang +Date: Thu, 2 Jul 2026 08:50:14 +0900 +Subject: ipv4: igmp: remove multicast group from hash table on device destruction + +From: Yuyang Huang + +commit 7993211bde166471dffac074dc965489f86531f8 upstream. + +When a device is destroyed under RTNL, ip_mc_destroy_dev() iterates through +the multicast list and calls ip_ma_put() on each membership, scheduling +them for RCU reclamation. However, they are not unlinked from the device's +multicast hash table (mc_hash). + +Since the device remains published in dev->ip_ptr until after +ip_mc_destroy_dev() completes, concurrent RCU readers traversing mc_hash +can still locate and access the multicast group after its refcount is +decremented. If the RCU callback runs and frees the group while a reader is +accessing it, a use-after-free occurs. + +Fix this by unlinking the multicast group from mc_hash using +ip_mc_hash_remove() before scheduling it for reclamation. + +BUG: KASAN: slab-use-after-free in ip_check_mc_rcu+0x149/0x3f0 +Read of size 4 at addr ffff888009bf1408 by task mausezahn/2276 + +Call Trace: + + dump_stack_lvl+0x67/0x90 + print_report+0x175/0x7c0 + kasan_report+0x147/0x180 + ip_check_mc_rcu+0x149/0x3f0 + udp_v4_early_demux+0x36d/0x12d0 + ip_rcv_finish_core+0xb8b/0x1390 + ip_rcv_finish+0x54/0x120 + NF_HOOK+0x213/0x2b0 + __netif_receive_skb+0x126/0x340 + process_backlog+0x4f2/0xf00 + __napi_poll+0x92/0x2c0 + net_rx_action+0x583/0xc60 + handle_softirqs+0x236/0x7f0 + do_softirq+0x57/0x80 + + +Allocated by task 2239: + kasan_save_track+0x3e/0x80 + __kasan_kmalloc+0x72/0x90 + ____ip_mc_inc_group+0x31a/0xa40 + __ip_mc_join_group+0x334/0x3f0 + do_ip_setsockopt+0x16fa/0x2010 + ip_setsockopt+0x3f/0x90 + do_sock_setsockopt+0x1ad/0x300 + +Freed by task 0: + kasan_save_track+0x3e/0x80 + kasan_save_free_info+0x40/0x50 + __kasan_slab_free+0x3a/0x60 + __rcu_free_sheaf_prepare+0xd4/0x220 + rcu_free_sheaf+0x36/0x190 + rcu_core+0x8d9/0x12f0 + handle_softirqs+0x236/0x7f0 + +Fixes: e9897071350b ("igmp: hash a hash table to speedup ip_check_mc_rcu()") +Cc: stable@vger.kernel.org +Signed-off-by: Yuyang Huang +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260701235014.73505-1-yuyanghuang@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/igmp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -1904,6 +1904,7 @@ void ip_mc_destroy_dev(struct in_device + #endif + + while ((i = rtnl_dereference(in_dev->mc_list)) != NULL) { ++ ip_mc_hash_remove(in_dev, i); + in_dev->mc_list = i->next_rcu; + in_dev->mc_count--; + ip_mc_clear_src(i); diff --git a/queue-6.18/ksmbd-fix-use-after-free-of-a-deferred-file_lock-on-smb2_close-then-smb2_cancel.patch b/queue-6.18/ksmbd-fix-use-after-free-of-a-deferred-file_lock-on-smb2_close-then-smb2_cancel.patch new file mode 100644 index 0000000000..2a13502b9c --- /dev/null +++ b/queue-6.18/ksmbd-fix-use-after-free-of-a-deferred-file_lock-on-smb2_close-then-smb2_cancel.patch @@ -0,0 +1,83 @@ +From 10f293a07f9e10e988b0ae44e2e99c631f5a68e0 Mon Sep 17 00:00:00 2001 +From: Gil Portnoy +Date: Wed, 10 Jun 2026 19:53:14 +0900 +Subject: ksmbd: fix use-after-free of a deferred file_lock on SMB2_CLOSE then SMB2_CANCEL + +From: Gil Portnoy + +commit 10f293a07f9e10e988b0ae44e2e99c631f5a68e0 upstream. + +Commit f580d27e8928 ("ksmbd: fix use-after-free of a deferred file_lock on +double SMB2_CANCEL") made smb2_cancel() skip a work whose state is +KSMBD_WORK_CANCELLED, so its cancel_fn cannot be fired a second time. But +KSMBD_WORK has three states (ACTIVE, CANCELLED, CLOSED), and the same +freeing producer path is reached for CLOSED too: + + SMB2_CLOSE on the locking handle -> set_close_state_blocked_works() sets + the deferred work's state to KSMBD_WORK_CLOSED and wakes the smb2_lock() + worker. The worker takes the non-ACTIVE early-exit, locks_free_lock()s + the file_lock and, because the state is not KSMBD_WORK_CANCELLED, takes + the STATUS_RANGE_NOT_LOCKED branch with "goto out2" -- which, like the + cancelled branch, skips release_async_work(). The work stays on + conn->async_requests with a live cancel_fn = smb2_remove_blocked_lock + pointing at the freed file_lock. + +A subsequent SMB2_CANCEL for the same AsyncId then passes the +KSMBD_WORK_CANCELLED-only guard (its state is KSMBD_WORK_CLOSED), so +smb2_cancel() fires cancel_fn again over the freed file_lock -- the same +use-after-free fixed, via SMB2_CLOSE instead of a first SMB2_CANCEL: + + BUG: KASAN: slab-use-after-free in __locks_delete_block + __locks_delete_block + locks_delete_block + ksmbd_vfs_posix_lock_unblock + smb2_remove_blocked_lock + smb2_cancel <- 2nd SMB2_CANCEL fires cancel_fn + handle_ksmbd_work + Allocated by ...: locks_alloc_lock <- smb2_lock + Freed by ...: locks_free_lock <- smb2_lock (non-ACTIVE early-exit) + ... cache file_lock_cache of size 192 + +Reproduced on mainline 7.1-rc7 (which already contains f580d27e8928) with +KASAN by an authenticated SMB client; the double-SMB2_CANCEL control is +silent on that kernel, so the splat is attributable to the CLOSE trigger. + +Only an ACTIVE deferred work may have its cancel_fn fired: both terminal +states (CANCELLED and CLOSED) reach the smb2_lock() early-exit that frees +the file_lock and skips release_async_work(). Guard on KSMBD_WORK_ACTIVE +so any non-active work is skipped. + +Fixes: f580d27e8928 ("ksmbd: fix use-after-free of a deferred file_lock on double SMB2_CANCEL") +Cc: stable@vger.kernel.org +Signed-off-by: Gil Portnoy +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smb2pdu.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -7334,14 +7334,14 @@ int smb2_cancel(struct ksmbd_work *work) + continue; + + /* +- * A cancelled deferred byte-range lock frees its +- * file_lock and takes the smb2_lock() early-exit that +- * skips release_async_work(), so the work stays on +- * conn->async_requests with a live cancel_fn pointing +- * at the freed file_lock. Re-firing it on a second +- * SMB2_CANCEL is a use-after-free. ++ * Only an ACTIVE deferred work may have its cancel_fn ++ * fired. A CANCELLED or CLOSED work already took the ++ * smb2_lock() non-ACTIVE early-exit that frees the ++ * file_lock and skips release_async_work(), so it is ++ * still on conn->async_requests with a live cancel_fn ++ * pointing at the freed file_lock. + */ +- if (iter->state == KSMBD_WORK_CANCELLED) ++ if (iter->state != KSMBD_WORK_ACTIVE) + break; + + ksmbd_debug(SMB, diff --git a/queue-6.18/media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch b/queue-6.18/media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch new file mode 100644 index 0000000000..e60abe1de8 --- /dev/null +++ b/queue-6.18/media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch @@ -0,0 +1,48 @@ +From c32fe4c4918c9aa49f61359e3b42619c4d8686de Mon Sep 17 00:00:00 2001 +From: Ricardo Ribalda +Date: Thu, 7 May 2026 20:58:10 +0000 +Subject: media: staging: ipu3-imgu: Add range check for imgu_css_cfg_acc_stripe + +From: Ricardo Ribalda + +commit c32fe4c4918c9aa49f61359e3b42619c4d8686de upstream. + +If the driver's stripe information is invalid it can result in an integer +underflow. Add a range check to avoid this kind of error. + +This patch fixes the following smatch error: +drivers/staging/media/ipu3/ipu3-css-params.c:1792 imgu_css_cfg_acc_stripe() warn: 'acc->stripe.bds_out_stripes[0]->width - 2 * f' 4294967168 can't fit into 65535 'acc->stripe.bds_out_stripes[1]->offset' + +Cc: stable@vger.kernel.org +Fixes: e11110a5b744 ("media: staging/intel-ipu3: css: Compute and program ccs") +Signed-off-by: Ricardo Ribalda +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/ipu3/ipu3-css-params.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/staging/media/ipu3/ipu3-css-params.c ++++ b/drivers/staging/media/ipu3/ipu3-css-params.c +@@ -1770,6 +1770,8 @@ static int imgu_css_cfg_acc_stripe(struc + acc->stripe.bds_out_stripes[0].width = + ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f); + } else { ++ u32 offset; ++ + /* Image processing is divided into two stripes */ + acc->stripe.bds_out_stripes[0].width = + acc->stripe.bds_out_stripes[1].width = +@@ -1788,8 +1790,10 @@ static int imgu_css_cfg_acc_stripe(struc + acc->stripe.bds_out_stripes[1].width += f; + } + /* Overlap between stripes is IPU3_UAPI_ISP_VEC_ELEMS * 4 */ +- acc->stripe.bds_out_stripes[1].offset = +- acc->stripe.bds_out_stripes[0].width - 2 * f; ++ offset = acc->stripe.bds_out_stripes[0].width - 2 * f; ++ if (offset > 65535) ++ return -EINVAL; ++ acc->stripe.bds_out_stripes[1].offset = offset; + } + + acc->stripe.effective_stripes[0].height = diff --git a/queue-6.18/mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch b/queue-6.18/mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch new file mode 100644 index 0000000000..ad5f2bacfb --- /dev/null +++ b/queue-6.18/mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch @@ -0,0 +1,70 @@ +From 8b2c1d41bc36c100b38ce5ee6def246c527eaf8a Mon Sep 17 00:00:00 2001 +From: Andrei Kuchynski +Date: Mon, 27 Apr 2026 13:17:21 +0000 +Subject: mfd: cros_ec: Delay dev_set_drvdata() until probe success + +From: Andrei Kuchynski + +commit 8b2c1d41bc36c100b38ce5ee6def246c527eaf8a upstream. + +If ec_device_probe() fails, cros_ec_class_release releases memory for the +cros_ec_dev structure. However, because the drvdata was already set, +sub-drivers like cros_ec_typec can still retrieve the stale pointer via the +platform device. This leads to a use-after-free when cros_ec_typec attempts +to access &typec->ec->ec->dev on a device that has already been released. +Move dev_set_drvdata() to ensure that the pointer is only made available +once all initialization steps have succeeded. + + sysfs: cannot create duplicate filename '/class/chromeos/cros_ec' + Call trace: + sysfs_do_create_link_sd+0x94/0xdc + sysfs_create_link+0x30/0x44 + device_add_class_symlinks+0x90/0x13c + device_add+0xf0/0x50c + ec_device_probe+0x150/0x4f0 + platform_probe+0xa0/0xe0 + ... + BUG: KASAN: invalid-access in __memcpy+0x44/0x230 + Write at addr f5ffff809e2d33ac by task kworker/u32:5/125 + Pointer tag: [f5], memory tag: [fe] + Tainted : [W]=WARN, [O]=OOT_MODULE + Hardware name: Google Navi unprovisioned 0x7FFFFFFF/sku0 board/sku3 + Workqueue: events_unbound deferred_probe_work_func + Call trace: + __memcpy+0x44/0x230 + cros_ec_check_features+0x60/0xcc [cros_ec_proto] + cros_typec_probe+0xe8/0x6e0 [cros_ec_typec] + platform_probe+0xa0/0xe0 + +Cc: stable@vger.kernel.org +Fixes: 1c1d152cc5ac ("platform/chrome: cros_ec_dev - utilize new cdev_device_add helper function") +Co-developed-by: Sergey Senozhatsky +Signed-off-by: Sergey Senozhatsky +Signed-off-by: Andrei Kuchynski +Reviewed-by: Benson Leung +Link: https://patch.msgid.link/20260427131721.1165078-1-akuchynski@chromium.org +Signed-off-by: Lee Jones +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mfd/cros_ec_dev.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mfd/cros_ec_dev.c ++++ b/drivers/mfd/cros_ec_dev.c +@@ -195,7 +195,6 @@ static int ec_device_probe(struct platfo + if (!ec) + return retval; + +- dev_set_drvdata(dev, ec); + ec->ec_dev = dev_get_drvdata(dev->parent); + ec->dev = dev; + ec->cmd_offset = ec_platform->cmd_offset; +@@ -237,6 +236,8 @@ static int ec_device_probe(struct platfo + if (retval) + goto failed; + ++ dev_set_drvdata(dev, ec); ++ + /* check whether this EC is a sensor hub. */ + if (cros_ec_get_sensor_count(ec) > 0) { + retval = mfd_add_hotplug_devices(ec->dev, diff --git a/queue-6.18/mm-damon-ops-common-handle-extreme-intervals-in-damon_hot_score.patch b/queue-6.18/mm-damon-ops-common-handle-extreme-intervals-in-damon_hot_score.patch new file mode 100644 index 0000000000..f0171a8932 --- /dev/null +++ b/queue-6.18/mm-damon-ops-common-handle-extreme-intervals-in-damon_hot_score.patch @@ -0,0 +1,90 @@ +From 35d4a3cf70a855b50e53189ac2f8463e20a02046 Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Tue, 23 Jun 2026 06:58:31 -0700 +Subject: mm/damon/ops-common: handle extreme intervals in damon_hot_score() + +From: SeongJae Park + +commit 35d4a3cf70a855b50e53189ac2f8463e20a02046 upstream. + +Fix three issues in damon_hot_score() that comes from wrong handling of +extreme (zero or too high) monitoring intervals user setup. + +When the user sets sampling interval zero, damon_max_nr_accesses(), which +is called from damon_hot_score(), causes a divide-by-zero. Needless to +say, it is a problem. + +When the user sets the aggregation interval zero, the function returns +zero. It is wrong, since the real maximum nr_acceses in the setup should +be one. Worse yet, it can cause another divide-by-zero from its caller, +damon_hot_score(), since it uses damon_max_nr_accesses() return value as a +denominator. + +When the user sets the aggregation interval very high, damon_hot_score() +could return a value out of [0, DAMOS_MAX_SCORE] range. Since the return +value is used as an index to the regions_score_histogram array, which is +DAMOS_MAX_SCORE+1 size, it causes out of bounds array access. + +The issues can be relatively easily reproduced like below. The sysfs +write permission is required, though. + + # ./damo start --damos_action lru_prio --damos_quota_space 100M \ + --damos_quota_interval 1s + # cd /sys/kernel/mm/damon/admin/kdamonds/0 + # echo 0 > contexts/0/monitoring_attrs/intervals/sample_us + # echo 0 > contexts/0/monitoring_attrs/intervals/aggr_us + # echo commit > state + # dmesg + [...] + [ 131.329762] Oops: divide error: 0000 [#1] SMP NOPTI + [...] + [ 131.336089] RIP: 0010:damon_hot_score+0x27/0xd0 + [...] + +Fix the divide-by-zero intervals problems by explicitly handling the zero +intervals in damon_max_nr_accesses(). Fix the out-of-bound array access +by applying [0, DAMOS_MAX_SCORE] bounds before returning from +damon_hot_score(). + +The issue was discovered [1] by Sashiko. + +Link: https://lore.kernel.org/20260623135834.67189-1-sj@kernel.org +Link: https://lore.kernel.org/20260619202459.145010-1-sj@kernel.org [1] +Fixes: 198f0f4c58b9 ("mm/damon/vaddr,paddr: support pageout prioritization") +Signed-off-by: SeongJae Park +Cc: # 5.16.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/damon.h | 8 ++++++-- + mm/damon/ops-common.c | 1 + + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/include/linux/damon.h ++++ b/include/linux/damon.h +@@ -939,9 +939,13 @@ static inline bool damon_target_has_pid( + + static inline unsigned int damon_max_nr_accesses(const struct damon_attrs *attrs) + { +- /* {aggr,sample}_interval are unsigned long, hence could overflow */ +- return min(attrs->aggr_interval / attrs->sample_interval, ++ unsigned long sample_interval; ++ unsigned long max_nr_accesses; ++ ++ sample_interval = attrs->sample_interval ? : 1; ++ max_nr_accesses = min(attrs->aggr_interval / sample_interval, + (unsigned long)UINT_MAX); ++ return max_nr_accesses ? : 1; + } + + +--- a/mm/damon/ops-common.c ++++ b/mm/damon/ops-common.c +@@ -128,6 +128,7 @@ int damon_hot_score(struct damon_ctx *c, + * Transform it to fit in [0, DAMOS_MAX_SCORE] + */ + hotness = hotness * DAMOS_MAX_SCORE / DAMON_MAX_SUBSCORE; ++ hotness = max(min(hotness, DAMOS_MAX_SCORE), 0); + + return hotness; + } diff --git a/queue-6.18/mm-shrinker-do-not-hold-rcu-lock-in-shrinker_debugfs_count_show.patch b/queue-6.18/mm-shrinker-do-not-hold-rcu-lock-in-shrinker_debugfs_count_show.patch new file mode 100644 index 0000000000..8ab76f0d2b --- /dev/null +++ b/queue-6.18/mm-shrinker-do-not-hold-rcu-lock-in-shrinker_debugfs_count_show.patch @@ -0,0 +1,74 @@ +From b902890c62d200b3509cb5e09cf1e0a66553c128 Mon Sep 17 00:00:00 2001 +From: Shakeel Butt +Date: Wed, 10 Jun 2026 16:20:48 -0700 +Subject: mm/shrinker: do not hold RCU lock in shrinker_debugfs_count_show() + +From: Shakeel Butt + +commit b902890c62d200b3509cb5e09cf1e0a66553c128 upstream. + +Reading the debugfs "count" file of a memcg-aware shrinker can sleep +inside an RCU read-side critical section: + + BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 + RCU nest depth: 1, expected: 0 + css_rstat_flush + mem_cgroup_flush_stats + zswap_shrinker_count + shrinker_debugfs_count_show + +shrinker_debugfs_count_show() invokes the ->count_objects() callback under +rcu_read_lock(). The zswap callback flushes memcg stats via +css_rstat_flush(), which may sleep, so it must not run under RCU. + +The RCU lock is not needed here. mem_cgroup_iter() takes RCU internally +and returns a memcg holding a css reference (dropped on the next iteration +or by mem_cgroup_iter_break()), so the memcg stays alive without it. The +shrinker is kept alive by the open debugfs file: shrinker_free() removes +the debugfs entries via debugfs_remove_recursive(), which waits for +in-flight readers to drain, before call_rcu(..., shrinker_free_rcu_cb). +The sibling "scan" handler already invokes the sleeping ->scan_objects() +callback with no RCU section. + +Drop the rcu_read_lock()/rcu_read_unlock(). + +Link: https://lore.kernel.org/20260610232048.62930-1-shakeel.butt@linux.dev +Fixes: 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers") +Signed-off-by: Shakeel Butt +Reported-by: Zenghui Yu +Closes: https://lore.kernel.org/all/c052a064-cddb-494f-a0d8-f8a10b4b1c4d@linux.dev/ +Suggested-by: Nhat Pham +Reviewed-by: SeongJae Park +Reviewed-by: Qi Zheng +Tested-by: Zenghui Yu (Huawei) +Reviewed-by: Nhat Pham +Acked-by: Muchun Song +Reviewed-by: Roman Gushchin +Cc: Dave Chinner +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/shrinker_debug.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/mm/shrinker_debug.c ++++ b/mm/shrinker_debug.c +@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(s + if (!count_per_node) + return -ENOMEM; + +- rcu_read_lock(); +- + memcg_aware = shrinker->flags & SHRINKER_MEMCG_AWARE; + + memcg = mem_cgroup_iter(NULL, NULL, NULL); +@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(s + } + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL); + +- rcu_read_unlock(); +- + kfree(count_per_node); + return ret; + } diff --git a/queue-6.18/mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch b/queue-6.18/mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch new file mode 100644 index 0000000000..19dedc5c2d --- /dev/null +++ b/queue-6.18/mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch @@ -0,0 +1,73 @@ +From e30453c61e185e914fde83c650e268067b140218 Mon Sep 17 00:00:00 2001 +From: Qi Zheng +Date: Wed, 17 Jun 2026 17:00:52 +0800 +Subject: mm: shrinker: fix NULL pointer dereference in debugfs + +From: Qi Zheng + +commit e30453c61e185e914fde83c650e268067b140218 upstream. + +shrinker_debugfs_add() creates both "count" and "scan" debugfs files +unconditionally. + +That assumes every shrinker implements both count_objects() and +scan_objects(), which is not guaranteed. For example, the xen-backend +shrinker sets count_objects() but leaves scan_objects() NULL, so writing +to its scan file calls through a NULL function pointer and panics the +kernel: + +BUG: kernel NULL pointer dereference, address: 0000000000000000 +RIP: 0010:0x0 +Code: Unable to access opcode bytes at 0xffffffffffffffd6. +Call Trace: + + shrinker_debugfs_scan_write+0x12e/0x270 + full_proxy_write+0x5f/0x90 + vfs_write+0xde/0x420 + ? filp_flush+0x75/0x90 + ? filp_close+0x1d/0x30 + ? do_dup2+0xb8/0x120 + ksys_write+0x68/0xf0 + ? filp_flush+0x75/0x90 + do_syscall_64+0xb3/0x5b0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +The count path has the same issue in principle if a shrinker omits +count_objects(). + +To fix it, only create "count" and "scan" debugfs files when the +corresponding callbacks are present. + +Link: https://lore.kernel.org/20260617090052.27325-1-qi.zheng@linux.dev +Fixes: bbf535fd6f06 ("mm: shrinkers: add scan interface for shrinker debugfs") +Signed-off-by: Qi Zheng +Reviewed-by: Muchun Song +Cc: Dave Chinner +Cc: Qi Zheng +Cc: Roman Gushchin +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/shrinker_debug.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/mm/shrinker_debug.c ++++ b/mm/shrinker_debug.c +@@ -182,10 +182,12 @@ int shrinker_debugfs_add(struct shrinker + } + shrinker->debugfs_entry = entry; + +- debugfs_create_file("count", 0440, entry, shrinker, +- &shrinker_debugfs_count_fops); +- debugfs_create_file("scan", 0220, entry, shrinker, +- &shrinker_debugfs_scan_fops); ++ if (shrinker->count_objects) ++ debugfs_create_file("count", 0440, entry, shrinker, ++ &shrinker_debugfs_count_fops); ++ if (shrinker->scan_objects) ++ debugfs_create_file("scan", 0220, entry, shrinker, ++ &shrinker_debugfs_scan_fops); + return 0; + } + diff --git a/queue-6.18/mm-shrinker-fix-shrinker_info-teardown-race-with-expansion.patch b/queue-6.18/mm-shrinker-fix-shrinker_info-teardown-race-with-expansion.patch new file mode 100644 index 0000000000..bea4956d91 --- /dev/null +++ b/queue-6.18/mm-shrinker-fix-shrinker_info-teardown-race-with-expansion.patch @@ -0,0 +1,112 @@ +From 65476d31d8056e859c48580f82295ce159196ffe Mon Sep 17 00:00:00 2001 +From: Qi Zheng +Date: Wed, 17 Jun 2026 16:56:58 +0800 +Subject: mm: shrinker: fix shrinker_info teardown race with expansion + +From: Qi Zheng + +commit 65476d31d8056e859c48580f82295ce159196ffe upstream. + +expand_shrinker_info() iterates all visible memcgs under shrinker_mutex, +including memcgs that have not finished ->css_online() yet. + +Once pn->shrinker_info has been published, teardown must stay serialized +with expand_shrinker_info() until that memcg is either fully online or no +longer visible to iteration. Today alloc_shrinker_info() breaks that rule +by dropping shrinker_mutex before freeing a partially initialized +shrinker_info array, which may cause the following race: + +CPU0 CPU1 +==== ==== + +css_create +--> list_add_tail_rcu(&css->sibling, &parent_css->children); + online_css + --> mem_cgroup_css_online + --> alloc_shrinker_info + --> alloc node0 info + rcu_assign_pointer(C->node0->shrinker_info, old0) + alloc node1 info -> FAIL -> goto err + mutex_unlock(shrinker_mutex) + + shrinker_alloc() + --> shrinker_memcg_alloc + --> mutex_lock(shrinker_mutex) + expand_shrinker_info + --> mem_cgroup_iter see the memcg + expand_one_shrinker_info + --> old0 = C->node0->shrinker_info + memcpy(new->unit, old0->unit, ...); + + free_shrinker_info + --> kvfree(old0); + + /* double free !! */ + kvfree_rcu(old0, rcu); + +The same problem exists later in mem_cgroup_css_online(). If +alloc_shrinker_info() succeeds but a subsequent objcg allocation fails, +the free_objcg -> free_shrinker_info() unwind path tears down the already +published pn->shrinker_info arrays without shrinker_mutex. The +expand_one_shrinker_info() can race with that teardown in the same way, +leading to use-after-free or double-free of the old shrinker_info. + +Fix this by serializing shrinker_info teardown with shrinker_mutex, and by +keeping alloc_shrinker_info() error cleanup inside the locked section. + +Link: https://lore.kernel.org/20260617085658.27096-1-qi.zheng@linux.dev +Fixes: 307bececcd12 ("mm: shrinker: add a secondary array for shrinker_info::{map, nr_deferred}") +Signed-off-by: Qi Zheng +Acked-by: Muchun Song +Cc: Dave Chinner +Cc: Qi Zheng +Cc: Roman Gushchin +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/shrinker.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/mm/shrinker.c ++++ b/mm/shrinker.c +@@ -59,12 +59,14 @@ static inline int shrinker_unit_alloc(st + return 0; + } + +-void free_shrinker_info(struct mem_cgroup *memcg) ++static void __free_shrinker_info(struct mem_cgroup *memcg) + { + struct mem_cgroup_per_node *pn; + struct shrinker_info *info; + int nid; + ++ lockdep_assert_held(&shrinker_mutex); ++ + for_each_node(nid) { + pn = memcg->nodeinfo[nid]; + info = rcu_dereference_protected(pn->shrinker_info, true); +@@ -74,6 +76,13 @@ void free_shrinker_info(struct mem_cgrou + } + } + ++void free_shrinker_info(struct mem_cgroup *memcg) ++{ ++ mutex_lock(&shrinker_mutex); ++ __free_shrinker_info(memcg); ++ mutex_unlock(&shrinker_mutex); ++} ++ + int alloc_shrinker_info(struct mem_cgroup *memcg) + { + int nid, ret = 0; +@@ -98,8 +107,8 @@ int alloc_shrinker_info(struct mem_cgrou + return ret; + + err: ++ __free_shrinker_info(memcg); + mutex_unlock(&shrinker_mutex); +- free_shrinker_info(memcg); + return -ENOMEM; + } + diff --git a/queue-6.18/mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch b/queue-6.18/mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch new file mode 100644 index 0000000000..c3971d90e1 --- /dev/null +++ b/queue-6.18/mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch @@ -0,0 +1,63 @@ +From 66366d291f666ddeda5f8c84f253e308de3e6b55 Mon Sep 17 00:00:00 2001 +From: Zijiang Huang +Date: Wed, 6 May 2026 21:09:19 +0800 +Subject: mm/swap: add cond_resched() in swap_reclaim_full_clusters to prevent softlockup + +From: Zijiang Huang + +commit 66366d291f666ddeda5f8c84f253e308de3e6b55 upstream. + +We hit a real softlockup in an internal stress test environment. The +workload was LTP memory/swap stress on a large arm64 machine, with 320 +CPUs, about 1TB memory and an 8.6GB swap device. The system was under +heavy load and the swap device had a large number of full clusters. The +softlockup was triggered during a stress test after about 3 days. + +So, add periodic cond_resched() calls during large full_clusters +reclaim operations to prevent softlockup issues. + +Detailed call trace as follow: + +PID: 3817773 TASK: ffff0883bb28b780 CPU: 48 COMMAND: "kworker/48:7" + #0 [ffff800080183d10] __crash_kexec at ffffa4c1361e5de4 + #1 [ffff800080183d90] panic at ffffa4c1360d5e9c + #2 [ffff800080183e20] watchdog_timer_fn at ffffa4c136231fa8 + ... + #16 [ffff8000c4ad3cb0] swap_cache_del_folio at ffffa4c1363e1614 + #17 [ffff8000c4ad3ce0] __try_to_reclaim_swap at ffffa4c1363e4bfc + #18 [ffff8000c4ad3d40] swap_reclaim_full_clusters at ffffa4c1363e5474 + #19 [ffff8000c4ad3da0] swap_reclaim_work at ffffa4c1363e550c + #20 [ffff8000c4ad3dc0] process_one_work at ffffa4c136102edc + #21 [ffff8000c4ad3e10] worker_thread at ffffa4c136103398 + #22 [ffff8000c4ad3e70] kthread at ffffa4c13610d95c + +Link: https://lore.kernel.org/20260506130919.2298807-1-kerayhuang@tencent.com +Fixes: 5168a68eb78f ("mm, swap: avoid over reclaim of full clusters") +Signed-off-by: Zijiang Huang +Reviewed-by: Kairui Song +Reviewed-by: Hao Peng +Reviewed-by: albinwyang +Reviewed-by: Baoquan He +Acked-by: Chris Li +Cc: Barry Song +Cc: Kairui Song +Cc: Kemeng Shi +Cc: Nhat Pham +Cc: Youngjun Park +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/swapfile.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -1008,6 +1008,7 @@ static void swap_reclaim_full_clusters(s + swap_cluster_unlock(ci); + if (to_scan <= 0) + break; ++ cond_resched(); + } + } + diff --git a/queue-6.18/mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch b/queue-6.18/mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch new file mode 100644 index 0000000000..197a575c34 --- /dev/null +++ b/queue-6.18/mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch @@ -0,0 +1,75 @@ +From 63b02a9409cb5180398491b093e48bcb5315f5fb Mon Sep 17 00:00:00 2001 +From: "Jose Fernandez (Anthropic)" +Date: Mon, 4 May 2026 12:55:17 +0000 +Subject: mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host + +From: Jose Fernandez (Anthropic) + +commit 63b02a9409cb5180398491b093e48bcb5315f5fb upstream. + +lookup_swap_cgroup_id() passes swap_cgroup_ctrl[type].map to +__swap_cgroup_id_lookup() without checking that the type was ever +registered via swap_cgroup_swapon(). On a swapless host every ctrl->map +is NULL, so __swap_cgroup_id_lookup() dereferences NULL + a scaled +swp_offset(). + +Since commit bea67dcc5eea ("mm: attempt to batch free swap entries for +zap_pte_range()"), zap_pte_range() -> swap_pte_batch() calls +lookup_swap_cgroup_id() on any non-present, non-none PTE that decodes as a +real swap entry, without first validating it against swap_info[]. A +single PTE corrupted into a type-0 swap entry takes the host down at +process exit. + +We hit this in production on a swapless 6.12.58 host: ~1s of +"get_swap_device: Bad swap file entry 3f800204222bb" (do_swap_page() being +correctly defensive about the same entry) followed by + + BUG: unable to handle page fault for address: 000003f800204220 + RIP: 0010:lookup_swap_cgroup_id+0x2b/0x60 + Call Trace: + swap_pte_batch+0xbf/0x230 + zap_pte_range+0x4c8/0x780 + unmap_page_range+0x190/0x3e0 + exit_mmap+0xd9/0x3c0 + do_exit+0x20c/0x4b0 + +syzbot has reported the identical stack. + +The source of the PTE corruption is a separate bug; this change makes the +teardown path as robust as the fault path already is. Every other caller +of lookup_swap_cgroup_id() is downstream of a get_swap_device() that has +already validated the entry, so the new branch is cold. + +Link: https://lore.kernel.org/20260504-swap-cgroup-fix-7-0-v1-1-f53ff41ee553@linux.dev +Fixes: bea67dcc5eea ("mm: attempt to batch free swap entries for zap_pte_range()") +Signed-off-by: Jose Fernandez (Anthropic) +Reported-by: syzbot+e12bd9ca48157add237a@syzkaller.appspotmail.com +Link: https://lore.kernel.org/r/69859728.050a0220.3b3015.0033.GAE@google.com +Assisted-by: Claude:unspecified +Cc: Barry Song +Cc: David Hildenbrand +Cc: Hugh Dickins +Cc: Johannes Weiner +Cc: Kairui Song +Cc: Michal Hocko +Cc: Muchun Song +Cc: Roman Gushchin +Cc: Shakeel Butt +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/swap_cgroup.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/mm/swap_cgroup.c ++++ b/mm/swap_cgroup.c +@@ -124,6 +124,8 @@ unsigned short lookup_swap_cgroup_id(swp + return 0; + + ctrl = &swap_cgroup_ctrl[swp_type(ent)]; ++ if (unlikely(!ctrl->map)) ++ return 0; + return __swap_cgroup_id_lookup(ctrl->map, swp_offset(ent)); + } + diff --git a/queue-6.18/net-af_key-initialize-alg_key_len-for-ipcomp-states.patch b/queue-6.18/net-af_key-initialize-alg_key_len-for-ipcomp-states.patch new file mode 100644 index 0000000000..2b12c2e637 --- /dev/null +++ b/queue-6.18/net-af_key-initialize-alg_key_len-for-ipcomp-states.patch @@ -0,0 +1,111 @@ +From d129c3177d7b1138fd5066fcc63a698b3ba415b0 Mon Sep 17 00:00:00 2001 +From: Zijing Yin +Date: Mon, 8 Jun 2026 07:44:41 -0700 +Subject: net: af_key: initialize alg_key_len for IPComp states + +From: Zijing Yin + +commit d129c3177d7b1138fd5066fcc63a698b3ba415b0 upstream. + +pfkey_msg2xfrm_state() handles the IPComp (SADB_X_SATYPE_IPCOMP) case by +allocating x->calg and copying only the algorithm name: + + x->calg = kmalloc_obj(*x->calg); + if (!x->calg) { + err = -ENOMEM; + goto out; + } + strcpy(x->calg->alg_name, a->name); + x->props.calgo = sa->sadb_sa_encrypt; + +Unlike the authentication (x->aalg) and encryption (x->ealg) branches of +the same function, the compression branch never initializes +calg->alg_key_len. IPComp carries no key and the allocation only +reserves sizeof(struct xfrm_algo) (i.e. no room for a key), so the field +is left containing uninitialized slab data. + +calg->alg_key_len is later used as a length by xfrm_algo_clone() when an +IPComp state is cloned during XFRM_MSG_MIGRATE: + + xfrm_state_migrate() + xfrm_state_clone_and_setup() + x->calg = xfrm_algo_clone(orig->calg); + kmemdup(orig, xfrm_alg_len(orig)); + +where xfrm_alg_len() returns sizeof(*alg) + (alg_key_len + 7) / 8. With +a non-zero garbage alg_key_len, kmemdup() reads past the end of the +68-byte calg object. Adding an IPComp SA via PF_KEY and then migrating +it triggers (net-next, KASAN, init_on_alloc=0): + + BUG: KASAN: slab-out-of-bounds in kmemdup_noprof+0x44/0x60 + Read of size 4164 at addr ff11000025a74980 by task diag2/9287 + CPU: 3 UID: 0 PID: 9287 Comm: diag2 7.1.0-rc6-g903db046d557 #1 + Call Trace: + + dump_stack_lvl+0x10e/0x1f0 + print_report+0xf7/0x600 + kasan_report+0xe4/0x120 + kasan_check_range+0x105/0x1b0 + __asan_memcpy+0x23/0x60 + kmemdup_noprof+0x44/0x60 + xfrm_state_migrate+0x70a/0x1da0 + xfrm_migrate+0x753/0x18a0 + xfrm_do_migrate+0xb47/0xf10 + xfrm_user_rcv_msg+0x411/0xb50 + netlink_rcv_skb+0x158/0x420 + xfrm_netlink_rcv+0x71/0x90 + netlink_unicast+0x584/0x850 + netlink_sendmsg+0x8b0/0xdc0 + ____sys_sendmsg+0x9f7/0xb90 + ___sys_sendmsg+0x134/0x1d0 + __sys_sendmsg+0x16d/0x220 + do_syscall_64+0x116/0x7d0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + Allocated by task 9287: + kasan_save_stack+0x33/0x60 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0xaa/0xb0 + pfkey_add+0x2652/0x2ea0 + pfkey_process+0x6d0/0x830 + pfkey_sendmsg+0x42c/0x850 + __sys_sendto+0x461/0x4b0 + __x64_sys_sendto+0xe0/0x1c0 + do_syscall_64+0x116/0x7d0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + The buggy address belongs to the object at ff11000025a74980 + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes inside of + allocated 68-byte region [ff11000025a74980, ff11000025a749c4) + +Depending on the uninitialized value the same field can instead request +an oversized kmemdup() allocation and make the migration clone fail. + +The XFRM netlink path is not affected: verify_one_alg() rejects an +XFRMA_ALG_COMP attribute shorter than xfrm_alg_len(), so a calg added via +XFRM_MSG_NEWSA is always self-consistent. + +Initialize calg->alg_key_len to 0, matching the aalg/ealg branches. + +Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)") +Cc: stable@vger.kernel.org +Signed-off-by: Zijing Yin +Reviewed-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/key/af_key.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -1218,6 +1218,7 @@ static struct xfrm_state * pfkey_msg2xfr + goto out; + } + strcpy(x->calg->alg_name, a->name); ++ x->calg->alg_key_len = 0; + x->props.calgo = sa->sadb_sa_encrypt; + } else { + int keysize = 0; diff --git a/queue-6.18/net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch b/queue-6.18/net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch new file mode 100644 index 0000000000..8cf962cb66 --- /dev/null +++ b/queue-6.18/net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch @@ -0,0 +1,100 @@ +From efb8763d7bbb40cff4cc55a6b62c3095a038149c Mon Sep 17 00:00:00 2001 +From: Wyatt Feng +Date: Mon, 15 Jun 2026 18:31:18 +0800 +Subject: net: ipv4: bound TCP reordering sysctl writes and MTU probe sizes + +From: Wyatt Feng + +commit efb8763d7bbb40cff4cc55a6b62c3095a038149c upstream. + +Reject invalid `net.ipv4.tcp_reordering` values before they reach TCP +socket state. The sysctl is stored as an `int` but copied into the +`u32` `tp->reordering` field for new sockets, so negative writes wrap +to large values. + +With `tcp_mtu_probing=2`, the wrapped value can overflow the +`tcp_mtu_probe()` size calculation and drive the MTU probing path into +an out-of-bounds read. Route `tcp_reordering` writes through +`proc_dointvec_minmax()` and require it to be at least 1. Also require +`tcp_max_reordering` to be at least 1 so the configured maximum cannot +become negative either. + +When registering the table for a non-init network namespace, relocate +`extra2` pointers that refer into `init_net.ipv4` so the +`tcp_reordering` upper bound follows that namespace's +`tcp_max_reordering`. + +Harden `tcp_mtu_probe()` itself by computing `size_needed` as `u64`. +This keeps the send queue and window checks from being bypassed through +signed integer overflow. + +Fixes: 91cc17c0e5e5 ("[TCP]: MTUprobe: receiver window & data available checks fixed") +Cc: stable@vger.kernel.org +Reported-by: Yuan Tan +Reported-by: Zhengchuan Liang +Reported-by: Xin Liu +Suggested-by: Eric Dumazet +Signed-off-by: Wyatt Feng +Signed-off-by: Ren Wei +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/1a5b7e1ef4d70fbad8c8ee0b82d8405f3c964a3d.1781395200.git.bronzed_45_vested@icloud.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/sysctl_net_ipv4.c | 10 ++++++++-- + net/ipv4/tcp_output.c | 4 ++-- + 2 files changed, 10 insertions(+), 4 deletions(-) + +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -1040,7 +1040,9 @@ static struct ctl_table ipv4_net_table[] + .data = &init_net.ipv4.sysctl_tcp_reordering, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = &init_net.ipv4.sysctl_tcp_max_reordering, + }, + { + .procname = "tcp_retries1", +@@ -1275,7 +1277,8 @@ static struct ctl_table ipv4_net_table[] + .data = &init_net.ipv4.sysctl_tcp_max_reordering, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, + }, + { + .procname = "tcp_dsack", +@@ -1640,6 +1643,9 @@ static __net_init int ipv4_sysctl_init_n + */ + table[i].mode &= ~0222; + } ++ if (table[i].extra2 >= (void *)&init_net.ipv4 && ++ table[i].extra2 < (void *)(&init_net.ipv4 + 1)) ++ table[i].extra2 += (void *)net - (void *)&init_net; + } + } + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2604,7 +2604,7 @@ static int tcp_mtu_probe(struct sock *sk + struct sk_buff *skb, *nskb, *next; + struct net *net = sock_net(sk); + int probe_size; +- int size_needed; ++ u64 size_needed; + int copy, len; + int mss_now; + int interval; +@@ -2628,7 +2628,7 @@ static int tcp_mtu_probe(struct sock *sk + mss_now = tcp_current_mss(sk); + probe_size = tcp_mtu_to_mss(sk, (icsk->icsk_mtup.search_high + + icsk->icsk_mtup.search_low) >> 1); +- size_needed = probe_size + (tp->reordering + 1) * tp->mss_cache; ++ size_needed = probe_size + (tp->reordering + 1) * (u64)tp->mss_cache; + interval = icsk->icsk_mtup.search_high - icsk->icsk_mtup.search_low; + /* When misfortune happens, we are reprobing actively, + * and then reprobe timer has expired. We stick with current diff --git a/queue-6.18/netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch b/queue-6.18/netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch new file mode 100644 index 0000000000..ee9c8fe840 --- /dev/null +++ b/queue-6.18/netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch @@ -0,0 +1,40 @@ +From a7f57320bbbc67e347bf5fff4b4a9bab980d5956 Mon Sep 17 00:00:00 2001 +From: Pratham Gupta +Date: Mon, 4 May 2026 22:11:57 -0700 +Subject: netfilter: ctnetlink: use nf_ct_exp_net() in expectation dump + +From: Pratham Gupta + +commit a7f57320bbbc67e347bf5fff4b4a9bab980d5956 upstream. + +Commit 02a3231b6d82 ("netfilter: nf_conntrack_expect: store netns and zone in expectation") +introduced exp->net so RCU-only expectation paths no longer need to +dereference exp->master for netns lookups. + +Commit 3db5647984de ("netfilter: nf_conntrack_expect: skip expectations in other netns via proc") +updated the proc path accordingly, but ctnetlink_exp_dump_table() still +compares against nf_ct_net(exp->master). + +Use nf_ct_exp_net(exp) here as well so the netlink dump path matches +the rest of the March 2026 expectation netns/RCU cleanup. + +Fixes: 02a3231b6d82 ("netfilter: nf_conntrack_expect: store netns and zone in expectation") +Cc: stable@vger.kernel.org +Signed-off-by: Pratham Gupta +Signed-off-by: Florian Westphal +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nf_conntrack_netlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -3159,7 +3159,7 @@ restart: + if (l3proto && exp->tuple.src.l3num != l3proto) + continue; + +- if (!net_eq(nf_ct_net(exp->master), net)) ++ if (!net_eq(nf_ct_exp_net(exp), net)) + continue; + + if (cb->args[1]) { diff --git a/queue-6.18/netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch b/queue-6.18/netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch new file mode 100644 index 0000000000..bfdb99d146 --- /dev/null +++ b/queue-6.18/netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch @@ -0,0 +1,77 @@ +From 7cd9103283b26b917360ec99d7d2f2d761bcf1ab Mon Sep 17 00:00:00 2001 +From: Xiang Mei +Date: Wed, 24 Jun 2026 18:00:06 -0700 +Subject: netfilter: ipset: fix race between dump and ip_set_list resize + +From: Xiang Mei + +commit 7cd9103283b26b917360ec99d7d2f2d761bcf1ab upstream. + +The release path of ip_set_dump_do() and ip_set_dump_done() read +inst->ip_set_list via ip_set_ref_netlink(), a plain rcu_dereference_raw() +of the array pointer. These run from netlink_recvmsg() without the nfnl +mutex and without an RCU read-side critical section. + +A concurrent ip_set_create() can grow the array: it publishes the new +array, calls synchronize_net() and then kvfree()s the old one. Since the +dump paths read the array outside any RCU reader, synchronize_net() does +not wait for them and the old array can be freed while they still index +into it, causing a use-after-free. + +The dumped set itself stays pinned via set->ref_netlink, so only the +array load needs protecting. Take rcu_read_lock() around it, matching +ip_set_get_byname() and __ip_set_put_byindex(). + + BUG: KASAN: slab-use-after-free in ip_set_dump_do (net/netfilter/ipset/ip_set_core.c:1697) + Read of size 8 at addr ffff88800b5c4018 by task exploit/150 + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ip_set_dump_do (net/netfilter/ipset/ip_set_core.c:1697) + netlink_dump (net/netlink/af_netlink.c:2325) + netlink_recvmsg (net/netlink/af_netlink.c:1976) + sock_recvmsg (net/socket.c:1159) + __sys_recvfrom (net/socket.c:2315) + ... + Oops: general protection fault, probably for non-canonical address ... KASAN NOPTI + KASAN: maybe wild-memory-access in range [0x02d6...d0-0x02d6...d7] + RIP: 0010:ip_set_dump_do (net/netfilter/ipset/ip_set_core.c:1698) + Kernel panic - not syncing: Fatal exception + +Fixes: 8a02bdd50b2e ("netfilter: ipset: Fix calling ip_set() macro at dumping") +Cc: stable@vger.kernel.org +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Jozsef Kadlecsik +Signed-off-by: Florian Westphal +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipset/ip_set_core.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1480,7 +1480,11 @@ ip_set_dump_done(struct netlink_callback + struct ip_set_net *inst = + (struct ip_set_net *)cb->args[IPSET_CB_NET]; + ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX]; +- struct ip_set *set = ip_set_ref_netlink(inst, index); ++ struct ip_set *set; ++ ++ rcu_read_lock(); ++ set = ip_set_ref_netlink(inst, index); ++ rcu_read_unlock(); + + if (set->variant->uref) + set->variant->uref(set, cb, false); +@@ -1685,7 +1689,9 @@ next_set: + release_refcount: + /* If there was an error or set is done, release set */ + if (ret || !cb->args[IPSET_CB_ARG0]) { ++ rcu_read_lock(); + set = ip_set_ref_netlink(inst, index); ++ rcu_read_unlock(); + if (set->variant->uref) + set->variant->uref(set, cb, false); + pr_debug("release set %s\n", set->name); diff --git a/queue-6.18/netpoll-fix-a-use-after-free-on-shutdown-path.patch b/queue-6.18/netpoll-fix-a-use-after-free-on-shutdown-path.patch new file mode 100644 index 0000000000..c5cde4b389 --- /dev/null +++ b/queue-6.18/netpoll-fix-a-use-after-free-on-shutdown-path.patch @@ -0,0 +1,91 @@ +From 45f1458a85017a023f138b22ac5c76abd477db42 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Thu, 25 Jun 2026 05:03:18 -0700 +Subject: netpoll: fix a use-after-free on shutdown path + +From: Breno Leitao + +commit 45f1458a85017a023f138b22ac5c76abd477db42 upstream. + +There is a use-after-free error on netpoll, which is clearly detected by +KASAN. + + BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x3b/0x80 + Read of size 1 at addr ... by task kworker/9:1 + Workqueue: events queue_process + Call Trace: + skb_dequeue+0x1e/0xb0 + queue_process+0x2c/0x600 + process_scheduled_works+0x4b6/0x850 + worker_thread+0x414/0x5a0 + Allocated by task 242: + __netpoll_setup+0x201/0x4a0 + netpoll_setup+0x249/0x550 + enabled_store+0x32f/0x380 + Freed by task 0: + kfree+0x1b7/0x540 + rcu_core+0x3f8/0x7a0 + +The problem happens when there is a pending TX worker running in +parallel with the cleanup path. + +This is what happens on netpoll shutdown path: + +1) __netpoll_cleanup() is called +2) set dev->npinfo to NULL +3) call_rcu() with rcu_cleanup_netpoll_info() + 3.1) rcu_cleanup_netpoll_info() tries to cancel all workers with + cancel_delayed_work(), but doesn't wait for the worker to finish +4) and kfree(npinfo); + +Because 3.1) doesn't really cancel the work, as the comment says "we +can't call cancel_delayed_work_sync here, as we are in softirq", the TX +worker can run after 4). + +Tl;DR: queue_process() is not an RCU reader, it reaches npinfo through +the work item via container_of(). + +Use disable_delayed_work_sync() to ensure the worker is completely +stopped and prevent any future re-arming attempts. Once npinfo is set +to NULL, senders will bail out and not queue new work. The disable flag +ensures any in-flight re-arming attempts also fail silently. + +In the future, we can do the cleanup inline here without needing the +npinfo->rcu rcu_head, but that is net-next material. + +Cc: stable@vger.kernel.org +Fixes: 38e6bc185d95 ("netpoll: make __netpoll_cleanup non-block") +Reviewed-by: Pavan Chebbi +Signed-off-by: Breno Leitao +Link: https://patch.msgid.link/20260625-netpoll_rcu_fix-v2-1-0748ffac1e98@debian.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/core/netpoll.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -812,14 +812,6 @@ static void rcu_cleanup_netpoll_info(str + container_of(rcu_head, struct netpoll_info, rcu); + + skb_queue_purge(&npinfo->txq); +- +- /* we can't call cancel_delayed_work_sync here, as we are in softirq */ +- cancel_delayed_work(&npinfo->tx_work); +- +- /* clean after last, unfinished work */ +- __skb_queue_purge(&npinfo->txq); +- /* now cancel it again */ +- cancel_delayed_work(&npinfo->tx_work); + kfree(npinfo); + } + +@@ -843,6 +835,7 @@ static void __netpoll_cleanup(struct net + ops->ndo_netpoll_cleanup(np->dev); + + RCU_INIT_POINTER(np->dev->npinfo, NULL); ++ disable_delayed_work_sync(&npinfo->tx_work); + call_rcu(&npinfo->rcu, rcu_cleanup_netpoll_info); + } + diff --git a/queue-6.18/ntb-epf-avoid-calling-pci_irq_vector-from-hardirq-context.patch b/queue-6.18/ntb-epf-avoid-calling-pci_irq_vector-from-hardirq-context.patch new file mode 100644 index 0000000000..67495a5113 --- /dev/null +++ b/queue-6.18/ntb-epf-avoid-calling-pci_irq_vector-from-hardirq-context.patch @@ -0,0 +1,73 @@ +From 4dcddc1c794d1c65eda68f1f8dd04a0fecc0870f Mon Sep 17 00:00:00 2001 +From: Koichiro Den +Date: Wed, 4 Mar 2026 17:30:28 +0900 +Subject: NTB: epf: Avoid calling pci_irq_vector() from hardirq context + +From: Koichiro Den + +commit 4dcddc1c794d1c65eda68f1f8dd04a0fecc0870f upstream. + +ntb_epf_vec_isr() calls pci_irq_vector() in hardirq context to derive +the vector number. pci_irq_vector() calls msi_get_virq() that takes a +mutex and can therefore trigger "scheduling while atomic" splats: + + BUG: scheduling while atomic: kworker/u33:0/55/0x00010001 + ... + Call trace: + ... + schedule+0x38/0x110 + schedule_preempt_disabled+0x28/0x50 + __mutex_lock.constprop.0+0x848/0x908 + __mutex_lock_slowpath+0x18/0x30 + mutex_lock+0x4c/0x60 + msi_domain_get_virq+0xe8/0x138 + pci_irq_vector+0x2c/0x60 + ntb_epf_vec_isr+0x28/0x120 [ntb_hw_epf] + __handle_irq_event_percpu+0x70/0x3a8 + handle_irq_event+0x48/0x100 + handle_edge_irq+0x100/0x1c8 + ... + +Cache the Linux IRQ number for vector 0 when vectors are allocated and +use it as a base in the ISR. Running the ISR in a threaded IRQ handler +would also avoid the problem, but that would be unnecessary here. + +Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Bjorn Helgaas +Reviewed-by: Dave Jiang +Cc: stable@vger.kernel.org # v5.12+ +Link: https://patch.msgid.link/20260304083028.1391068-3-den@valinux.co.jp +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ntb/hw/epf/ntb_hw_epf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/ntb/hw/epf/ntb_hw_epf.c ++++ b/drivers/ntb/hw/epf/ntb_hw_epf.c +@@ -92,6 +92,7 @@ struct ntb_epf_dev { + + int db_val; + u64 db_valid_mask; ++ int irq_base; + }; + + #define ntb_ndev(__ntb) container_of(__ntb, struct ntb_epf_dev, ntb) +@@ -318,7 +319,7 @@ static irqreturn_t ntb_epf_vec_isr(int i + struct ntb_epf_dev *ndev = dev; + int irq_no; + +- irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0); ++ irq_no = irq - ndev->irq_base; + ndev->db_val = irq_no + 1; + + if (irq_no == 0) +@@ -350,6 +351,7 @@ static int ntb_epf_init_isr(struct ntb_e + argument &= ~MSIX_ENABLE; + } + ++ ndev->irq_base = pci_irq_vector(pdev, 0); + for (i = 0; i < irq; i++) { + ret = request_irq(pci_irq_vector(pdev, i), ntb_epf_vec_isr, + 0, "ntb_epf", ndev); diff --git a/queue-6.18/series b/queue-6.18/series index 833b6e1827..4c1aa383e8 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -141,3 +141,54 @@ pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch pci-qcom-initialize-dwc-msi-lock-for-firmware-managed-ecam-hosts.patch pci-iov-skip-vf-resizable-bar-restore-on-read-error.patch +tcp-restore-rcu-grace-period-in-tcp_ao_destroy_sock.patch +mm-damon-ops-common-handle-extreme-intervals-in-damon_hot_score.patch +netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch +virtio_pci-fix-vq-info-pointer-lookup-via-wrong-index.patch +virtio-mmio-fix-device-release-warning-on-module-unload.patch +hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch +usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch +usb-dwc3-run-gadget-disconnect-from-sleepable-suspend-context.patch +usb-misc-usbio-fix-disconnect-uaf-in-client-teardown.patch +6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch +tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch +staging-vme_user-bound-slave-read-write-to-the-kern_buf-size.patch +smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch +staging-vme_user-fix-location-monitor-leak-in-fake-bridge.patch +staging-vme_user-fix-location-monitor-leak-in-tsi148-bridge.patch +media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch +staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch +staging-media-ipu7-fix-double-free-and-use-after-free-in-error-paths.patch +staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch +staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch +staging-rtl8723bs-fix-oob-read-in-onassocrsp-ie-loop.patch +staging-rtl8723bs-fix-oob-read-in-update_beacon_info-ie-loop.patch +staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch +staging-rtl8723bs-fix-oob-reads-in-is_ap_in_tkip-ie-loop.patch +staging-rtl8723bs-fix-oob-write-in-ht_caps_handler.patch +crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch +crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch +ksmbd-fix-use-after-free-of-a-deferred-file_lock-on-smb2_close-then-smb2_cancel.patch +net-af_key-initialize-alg_key_len-for-ipcomp-states.patch +audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch +bluetooth-l2cap-fix-uaf-in-channel-timeout-by-holding-conn-ref.patch +bluetooth-mgmt-fix-uaf-of-hci_conn_params-in-add_device_complete.patch +coresight-etb10-restore-atomic_t-for-shared-reading-state.patch +debugobjects-plug-race-against-a-concurrent-oom-disable.patch +fs-ntfs3-validate-dirty-page-table-capacity-in-log_replay-copy_lcns.patch +ntb-epf-avoid-calling-pci_irq_vector-from-hardirq-context.patch +gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch +gpio-sch-use-raw_spinlock_t-in-the-irq-startup-path.patch +io_uring-nop-fix-file-reference-leak-with-iosqe_fixed_file.patch +io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch +io_uring-rw-preserve-partial-result-for-iopoll.patch +netpoll-fix-a-use-after-free-on-shutdown-path.patch +ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch +net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch +mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch +mm-shrinker-do-not-hold-rcu-lock-in-shrinker_debugfs_count_show.patch +mm-shrinker-fix-shrinker_info-teardown-race-with-expansion.patch +mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch +mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch +mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch +netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch diff --git a/queue-6.18/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch b/queue-6.18/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch new file mode 100644 index 0000000000..3432a973f4 --- /dev/null +++ b/queue-6.18/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch @@ -0,0 +1,202 @@ +From 53b7c271f06be4dd5cfc8c6ef552a8355c891a7f Mon Sep 17 00:00:00 2001 +From: Shoichiro Miyamoto +Date: Tue, 7 Jul 2026 20:23:58 +0900 +Subject: smb: client: restrict implied bcc[0] exemption to responses without data area + +From: Shoichiro Miyamoto + +commit 53b7c271f06be4dd5cfc8c6ef552a8355c891a7f upstream. + +smb2_check_message() has a long-standing quirk that accepts a response +whose calculated length is one byte larger than the bytes actually +received ("server can return one byte more due to implied bcc[0]"). +This was introduced to accommodate servers that omit the trailing bcc[0] +overlap byte when no data area is present. + +However, the exemption is applied unconditionally, regardless of whether +the command actually carries a data area (has_smb2_data_area[]). When a +response with a data area is subject to the +1 exemption, the reported +data can extend one byte beyond the bytes actually received, yet +smb2_check_message() still accepts it. The subsequent decoder then reads +past the end of the receive buffer. This is reachable during NEGOTIATE +and SESSION_SETUP, before the session is established. + +The resulting out-of-bounds reads are visible under KASAN when mounting +against a non-conforming server; both the SPNEGO/negTokenInit and the +NTLMSSP challenge decoders are affected: + + BUG: KASAN: slab-out-of-bounds in asn1_ber_decoder+0x16a7/0x1b00 + Read of size 1 at addr ffff8880084d67c0 by task mount.cifs/81 + CPU: 1 UID: 0 PID: 81 Comm: mount.cifs Not tainted 7.1.0-rc6 #1 + Call Trace: + + dump_stack_lvl+0x4e/0x70 + print_report+0x157/0x4c9 + kasan_report+0xce/0x100 + asn1_ber_decoder+0x16a7/0x1b00 + decode_negTokenInit+0x19/0x30 + SMB2_negotiate+0x31d9/0x4c90 + cifs_negotiate_protocol+0x1f2/0x3f0 + cifs_get_smb_ses+0x93f/0x17e0 + cifs_mount_get_session+0x7f/0x3a0 + cifs_mount+0xb4/0xcf0 + cifs_smb3_do_mount+0x23a/0x1500 + smb3_get_tree+0x3b0/0x630 + vfs_get_tree+0x82/0x2d0 + fc_mount+0x10/0x1b0 + path_mount+0x50d/0x1de0 + __x64_sys_mount+0x20b/0x270 + do_syscall_64+0xee/0x590 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Allocated by task 85: + kmem_cache_alloc_noprof+0x106/0x380 + mempool_alloc_noprof+0x116/0x1e0 + cifs_small_buf_get+0x31/0x80 + allocate_buffers+0x10d/0x2b0 + cifs_demultiplex_thread+0x1d5/0x1d50 + kthread+0x2c6/0x390 + ret_from_fork+0x36e/0x5a0 + ret_from_fork_asm+0x1a/0x30 + The buggy address is located 0 bytes to the right of + allocated 448-byte region [ffff8880084d6600, ffff8880084d67c0) + which belongs to the cache cifs_small_rq of size 448 + + BUG: KASAN: slab-out-of-bounds in kmemdup_noprof+0x36/0x50 + Read of size 329 at addr ffff88800726c678 by task mount.cifs/89 + CPU: 0 UID: 0 PID: 89 Comm: mount.cifs Tainted: G B 7.1.0-rc6 #1 + Call Trace: + + dump_stack_lvl+0x4e/0x70 + print_report+0x157/0x4c9 + kasan_report+0xce/0x100 + kasan_check_range+0x10f/0x1e0 + __asan_memcpy+0x23/0x60 + kmemdup_noprof+0x36/0x50 + decode_ntlmssp_challenge+0x457/0x680 + SMB2_sess_auth_rawntlmssp_negotiate+0x6f0/0xcb0 + SMB2_sess_setup+0x219/0x4f0 + cifs_setup_session+0x248/0xaf0 + cifs_get_smb_ses+0xf79/0x17e0 + cifs_mount_get_session+0x7f/0x3a0 + cifs_mount+0xb4/0xcf0 + cifs_smb3_do_mount+0x23a/0x1500 + smb3_get_tree+0x3b0/0x630 + vfs_get_tree+0x82/0x2d0 + fc_mount+0x10/0x1b0 + path_mount+0x50d/0x1de0 + __x64_sys_mount+0x20b/0x270 + do_syscall_64+0xee/0x590 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Allocated by task 93: + kmem_cache_alloc_noprof+0x106/0x380 + mempool_alloc_noprof+0x116/0x1e0 + cifs_small_buf_get+0x31/0x80 + allocate_buffers+0x10d/0x2b0 + cifs_demultiplex_thread+0x1d5/0x1d50 + kthread+0x2c6/0x390 + ret_from_fork+0x36e/0x5a0 + ret_from_fork_asm+0x1a/0x30 + The buggy address is located 120 bytes inside of + allocated 448-byte region [ffff88800726c600, ffff88800726c7c0) + which belongs to the cache cifs_small_rq of size 448 + +Restrict the +1 exemption to responses that have no data area, so that +it still covers the bcc[0] omission it was meant for. When a data area +is present, the +1 discrepancy instead means the reported data length +overruns the received buffer, so the response must be rejected. + +Fixes: 093b2bdad322 ("CIFS: Make demultiplex_thread work with SMB2 code") +Cc: stable@vger.kernel.org +Signed-off-by: Shoichiro Miyamoto +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/smb2misc.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +--- a/fs/smb/client/smb2misc.c ++++ b/fs/smb/client/smb2misc.c +@@ -19,6 +19,8 @@ + #include "nterr.h" + #include "cached_dir.h" + ++static unsigned int __smb2_calc_size(void *buf, bool *have_data); ++ + static int + check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid) + { +@@ -144,6 +146,7 @@ smb2_check_message(char *buf, unsigned i + int command; + __u32 calc_len; /* calculated length */ + __u64 mid; ++ bool have_data; + + /* If server is a channel, select the primary channel */ + pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; +@@ -227,7 +230,8 @@ smb2_check_message(char *buf, unsigned i + } + } + +- calc_len = smb2_calc_size(buf); ++ have_data = false; ++ calc_len = __smb2_calc_size(buf, &have_data); + + /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might + * be 0, and not a real miscalculation */ +@@ -246,8 +250,13 @@ smb2_check_message(char *buf, unsigned i + /* Windows 7 server returns 24 bytes more */ + if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) + return 0; +- /* server can return one byte more due to implied bcc[0] */ +- if (calc_len == len + 1) ++ /* ++ * Server can return one byte more due to implied bcc[0]. ++ * Allow it only when there is no data area; if data_length > 0 ++ * the +1 gap indicates an overreported data length rather than ++ * the bcc[0] omission. ++ */ ++ if (calc_len == len + 1 && !have_data) + return 0; + + /* +@@ -408,14 +417,17 @@ smb2_get_data_area_len(int *off, int *le + /* + * Calculate the size of the SMB message based on the fixed header + * portion, the number of word parameters and the data portion of the message. ++ * If have_data is non-NULL, it is set to true when a non-empty data area was ++ * found (data_length > 0), allowing callers to distinguish the implied bcc[0] ++ * case (no data area) from an overreported data length. + */ +-unsigned int +-smb2_calc_size(void *buf) ++static unsigned int ++__smb2_calc_size(void *buf, bool *have_data) + { + struct smb2_pdu *pdu = buf; + struct smb2_hdr *shdr = &pdu->hdr; + int offset; /* the offset from the beginning of SMB to data area */ +- int data_length; /* the length of the variable length data area */ ++ int data_length = 0; /* the length of the variable length data area */ + /* Structure Size has already been checked to make sure it is 64 */ + int len = le16_to_cpu(shdr->StructureSize); + +@@ -448,9 +460,17 @@ smb2_calc_size(void *buf) + } + calc_size_exit: + cifs_dbg(FYI, "SMB2 len %d\n", len); ++ if (have_data) ++ *have_data = (data_length > 0); + return len; + } + ++unsigned int ++smb2_calc_size(void *buf) ++{ ++ return __smb2_calc_size(buf, NULL); ++} ++ + /* Note: caller must free return buffer */ + __le16 * + cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) diff --git a/queue-6.18/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch b/queue-6.18/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch new file mode 100644 index 0000000000..273e2a97e2 --- /dev/null +++ b/queue-6.18/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch @@ -0,0 +1,60 @@ +From f4d51e55dd47ef467fbe37d8575e20eee41b092d Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 25 Mar 2026 13:59:43 +0100 +Subject: staging: media: atomisp: reduce load_primary_binaries() stack usage + +From: Arnd Bergmann + +commit f4d51e55dd47ef467fbe37d8575e20eee41b092d upstream. + +The load_primary_binaries() function is overly complex and has som large +variables on the stack, which can cause warnings depending on CONFIG_FRAME_WARN +setting: + +drivers/staging/media/atomisp/pci/sh_css.c: In function 'load_primary_binaries': +drivers/staging/media/atomisp/pci/sh_css.c:5260:1: error: the frame size of 1560 bytes is larger than 1536 bytes [-Werror=frame-larger-than=] + +Half of the stack usage is for the prim_descr[] array, but only one +member of the array is used at any given time. + +Reduce the stack usage by turning the array into a single structure. + +Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") +Cc: stable@vger.kernel.org +Signed-off-by: Arnd Bergmann +Reviewed-by: Andy Shevchenko +Signed-off-by: Sakari Ailus +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -5021,7 +5021,6 @@ static int load_primary_binaries( + struct ia_css_capture_settings *mycs; + unsigned int i; + bool need_extra_yuv_scaler = false; +- struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; + + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); +@@ -5191,15 +5190,16 @@ static int load_primary_binaries( + + /* Primary */ + for (i = 0; i < mycs->num_primary_stage; i++) { ++ struct ia_css_binary_descr prim_descr; + struct ia_css_frame_info *local_vf_info = NULL; + + if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && + (i == mycs->num_primary_stage - 1)) + local_vf_info = &vf_info; +- ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], ++ ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr, + &prim_in_info, &prim_out_info, + local_vf_info, i); +- err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); ++ err = ia_css_binary_find(&prim_descr, &mycs->primary_binary[i]); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; diff --git a/queue-6.18/staging-media-ipu7-fix-double-free-and-use-after-free-in-error-paths.patch b/queue-6.18/staging-media-ipu7-fix-double-free-and-use-after-free-in-error-paths.patch new file mode 100644 index 0000000000..71679141f9 --- /dev/null +++ b/queue-6.18/staging-media-ipu7-fix-double-free-and-use-after-free-in-error-paths.patch @@ -0,0 +1,107 @@ +From d3a9a8cf2d7fd61a2f63df61f6cbc0a9bb007cc0 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Mon, 13 Apr 2026 17:12:44 +0200 +Subject: staging: media: ipu7: fix double-free and use-after-free in error paths + +From: Alexandru Hossu + +commit d3a9a8cf2d7fd61a2f63df61f6cbc0a9bb007cc0 upstream. + +In both ipu7_isys_init() and ipu7_psys_init(), pdata is allocated and +then passed to ipu7_bus_initialize_device(), which stores it in +adev->pdata. The ipu7_bus_release() function frees adev->pdata when the +device's reference count drops to zero. + +Two error paths incorrectly call kfree(pdata) after the device teardown +has already freed it: + +1. When ipu7_mmu_init() fails: put_device() is called, which drops the + reference count to zero and triggers ipu7_bus_release() -> + kfree(pdata). The subsequent kfree(pdata) is a double-free. + +2. When ipu7_bus_add_device() fails: it calls auxiliary_device_uninit() + internally, which calls put_device() -> ipu7_bus_release() -> + kfree(pdata). The subsequent kfree(pdata) is again a double-free. + +Note that the kfree(pdata) when ipu7_bus_initialize_device() itself +fails is correct, because in that case auxiliary_device_init() failed +and the release function was never set up, so pdata must be freed +manually. + +Additionally, the error code was not saved before calling put_device(), +causing ERR_CAST() to dereference the already-freed adev pointer when +constructing the return value. Fix this by saving the error from +dev_err_probe() before put_device() and returning ERR_PTR() instead. + +Remove the redundant kfree(pdata) calls and fix the use-after-free in +the return values of the two affected error paths. + +Fixes: b7fe4c0019b1 ("media: staging/ipu7: add Intel IPU7 PCI device driver") +Cc: stable@vger.kernel.org +Reviewed-by: Dan Carpenter +Signed-off-by: Alexandru Hossu +Signed-off-by: Sakari Ailus +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/ipu7/ipu7.c | 22 ++++++++-------------- + 1 file changed, 8 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c +index c771e763f8c5..310e3f24e571 100644 +--- a/drivers/staging/media/ipu7/ipu7.c ++++ b/drivers/staging/media/ipu7/ipu7.c +@@ -2169,21 +2169,18 @@ ipu7_isys_init(struct pci_dev *pdev, struct device *parent, + isys_adev->mmu = ipu7_mmu_init(dev, base, ISYS_MMID, + &ipdata->hw_variant); + if (IS_ERR(isys_adev->mmu)) { +- dev_err_probe(dev, PTR_ERR(isys_adev->mmu), +- "ipu7_mmu_init(isys_adev->mmu) failed\n"); ++ ret = dev_err_probe(dev, PTR_ERR(isys_adev->mmu), ++ "ipu7_mmu_init(isys_adev->mmu) failed\n"); + put_device(&isys_adev->auxdev.dev); +- kfree(pdata); +- return ERR_CAST(isys_adev->mmu); ++ return ERR_PTR(ret); + } + + isys_adev->mmu->dev = &isys_adev->auxdev.dev; + isys_adev->subsys = IPU_IS; + + ret = ipu7_bus_add_device(isys_adev); +- if (ret) { +- kfree(pdata); ++ if (ret) + return ERR_PTR(ret); +- } + + return isys_adev; + } +@@ -2216,21 +2213,18 @@ ipu7_psys_init(struct pci_dev *pdev, struct device *parent, + psys_adev->mmu = ipu7_mmu_init(&pdev->dev, base, PSYS_MMID, + &ipdata->hw_variant); + if (IS_ERR(psys_adev->mmu)) { +- dev_err_probe(&pdev->dev, PTR_ERR(psys_adev->mmu), +- "ipu7_mmu_init(psys_adev->mmu) failed\n"); ++ ret = dev_err_probe(&pdev->dev, PTR_ERR(psys_adev->mmu), ++ "ipu7_mmu_init(psys_adev->mmu) failed\n"); + put_device(&psys_adev->auxdev.dev); +- kfree(pdata); +- return ERR_CAST(psys_adev->mmu); ++ return ERR_PTR(ret); + } + + psys_adev->mmu->dev = &psys_adev->auxdev.dev; + psys_adev->subsys = IPU_PS; + + ret = ipu7_bus_add_device(psys_adev); +- if (ret) { +- kfree(pdata); ++ if (ret) + return ERR_PTR(ret); +- } + + return psys_adev; + } +-- +2.55.0 + diff --git a/queue-6.18/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch b/queue-6.18/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch new file mode 100644 index 0000000000..ffdc98d02e --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch @@ -0,0 +1,61 @@ +From 5a752a616e756844388a1a45404db9fc29fec655 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:27 +0200 +Subject: staging: rtl8723bs: fix heap buffer overflow in rtw_cfg80211_set_wpa_ie() + +From: Alexandru Hossu + +commit 5a752a616e756844388a1a45404db9fc29fec655 upstream. + +supplicant_ie is a 256-byte array in struct security_priv. The WPA and +WPA2 IE copy paths use: + + memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2); + +where wpa_ielen is the raw IE length field (u8, 0-255). When a local user +supplies a connect request via nl80211 with a crafted WPA IE of length 255, +wpa_ielen + 2 equals 257, overflowing the 256-byte buffer by one byte into +the adjacent last_mic_err_time field. + +rtw_parse_wpa_ie() does not prevent this: its length consistency check +compares *(wpa_ie+1) against (u8)(wpa_ie_len-2), which is (u8)(255) == 255 +when wpa_ie_len = 257, so the check passes silently. + +Add explicit bounds checks for both the WPA and WPA2 paths before the +memcpy, rejecting any IE whose total size (wpa_ielen + 2) exceeds the +supplicant_ie buffer. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Reviewed-by: Luka Gejak +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-4-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -1446,6 +1446,10 @@ static int rtw_cfg80211_set_wpa_ie(struc + + pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen); + if (pwpa && wpa_ielen > 0) { ++ if (wpa_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) { ++ ret = -EINVAL; ++ goto exit; ++ } + if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; +@@ -1455,6 +1459,10 @@ static int rtw_cfg80211_set_wpa_ie(struc + + pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen); + if (pwpa2 && wpa2_ielen > 0) { ++ if (wpa2_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) { ++ ret = -EINVAL; ++ goto exit; ++ } + if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; diff --git a/queue-6.18/staging-rtl8723bs-fix-oob-read-in-onassocrsp-ie-loop.patch b/queue-6.18/staging-rtl8723bs-fix-oob-read-in-onassocrsp-ie-loop.patch new file mode 100644 index 0000000000..d0bb3406d0 --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-oob-read-in-onassocrsp-ie-loop.patch @@ -0,0 +1,47 @@ +From f9654207e92283e0acac5d64fe5f8835383b5a23 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:29 +0200 +Subject: staging: rtl8723bs: fix OOB read in OnAssocRsp() IE loop + +From: Alexandru Hossu + +commit f9654207e92283e0acac5d64fe5f8835383b5a23 upstream. + +The IE parsing loop in OnAssocRsp() advances by (pIE->length + 2) each +iteration but only guards on i < pkt_len. When a malicious AP sends an +AssocResponse whose last IE has only one byte remaining in the frame +(the element_id byte lands at pkt_len-1), the loop reads pIE->length +from pframe[pkt_len], which is one byte past the allocated receive buffer. + +Additionally, even when the header bytes are in bounds, pIE->length +itself can extend the data window beyond pkt_len, silently passing a +truncated IE to the handler functions. + +Add two guards at the top of the loop body: + 1. Break if fewer than sizeof(*pIE) bytes remain (can't read header). + 2. Break if the IE's declared data extends past pkt_len. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Signed-off-by: Alexandru Hossu +Reviewed-by: Luka Gejak +Link: https://patch.msgid.link/20260522004531.1038924-6-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -1430,7 +1430,11 @@ unsigned int OnAssocRsp(struct adapter * + /* to handle HT, WMM, rate adaptive, update MAC reg */ + /* for not to handle the synchronous IO in the tasklet */ + for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { ++ if (i + sizeof(*pIE) > pkt_len) ++ break; + pIE = (struct ndis_80211_var_ie *)(pframe + i); ++ if (i + sizeof(*pIE) + pIE->length > pkt_len) ++ break; + + switch (pIE->element_id) { + case WLAN_EID_VENDOR_SPECIFIC: diff --git a/queue-6.18/staging-rtl8723bs-fix-oob-read-in-update_beacon_info-ie-loop.patch b/queue-6.18/staging-rtl8723bs-fix-oob-read-in-update_beacon_info-ie-loop.patch new file mode 100644 index 0000000000..c6076d817d --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-oob-read-in-update_beacon_info-ie-loop.patch @@ -0,0 +1,59 @@ +From ed51de4a86e173c3b0ef78e039c2e49e08b11f16 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:25 +0200 +Subject: staging: rtl8723bs: fix OOB read in update_beacon_info() IE loop + +From: Alexandru Hossu + +commit ed51de4a86e173c3b0ef78e039c2e49e08b11f16 upstream. + +The IE parsing loop in update_beacon_info() advances by +(pIE->length + 2) each iteration but only guards on i < len. +When a malicious AP sends a Beacon whose last IE has only one byte +remaining in the frame (the element_id byte lands at len-1), the loop +reads pIE->length from one byte past the allocated receive buffer. + +Additionally, even when the header bytes are in bounds, pIE->length +itself can extend the data window beyond len, passing a truncated IE +to the handler functions. + +Add two guards at the top of the loop body: + 1. Break if fewer than sizeof(*pIE) bytes remain (can't read header). + 2. Break if the IE's declared data extends past len. + +Also replace i += (pIE->length + 2) with i += sizeof(*pIE) + pIE->length +for consistency with the sizeof(*pIE) guards added above. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Reviewed-by: Luka Gejak +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-2-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c ++++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +@@ -1288,7 +1288,11 @@ void update_beacon_info(struct adapter * + len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN); + + for (i = 0; i < len;) { ++ if (i + sizeof(*pIE) > len) ++ break; + pIE = (struct ndis_80211_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i); ++ if (i + sizeof(*pIE) + pIE->length > len) ++ break; + + switch (pIE->element_id) { + case WLAN_EID_VENDOR_SPECIFIC: +@@ -1313,7 +1317,7 @@ void update_beacon_info(struct adapter * + break; + } + +- i += (pIE->length + 2); ++ i += sizeof(*pIE) + pIE->length; + } + } + diff --git a/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch b/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch new file mode 100644 index 0000000000..dd8972610d --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch @@ -0,0 +1,63 @@ +From ef61d628dfad38fead1fd2e08979ae9126d011d5 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:26 +0200 +Subject: staging: rtl8723bs: fix OOB reads in IE loops in issue_assocreq() and join_cmd_hdl() + +From: Alexandru Hossu + +commit ef61d628dfad38fead1fd2e08979ae9126d011d5 upstream. + +Two IE parsing loops are missing the header bounds checks before they +dereference pIE->length: + + - issue_assocreq() walks pmlmeinfo->network.ies to build the + association request. If the stored IE data ends with only an + element_id byte and no length byte, pIE->length is read one byte + past the end of the buffer. + + - join_cmd_hdl() walks pnetwork->ies during station join and has + the same problem under the same conditions. + +Both buffers are filled from AP beacon and probe-response frames, so a +malicious AP that sends a truncated final IE can trigger the issue. + +Apply the two-guard pattern established in update_beacon_info(): + 1. Break if fewer than sizeof(*pIE) bytes remain. + 2. Break if the IE's declared data extends past the buffer end. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Reviewed-by: Luka Gejak +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-3-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -2972,7 +2972,11 @@ void issue_assocreq(struct adapter *pada + + /* vendor specific IE, such as WPA, WMM, WPS */ + for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) { ++ if (i + sizeof(*pIE) > pmlmeinfo->network.ie_length) ++ break; + pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i); ++ if (i + sizeof(*pIE) + pIE->length > pmlmeinfo->network.ie_length) ++ break; + + switch (pIE->element_id) { + case WLAN_EID_VENDOR_SPECIFIC: +@@ -5370,7 +5374,11 @@ u8 join_cmd_hdl(struct adapter *padapter + + /* sizeof(struct ndis_802_11_fix_ie) */ + for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) { ++ if (i + sizeof(*pIE) > pnetwork->ie_length) ++ break; + pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i); ++ if (i + sizeof(*pIE) + pIE->length > pnetwork->ie_length) ++ break; + + switch (pIE->element_id) { + case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ diff --git a/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-is_ap_in_tkip-ie-loop.patch b/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-is_ap_in_tkip-ie-loop.patch new file mode 100644 index 0000000000..4242ba3eb1 --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-oob-reads-in-is_ap_in_tkip-ie-loop.patch @@ -0,0 +1,71 @@ +From 3bf39f711ff27c64be8680a8938bcc5001982e81 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:30 +0200 +Subject: staging: rtl8723bs: fix OOB reads in is_ap_in_tkip() IE loop + +From: Alexandru Hossu + +commit 3bf39f711ff27c64be8680a8938bcc5001982e81 upstream. + +The loop in is_ap_in_tkip() iterates over IEs without verifying that +enough bytes remain before dereferencing the IE header or its payload: + +- pIE->element_id and pIE->length are read without checking that + i + sizeof(*pIE) <= ie_length, so a truncated IE at the end of the + buffer causes an OOB read. + +- For WLAN_EID_VENDOR_SPECIFIC the code compares pIE->data + 12, + which requires pIE->length >= 16. For WLAN_EID_RSN it compares + pIE->data + 8, requiring pIE->length >= 12. Neither requirement + is checked. + +Add the missing IE header and payload bounds checks and guard each +data access with an explicit pIE->length minimum, matching the +pattern established in update_beacon_info(). + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-7-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c ++++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +@@ -1333,15 +1333,23 @@ unsigned int is_ap_in_tkip(struct adapte + for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) { + pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i); + ++ if (i + sizeof(*pIE) > pmlmeinfo->network.ie_length) ++ break; ++ if (i + sizeof(*pIE) + pIE->length > pmlmeinfo->network.ie_length) ++ break; ++ + switch (pIE->element_id) { + case WLAN_EID_VENDOR_SPECIFIC: +- if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4))) ++ if (pIE->length >= 16 && ++ !memcmp(pIE->data, RTW_WPA_OUI, 4) && ++ !memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)) + return true; + + break; + + case WLAN_EID_RSN: +- if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4)) ++ if (pIE->length >= 12 && ++ !memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4)) + return true; + break; + +@@ -1349,7 +1357,7 @@ unsigned int is_ap_in_tkip(struct adapte + break; + } + +- i += (pIE->length + 2); ++ i += sizeof(*pIE) + pIE->length; + } + + return false; diff --git a/queue-6.18/staging-rtl8723bs-fix-oob-write-in-ht_caps_handler.patch b/queue-6.18/staging-rtl8723bs-fix-oob-write-in-ht_caps_handler.patch new file mode 100644 index 0000000000..4286c2c2e8 --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-oob-write-in-ht_caps_handler.patch @@ -0,0 +1,47 @@ +From f8001e1a516ba3b495728c65b61f799cbfad6bd0 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:45:28 +0200 +Subject: staging: rtl8723bs: fix OOB write in HT_caps_handler() + +From: Alexandru Hossu + +commit f8001e1a516ba3b495728c65b61f799cbfad6bd0 upstream. + +HT_caps_handler() iterates pIE->length bytes and writes into +HT_caps.u.HT_cap[], which is a fixed 26-byte array (sizeof struct +HT_caps_element). Because pIE->length is a raw u8 from an over-the-air +802.11 AssocResponse frame and is never validated, a malicious AP can +set it up to 255, causing up to 229 bytes of out-of-bounds writes into +adjacent fields of struct mlme_ext_info. + +Truncate the iteration count to the size of HT_caps.u.HT_cap using +umin() so that data from a longer-than-expected IE is silently ignored +rather than written out of bounds, preserving interoperability with APs +that pad the element. An early return on oversized IEs was considered +but rejected: it would bypass the pmlmeinfo->HT_caps_enable = 1 +assignment that precedes the loop, silently disabling HT mode for APs +that append extra bytes to the HT Capabilities IE. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Signed-off-by: Alexandru Hossu +Reviewed-by: Luka Gejak +Link: https://patch.msgid.link/20260522004531.1038924-5-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c ++++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +@@ -935,7 +935,8 @@ void HT_caps_handler(struct adapter *pad + + pmlmeinfo->HT_caps_enable = 1; + +- for (i = 0; i < (pIE->length); i++) { ++ for (i = 0; i < umin(pIE->length, ++ sizeof(pmlmeinfo->HT_caps.u.HT_cap)); i++) { + if (i != 2) { + /* Commented by Albert 2010/07/12 */ + /* Got the endian issue here. */ diff --git a/queue-6.18/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch b/queue-6.18/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch new file mode 100644 index 0000000000..6efa364989 --- /dev/null +++ b/queue-6.18/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch @@ -0,0 +1,69 @@ +From a1fc19d61f661d47204f095b593de507884849f7 Mon Sep 17 00:00:00 2001 +From: Alexandru Hossu +Date: Fri, 22 May 2026 02:46:05 +0200 +Subject: staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth() + +From: Alexandru Hossu + +commit a1fc19d61f661d47204f095b593de507884849f7 upstream. + +OnAuth() has two bugs in the shared-key authentication path. + +When the Privacy bit is set, rtw_wep_decrypt() is called without +verifying that the frame is long enough to contain a valid WEP IV and +ICV. Inside rtw_wep_decrypt(), length is computed as: + + length = len - WLAN_HDR_A3_LEN - iv_len + +and then passed as (length - 4) to crc32_le(). If len is less than +WLAN_HDR_A3_LEN + iv_len + icv_len (32 bytes), length - 4 is negative +and, after the implicit cast to size_t, causes crc32_le() to read far +beyond the frame buffer. Add a minimum length check before accessing +the IV field and calling the decryption path. + +When processing a seq=3 response, rtw_get_ie() stores the Challenge +Text IE length in ie_len, but the subsequent memcmp() always reads 128 +bytes regardless of ie_len. IEEE 802.11 mandates a challenge text of +exactly 128 bytes; reject any IE whose length field differs, matching +the check already applied to OnAuthClient(). + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004605.1039209-1-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -703,6 +703,9 @@ unsigned int OnAuth(struct adapter *pada + if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + return _FAIL; + ++ if (len < WLAN_HDR_A3_LEN) ++ return _FAIL; ++ + sa = GetAddr2Ptr(pframe); + + auth_mode = psecuritypriv->dot11AuthAlgrthm; +@@ -714,6 +717,9 @@ unsigned int OnAuth(struct adapter *pada + prxattrib->hdrlen = WLAN_HDR_A3_LEN; + prxattrib->encrypt = _WEP40_; + ++ if (len < WLAN_HDR_A3_LEN + 8) ++ return _FAIL; ++ + iv = pframe+prxattrib->hdrlen; + prxattrib->key_index = ((iv[3]>>6)&0x3); + +@@ -818,7 +824,7 @@ unsigned int OnAuth(struct adapter *pada + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len, + len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + +- if (!p || ie_len <= 0) { ++ if (!p || ie_len != 128) { + status = WLAN_STATUS_CHALLENGE_FAIL; + goto auth_fail; + } diff --git a/queue-6.18/staging-vme_user-bound-slave-read-write-to-the-kern_buf-size.patch b/queue-6.18/staging-vme_user-bound-slave-read-write-to-the-kern_buf-size.patch new file mode 100644 index 0000000000..a6b80c5f95 --- /dev/null +++ b/queue-6.18/staging-vme_user-bound-slave-read-write-to-the-kern_buf-size.patch @@ -0,0 +1,85 @@ +From 9f32f38265014fac7f5dc9490fb01a638ce6e121 Mon Sep 17 00:00:00 2001 +From: Michael Tautschnig +Date: Thu, 18 Jun 2026 13:47:09 +0200 +Subject: staging: vme_user: bound slave read/write to the kern_buf size + +From: Michael Tautschnig + +commit 9f32f38265014fac7f5dc9490fb01a638ce6e121 upstream. + +The SLAVE-path helpers buffer_to_user() and buffer_from_user() copy +'count' bytes into/out of the fixed-size kern_buf (size_buf == +PCI_BUF_SIZE == 0x20000, 128 KiB) using *ppos as the offset, without +bounding *ppos + count against size_buf. + +vme_user_write()/vme_user_read() only clamp count to the VME window size +(image_size = vme_get_size(resource)), which VME_SET_SLAVE sets from the +user-supplied slave.size -- validated against the VME address space (up +to VME_A32_MAX = 4 GiB), not against PCI_BUF_SIZE. When the window +exceeds 128 KiB, a write()/read() copies past the kern_buf allocation. + +Clamp count against size_buf in both helpers, with an early return when +*ppos is already at/after the buffer end. *ppos is >= 0 here (the caller +rejects negative offsets), so size_buf - *ppos cannot wrap. This mirrors +the existing clamp in the MASTER-path helpers resource_to_user() / +resource_from_user(), and matches the read()/write() convention of a +short transfer at end-of-buffer. + +Found by static analysis (CodeQL taint tracking + CBMC bounded model +checking) and confirmed dynamically under KASAN with the vme_fake bridge: + + BUG: KASAN: slab-out-of-bounds in _copy_from_user+0x2d/0x80 + Write of size 262144 at addr ffff888004100000 by task trigger/68 + _copy_from_user+0x2d/0x80 + vme_user_write+0x13e/0x240 [vme_user] + vfs_write+0x1b8/0x7a0 + ksys_write+0xb8/0x150 + +Fixes: f00a86d98a1e ("Staging: vme: add VME userspace driver") +Cc: stable +Signed-off-by: Michael Tautschnig +Link: https://patch.msgid.link/20260618114709.72499-1-tautschn@amazon.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/vme_user/vme_user.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/staging/vme_user/vme_user.c ++++ b/drivers/staging/vme_user/vme_user.c +@@ -156,6 +156,17 @@ static ssize_t buffer_to_user(unsigned i + { + void *image_ptr; + ++ /* ++ * The slave window (image_size) can exceed the fixed kern_buf ++ * (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf. ++ * *ppos is >= 0 here (checked by the caller), so the ++ * subtraction below cannot wrap. ++ */ ++ if (*ppos >= image[minor].size_buf) ++ return 0; ++ if (count > image[minor].size_buf - *ppos) ++ count = image[minor].size_buf - *ppos; ++ + image_ptr = image[minor].kern_buf + *ppos; + if (copy_to_user(buf, image_ptr, (unsigned long)count)) + return -EFAULT; +@@ -168,6 +179,17 @@ static ssize_t buffer_from_user(unsigned + { + void *image_ptr; + ++ /* ++ * The slave window (image_size) can exceed the fixed kern_buf ++ * (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf. ++ * *ppos is >= 0 here (checked by the caller), so the ++ * subtraction below cannot wrap. ++ */ ++ if (*ppos >= image[minor].size_buf) ++ return 0; ++ if (count > image[minor].size_buf - *ppos) ++ count = image[minor].size_buf - *ppos; ++ + image_ptr = image[minor].kern_buf + *ppos; + if (copy_from_user(image_ptr, buf, (unsigned long)count)) + return -EFAULT; diff --git a/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-fake-bridge.patch b/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-fake-bridge.patch new file mode 100644 index 0000000000..47974e16d0 --- /dev/null +++ b/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-fake-bridge.patch @@ -0,0 +1,62 @@ +From e8422d89e8af41d87f0e9db564be8e2634f4c602 Mon Sep 17 00:00:00 2001 +From: Hao-Qun Huang +Date: Sat, 4 Jul 2026 14:58:15 +0800 +Subject: staging: vme_user: fix location monitor leak in fake bridge + +From: Hao-Qun Huang + +commit e8422d89e8af41d87f0e9db564be8e2634f4c602 upstream. + +fake_init() allocates a location monitor resource and links it into +fake_bridge->lm_resources. The init error path frees this list, but +fake_exit() only frees the slave and master resource lists. Loading +and unloading the module therefore triggers a kmemleak warning: + + unreferenced object 0xffff8b8b82aebe40 (size 64): + comm "init", pid 1, jiffies 4294894572 + backtrace (crc c1e013ef): + kmemleak_alloc+0x4e/0x90 + __kmalloc_cache_noprof+0x338/0x430 + 0xffffffffc0602246 + do_one_initcall+0x4f/0x320 + do_init_module+0x68/0x270 + load_module+0x2a3b/0x2d90 + +Free the lm_resources list in fake_exit() as well, before fake_bridge +is freed. + +Fixes: 658bcdae9c67 ("vme: Adding Fake VME driver") +Cc: stable +Cc: Martyn Welch +Assisted-by: Claude:claude-fable-5 +Signed-off-by: Hao-Qun Huang +Link: https://patch.msgid.link/20260704065817.403111-1-alvinhuang0603@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/vme_user/vme_fake.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/vme_user/vme_fake.c ++++ b/drivers/staging/vme_user/vme_fake.c +@@ -1239,6 +1239,7 @@ static void __exit fake_exit(void) + { + struct list_head *pos = NULL; + struct list_head *tmplist; ++ struct vme_lm_resource *lm; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + int i; +@@ -1269,6 +1270,13 @@ static void __exit fake_exit(void) + + fake_crcsr_exit(fake_bridge); + /* resources are stored in link list */ ++ list_for_each_safe(pos, tmplist, &fake_bridge->lm_resources) { ++ lm = list_entry(pos, struct vme_lm_resource, list); ++ list_del(pos); ++ kfree(lm); ++ } ++ ++ /* resources are stored in link list */ + list_for_each_safe(pos, tmplist, &fake_bridge->slave_resources) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); diff --git a/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-tsi148-bridge.patch b/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-tsi148-bridge.patch new file mode 100644 index 0000000000..a70f23cff6 --- /dev/null +++ b/queue-6.18/staging-vme_user-fix-location-monitor-leak-in-tsi148-bridge.patch @@ -0,0 +1,53 @@ +From 151edde741f8bc7f2931c5f44ab376d32b0c8beb Mon Sep 17 00:00:00 2001 +From: Hao-Qun Huang +Date: Sat, 4 Jul 2026 14:58:16 +0800 +Subject: staging: vme_user: fix location monitor leak in tsi148 bridge + +From: Hao-Qun Huang + +commit 151edde741f8bc7f2931c5f44ab376d32b0c8beb upstream. + +tsi148_probe() allocates a location monitor resource and links it into +tsi148_bridge->lm_resources. The probe error path frees this list, but +tsi148_remove() only frees the dma, slave and master resource lists, so +the location monitor resource is leaked on device unbind or module +unload. + +Free the lm_resources list in tsi148_remove() as well, before +tsi148_bridge is freed. + +Fixes: d22b8ed9a3b0 ("Staging: vme: add Tundra TSI148 VME-PCI Bridge driver") +Cc: stable +Cc: Martyn Welch +Assisted-by: Claude:claude-fable-5 +Signed-off-by: Hao-Qun Huang +Link: https://patch.msgid.link/20260704065817.403111-2-alvinhuang0603@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/vme_user/vme_tsi148.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/vme_user/vme_tsi148.c ++++ b/drivers/staging/vme_user/vme_tsi148.c +@@ -2536,6 +2536,7 @@ static void tsi148_remove(struct pci_dev + { + struct list_head *pos = NULL; + struct list_head *tmplist; ++ struct vme_lm_resource *lm; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; +@@ -2593,6 +2594,13 @@ static void tsi148_remove(struct pci_dev + tsi148_crcsr_exit(tsi148_bridge, pdev); + + /* resources are stored in link list */ ++ list_for_each_safe(pos, tmplist, &tsi148_bridge->lm_resources) { ++ lm = list_entry(pos, struct vme_lm_resource, list); ++ list_del(pos); ++ kfree(lm); ++ } ++ ++ /* resources are stored in link list */ + list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); diff --git a/queue-6.18/tcp-restore-rcu-grace-period-in-tcp_ao_destroy_sock.patch b/queue-6.18/tcp-restore-rcu-grace-period-in-tcp_ao_destroy_sock.patch new file mode 100644 index 0000000000..9969e6bde4 --- /dev/null +++ b/queue-6.18/tcp-restore-rcu-grace-period-in-tcp_ao_destroy_sock.patch @@ -0,0 +1,112 @@ +From 8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Thu, 25 Jun 2026 19:21:39 +0100 +Subject: tcp: restore RCU grace period in tcp_ao_destroy_sock + +From: Michael Bommarito + +commit 8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30 upstream. + +Commit 51e547e8c89c ("tcp: Free TCP-AO/TCP-MD5 info/keys without RCU") +removed the call_rcu() callback from tcp_ao_destroy_sock(), arguing that +"the destruction of info/keys is delayed until the socket destructor" +and therefore "no one can discover it anymore". + +That argument does not hold for the call site in tcp_connect() +(net/ipv4/tcp_output.c:4327-4332). At that point the socket is in +TCP_SYN_SENT, has already been inserted into the inet ehash by +inet_hash_connect() in tcp_v4_connect(), and is therefore very much +discoverable: any softirq running tcp_v4_rcv() on another CPU can take +the socket out of the ehash, walk into tcp_inbound_hash(), and load +tp->ao_info via implicit RCU before bh_lock_sock_nested() is taken on +the destroying CPU. + +The reader path then enters __tcp_ao_do_lookup() (net/ipv4/tcp_ao.c:208) +which re-loads tp->ao_info via rcu_dereference_check(); the re-load can +still observe the (about-to-be-freed) pointer because there is no +synchronize_rcu() between rcu_assign_pointer(tp->ao_info, NULL) and +tcp_ao_info_free() in tcp_ao_destroy_sock(). The captured pointer is +then walked at line 223: + + hlist_for_each_entry_rcu(key, &ao->head, node, ...) + +The writer's synchronous kfree() is free to complete between the line +218 re-fetch and the line 223 hlist iteration. The slab is reused +(or simply LIST_POISON1-stamped if not yet reused) and the iteration +walks attacker-controlled or poison memory in softirq context. + +Reproducer (no debug shim, stock x86_64 v7.1-rc2 SMP+KASAN, QEMU+KVM): +an unprivileged uid=1000 process inside CLONE_NEWUSER|CLONE_NEWNET +installs TCP_MD5SIG + TCP_AO_ADD_KEY on a TCP socket, sprays forged +TCP-AO segments toward its eventual 4-tuple via raw sockets, then +calls connect(). The md5-wins reconciliation in tcp_connect() fires +tcp_ao_destroy_sock(); the softirq backlog reader on the loopback +NAPI path crashes on the freed ao->head.first walk: + + Oops: general protection fault, probably for non-canonical + address 0xfbd59c000000002f + KASAN: maybe wild-memory-access in range + [0xdead000000000178-0xdead00000000017f] + CPU: 0 UID: 1000 PID: 100 Comm: repro_userns + RIP: 0010:__tcp_ao_do_lookup+0x107/0x1c0 + Call Trace: + __tcp_ao_do_lookup+0x107/0x1c0 + tcp_ao_inbound_lookup.constprop.0+0x12a/0x200 + tcp_inbound_ao_hash+0x5ea/0x1520 + tcp_inbound_hash+0x7ce/0x1240 + tcp_v4_rcv+0x1e7a/0x3e10 + ... + +Restore the RCU grace period: re-add struct rcu_head to tcp_ao_info +and replace the synchronous tcp_ao_info_free() with a call_rcu() +callback. Readers that captured tp->ao_info before rcu_assign_pointer +NULLed it now see the object remain valid until rcu_read_unlock(). +With the patch applied the reproducer runs cleanly for 2000 iterations +on the same kernel build. + +Fixes: 51e547e8c89c ("tcp: Free TCP-AO/TCP-MD5 info/keys without RCU") +Cc: stable@vger.kernel.org # v6.18+ +Reviewed-by: Dmitry Safonov +Signed-off-by: Michael Bommarito +Reviewed-by: Eric Dumazet +Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> +Link: https://patch.msgid.link/20260625-tcp-md5-connect-v3-1-1fd313d6c1e0@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/net/tcp_ao.h | 1 + + net/ipv4/tcp_ao.c | 5 +++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/include/net/tcp_ao.h ++++ b/include/net/tcp_ao.h +@@ -130,6 +130,7 @@ struct tcp_ao_info { + u32 snd_sne; + u32 rcv_sne; + refcount_t refcnt; /* Protects twsk destruction */ ++ struct rcu_head rcu; + }; + + #ifdef CONFIG_TCP_MD5SIG +--- a/net/ipv4/tcp_ao.c ++++ b/net/ipv4/tcp_ao.c +@@ -270,8 +270,9 @@ static void tcp_ao_key_free_rcu(struct r + kfree_sensitive(key); + } + +-static void tcp_ao_info_free(struct tcp_ao_info *ao) ++static void tcp_ao_info_free_rcu(struct rcu_head *head) + { ++ struct tcp_ao_info *ao = container_of(head, struct tcp_ao_info, rcu); + struct tcp_ao_key *key; + struct hlist_node *n; + +@@ -311,7 +312,7 @@ void tcp_ao_destroy_sock(struct sock *sk + + if (!twsk) + tcp_ao_sk_omem_free(sk, ao); +- tcp_ao_info_free(ao); ++ call_rcu(&ao->rcu, tcp_ao_info_free_rcu); + } + + void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp) diff --git a/queue-6.18/tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch b/queue-6.18/tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch new file mode 100644 index 0000000000..3ef5d27066 --- /dev/null +++ b/queue-6.18/tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch @@ -0,0 +1,164 @@ +From 2b66974a1b6134a4bbc3bfed181f7418f688eb54 Mon Sep 17 00:00:00 2001 +From: Samuel Page +Date: Thu, 25 Jun 2026 15:38:15 +0100 +Subject: tipc: fix out-of-bounds read in broadcast Gap ACK blocks + +From: Samuel Page + +commit 2b66974a1b6134a4bbc3bfed181f7418f688eb54 upstream. + +A broadcast PROTOCOL/STATE_MSG can carry a Gap ACK blocks record in its +data area. tipc_get_gap_ack_blks() only verifies that the record's len +field is self-consistent with its ugack_cnt/bgack_cnt counts +(sz == struct_size(p, gacks, ugack_cnt + bgack_cnt)); it does not check +that the record actually fits in the message data area, msg_data_sz(). + +The unicast caller tipc_link_proto_rcv() bounds it ("if (glen > dlen) +break;"), but the broadcast caller tipc_bcast_sync_rcv() discards the +returned size, so tipc_link_advance_transmq() copies the record off the +receive skb with an attacker-controlled count: + + this_ga = kmemdup(ga, struct_size(ga, gacks, ga->bgack_cnt), + GFP_ATOMIC); + +A TIPC neighbour that negotiated TIPC_GAP_ACK_BLOCK triggers it with one +ordinary broadcast STATE_MSG (msg_bc_ack_invalid() clear), sized so its +data area is short, carrying a Gap ACK record with len = 0x400, +bgack_cnt = 0xff and ugack_cnt = 0. len then equals +struct_size(p, gacks, 255), so the consistency check passes and ga is +non-NULL; kmemdup() reads struct_size(ga, gacks, 255) = 1024 bytes out +of the much smaller skb: + + BUG: KASAN: slab-out-of-bounds in kmemdup_noprof+0x48/0x60 + Read of size 1024 at addr ffff0000c7030d38 by task poc864/69 + Call trace: + kmemdup_noprof+0x48/0x60 + tipc_link_advance_transmq+0x86c/0xb80 + tipc_link_bc_ack_rcv+0x19c/0x1e0 + tipc_bcast_sync_rcv+0x1c4/0x2c4 + tipc_rcv+0x85c/0x1340 + tipc_l2_rcv_msg+0xac/0x104 + The buggy address belongs to the object at ffff0000c7030d00 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 56 bytes inside of + allocated 704-byte region [ffff0000c7030d00, ffff0000c7030fc0) + +The copied-out bytes are subsequently consumed as gap/ack values, but +the read is already out of bounds at the kmemdup() regardless of how +they are used. + +The unicast STATE path drops such a message: "if (glen > dlen) break;" +skips the rest of STATE_MSG handling and the skb is freed. Make the +broadcast path drop it too. tipc_bcast_sync_rcv() now bounds the record +against msg_data_sz() and, when it does not fit, reports it back through +tipc_node_bc_sync_rcv() to tipc_rcv() so the skb is discarded rather than +processed. ga is not cleared on this path: ga == NULL already means +"legacy peer without Selective ACK", a distinct legitimate state. + +Fixes: d7626b5acff9 ("tipc: introduce Gap ACK blocks for broadcast link") +Cc: stable@vger.kernel.org +Signed-off-by: Samuel Page +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260625143815.1525412-1-sam@bynar.io +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/bcast.c | 22 ++++++++++++++-------- + net/tipc/bcast.h | 2 +- + net/tipc/node.c | 15 ++++++++++++--- + 3 files changed, 27 insertions(+), 12 deletions(-) + +--- a/net/tipc/bcast.c ++++ b/net/tipc/bcast.c +@@ -497,12 +497,13 @@ void tipc_bcast_ack_rcv(struct net *net, + */ + int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, + struct tipc_msg *hdr, +- struct sk_buff_head *retrq) ++ struct sk_buff_head *retrq, bool *valid) + { + struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq; + struct tipc_gap_ack_blks *ga; + struct sk_buff_head xmitq; + int rc = 0; ++ u16 glen; + + __skb_queue_head_init(&xmitq); + +@@ -510,13 +511,18 @@ int tipc_bcast_sync_rcv(struct net *net, + if (msg_type(hdr) != STATE_MSG) { + tipc_link_bc_init_rcv(l, hdr); + } else if (!msg_bc_ack_invalid(hdr)) { +- tipc_get_gap_ack_blks(&ga, l, hdr, false); +- if (!sysctl_tipc_bc_retruni) +- retrq = &xmitq; +- rc = tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), +- msg_bc_gap(hdr), ga, &xmitq, +- retrq); +- rc |= tipc_link_bc_sync_rcv(l, hdr, &xmitq); ++ glen = tipc_get_gap_ack_blks(&ga, l, hdr, false); ++ if (glen > msg_data_sz(hdr)) { ++ /* Malformed Gap ACK blocks; caller drops the msg */ ++ *valid = false; ++ } else { ++ if (!sysctl_tipc_bc_retruni) ++ retrq = &xmitq; ++ rc = tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), ++ msg_bc_gap(hdr), ga, &xmitq, ++ retrq); ++ rc |= tipc_link_bc_sync_rcv(l, hdr, &xmitq); ++ } + } + tipc_bcast_unlock(net); + +--- a/net/tipc/bcast.h ++++ b/net/tipc/bcast.h +@@ -97,7 +97,7 @@ void tipc_bcast_ack_rcv(struct net *net, + struct tipc_msg *hdr); + int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, + struct tipc_msg *hdr, +- struct sk_buff_head *retrq); ++ struct sk_buff_head *retrq, bool *valid); + int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg, + struct tipc_link *bcl); + int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]); +--- a/net/tipc/node.c ++++ b/net/tipc/node.c +@@ -1831,12 +1831,15 @@ static void tipc_node_mcast_rcv(struct t + } + + static void tipc_node_bc_sync_rcv(struct tipc_node *n, struct tipc_msg *hdr, +- int bearer_id, struct sk_buff_head *xmitq) ++ int bearer_id, struct sk_buff_head *xmitq, ++ bool *valid) + { + struct tipc_link *ucl; + int rc; + +- rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr, xmitq); ++ rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr, xmitq, valid); ++ if (!*valid) ++ return; + + if (rc & TIPC_LINK_DOWN_EVT) { + tipc_node_reset_links(n); +@@ -2140,12 +2143,18 @@ rcv: + + /* Ensure broadcast reception is in synch with peer's send state */ + if (unlikely(usr == LINK_PROTOCOL)) { ++ bool valid = true; ++ + if (unlikely(skb_linearize(skb))) { + tipc_node_put(n); + goto discard; + } + hdr = buf_msg(skb); +- tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq); ++ tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq, &valid); ++ if (!valid) { ++ tipc_node_put(n); ++ goto discard; ++ } + } else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) { + tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr); + } diff --git a/queue-6.18/usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch b/queue-6.18/usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch new file mode 100644 index 0000000000..1f7b28f695 --- /dev/null +++ b/queue-6.18/usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch @@ -0,0 +1,65 @@ +From abf76d3239dee97b66e7241ad04811f1ce562e28 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 9 Jun 2026 13:37:36 -0400 +Subject: USB: chaoskey: Fix slab-use-after-free in chaoskey_release() + +From: Alan Stern + +commit abf76d3239dee97b66e7241ad04811f1ce562e28 upstream. + +The chaoskey driver has a use-after-free bug in its release routine. +If the user closes the device file after the USB device has been +unplugged, a debugging log statement will try to access the +usb_interface structure after it has been deallocated: + + BUG: KASAN: slab-use-after-free in dev_driver_string (drivers/base/core.c:2406) + Read of size 8 at addr ffff888168e8a0b8 by task chaoskey_raw_re/10106 + + Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + Call Trace: + + dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) + print_report (mm/kasan/report.c:378 mm/kasan/report.c:482) + kasan_report (mm/kasan/report.c:595) + dev_driver_string (drivers/base/core.c:2406) + __dynamic_dev_dbg (lib/dynamic_debug.c:906) + chaoskey_release (drivers/usb/misc/chaoskey.c:323) + __fput (fs/file_table.c:510) + fput_close_sync (fs/file_table.c:615) + __x64_sys_close (fs/open.c:1507 fs/open.c:1492 fs/open.c:1492) + do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +The driver's last reference to the interface structure is dropped in +the chaoskey_free() routine, so the code must not use the interface -- +even in a debugging statement -- after that routine returns. +(Exception: If we know that another reference is held by someone else, +such as the device core while the disconnect routine runs, there's no +problem. Thanks to Johan Hovold for pointing this out.) + +Since the bad access is part of an unimportant debugging statement, +we can fix the problem simply by removing the whole statement. + +Reported-by: Shuangpeng Bai +Closes: https://lore.kernel.org/linux-usb/20EC9664-054E-438B-B411-2145D347F97B@gmail.com/ +Tested-by: Shuangpeng Bai +Signed-off-by: Alan Stern +Fixes: 66e3e591891d ("usb: Add driver for Altus Metrum ChaosKey device (v2)") +Cc: stable +Reviewed-by: Johan Hovold +Link: https://patch.msgid.link/bb5b1dc6-eb59-43e1-8d26-51e658e88bbe@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/chaoskey.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/usb/misc/chaoskey.c ++++ b/drivers/usb/misc/chaoskey.c +@@ -320,7 +320,6 @@ bail: + mutex_unlock(&dev->lock); + destruction: + mutex_unlock(&chaoskey_list_lock); +- usb_dbg(interface, "release success"); + return rv; + } + diff --git a/queue-6.18/usb-dwc3-run-gadget-disconnect-from-sleepable-suspend-context.patch b/queue-6.18/usb-dwc3-run-gadget-disconnect-from-sleepable-suspend-context.patch new file mode 100644 index 0000000000..6c83c3d6b4 --- /dev/null +++ b/queue-6.18/usb-dwc3-run-gadget-disconnect-from-sleepable-suspend-context.patch @@ -0,0 +1,113 @@ +From 010382937fb69892b3469ac4d30af072262f59e8 Mon Sep 17 00:00:00 2001 +From: Runyu Xiao +Date: Fri, 12 Jun 2026 13:20:05 +0800 +Subject: usb: dwc3: run gadget disconnect from sleepable suspend context + +From: Runyu Xiao + +commit 010382937fb69892b3469ac4d30af072262f59e8 upstream. + +dwc3_gadget_suspend() takes dwc->lock with IRQs disabled and then calls +dwc3_disconnect_gadget(). For async callbacks that helper only uses +plain spin_unlock()/spin_lock(), so the gadget ->disconnect() callback +still runs with IRQs disabled and any sleepable callback trips Lockdep. + +This issue was found by our static analysis tool and then manually +reviewed against the current tree. + +The grounded PoC kept the dwc3_gadget_suspend() -> +dwc3_disconnect_gadget() -> gadget_driver->disconnect() chain, and +Lockdep reported: + + BUG: sleeping function called from invalid context + gadget_disconnect+0x21/0x39 [vuln_msv] + dwc3_gadget_suspend.constprop.0+0x2b/0x42 [vuln_msv] + +Keep the disconnect callback selection in one common helper, but add a +sleepable suspend-side wrapper which snapshots the callback under +dwc->lock and then runs it after spin_unlock_irqrestore(). The regular +event path still uses the existing spin_unlock()/spin_lock() window. + +Fixes: c8540870af4c ("usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()") +Cc: stable +Signed-off-by: Runyu Xiao +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20260612052005.3849659-1-runyu.xiao@seu.edu.cn +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/gadget.c | 43 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 7 deletions(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -3934,15 +3934,48 @@ static void dwc3_endpoint_interrupt(stru + } + } + ++static bool dwc3_prepare_disconnect_gadget(struct dwc3 *dwc, ++ struct usb_gadget_driver **driver, ++ struct usb_gadget **gadget) ++{ ++ if (!dwc->async_callbacks || !dwc->gadget_driver || ++ !dwc->gadget_driver->disconnect) ++ return false; ++ ++ *driver = dwc->gadget_driver; ++ *gadget = dwc->gadget; ++ ++ return true; ++} ++ + static void dwc3_disconnect_gadget(struct dwc3 *dwc) + { +- if (dwc->async_callbacks && dwc->gadget_driver->disconnect) { ++ struct usb_gadget_driver *driver; ++ struct usb_gadget *gadget; ++ ++ if (dwc3_prepare_disconnect_gadget(dwc, &driver, &gadget)) { + spin_unlock(&dwc->lock); +- dwc->gadget_driver->disconnect(dwc->gadget); ++ driver->disconnect(gadget); + spin_lock(&dwc->lock); + } + } + ++static void dwc3_disconnect_gadget_sleepable(struct dwc3 *dwc) ++{ ++ struct usb_gadget_driver *driver; ++ struct usb_gadget *gadget; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dwc->lock, flags); ++ if (!dwc3_prepare_disconnect_gadget(dwc, &driver, &gadget)) { ++ spin_unlock_irqrestore(&dwc->lock, flags); ++ return; ++ } ++ ++ spin_unlock_irqrestore(&dwc->lock, flags); ++ driver->disconnect(gadget); ++} ++ + static void dwc3_suspend_gadget(struct dwc3 *dwc) + { + if (dwc->async_callbacks && dwc->gadget_driver->suspend) { +@@ -4836,7 +4869,6 @@ void dwc3_gadget_exit(struct dwc3 *dwc) + + int dwc3_gadget_suspend(struct dwc3 *dwc) + { +- unsigned long flags; + int ret; + + ret = dwc3_gadget_soft_disconnect(dwc); +@@ -4850,10 +4882,7 @@ int dwc3_gadget_suspend(struct dwc3 *dwc + return -EAGAIN; + } + +- spin_lock_irqsave(&dwc->lock, flags); +- if (dwc->gadget_driver) +- dwc3_disconnect_gadget(dwc); +- spin_unlock_irqrestore(&dwc->lock, flags); ++ dwc3_disconnect_gadget_sleepable(dwc); + + return 0; + } diff --git a/queue-6.18/usb-misc-usbio-fix-disconnect-uaf-in-client-teardown.patch b/queue-6.18/usb-misc-usbio-fix-disconnect-uaf-in-client-teardown.patch new file mode 100644 index 0000000000..59b57e63fa --- /dev/null +++ b/queue-6.18/usb-misc-usbio-fix-disconnect-uaf-in-client-teardown.patch @@ -0,0 +1,149 @@ +From 0bfeec21984fedd32987f4e4c0cde34b445af404 Mon Sep 17 00:00:00 2001 +From: Cen Zhang +Date: Thu, 18 Jun 2026 20:40:29 +0800 +Subject: usb: misc: usbio: fix disconnect UAF in client teardown + +From: Cen Zhang + +commit 0bfeec21984fedd32987f4e4c0cde34b445af404 upstream. + +usbio_disconnect() walks usbio->cli_list in reverse and uninitializes each +auxiliary device. auxiliary_device_uninit() drops the device reference, and +for an unbound child that can run usbio_auxdev_release() and free the +containing struct usbio_client. + +list_for_each_entry_reverse() advances after the loop body by reading +client->link.prev. If the current client is freed by +auxiliary_device_uninit(), the iterator dereferences freed memory. + +Use list_for_each_entry_safe_reverse() so the previous client is +cached before the body can drop the final reference. This preserves +reverse teardown order while keeping the next iterator cursor independent +of the current client's lifetime. + +Validation reproduced this kernel report: +BUG: KASAN: slab-use-after-free in usbio_disconnect+0x12e/0x150 + +Call Trace: + + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + ? usbio_disconnect+0x12e/0x150 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __virt_addr_valid+0x188/0x320 + ? usbio_disconnect+0x12e/0x150 + kasan_report+0xe0/0x110 + ? usbio_disconnect+0x12e/0x150 + usbio_disconnect+0x12e/0x150 + usb_unbind_interface+0xf3/0x400 + really_probe+0x316/0x660 + __driver_probe_device+0x106/0x240 + driver_probe_device+0x4a/0x110 + __device_attach_driver+0xf1/0x1a0 + ? __pfx___device_attach_driver+0x10/0x10 + bus_for_each_drv+0xf9/0x160 + ? __pfx_bus_for_each_drv+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? trace_hardirqs_on+0x18/0x130 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? _raw_spin_unlock_irqrestore+0x44/0x60 + __device_attach+0x133/0x2a0 + ? __pfx___device_attach+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? do_raw_spin_unlock+0x9a/0x100 + ? srso_alias_return_thunk+0x5/0xfbef5 + device_initial_probe+0x55/0x70 + bus_probe_device+0x4a/0xd0 + device_add+0x9b9/0xc10 + ? __pfx_device_add+0x10/0x10 + ? _raw_spin_unlock_irqrestore+0x44/0x60 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? lockdep_hardirqs_on_prepare+0xea/0x1a0 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? usb_enable_lpm+0x3c/0x260 + usb_set_configuration+0xb64/0xf20 + usb_generic_driver_probe+0x5f/0x90 + usb_probe_device+0x71/0x1b0 + really_probe+0x46b/0x660 + __driver_probe_device+0x106/0x240 + driver_probe_device+0x4a/0x110 + __device_attach_driver+0xf1/0x1a0 + ? __pfx___device_attach_driver+0x10/0x10 + bus_for_each_drv+0xf9/0x160 + ? __pfx_bus_for_each_drv+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? trace_hardirqs_on+0x18/0x130 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? _raw_spin_unlock_irqrestore+0x44/0x60 + __device_attach+0x133/0x2a0 + ? __pfx___device_attach+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? do_raw_spin_unlock+0x9a/0x100 + ? srso_alias_return_thunk+0x5/0xfbef5 + device_initial_probe+0x55/0x70 + bus_probe_device+0x4a/0xd0 + device_add+0x9b9/0xc10 + ? __pfx_device_add+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? add_device_randomness+0xb7/0xf0 + usb_new_device+0x492/0x870 + hub_event+0x1b10/0x29c0 + ? __pfx_hub_event+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? lock_acquire+0x187/0x300 + ? process_one_work+0x475/0xb90 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? lock_release+0xc8/0x290 + ? srso_alias_return_thunk+0x5/0xfbef5 + process_one_work+0x4d7/0xb90 + ? __pfx_process_one_work+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __list_add_valid_or_report+0x37/0xf0 + ? __pfx_hub_event+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + worker_thread+0x2d8/0x570 + ? __pfx_worker_thread+0x10/0x10 + kthread+0x1ad/0x1f0 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x3c9/0x540 + ? __pfx_ret_from_fork+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __switch_to+0x2e9/0x730 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fixes: 121a0f839dbb ("usb: misc: Add Intel USBIO bridge driver") +Cc: stable +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Reviewed-by: Hans de Goede +Acked-by: Sakari Ailus +Link: https://patch.msgid.link/20260618124029.3704089-1-zzzccc427@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/usbio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/misc/usbio.c ++++ b/drivers/usb/misc/usbio.c +@@ -518,7 +518,7 @@ static int usbio_resume(struct usb_inter + static void usbio_disconnect(struct usb_interface *intf) + { + struct usbio_device *usbio = usb_get_intfdata(intf); +- struct usbio_client *client; ++ struct usbio_client *client, *next; + + /* Wakeup any clients waiting for a reply */ + usbio->rxdat_len = 0; +@@ -535,7 +535,7 @@ static void usbio_disconnect(struct usb_ + usb_kill_urb(usbio->urb); + usb_free_urb(usbio->urb); + +- list_for_each_entry_reverse(client, &usbio->cli_list, link) { ++ list_for_each_entry_safe_reverse(client, next, &usbio->cli_list, link) { + auxiliary_device_delete(&client->auxdev); + auxiliary_device_uninit(&client->auxdev); + } diff --git a/queue-6.18/virtio-mmio-fix-device-release-warning-on-module-unload.patch b/queue-6.18/virtio-mmio-fix-device-release-warning-on-module-unload.patch new file mode 100644 index 0000000000..3bba47914f --- /dev/null +++ b/queue-6.18/virtio-mmio-fix-device-release-warning-on-module-unload.patch @@ -0,0 +1,103 @@ +From c687bc35694698ec4c7f92bf929c3d659f0cecb8 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 27 Apr 2026 16:37:10 +0200 +Subject: virtio-mmio: fix device release warning on module unload + +From: Johan Hovold + +commit c687bc35694698ec4c7f92bf929c3d659f0cecb8 upstream. + +Driver core expects devices to be allocated dynamically and complains +loudly when a device that lacks a release function is freed. + +Use __root_device_register() to allocate and register the root device +instead of open coding using a static device. + +Note that root_device_register(), which also creates a link to the +module, cannot be used as the device is registered when parsing the +module parameters which happens before the module kobject has been set +up. + +Fixes: 81a054ce0b46 ("virtio-mmio: Devices parameter parsing") +Cc: stable@vger.kernel.org # 3.5 +Cc: Pawel Moll +Signed-off-by: Johan Hovold +Signed-off-by: Michael S. Tsirkin +Message-ID: <20260427143710.14702-1-johan@kernel.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virtio/virtio_mmio.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +--- a/drivers/virtio/virtio_mmio.c ++++ b/drivers/virtio/virtio_mmio.c +@@ -662,9 +662,7 @@ static void virtio_mmio_remove(struct pl + + #if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES) + +-static struct device vm_cmdline_parent = { +- .init_name = "virtio-mmio-cmdline", +-}; ++static struct device *vm_cmdline_parent; + + static int vm_cmdline_parent_registered; + static int vm_cmdline_id; +@@ -672,7 +670,6 @@ static int vm_cmdline_id; + static int vm_cmdline_set(const char *device, + const struct kernel_param *kp) + { +- int err; + struct resource resources[2] = {}; + char *str; + long long base, size; +@@ -704,11 +701,10 @@ static int vm_cmdline_set(const char *de + resources[1].start = resources[1].end = irq; + + if (!vm_cmdline_parent_registered) { +- err = device_register(&vm_cmdline_parent); +- if (err) { +- put_device(&vm_cmdline_parent); ++ vm_cmdline_parent = __root_device_register("virtio-mmio-cmdline", NULL); ++ if (IS_ERR(vm_cmdline_parent)) { + pr_err("Failed to register parent device!\n"); +- return err; ++ return PTR_ERR(vm_cmdline_parent); + } + vm_cmdline_parent_registered = 1; + } +@@ -719,7 +715,7 @@ static int vm_cmdline_set(const char *de + (unsigned long long)resources[0].end, + (int)resources[1].start); + +- pdev = platform_device_register_resndata(&vm_cmdline_parent, ++ pdev = platform_device_register_resndata(vm_cmdline_parent, + "virtio-mmio", vm_cmdline_id++, + resources, ARRAY_SIZE(resources), NULL, 0); + +@@ -743,8 +739,12 @@ static int vm_cmdline_get_device(struct + static int vm_cmdline_get(char *buffer, const struct kernel_param *kp) + { + buffer[0] = '\0'; +- device_for_each_child(&vm_cmdline_parent, buffer, +- vm_cmdline_get_device); ++ ++ if (vm_cmdline_parent_registered) { ++ device_for_each_child(vm_cmdline_parent, buffer, ++ vm_cmdline_get_device); ++ } ++ + return strlen(buffer) + 1; + } + +@@ -766,9 +766,9 @@ static int vm_unregister_cmdline_device( + static void vm_unregister_cmdline_devices(void) + { + if (vm_cmdline_parent_registered) { +- device_for_each_child(&vm_cmdline_parent, NULL, ++ device_for_each_child(vm_cmdline_parent, NULL, + vm_unregister_cmdline_device); +- device_unregister(&vm_cmdline_parent); ++ root_device_unregister(vm_cmdline_parent); + vm_cmdline_parent_registered = 0; + } + } diff --git a/queue-6.18/virtio_pci-fix-vq-info-pointer-lookup-via-wrong-index.patch b/queue-6.18/virtio_pci-fix-vq-info-pointer-lookup-via-wrong-index.patch new file mode 100644 index 0000000000..23bbc3efb5 --- /dev/null +++ b/queue-6.18/virtio_pci-fix-vq-info-pointer-lookup-via-wrong-index.patch @@ -0,0 +1,96 @@ +From f7d380fb525c13bdd114369a1979c80c346e6abc Mon Sep 17 00:00:00 2001 +From: Ammar Faizi +Date: Sun, 15 Mar 2026 21:18:08 +0700 +Subject: virtio_pci: fix vq info pointer lookup via wrong index + +From: Ammar Faizi + +commit f7d380fb525c13bdd114369a1979c80c346e6abc upstream. + +Unbinding a virtio balloon device: + + echo virtio0 > /sys/bus/virtio/drivers/virtio_balloon/unbind + +triggers a NULL pointer dereference. The dmesg says: + + BUG: kernel NULL pointer dereference, address: 0000000000000008 + [...] + RIP: 0010:__list_del_entry_valid_or_report+0x5/0xf0 + Call Trace: + + vp_del_vqs+0x121/0x230 + remove_common+0x135/0x150 + virtballoon_remove+0xee/0x100 + virtio_dev_remove+0x3b/0x80 + device_release_driver_internal+0x187/0x2c0 + unbind_store+0xb9/0xe0 + kernfs_fop_write_iter.llvm.11660790530567441834+0xf6/0x180 + vfs_write+0x2a9/0x3b0 + ksys_write+0x5c/0xd0 + do_syscall_64+0x54/0x230 + entry_SYSCALL_64_after_hwframe+0x29/0x31 + [...] + + +The virtio_balloon device registers 5 queues (inflate, deflate, stats, +free_page, reporting) but only the first two are unconditional. The +stats, free_page and reporting queues are each conditional on their +respective feature bits. When any of these features are absent, the +corresponding vqs_info entry has name == NULL, creating holes in the +array. + +The root cause is an indexing mismatch introduced when vq info storage +was changed to be passed as an argument. vp_find_vqs_msix() and +vp_find_vqs_intx() store the info pointer at vp_dev->vqs[i], where 'i' +is the caller's sparse array index. However, the virtqueue itself gets +vq->index assigned from queue_idx, a dense index that skips NULL +entries. When holes exist, 'i' and queue_idx diverge. Later, +vp_del_vqs() looks up info via vp_dev->vqs[vq->index] using the dense +index into the sparsely-populated array, and hits NULL. + +Fix this by storing info at vp_dev->vqs[queue_idx] instead of +vp_dev->vqs[i], so the store index matches the lookup index +(vq->index). Apply the fix to both the MSIX and INTX paths. + +Cc: Yichun Zhang +Cc: Jiri Pirko +Cc: stable@vger.kernel.org # v6.11+ +Tested-by: Yuka +Fixes: 89a1c435aec2 ("virtio_pci: pass vq info as an argument to vp_setup_vq()") +Signed-off-by: Ammar Faizi +Message-Id: <20260315141808.547081-1-ammarfaizi2@openresty.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virtio/virtio_pci_common.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/virtio/virtio_pci_common.c ++++ b/drivers/virtio/virtio_pci_common.c +@@ -426,10 +426,11 @@ static int vp_find_vqs_msix(struct virti + vqs[i] = NULL; + continue; + } +- vqs[i] = vp_find_one_vq_msix(vdev, queue_idx++, vqi->callback, ++ vqs[i] = vp_find_one_vq_msix(vdev, queue_idx, vqi->callback, + vqi->name, vqi->ctx, false, + &allocated_vectors, vector_policy, +- &vp_dev->vqs[i]); ++ &vp_dev->vqs[queue_idx]); ++ queue_idx++; + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto error_find; +@@ -488,9 +489,10 @@ static int vp_find_vqs_intx(struct virti + vqs[i] = NULL; + continue; + } +- vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, ++ vqs[i] = vp_setup_vq(vdev, queue_idx, vqi->callback, + vqi->name, vqi->ctx, +- VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[i]); ++ VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[queue_idx]); ++ queue_idx++; + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto out_del_vqs;