From: Greg Kroah-Hartman Date: Mon, 13 Jul 2026 13:46:48 +0000 (+0200) Subject: 5.10-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e392e85290057f59152ae484e80fa3ded8aaffc;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-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 crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch debugobjects-plug-race-against-a-concurrent-oom-disable.patch gpio-eic-sprd-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 ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.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 net-af_key-initialize-alg_key_len-for-ipcomp-states.patch net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch virtio-mmio-fix-device-release-warning-on-module-unload.patch --- diff --git a/queue-5.10/6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch b/queue-5.10/6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch new file mode 100644 index 0000000000..d34e8f48b6 --- /dev/null +++ b/queue-5.10/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 +@@ -168,9 +168,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-5.10/audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch b/queue-5.10/audit-fix-data-races-of-skb_queue_len-readers-on-audit_queue.patch new file mode 100644 index 0000000000..99c33b927c --- /dev/null +++ b/queue-5.10/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 +@@ -912,7 +912,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; +@@ -1247,7 +1247,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); +@@ -1588,7 +1588,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 */ +@@ -1890,7 +1890,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); + +@@ -1910,7 +1910,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-5.10/crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch b/queue-5.10/crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.patch new file mode 100644 index 0000000000..1b9d275ea9 --- /dev/null +++ b/queue-5.10/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 +@@ -275,8 +275,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-5.10/debugobjects-plug-race-against-a-concurrent-oom-disable.patch b/queue-5.10/debugobjects-plug-race-against-a-concurrent-oom-disable.patch new file mode 100644 index 0000000000..f3eef1a101 --- /dev/null +++ b/queue-5.10/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 +@@ -722,6 +722,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) { +@@ -899,6 +907,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-5.10/gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch b/queue-5.10/gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch new file mode 100644 index 0000000000..3690ba0233 --- /dev/null +++ b/queue-5.10/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 +@@ -94,7 +94,7 @@ struct sprd_eic { + struct irq_chip intc; + void __iomem *base[SPRD_EIC_MAX_BANK]; + enum sprd_eic_type type; +- spinlock_t lock; ++ raw_spinlock_t lock; + int irq; + }; + +@@ -146,7 +146,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) +@@ -155,7 +155,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) +@@ -606,7 +606,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-5.10/hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch b/queue-5.10/hwrng-virtio-clamp-device-reported-used.len-at-copy_data.patch new file mode 100644 index 0000000000..f347fc545b --- /dev/null +++ b/queue-5.10/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-5.10/io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch b/queue-5.10/io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.patch new file mode 100644 index 0000000000..5806f31864 --- /dev/null +++ b/queue-5.10/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 +@@ -556,7 +556,6 @@ static void io_worker_handle_work(struct + struct io_wq *wq = wqe->wq; + + do { +- bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state); + struct io_wq_work *work; + get_next: + /* +@@ -578,6 +577,7 @@ get_next: + + /* 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 hash = io_get_work_hash(work); + diff --git a/queue-5.10/ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch b/queue-5.10/ipv4-igmp-remove-multicast-group-from-hash-table-on-device-destruction.patch new file mode 100644 index 0000000000..0dfc303579 --- /dev/null +++ b/queue-5.10/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 +@@ -1816,6 +1816,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-5.10/media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch b/queue-5.10/media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch new file mode 100644 index 0000000000..0f8d8ad550 --- /dev/null +++ b/queue-5.10/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 +@@ -1773,6 +1773,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 = +@@ -1791,8 +1793,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-5.10/mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch b/queue-5.10/mfd-cros_ec-delay-dev_set_drvdata-until-probe-success.patch new file mode 100644 index 0000000000..692273e40d --- /dev/null +++ b/queue-5.10/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 +@@ -137,7 +137,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; +@@ -179,6 +178,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-5.10/net-af_key-initialize-alg_key_len-for-ipcomp-states.patch b/queue-5.10/net-af_key-initialize-alg_key_len-for-ipcomp-states.patch new file mode 100644 index 0000000000..f489d95deb --- /dev/null +++ b/queue-5.10/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 +@@ -1206,6 +1206,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-5.10/net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch b/queue-5.10/net-ipv4-bound-tcp-reordering-sysctl-writes-and-mtu-probe-sizes.patch new file mode 100644 index 0000000000..556ec830d3 --- /dev/null +++ b/queue-5.10/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 +@@ -892,7 +892,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", +@@ -1109,7 +1111,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", +@@ -1336,6 +1339,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 +@@ -2343,7 +2343,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; +@@ -2367,7 +2367,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-5.10/netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch b/queue-5.10/netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.patch new file mode 100644 index 0000000000..07571a2f27 --- /dev/null +++ b/queue-5.10/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 +@@ -1490,7 +1490,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); +@@ -1695,7 +1699,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-5.10/series b/queue-5.10/series index 19b9782cd6..e3d5360c50 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -63,3 +63,19 @@ binder-fix-uaf-in-binder_thread_release.patch usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch pci-altera-do-not-dispose-parent-irq-mapping.patch pci-host-common-request-bus-reassignment-when-not-probe-only.patch +netfilter-ipset-fix-race-between-dump-and-ip_set_list-resize.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 +6lowpan-fix-nhc-entry-use-after-free-on-error-path.patch +tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch +media-staging-ipu3-imgu-add-range-check-for-imgu_css_cfg_acc_stripe.patch +crypto-amlogic-avoid-double-cleanup-in-meson_crypto_probe.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 +debugobjects-plug-race-against-a-concurrent-oom-disable.patch +gpio-eic-sprd-use-raw_spinlock_t-in-the-irq-startup-path.patch +io_uring-io-wq-re-check-io_wq_bit_exit-for-each-linked-work-item.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 diff --git a/queue-5.10/tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch b/queue-5.10/tipc-fix-out-of-bounds-read-in-broadcast-gap-ack-blocks.patch new file mode 100644 index 0000000000..18143db453 --- /dev/null +++ b/queue-5.10/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 +@@ -1804,12 +1804,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); +@@ -2111,12 +2114,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-5.10/usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch b/queue-5.10/usb-chaoskey-fix-slab-use-after-free-in-chaoskey_release.patch new file mode 100644 index 0000000000..7482266eb1 --- /dev/null +++ b/queue-5.10/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 +@@ -321,7 +321,6 @@ bail: + mutex_unlock(&dev->lock); + destruction: + mutex_unlock(&chaoskey_list_lock); +- usb_dbg(interface, "release success"); + return rv; + } + diff --git a/queue-5.10/virtio-mmio-fix-device-release-warning-on-module-unload.patch b/queue-5.10/virtio-mmio-fix-device-release-warning-on-module-unload.patch new file mode 100644 index 0000000000..02d922d4b1 --- /dev/null +++ b/queue-5.10/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 +@@ -675,9 +675,7 @@ static int virtio_mmio_remove(struct pla + + #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; +@@ -685,7 +683,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 int base, size; +@@ -717,11 +714,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; + } +@@ -732,7 +728,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); + +@@ -756,8 +752,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; + } + +@@ -779,9 +779,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; + } + }