From: Greg Kroah-Hartman Date: Mon, 13 Apr 2026 14:30:57 +0000 (+0200) Subject: 5.15-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9792a5fe9580fff4fdaa391c7c32e6bfeb66d2c4;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch ext4-fix-the-might_sleep-warnings-in-kvfree.patch ext4-fix-use-after-free-in-update_super_work-when-racing-with-umount.patch ext4-publish-jinode-after-initialization.patch i2c-cp2615-fix-serial-string-null-deref-at-probe.patch i2c-cp2615-replace-deprecated-strncpy-with-strscpy.patch ksmbd-fix-dangling-pointer-in-krb_authenticate.patch ksmbd-fix-potencial-oob-in-get_file_all_info-for-compound-requests.patch ksmbd-fix-refcount-leak-when-invalid-session-is-found-on-session-lookup.patch ksmbd-replace-hardcoded-hdr2_len-with-offsetof-in-smb2_calc_max_out_buf_len.patch kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch revert-mptcp-add-needs_id-for-netlink-appending-addr.patch scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch tracing-fix-potential-deadlock-in-cpu-hotplug-with-osnoise.patch usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch --- diff --git a/queue-5.15/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch b/queue-5.15/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch new file mode 100644 index 0000000000..a8660afdea --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch @@ -0,0 +1,64 @@ +From stable+bounces-227804-greg=kroah.com@vger.kernel.org Sun Mar 22 02:27:44 2026 +From: Sasha Levin +Date: Sat, 21 Mar 2026 21:27:39 -0400 +Subject: Bluetooth: L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ +To: stable@vger.kernel.org +Cc: Luiz Augusto von Dentz , Yiming Qian , Sasha Levin +Message-ID: <20260322012739.673067-1-sashal@kernel.org> + +From: Luiz Augusto von Dentz + +[ Upstream commit 5b3e2052334f2ff6d5200e952f4aa66994d09899 ] + +Currently the code attempts to accept requests regardless of the +command identifier which may cause multiple requests to be marked +as pending (FLAG_DEFER_SETUP) which can cause more than +L2CAP_ECRED_MAX_CID(5) to be allocated in l2cap_ecred_rsp_defer +causing an overflow. + +The spec is quite clear that the same identifier shall not be used on +subsequent requests: + +'Within each signaling channel a different Identifier shall be used +for each successive request or indication.' +https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-62/out/en/host/logical-link-control-and-adaptation-protocol-specification.html#UUID-32a25a06-4aa4-c6c7-77c5-dcfe3682355d + +So this attempts to check if there are any channels pending with the +same identifier and rejects if any are found. + +Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode") +Reported-by: Yiming Qian +Signed-off-by: Luiz Augusto von Dentz +[ adapted variable names ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_core.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6043,7 +6043,7 @@ static inline int l2cap_ecred_conn_req(s + u16 mtu, mps; + __le16 psm; + u8 result, len = 0; +- int i, num_scid; ++ int i, num_scid = 0; + bool defer = false; + + if (!enable_ecred) +@@ -6053,6 +6053,14 @@ static inline int l2cap_ecred_conn_req(s + result = L2CAP_CR_LE_INVALID_PARAMS; + goto response; + } ++ ++ /* Check if there are no pending channels with the same ident */ ++ __l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer, ++ &num_scid); ++ if (num_scid) { ++ result = L2CAP_CR_LE_INVALID_PARAMS; ++ goto response; ++ } + + cmd_len -= sizeof(*req); + num_scid = cmd_len / sizeof(u16); diff --git a/queue-5.15/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch b/queue-5.15/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch new file mode 100644 index 0000000000..3c5b72f981 --- /dev/null +++ b/queue-5.15/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch @@ -0,0 +1,79 @@ +From stable+bounces-232813-greg=kroah.com@vger.kernel.org Wed Apr 1 18:24:04 2026 +From: Sasha Levin +Date: Wed, 1 Apr 2026 12:16:58 -0400 +Subject: dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock +To: stable@vger.kernel.org +Cc: Claudiu Beznea , Biju Das , Frank Li , Claudiu Beznea , Vinod Koul , Sasha Levin +Message-ID: <20260401161658.115456-1-sashal@kernel.org> + +From: Claudiu Beznea + +[ Upstream commit 89a8567d84bde88cb7cdbbac2ab2299c4f991490 ] + +Both rz_dmac_disable_hw() and rz_dmac_irq_handle_channel() update the +CHCTRL register. To avoid concurrency issues when configuring +functionalities exposed by this registers, take the virtual channel lock. +All other CHCTRL updates were already protected by the same lock. + +Previously, rz_dmac_disable_hw() disabled and re-enabled local IRQs, before +accessing CHCTRL registers but this does not ensure race-free access. +Remove the local IRQ disable/enable code as well. + +Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC") +Cc: stable@vger.kernel.org +Reviewed-by: Biju Das +Reviewed-by: Frank Li +Signed-off-by: Claudiu Beznea +Link: https://patch.msgid.link/20260316133252.240348-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +[ replaced scoped_guard(spinlock_irqsave, ...) ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/sh/rz-dmac.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/dma/sh/rz-dmac.c ++++ b/drivers/dma/sh/rz-dmac.c +@@ -283,13 +283,10 @@ static void rz_dmac_disable_hw(struct rz + { + struct dma_chan *chan = &channel->vc.chan; + struct rz_dmac *dmac = to_rz_dmac(chan->device); +- unsigned long flags; + + dev_dbg(dmac->dev, "%s channel %d\n", __func__, channel->index); + +- local_irq_save(flags); + rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1); +- local_irq_restore(flags); + } + + static void rz_dmac_set_dmars_register(struct rz_dmac *dmac, int nr, u32 dmars) +@@ -536,8 +533,8 @@ static int rz_dmac_terminate_all(struct + unsigned int i; + LIST_HEAD(head); + +- rz_dmac_disable_hw(channel); + spin_lock_irqsave(&channel->vc.lock, flags); ++ rz_dmac_disable_hw(channel); + for (i = 0; i < DMAC_NR_LMDESC; i++) + lmdesc[i].header = 0; + +@@ -646,13 +643,17 @@ static void rz_dmac_irq_handle_channel(s + { + struct dma_chan *chan = &channel->vc.chan; + struct rz_dmac *dmac = to_rz_dmac(chan->device); ++ unsigned long flags; + u32 chstat, chctrl; + + chstat = rz_dmac_ch_readl(channel, CHSTAT, 1); + if (chstat & CHSTAT_ER) { + dev_err(dmac->dev, "DMAC err CHSTAT_%d = %08X\n", + channel->index, chstat); ++ ++ spin_lock_irqsave(&channel->vc.lock, flags); + rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1); ++ spin_unlock_irqrestore(&channel->vc.lock, flags); + goto done; + } + diff --git a/queue-5.15/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch b/queue-5.15/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch new file mode 100644 index 0000000000..749768a976 --- /dev/null +++ b/queue-5.15/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch @@ -0,0 +1,107 @@ +From stable+bounces-232632-greg=kroah.com@vger.kernel.org Wed Apr 1 02:47:53 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 20:45:24 -0400 +Subject: dmaengine: sh: rz-dmac: Protect the driver specific lists +To: stable@vger.kernel.org +Cc: Claudiu Beznea , Frank Li , Claudiu Beznea , Vinod Koul , Sasha Levin +Message-ID: <20260401004524.4038525-1-sashal@kernel.org> + +From: Claudiu Beznea + +[ Upstream commit abb863e6213dc41a58ef8bb3289b7e77460dabf3 ] + +The driver lists (ld_free, ld_queue) are used in +rz_dmac_free_chan_resources(), rz_dmac_terminate_all(), +rz_dmac_issue_pending(), and rz_dmac_irq_handler_thread(), all under +the virtual channel lock. Take the same lock in rz_dmac_prep_slave_sg() +and rz_dmac_prep_dma_memcpy() as well to avoid concurrency issues, since +these functions also check whether the lists are empty and update or +remove list entries. + +Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC") +Cc: stable@vger.kernel.org +Reviewed-by: Frank Li +Signed-off-by: Claudiu Beznea +Link: https://patch.msgid.link/20260316133252.240348-2-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +[ replaced scoped_guard(spinlock_irqsave) with explicit spin_lock_irqsave/spin_unlock_irqrestore calls ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/sh/rz-dmac.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +--- a/drivers/dma/sh/rz-dmac.c ++++ b/drivers/dma/sh/rz-dmac.c +@@ -419,6 +419,7 @@ static int rz_dmac_alloc_chan_resources( + if (!desc) + break; + ++ /* No need to lock. This is called only for the 1st client. */ + list_add_tail(&desc->node, &channel->ld_free); + channel->descs_allocated++; + } +@@ -470,12 +471,17 @@ rz_dmac_prep_dma_memcpy(struct dma_chan + struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); + struct rz_dmac *dmac = to_rz_dmac(chan->device); + struct rz_dmac_desc *desc; ++ unsigned long irqflags; + + dev_dbg(dmac->dev, "%s channel: %d src=0x%pad dst=0x%pad len=%zu\n", + __func__, channel->index, &src, &dest, len); + +- if (list_empty(&channel->ld_free)) ++ spin_lock_irqsave(&channel->vc.lock, irqflags); ++ ++ if (list_empty(&channel->ld_free)) { ++ spin_unlock_irqrestore(&channel->vc.lock, irqflags); + return NULL; ++ } + + desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); + +@@ -486,6 +492,9 @@ rz_dmac_prep_dma_memcpy(struct dma_chan + desc->direction = DMA_MEM_TO_MEM; + + list_move_tail(channel->ld_free.next, &channel->ld_queue); ++ ++ spin_unlock_irqrestore(&channel->vc.lock, irqflags); ++ + return vchan_tx_prep(&channel->vc, &desc->vd, flags); + } + +@@ -498,17 +507,21 @@ rz_dmac_prep_slave_sg(struct dma_chan *c + struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); + struct rz_dmac_desc *desc; + struct scatterlist *sg; ++ unsigned long irqflags; + int dma_length = 0; + int i = 0; + +- if (list_empty(&channel->ld_free)) ++ spin_lock_irqsave(&channel->vc.lock, irqflags); ++ ++ if (list_empty(&channel->ld_free)) { ++ spin_unlock_irqrestore(&channel->vc.lock, irqflags); + return NULL; ++ } + + desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); + +- for_each_sg(sgl, sg, sg_len, i) { ++ for_each_sg(sgl, sg, sg_len, i) + dma_length += sg_dma_len(sg); +- } + + desc->type = RZ_DMAC_DESC_SLAVE_SG; + desc->sg = sgl; +@@ -522,6 +535,9 @@ rz_dmac_prep_slave_sg(struct dma_chan *c + desc->dest = channel->dst_per_address; + + list_move_tail(channel->ld_free.next, &channel->ld_queue); ++ ++ spin_unlock_irqrestore(&channel->vc.lock, irqflags); ++ + return vchan_tx_prep(&channel->vc, &desc->vd, flags); + } + diff --git a/queue-5.15/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch b/queue-5.15/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch new file mode 100644 index 0000000000..5435e7e30a --- /dev/null +++ b/queue-5.15/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch @@ -0,0 +1,237 @@ +From stable+bounces-227778-greg=kroah.com@vger.kernel.org Sat Mar 21 17:31:28 2026 +From: Sasha Levin +Date: Sat, 21 Mar 2026 12:31:22 -0400 +Subject: drm: Fix use-after-free on framebuffers and property blobs when calling drm_dev_unplug +To: stable@vger.kernel.org +Cc: "Maarten Lankhorst" , "Thomas Hellström" , "Sasha Levin" +Message-ID: <20260321163122.490593-1-sashal@kernel.org> + +From: Maarten Lankhorst + +[ Upstream commit 6bee098b91417654703e17eb5c1822c6dfd0c01d ] + +When trying to do a rather aggressive test of igt's "xe_module_load +--r reload" with a full desktop environment and game running I noticed +a few OOPSes when dereferencing freed pointers, related to +framebuffers and property blobs after the compositor exits. + +Solve this by guarding the freeing in drm_file with drm_dev_enter/exit, +and immediately put the references from struct drm_file objects during +drm_dev_unplug(). + +Related warnings for framebuffers on the subtest: +[ 739.713076] ------------[ cut here ]------------ + WARN_ON(!list_empty(&dev->mode_config.fb_list)) +[ 739.713079] WARNING: drivers/gpu/drm/drm_mode_config.c:584 at drm_mode_config_cleanup+0x30b/0x320 [drm], CPU#12: xe_module_load/13145 +.... +[ 739.713328] Call Trace: +[ 739.713330] +[ 739.713335] ? intel_pmdemand_destroy_state+0x11/0x20 [xe] +[ 739.713574] ? intel_atomic_global_obj_cleanup+0xe4/0x1a0 [xe] +[ 739.713794] intel_display_driver_remove_noirq+0x51/0xb0 [xe] +[ 739.714041] xe_display_fini_early+0x33/0x50 [xe] +[ 739.714284] devm_action_release+0xf/0x20 +[ 739.714294] devres_release_all+0xad/0xf0 +[ 739.714301] device_unbind_cleanup+0x12/0xa0 +[ 739.714305] device_release_driver_internal+0x1b7/0x210 +[ 739.714311] device_driver_detach+0x14/0x20 +[ 739.714315] unbind_store+0xa6/0xb0 +[ 739.714319] drv_attr_store+0x21/0x30 +[ 739.714322] sysfs_kf_write+0x48/0x60 +[ 739.714328] kernfs_fop_write_iter+0x16b/0x240 +[ 739.714333] vfs_write+0x266/0x520 +[ 739.714341] ksys_write+0x72/0xe0 +[ 739.714345] __x64_sys_write+0x19/0x20 +[ 739.714347] x64_sys_call+0xa15/0xa30 +[ 739.714355] do_syscall_64+0xd8/0xab0 +[ 739.714361] entry_SYSCALL_64_after_hwframe+0x4b/0x53 + +and + +[ 739.714459] ------------[ cut here ]------------ +[ 739.714461] xe 0000:67:00.0: [drm] drm_WARN_ON(!list_empty(&fb->filp_head)) +[ 739.714464] WARNING: drivers/gpu/drm/drm_framebuffer.c:833 at drm_framebuffer_free+0x6c/0x90 [drm], CPU#12: xe_module_load/13145 +[ 739.714715] RIP: 0010:drm_framebuffer_free+0x7a/0x90 [drm] +... +[ 739.714869] Call Trace: +[ 739.714871] +[ 739.714876] drm_mode_config_cleanup+0x26a/0x320 [drm] +[ 739.714998] ? __drm_printfn_seq_file+0x20/0x20 [drm] +[ 739.715115] ? drm_mode_config_cleanup+0x207/0x320 [drm] +[ 739.715235] intel_display_driver_remove_noirq+0x51/0xb0 [xe] +[ 739.715576] xe_display_fini_early+0x33/0x50 [xe] +[ 739.715821] devm_action_release+0xf/0x20 +[ 739.715828] devres_release_all+0xad/0xf0 +[ 739.715843] device_unbind_cleanup+0x12/0xa0 +[ 739.715850] device_release_driver_internal+0x1b7/0x210 +[ 739.715856] device_driver_detach+0x14/0x20 +[ 739.715860] unbind_store+0xa6/0xb0 +[ 739.715865] drv_attr_store+0x21/0x30 +[ 739.715868] sysfs_kf_write+0x48/0x60 +[ 739.715873] kernfs_fop_write_iter+0x16b/0x240 +[ 739.715878] vfs_write+0x266/0x520 +[ 739.715886] ksys_write+0x72/0xe0 +[ 739.715890] __x64_sys_write+0x19/0x20 +[ 739.715893] x64_sys_call+0xa15/0xa30 +[ 739.715900] do_syscall_64+0xd8/0xab0 +[ 739.715905] entry_SYSCALL_64_after_hwframe+0x4b/0x53 + +and then finally file close blows up: + +[ 743.186530] Oops: general protection fault, probably for non-canonical address 0xdead000000000122: 0000 [#1] SMP +[ 743.186535] CPU: 3 UID: 1000 PID: 3453 Comm: kwin_wayland Tainted: G W 7.0.0-rc1-valkyria+ #110 PREEMPT_{RT,(lazy)} +[ 743.186537] Tainted: [W]=WARN +[ 743.186538] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021 +[ 743.186539] RIP: 0010:drm_framebuffer_cleanup+0x55/0xc0 [drm] +[ 743.186588] Code: d8 72 73 0f b6 42 05 ff c3 39 c3 72 e8 49 8d bd 50 07 00 00 31 f6 e8 3a 80 d3 e1 49 8b 44 24 10 49 8d 7c 24 08 49 8b 54 24 08 <48> 3b 38 0f 85 95 7f 02 00 48 3b 7a 08 0f 85 8b 7f 02 00 48 89 42 +[ 743.186589] RSP: 0018:ffffc900085e3cf8 EFLAGS: 00010202 +[ 743.186591] RAX: dead000000000122 RBX: 0000000000000001 RCX: ffffffff8217ed03 +[ 743.186592] RDX: dead000000000100 RSI: 0000000000000000 RDI: ffff88814675ba08 +[ 743.186593] RBP: ffffc900085e3d10 R08: 0000000000000000 R09: 0000000000000000 +[ 743.186593] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88814675ba00 +[ 743.186594] R13: ffff88810d778000 R14: ffff888119f6dca0 R15: ffff88810c660bb0 +[ 743.186595] FS: 00007ff377d21280(0000) GS:ffff888cec3f8000(0000) knlGS:0000000000000000 +[ 743.186596] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 743.186596] CR2: 000055690b55e000 CR3: 0000000113586003 CR4: 00000000003706f0 +[ 743.186597] Call Trace: +[ 743.186598] +[ 743.186603] intel_user_framebuffer_destroy+0x12/0x90 [xe] +[ 743.186722] drm_framebuffer_free+0x3a/0x90 [drm] +[ 743.186750] ? trace_hardirqs_on+0x5f/0x120 +[ 743.186754] drm_mode_object_put+0x51/0x70 [drm] +[ 743.186786] drm_fb_release+0x105/0x190 [drm] +[ 743.186812] ? rt_mutex_slowunlock+0x3aa/0x410 +[ 743.186817] ? rt_spin_lock+0xea/0x1b0 +[ 743.186819] drm_file_free+0x1e0/0x2c0 [drm] +[ 743.186843] drm_release_noglobal+0x91/0xf0 [drm] +[ 743.186865] __fput+0x100/0x2e0 +[ 743.186869] fput_close_sync+0x40/0xa0 +[ 743.186870] __x64_sys_close+0x3e/0x80 +[ 743.186873] x64_sys_call+0xa07/0xa30 +[ 743.186879] do_syscall_64+0xd8/0xab0 +[ 743.186881] entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[ 743.186882] RIP: 0033:0x7ff37e567732 +[ 743.186884] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00 +[ 743.186885] RSP: 002b:00007ffc818169a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000003 +[ 743.186886] RAX: ffffffffffffffda RBX: 00007ffc81816a30 RCX: 00007ff37e567732 +[ 743.186887] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012 +[ 743.186888] RBP: 00007ffc818169d0 R08: 0000000000000000 R09: 0000000000000000 +[ 743.186889] R10: 0000000000000000 R11: 0000000000000246 R12: 000055d60a7996e0 +[ 743.186889] R13: 00007ffc81816a90 R14: 00007ffc81816a90 R15: 000055d60a782a30 +[ 743.186892] +[ 743.186893] Modules linked in: rfcomm snd_hrtimer xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp xt_addrtype nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep mtd_intel_dg snd_hda_codec_intelhdmi mtd snd_hda_codec_hdmi nls_utf8 mxm_wmi intel_wmi_thunderbolt gigabyte_wmi wmi_bmof xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 i2c_mux snd i2c_smbus btusb btrtl btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink +[ 743.186938] ---[ end trace 0000000000000000 ]--- + +And for property blobs: + +void drm_mode_config_cleanup(struct drm_device *dev) +{ +... + list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, + head_global) { + drm_property_blob_put(blob); + } + +Resulting in: + +[ 371.072940] BUG: unable to handle page fault for address: 000001ffffffffff +[ 371.072944] #PF: supervisor read access in kernel mode +[ 371.072945] #PF: error_code(0x0000) - not-present page +[ 371.072947] PGD 0 P4D 0 +[ 371.072950] Oops: Oops: 0000 [#1] SMP +[ 371.072953] CPU: 0 UID: 1000 PID: 3693 Comm: kwin_wayland Not tainted 7.0.0-rc1-valkyria+ #111 PREEMPT_{RT,(lazy)} +[ 371.072956] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021 +[ 371.072957] RIP: 0010:drm_property_destroy_user_blobs+0x3b/0x90 [drm] +[ 371.073019] Code: 00 00 48 83 ec 10 48 8b 86 30 01 00 00 48 39 c3 74 59 48 89 c2 48 8d 48 c8 48 8b 00 4c 8d 60 c8 eb 04 4c 8d 60 c8 48 8b 71 40 <48> 39 16 0f 85 39 32 01 00 48 3b 50 08 0f 85 2f 32 01 00 48 89 70 +[ 371.073021] RSP: 0018:ffffc90006a73de8 EFLAGS: 00010293 +[ 371.073022] RAX: 000001ffffffffff RBX: ffff888118a1a930 RCX: ffff8881b92355c0 +[ 371.073024] RDX: ffff8881b92355f8 RSI: 000001ffffffffff RDI: ffff888118be4000 +[ 371.073025] RBP: ffffc90006a73e08 R08: ffff8881009b7300 R09: ffff888cecc5b000 +[ 371.073026] R10: ffffc90006a73e90 R11: 0000000000000002 R12: 000001ffffffffc7 +[ 371.073027] R13: ffff888118a1a980 R14: ffff88810b366d20 R15: ffff888118a1a970 +[ 371.073028] FS: 00007f1faccbb280(0000) GS:ffff888cec2db000(0000) knlGS:0000000000000000 +[ 371.073029] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 371.073030] CR2: 000001ffffffffff CR3: 000000010655c001 CR4: 00000000003706f0 +[ 371.073031] Call Trace: +[ 371.073033] +[ 371.073036] drm_file_free+0x1df/0x2a0 [drm] +[ 371.073077] drm_release_noglobal+0x7a/0xe0 [drm] +[ 371.073113] __fput+0xe2/0x2b0 +[ 371.073118] fput_close_sync+0x40/0xa0 +[ 371.073119] __x64_sys_close+0x3e/0x80 +[ 371.073122] x64_sys_call+0xa07/0xa30 +[ 371.073126] do_syscall_64+0xc0/0x840 +[ 371.073130] entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[ 371.073132] RIP: 0033:0x7f1fb3501732 +[ 371.073133] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00 +[ 371.073135] RSP: 002b:00007ffe8e6f0278 EFLAGS: 00000246 ORIG_RAX: 0000000000000003 +[ 371.073136] RAX: ffffffffffffffda RBX: 00007ffe8e6f0300 RCX: 00007f1fb3501732 +[ 371.073137] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012 +[ 371.073138] RBP: 00007ffe8e6f02a0 R08: 0000000000000000 R09: 0000000000000000 +[ 371.073139] R10: 0000000000000000 R11: 0000000000000246 R12: 00005585ba46eea0 +[ 371.073140] R13: 00007ffe8e6f0360 R14: 00007ffe8e6f0360 R15: 00005585ba458a30 +[ 371.073143] +[ 371.073144] Modules linked in: rfcomm snd_hrtimer xt_addrtype xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep snd_hda_codec_intelhdmi snd_hda_codec_hdmi mtd_intel_dg mtd nls_utf8 wmi_bmof mxm_wmi gigabyte_wmi intel_wmi_thunderbolt xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 btusb i2c_mux i2c_smbus btrtl snd btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink +[ 371.073198] CR2: 000001ffffffffff +[ 371.073199] ---[ end trace 0000000000000000 ]--- + +Add a guard around file close, and ensure the warnings from drm_mode_config +do not trigger. Fix those by allowing an open reference to the file descriptor +and cleaning up the file linked list entry in drm_mode_config_cleanup(). + +Cc: # v4.18+ +Fixes: bee330f3d672 ("drm: Use srcu to protect drm_device.unplugged") +Cc: Thomas Hellström +Reviewed-by: Thomas Hellström +Link: https://patch.msgid.link/20260313151728.14990-4-dev@lankhorst.se +Signed-off-by: Maarten Lankhorst +[ adapted drm_dbg_printer(dev, DRM_UT_KMS, ...) call to older drm_debug_printer(...) API ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/drm_file.c | 5 ++++- + drivers/gpu/drm/drm_mode_config.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/drm_file.c ++++ b/drivers/gpu/drm/drm_file.c +@@ -244,6 +244,7 @@ static void drm_events_release(struct dr + void drm_file_free(struct drm_file *file) + { + struct drm_device *dev; ++ int idx; + + if (!file) + return; +@@ -269,9 +270,11 @@ void drm_file_free(struct drm_file *file + + drm_events_release(file); + +- if (drm_core_check_feature(dev, DRIVER_MODESET)) { ++ if (drm_core_check_feature(dev, DRIVER_MODESET) && ++ drm_dev_enter(dev, &idx)) { + drm_fb_release(file); + drm_property_destroy_user_blobs(dev, file); ++ drm_dev_exit(idx); + } + + if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) +--- a/drivers/gpu/drm/drm_mode_config.c ++++ b/drivers/gpu/drm/drm_mode_config.c +@@ -543,10 +543,13 @@ void drm_mode_config_cleanup(struct drm_ + */ + WARN_ON(!list_empty(&dev->mode_config.fb_list)); + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { +- struct drm_printer p = drm_debug_printer("[leaked fb]"); ++ if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) { ++ struct drm_printer p = drm_debug_printer("[leaked fb]"); + +- drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); +- drm_framebuffer_print_info(&p, 1, fb); ++ drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); ++ drm_framebuffer_print_info(&p, 1, fb); ++ } ++ list_del_init(&fb->filp_head); + drm_framebuffer_free(&fb->base.refcount); + } + diff --git a/queue-5.15/ext4-fix-the-might_sleep-warnings-in-kvfree.patch b/queue-5.15/ext4-fix-the-might_sleep-warnings-in-kvfree.patch new file mode 100644 index 0000000000..f3e684bb3f --- /dev/null +++ b/queue-5.15/ext4-fix-the-might_sleep-warnings-in-kvfree.patch @@ -0,0 +1,194 @@ +From stable+bounces-233078-greg=kroah.com@vger.kernel.org Thu Apr 2 19:21:46 2026 +From: Sasha Levin +Date: Thu, 2 Apr 2026 13:14:20 -0400 +Subject: ext4: fix the might_sleep() warnings in kvfree() +To: stable@vger.kernel.org +Cc: Zqiang , Baokun Li , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20260402171420.1528128-1-sashal@kernel.org> + +From: Zqiang + +[ Upstream commit 496bb99b7e66f48b178126626f47e9ba79e2d0fa ] + +Use the kvfree() in the RCU read critical section can trigger +the following warnings: + +EXT4-fs (vdb): unmounting filesystem cd983e5b-3c83-4f5a-a136-17b00eb9d018. + +WARNING: suspicious RCU usage + +./include/linux/rcupdate.h:409 Illegal context switch in RCU read-side critical section! + +other info that might help us debug this: + +rcu_scheduler_active = 2, debug_locks = 1 + +Call Trace: + + dump_stack_lvl+0xbb/0xd0 + dump_stack+0x14/0x20 + lockdep_rcu_suspicious+0x15a/0x1b0 + __might_resched+0x375/0x4d0 + ? put_object.part.0+0x2c/0x50 + __might_sleep+0x108/0x160 + vfree+0x58/0x910 + ? ext4_group_desc_free+0x27/0x270 + kvfree+0x23/0x40 + ext4_group_desc_free+0x111/0x270 + ext4_put_super+0x3c8/0xd40 + generic_shutdown_super+0x14c/0x4a0 + ? __pfx_shrinker_free+0x10/0x10 + kill_block_super+0x40/0x90 + ext4_kill_sb+0x6d/0xb0 + deactivate_locked_super+0xb4/0x180 + deactivate_super+0x7e/0xa0 + cleanup_mnt+0x296/0x3e0 + __cleanup_mnt+0x16/0x20 + task_work_run+0x157/0x250 + ? __pfx_task_work_run+0x10/0x10 + ? exit_to_user_mode_loop+0x6a/0x550 + exit_to_user_mode_loop+0x102/0x550 + do_syscall_64+0x44a/0x500 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + +BUG: sleeping function called from invalid context at mm/vmalloc.c:3441 +in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 556, name: umount +preempt_count: 1, expected: 0 +CPU: 3 UID: 0 PID: 556 Comm: umount +Call Trace: + + dump_stack_lvl+0xbb/0xd0 + dump_stack+0x14/0x20 + __might_resched+0x275/0x4d0 + ? put_object.part.0+0x2c/0x50 + __might_sleep+0x108/0x160 + vfree+0x58/0x910 + ? ext4_group_desc_free+0x27/0x270 + kvfree+0x23/0x40 + ext4_group_desc_free+0x111/0x270 + ext4_put_super+0x3c8/0xd40 + generic_shutdown_super+0x14c/0x4a0 + ? __pfx_shrinker_free+0x10/0x10 + kill_block_super+0x40/0x90 + ext4_kill_sb+0x6d/0xb0 + deactivate_locked_super+0xb4/0x180 + deactivate_super+0x7e/0xa0 + cleanup_mnt+0x296/0x3e0 + __cleanup_mnt+0x16/0x20 + task_work_run+0x157/0x250 + ? __pfx_task_work_run+0x10/0x10 + ? exit_to_user_mode_loop+0x6a/0x550 + exit_to_user_mode_loop+0x102/0x550 + do_syscall_64+0x44a/0x500 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +The above scenarios occur in initialization failures and teardown +paths, there are no parallel operations on the resources released +by kvfree(), this commit therefore remove rcu_read_lock/unlock() and +use rcu_access_pointer() instead of rcu_dereference() operations. + +Fixes: 7c990728b99e ("ext4: fix potential race between s_flex_groups online resizing and access") +Fixes: df3da4ea5a0f ("ext4: fix potential race between s_group_info online resizing and access") +Signed-off-by: Zqiang +Reviewed-by: Baokun Li +Link: https://patch.msgid.link/20260319094545.19291-1-qiang.zhang@linux.dev +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ adapted fix to inlined teardown code ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 10 +++------- + fs/ext4/super.c | 14 ++++---------- + 2 files changed, 7 insertions(+), 17 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3353,9 +3353,7 @@ err_freebuddy: + rcu_read_unlock(); + iput(sbi->s_buddy_cache); + err_freesgi: +- rcu_read_lock(); +- kvfree(rcu_dereference(sbi->s_group_info)); +- rcu_read_unlock(); ++ kvfree(rcu_access_pointer(sbi->s_group_info)); + return -ENOMEM; + } + +@@ -3634,7 +3632,8 @@ int ext4_mb_release(struct super_block * + flush_work(&sbi->s_discard_work); + WARN_ON_ONCE(!list_empty(&sbi->s_discard_list)); + +- if (sbi->s_group_info) { ++ group_info = rcu_access_pointer(sbi->s_group_info); ++ if (group_info) { + for (i = 0; i < ngroups; i++) { + cond_resched(); + grinfo = ext4_get_group_info(sb, i); +@@ -3652,12 +3651,9 @@ int ext4_mb_release(struct super_block * + num_meta_group_infos = (ngroups + + EXT4_DESC_PER_BLOCK(sb) - 1) >> + EXT4_DESC_PER_BLOCK_BITS(sb); +- rcu_read_lock(); +- group_info = rcu_dereference(sbi->s_group_info); + for (i = 0; i < num_meta_group_infos; i++) + kfree(group_info[i]); + kvfree(group_info); +- rcu_read_unlock(); + } + kfree(sbi->s_mb_largest_free_orders); + kfree(sbi->s_mb_largest_free_orders_locks); +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1220,18 +1220,16 @@ static void ext4_put_super(struct super_ + if (!sb_rdonly(sb)) + ext4_commit_super(sb); + +- rcu_read_lock(); +- group_desc = rcu_dereference(sbi->s_group_desc); ++ group_desc = rcu_access_pointer(sbi->s_group_desc); + for (i = 0; i < sbi->s_gdb_count; i++) + brelse(group_desc[i]); + kvfree(group_desc); +- flex_groups = rcu_dereference(sbi->s_flex_groups); ++ flex_groups = rcu_access_pointer(sbi->s_flex_groups); + if (flex_groups) { + for (i = 0; i < sbi->s_flex_groups_allocated; i++) + kvfree(flex_groups[i]); + kvfree(flex_groups); + } +- rcu_read_unlock(); + percpu_counter_destroy(&sbi->s_freeclusters_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); +@@ -5075,14 +5073,12 @@ failed_mount7: + ext4_unregister_li_request(sb); + failed_mount6: + ext4_mb_release(sb); +- rcu_read_lock(); +- flex_groups = rcu_dereference(sbi->s_flex_groups); ++ flex_groups = rcu_access_pointer(sbi->s_flex_groups); + if (flex_groups) { + for (i = 0; i < sbi->s_flex_groups_allocated; i++) + kvfree(flex_groups[i]); + kvfree(flex_groups); + } +- rcu_read_unlock(); + percpu_counter_destroy(&sbi->s_freeclusters_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); +@@ -5120,12 +5116,10 @@ failed_mount3: + ext4_stop_mmpd(sbi); + del_timer_sync(&sbi->s_err_report); + failed_mount2: +- rcu_read_lock(); +- group_desc = rcu_dereference(sbi->s_group_desc); ++ group_desc = rcu_access_pointer(sbi->s_group_desc); + for (i = 0; i < db_count; i++) + brelse(group_desc[i]); + kvfree(group_desc); +- rcu_read_unlock(); + failed_mount: + if (sbi->s_chksum_driver) + crypto_free_shash(sbi->s_chksum_driver); diff --git a/queue-5.15/ext4-fix-use-after-free-in-update_super_work-when-racing-with-umount.patch b/queue-5.15/ext4-fix-use-after-free-in-update_super_work-when-racing-with-umount.patch new file mode 100644 index 0000000000..4c06a35667 --- /dev/null +++ b/queue-5.15/ext4-fix-use-after-free-in-update_super_work-when-racing-with-umount.patch @@ -0,0 +1,118 @@ +From stable+bounces-233068-greg=kroah.com@vger.kernel.org Thu Apr 2 18:46:58 2026 +From: Sasha Levin +Date: Thu, 2 Apr 2026 12:37:40 -0400 +Subject: ext4: fix use-after-free in update_super_work when racing with umount +To: stable@vger.kernel.org +Cc: Jiayuan Chen , Jiayuan Chen , Jan Kara , "Ritesh Harjani (IBM)" , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20260402163740.1407640-1-sashal@kernel.org> + +From: Jiayuan Chen + +[ Upstream commit d15e4b0a418537aafa56b2cb80d44add83e83697 ] + +Commit b98535d09179 ("ext4: fix bug_on in start_this_handle during umount +filesystem") moved ext4_unregister_sysfs() before flushing s_sb_upd_work +to prevent new error work from being queued via /proc/fs/ext4/xx/mb_groups +reads during unmount. However, this introduced a use-after-free because +update_super_work calls ext4_notify_error_sysfs() -> sysfs_notify() which +accesses the kobject's kernfs_node after it has been freed by kobject_del() +in ext4_unregister_sysfs(): + + update_super_work ext4_put_super + ----------------- -------------- + ext4_unregister_sysfs(sb) + kobject_del(&sbi->s_kobj) + __kobject_del() + sysfs_remove_dir() + kobj->sd = NULL + sysfs_put(sd) + kernfs_put() // RCU free + ext4_notify_error_sysfs(sbi) + sysfs_notify(&sbi->s_kobj) + kn = kobj->sd // stale pointer + kernfs_get(kn) // UAF on freed kernfs_node + ext4_journal_destroy() + flush_work(&sbi->s_sb_upd_work) + +Instead of reordering the teardown sequence, fix this by making +ext4_notify_error_sysfs() detect that sysfs has already been torn down +by checking s_kobj.state_in_sysfs, and skipping the sysfs_notify() call +in that case. A dedicated mutex (s_error_notify_mutex) serializes +ext4_notify_error_sysfs() against kobject_del() in ext4_unregister_sysfs() +to prevent TOCTOU races where the kobject could be deleted between the +state_in_sysfs check and the sysfs_notify() call. + +Fixes: b98535d09179 ("ext4: fix bug_on in start_this_handle during umount filesystem") +Cc: Jiayuan Chen +Suggested-by: Jan Kara +Signed-off-by: Jiayuan Chen +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20260319120336.157873-1-jiayuan.chen@linux.dev +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ adapted mutex_init placement ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4.h | 1 + + fs/ext4/super.c | 1 + + fs/ext4/sysfs.c | 10 +++++++++- + 3 files changed, 11 insertions(+), 1 deletion(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1540,6 +1540,7 @@ struct ext4_sb_info { + struct proc_dir_entry *s_proc; + struct kobject s_kobj; + struct completion s_kobj_unregister; ++ struct mutex s_error_notify_mutex; /* protects sysfs_notify vs kobject_del */ + struct super_block *s_sb; + struct buffer_head *s_mmp_bh; + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4626,6 +4626,7 @@ static int ext4_fill_super(struct super_ + + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); + spin_lock_init(&sbi->s_error_lock); ++ mutex_init(&sbi->s_error_notify_mutex); + INIT_WORK(&sbi->s_error_work, flush_stashed_error_work); + + /* Register extent status tree shrinker */ +--- a/fs/ext4/sysfs.c ++++ b/fs/ext4/sysfs.c +@@ -513,7 +513,10 @@ static struct kobj_type ext4_feat_ktype + + void ext4_notify_error_sysfs(struct ext4_sb_info *sbi) + { +- sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); ++ mutex_lock(&sbi->s_error_notify_mutex); ++ if (sbi->s_kobj.state_in_sysfs) ++ sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); ++ mutex_unlock(&sbi->s_error_notify_mutex); + } + + static struct kobject *ext4_root; +@@ -526,8 +529,10 @@ int ext4_register_sysfs(struct super_blo + int err; + + init_completion(&sbi->s_kobj_unregister); ++ mutex_lock(&sbi->s_error_notify_mutex); + err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, ext4_root, + "%s", sb->s_id); ++ mutex_unlock(&sbi->s_error_notify_mutex); + if (err) { + kobject_put(&sbi->s_kobj); + wait_for_completion(&sbi->s_kobj_unregister); +@@ -560,7 +565,10 @@ void ext4_unregister_sysfs(struct super_ + + if (sbi->s_proc) + remove_proc_subtree(sb->s_id, ext4_proc_root); ++ ++ mutex_lock(&sbi->s_error_notify_mutex); + kobject_del(&sbi->s_kobj); ++ mutex_unlock(&sbi->s_error_notify_mutex); + } + + int __init ext4_init_sysfs(void) diff --git a/queue-5.15/ext4-publish-jinode-after-initialization.patch b/queue-5.15/ext4-publish-jinode-after-initialization.patch new file mode 100644 index 0000000000..1227f93aaa --- /dev/null +++ b/queue-5.15/ext4-publish-jinode-after-initialization.patch @@ -0,0 +1,152 @@ +From stable+bounces-233127-greg=kroah.com@vger.kernel.org Fri Apr 3 02:43:37 2026 +From: Sasha Levin +Date: Thu, 2 Apr 2026 20:36:15 -0400 +Subject: ext4: publish jinode after initialization +To: stable@vger.kernel.org +Cc: Li Chen , Jan Kara , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20260403003615.1839386-1-sashal@kernel.org> + +From: Li Chen + +[ Upstream commit 1aec30021edd410b986c156f195f3d23959a9d11 ] + +ext4_inode_attach_jinode() publishes ei->jinode to concurrent users. +It used to set ei->jinode before jbd2_journal_init_jbd_inode(), +allowing a reader to observe a non-NULL jinode with i_vfs_inode +still unset. + +The fast commit flush path can then pass this jinode to +jbd2_wait_inode_data(), which dereferences i_vfs_inode->i_mapping and +may crash. + +Below is the crash I observe: +``` +BUG: unable to handle page fault for address: 000000010beb47f4 +PGD 110e51067 P4D 110e51067 PUD 0 +Oops: Oops: 0000 [#1] SMP NOPTI +CPU: 1 UID: 0 PID: 4850 Comm: fc_fsync_bench_ Not tainted 6.18.0-00764-g795a690c06a5 #1 PREEMPT(voluntary) +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.17.0-2-2 04/01/2014 +RIP: 0010:xas_find_marked+0x3d/0x2e0 +Code: e0 03 48 83 f8 02 0f 84 f0 01 00 00 48 8b 47 08 48 89 c3 48 39 c6 0f 82 fd 01 00 00 48 85 c9 74 3d 48 83 f9 03 77 63 4c 8b 0f <49> 8b 71 08 48 c7 47 18 00 00 00 00 48 89 f1 83 e1 03 48 83 f9 02 +RSP: 0018:ffffbbee806e7bf0 EFLAGS: 00010246 +RAX: 000000000010beb4 RBX: 000000000010beb4 RCX: 0000000000000003 +RDX: 0000000000000001 RSI: 0000002000300000 RDI: ffffbbee806e7c10 +RBP: 0000000000000001 R08: 0000002000300000 R09: 000000010beb47ec +R10: ffff9ea494590090 R11: 0000000000000000 R12: 0000002000300000 +R13: ffffbbee806e7c90 R14: ffff9ea494513788 R15: ffffbbee806e7c88 +FS: 00007fc2f9e3e6c0(0000) GS:ffff9ea6b1444000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000010beb47f4 CR3: 0000000119ac5000 CR4: 0000000000750ef0 +PKRU: 55555554 +Call Trace: + +filemap_get_folios_tag+0x87/0x2a0 +__filemap_fdatawait_range+0x5f/0xd0 +? srso_alias_return_thunk+0x5/0xfbef5 +? __schedule+0x3e7/0x10c0 +? srso_alias_return_thunk+0x5/0xfbef5 +? srso_alias_return_thunk+0x5/0xfbef5 +? srso_alias_return_thunk+0x5/0xfbef5 +? preempt_count_sub+0x5f/0x80 +? srso_alias_return_thunk+0x5/0xfbef5 +? cap_safe_nice+0x37/0x70 +? srso_alias_return_thunk+0x5/0xfbef5 +? preempt_count_sub+0x5f/0x80 +? srso_alias_return_thunk+0x5/0xfbef5 +filemap_fdatawait_range_keep_errors+0x12/0x40 +ext4_fc_commit+0x697/0x8b0 +? ext4_file_write_iter+0x64b/0x950 +? srso_alias_return_thunk+0x5/0xfbef5 +? preempt_count_sub+0x5f/0x80 +? srso_alias_return_thunk+0x5/0xfbef5 +? vfs_write+0x356/0x480 +? srso_alias_return_thunk+0x5/0xfbef5 +? preempt_count_sub+0x5f/0x80 +ext4_sync_file+0xf7/0x370 +do_fsync+0x3b/0x80 +? syscall_trace_enter+0x108/0x1d0 +__x64_sys_fdatasync+0x16/0x20 +do_syscall_64+0x62/0x2c0 +entry_SYSCALL_64_after_hwframe+0x76/0x7e +... +``` + +Fix this by initializing the jbd2_inode first. +Use smp_wmb() and WRITE_ONCE() to publish ei->jinode after +initialization. Readers use READ_ONCE() to fetch the pointer. + +Fixes: a361293f5fede ("jbd2: Fix oops in jbd2_journal_file_inode()") +Cc: stable@vger.kernel.org +Signed-off-by: Li Chen +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20260225082617.147957-1-me@linux.beauty +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ adapted READ_ONCE(jinode) wrapping to split ext4_fc_submit_inode_data_all() and ext4_fc_wait_inode_data_all() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/fast_commit.c | 4 ++-- + fs/ext4/inode.c | 15 +++++++++++---- + 2 files changed, 13 insertions(+), 6 deletions(-) + +--- a/fs/ext4/fast_commit.c ++++ b/fs/ext4/fast_commit.c +@@ -979,7 +979,7 @@ static int ext4_fc_submit_inode_data_all + finish_wait(&ei->i_fc_wait, &wait); + } + spin_unlock(&sbi->s_fc_lock); +- ret = jbd2_submit_inode_data(ei->jinode); ++ ret = jbd2_submit_inode_data(READ_ONCE(ei->jinode)); + if (ret) + return ret; + spin_lock(&sbi->s_fc_lock); +@@ -1004,7 +1004,7 @@ static int ext4_fc_wait_inode_data_all(j + continue; + spin_unlock(&sbi->s_fc_lock); + +- ret = jbd2_wait_inode_data(journal, pos->jinode); ++ ret = jbd2_wait_inode_data(journal, READ_ONCE(pos->jinode)); + if (ret) + return ret; + spin_lock(&sbi->s_fc_lock); +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -122,6 +122,8 @@ void ext4_inode_csum_set(struct inode *i + static inline int ext4_begin_ordered_truncate(struct inode *inode, + loff_t new_size) + { ++ struct jbd2_inode *jinode = READ_ONCE(EXT4_I(inode)->jinode); ++ + trace_ext4_begin_ordered_truncate(inode, new_size); + /* + * If jinode is zero, then we never opened the file for +@@ -129,10 +131,10 @@ static inline int ext4_begin_ordered_tru + * jbd2_journal_begin_ordered_truncate() since there's no + * outstanding writes we need to flush. + */ +- if (!EXT4_I(inode)->jinode) ++ if (!jinode) + return 0; + return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode), +- EXT4_I(inode)->jinode, ++ jinode, + new_size); + } + +@@ -4145,8 +4147,13 @@ int ext4_inode_attach_jinode(struct inod + spin_unlock(&inode->i_lock); + return -ENOMEM; + } +- ei->jinode = jinode; +- jbd2_journal_init_jbd_inode(ei->jinode, inode); ++ jbd2_journal_init_jbd_inode(jinode, inode); ++ /* ++ * Publish ->jinode only after it is fully initialized so that ++ * readers never observe a partially initialized jbd2_inode. ++ */ ++ smp_wmb(); ++ WRITE_ONCE(ei->jinode, jinode); + jinode = NULL; + } + spin_unlock(&inode->i_lock); diff --git a/queue-5.15/i2c-cp2615-fix-serial-string-null-deref-at-probe.patch b/queue-5.15/i2c-cp2615-fix-serial-string-null-deref-at-probe.patch new file mode 100644 index 0000000000..9f001aed09 --- /dev/null +++ b/queue-5.15/i2c-cp2615-fix-serial-string-null-deref-at-probe.patch @@ -0,0 +1,43 @@ +From stable+bounces-227986-greg=kroah.com@vger.kernel.org Mon Mar 23 14:27:25 2026 +From: Sasha Levin +Date: Mon, 23 Mar 2026 09:19:10 -0400 +Subject: i2c: cp2615: fix serial string NULL-deref at probe +To: stable@vger.kernel.org +Cc: "Johan Hovold" , "Bence Csókás" , "Andi Shyti" , "Sasha Levin" +Message-ID: <20260323131910.1715046-2-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit aa79f996eb41e95aed85a1bd7f56bcd6a3842008 ] + +The cp2615 driver uses the USB device serial string as the i2c adapter +name but does not make sure that the string exists. + +Verify that the device has a serial number before accessing it to avoid +triggering a NULL-pointer dereference (e.g. with malicious devices). + +Fixes: 4a7695429ead ("i2c: cp2615: add i2c driver for Silicon Labs' CP2615 Digital Audio Bridge") +Cc: stable@vger.kernel.org # 5.13 +Cc: Bence Csókás +Signed-off-by: Johan Hovold +Reviewed-by: Bence Csókás +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260309075016.25612-1-johan@kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-cp2615.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/i2c/busses/i2c-cp2615.c ++++ b/drivers/i2c/busses/i2c-cp2615.c +@@ -298,6 +298,9 @@ cp2615_i2c_probe(struct usb_interface *u + if (!adap) + return -ENOMEM; + ++ if (!usbdev->serial) ++ return -EINVAL; ++ + strscpy(adap->name, usbdev->serial, sizeof(adap->name)); + adap->owner = THIS_MODULE; + adap->dev.parent = &usbif->dev; diff --git a/queue-5.15/i2c-cp2615-replace-deprecated-strncpy-with-strscpy.patch b/queue-5.15/i2c-cp2615-replace-deprecated-strncpy-with-strscpy.patch new file mode 100644 index 0000000000..22badbd0c9 --- /dev/null +++ b/queue-5.15/i2c-cp2615-replace-deprecated-strncpy-with-strscpy.patch @@ -0,0 +1,53 @@ +From stable+bounces-227985-greg=kroah.com@vger.kernel.org Mon Mar 23 14:26:27 2026 +From: Sasha Levin +Date: Mon, 23 Mar 2026 09:19:09 -0400 +Subject: i2c: cp2615: replace deprecated strncpy with strscpy +To: stable@vger.kernel.org +Cc: Justin Stitt , Kees Cook , Wolfram Sang , Sasha Levin +Message-ID: <20260323131910.1715046-1-sashal@kernel.org> + +From: Justin Stitt + +[ Upstream commit e2def33f9ee1b1a8cda4ec5cde69840b5708f068 ] + +`strncpy` is deprecated for use on NUL-terminated destination strings [1]. + +We should prefer more robust and less ambiguous string interfaces. + +We expect name to be NUL-terminated based on its numerous uses with +functions that expect NUL-terminated strings. + +For example in i2c-core-base.c +1533: +| dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); + +NUL-padding is not required as `adap` is already zero-alloacted with: +| adap = devm_kzalloc(&usbif->dev, sizeof(struct i2c_adapter), GFP_KERNEL); + +With the above in mind, a suitable replacement is `strscpy` [2] due to +the fact that it guarantees NUL-termination on the destination buffer +without unnecessarily NUL-padding. + +Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] +Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] +Link: https://github.com/KSPP/linux/issues/90 +Signed-off-by: Justin Stitt +Reviewed-by: Kees Cook +Signed-off-by: Wolfram Sang +Stable-dep-of: aa79f996eb41 ("i2c: cp2615: fix serial string NULL-deref at probe") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-cp2615.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-cp2615.c ++++ b/drivers/i2c/busses/i2c-cp2615.c +@@ -298,7 +298,7 @@ cp2615_i2c_probe(struct usb_interface *u + if (!adap) + return -ENOMEM; + +- strncpy(adap->name, usbdev->serial, sizeof(adap->name) - 1); ++ strscpy(adap->name, usbdev->serial, sizeof(adap->name)); + adap->owner = THIS_MODULE; + adap->dev.parent = &usbif->dev; + adap->dev.of_node = usbif->dev.of_node; diff --git a/queue-5.15/ksmbd-fix-dangling-pointer-in-krb_authenticate.patch b/queue-5.15/ksmbd-fix-dangling-pointer-in-krb_authenticate.patch new file mode 100644 index 0000000000..761ede4c39 --- /dev/null +++ b/queue-5.15/ksmbd-fix-dangling-pointer-in-krb_authenticate.patch @@ -0,0 +1,41 @@ +From stable+bounces-222537-greg=kroah.com@vger.kernel.org Mon Mar 2 08:53:14 2026 +From: Leon Chen +Date: Mon, 2 Mar 2026 15:52:47 +0800 +Subject: ksmbd: Fix dangling pointer in krb_authenticate +To: seanheelan@gmail.com, linkinjeon@kernel.org, stfrench@microsoft.com, stable@vger.kernel.org +Message-ID: <20260302075247.3519-1-leonchen.oss@139.com> + +From: Sean Heelan + +[ Upstream commit 1e440d5b25b7efccb3defe542a73c51005799a5f ] + +krb_authenticate frees sess->user and does not set the pointer +to NULL. It calls ksmbd_krb5_authenticate to reinitialise +sess->user but that function may return without doing so. If +that happens then smb2_sess_setup, which calls krb_authenticate, +will be accessing free'd memory when it later uses sess->user. + +Cc: stable@vger.kernel.org +Signed-off-by: Sean Heelan +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Leon Chen +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1619,8 +1619,10 @@ static int krb5_authenticate(struct ksmb + if (prev_sess_id && prev_sess_id != sess->id) + destroy_previous_session(conn, sess->user, prev_sess_id); + +- if (sess->state == SMB2_SESSION_VALID) ++ if (sess->state == SMB2_SESSION_VALID) { + ksmbd_free_user(sess->user); ++ sess->user = NULL; ++ } + + retval = ksmbd_krb5_authenticate(sess, in_blob, in_len, + out_blob, &out_len); diff --git a/queue-5.15/ksmbd-fix-potencial-oob-in-get_file_all_info-for-compound-requests.patch b/queue-5.15/ksmbd-fix-potencial-oob-in-get_file_all_info-for-compound-requests.patch new file mode 100644 index 0000000000..30e8add08a --- /dev/null +++ b/queue-5.15/ksmbd-fix-potencial-oob-in-get_file_all_info-for-compound-requests.patch @@ -0,0 +1,76 @@ +From stable+bounces-231265-greg=kroah.com@vger.kernel.org Mon Mar 30 21:13:07 2026 +From: Sasha Levin +Date: Mon, 30 Mar 2026 15:10:37 -0400 +Subject: ksmbd: fix potencial OOB in get_file_all_info() for compound requests +To: stable@vger.kernel.org +Cc: Namjae Jeon , Asim Viladi Oglu Manizada , Steve French , Sasha Levin +Message-ID: <20260330191037.1035485-1-sashal@kernel.org> + +From: Namjae Jeon + +[ Upstream commit beef2634f81f1c086208191f7228bce1d366493d ] + +When a compound request consists of QUERY_DIRECTORY + QUERY_INFO +(FILE_ALL_INFORMATION) and the first command consumes nearly the entire +max_trans_size, get_file_all_info() would blindly call smbConvertToUTF16() +with PATH_MAX, causing out-of-bounds write beyond the response buffer. +In get_file_all_info(), there was a missing validation check for +the client-provided OutputBufferLength before copying the filename into +FileName field of the smb2_file_all_info structure. +If the filename length exceeds the available buffer space, it could lead to +potential buffer overflows or memory corruption during smbConvertToUTF16 +conversion. This calculating the actual free buffer size using +smb2_calc_max_out_buf_len() and returning -EINVAL if the buffer is +insufficient and updating smbConvertToUTF16 to use the actual filename +length (clamped by PATH_MAX) to ensure a safe copy operation. + +Cc: stable@vger.kernel.org +Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound") +Reported-by: Asim Viladi Oglu Manizada +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +[ adapted variable declarations ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -4580,6 +4580,8 @@ static int get_file_all_info(struct ksmb + int conv_len; + char *filename; + u64 time; ++ int buf_free_len, filename_len; ++ struct smb2_query_info_req *req = ksmbd_req_buf_next(work); + + if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { + ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n", +@@ -4591,6 +4593,16 @@ static int get_file_all_info(struct ksmb + if (IS_ERR(filename)) + return PTR_ERR(filename); + ++ filename_len = strlen(filename); ++ buf_free_len = smb2_calc_max_out_buf_len(work, ++ offsetof(struct smb2_query_info_rsp, Buffer) + ++ offsetof(struct smb2_file_all_info, FileName), ++ le32_to_cpu(req->OutputBufferLength)); ++ if (buf_free_len < (filename_len + 1) * 2) { ++ kfree(filename); ++ return -EINVAL; ++ } ++ + inode = file_inode(fp->filp); + generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat); + +@@ -4622,7 +4634,8 @@ static int get_file_all_info(struct ksmb + file_info->Mode = fp->coption; + file_info->AlignmentRequirement = 0; + conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename, +- PATH_MAX, conn->local_nls, 0); ++ min(filename_len, PATH_MAX), ++ conn->local_nls, 0); + conv_len *= 2; + file_info->FileNameLength = cpu_to_le32(conv_len); + rsp->OutputBufferLength = diff --git a/queue-5.15/ksmbd-fix-refcount-leak-when-invalid-session-is-found-on-session-lookup.patch b/queue-5.15/ksmbd-fix-refcount-leak-when-invalid-session-is-found-on-session-lookup.patch new file mode 100644 index 0000000000..c620156d25 --- /dev/null +++ b/queue-5.15/ksmbd-fix-refcount-leak-when-invalid-session-is-found-on-session-lookup.patch @@ -0,0 +1,43 @@ +From stable+bounces-219895-greg=kroah.com@vger.kernel.org Fri Feb 27 04:16:14 2026 +From: Li hongliang <1468888505@139.com> +Date: Fri, 27 Feb 2026 11:16:01 +0800 +Subject: ksmbd: Fix refcount leak when invalid session is found on session lookup +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, linkinjeon@kernel.org +Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, roger.andersen@protonmail.com, spolu@dust.tt, stfrench@microsoft.com, senozhatsky@chromium.org, sfrench@samba.org, hyc.lee@gmail.com, sashal@kernel.org, linux-cifs@vger.kernel.org +Message-ID: <20260227031601.1548925-1-1468888505@139.com> + +From: Namjae Jeon + +[ Upstream commit cafb57f7bdd57abba87725eb4e82bbdca4959644 ] + +When a session is found but its state is not SMB2_SESSION_VALID, It +indicates that no valid session was found, but it is missing to decrement +the reference count acquired by the session lookup, which results in +a reference count leak. This patch fixes the issue by explicitly calling +ksmbd_user_session_put to release the reference to the session. + +Cc: stable@vger.kernel.org +Reported-by: Alexandre +Reported-by: Stanislas Polu +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/mgmt/user_session.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -302,8 +302,10 @@ struct ksmbd_session *ksmbd_session_look + sess = ksmbd_session_lookup(conn, id); + if (!sess && conn->binding) + sess = ksmbd_session_lookup_slowpath(id); +- if (sess && sess->state != SMB2_SESSION_VALID) ++ if (sess && sess->state != SMB2_SESSION_VALID) { ++ ksmbd_user_session_put(sess); + sess = NULL; ++ } + return sess; + } + diff --git a/queue-5.15/ksmbd-replace-hardcoded-hdr2_len-with-offsetof-in-smb2_calc_max_out_buf_len.patch b/queue-5.15/ksmbd-replace-hardcoded-hdr2_len-with-offsetof-in-smb2_calc_max_out_buf_len.patch new file mode 100644 index 0000000000..e2724d9ac8 --- /dev/null +++ b/queue-5.15/ksmbd-replace-hardcoded-hdr2_len-with-offsetof-in-smb2_calc_max_out_buf_len.patch @@ -0,0 +1,80 @@ +From stable+bounces-231242-greg=kroah.com@vger.kernel.org Mon Mar 30 16:53:40 2026 +From: Sasha Levin +Date: Mon, 30 Mar 2026 10:40:42 -0400 +Subject: ksmbd: replace hardcoded hdr2_len with offsetof() in smb2_calc_max_out_buf_len() +To: stable@vger.kernel.org +Cc: Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20260330144043.880361-1-sashal@kernel.org> + +From: Namjae Jeon + +[ Upstream commit 0e55f63dd08f09651d39e1b709a91705a8a0ddcb ] + +After this commit (e2b76ab8b5c9 "ksmbd: add support for read compound"), +response buffer management was changed to use dynamic iov array. +In the new design, smb2_calc_max_out_buf_len() expects the second +argument (hdr2_len) to be the offset of ->Buffer field in the +response structure, not a hardcoded magic number. +Fix the remaining call sites to use the correct offsetof() value. + +Cc: stable@vger.kernel.org +Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound") +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +[ adapted `req->CtlCode` field access to `req->CntCode` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -4123,8 +4123,9 @@ int smb2_query_dir(struct ksmbd_work *wo + d_info.wptr = (char *)rsp->Buffer; + d_info.rptr = (char *)rsp->Buffer; + d_info.out_buf_len = +- smb2_calc_max_out_buf_len(work, 8, +- le32_to_cpu(req->OutputBufferLength)); ++ smb2_calc_max_out_buf_len(work, ++ offsetof(struct smb2_query_directory_rsp, Buffer), ++ le32_to_cpu(req->OutputBufferLength)); + if (d_info.out_buf_len < 0) { + rc = -EINVAL; + goto err_out; +@@ -4374,8 +4375,9 @@ static int smb2_get_ea(struct ksmbd_work + } + + buf_free_len = +- smb2_calc_max_out_buf_len(work, 8, +- le32_to_cpu(req->OutputBufferLength)); ++ smb2_calc_max_out_buf_len(work, ++ offsetof(struct smb2_query_info_rsp, Buffer), ++ le32_to_cpu(req->OutputBufferLength)); + if (buf_free_len < 0) + return -EINVAL; + +@@ -4685,8 +4687,9 @@ static void get_file_stream_info(struct + file_info = (struct smb2_file_stream_info *)rsp->Buffer; + + buf_free_len = +- smb2_calc_max_out_buf_len(work, 8, +- le32_to_cpu(req->OutputBufferLength)); ++ smb2_calc_max_out_buf_len(work, ++ offsetof(struct smb2_query_info_rsp, Buffer), ++ le32_to_cpu(req->OutputBufferLength)); + if (buf_free_len < 0) + goto out; + +@@ -7726,8 +7729,9 @@ int smb2_ioctl(struct ksmbd_work *work) + + buffer = (char *)req + le32_to_cpu(req->InputOffset); + cnt_code = le32_to_cpu(req->CntCode); +- ret = smb2_calc_max_out_buf_len(work, 48, +- le32_to_cpu(req->MaxOutputResponse)); ++ ret = smb2_calc_max_out_buf_len(work, ++ offsetof(struct smb2_ioctl_rsp, Buffer), ++ le32_to_cpu(req->MaxOutputResponse)); + if (ret < 0) { + rsp->hdr.Status = STATUS_INVALID_PARAMETER; + goto out; diff --git a/queue-5.15/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch b/queue-5.15/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch new file mode 100644 index 0000000000..e4322ca93f --- /dev/null +++ b/queue-5.15/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch @@ -0,0 +1,87 @@ +From stable+bounces-232616-greg=kroah.com@vger.kernel.org Wed Apr 1 02:22:29 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 20:19:21 -0400 +Subject: KVM: x86/mmu: Drop/zap existing present SPTE even when creating an MMIO SPTE +To: stable@vger.kernel.org +Cc: Sean Christopherson , Alexander Bulekov , Fred Griffoul , Sasha Levin +Message-ID: <20260401001921.3983428-1-sashal@kernel.org> + +From: Sean Christopherson + +[ Upstream commit aad885e774966e97b675dfe928da164214a71605 ] + +When installing an emulated MMIO SPTE, do so *after* dropping/zapping the +existing SPTE (if it's shadow-present). While commit a54aa15c6bda3 was +right about it being impossible to convert a shadow-present SPTE to an +MMIO SPTE due to a _guest_ write, it failed to account for writes to guest +memory that are outside the scope of KVM. + +E.g. if host userspace modifies a shadowed gPTE to switch from a memslot +to emulted MMIO and then the guest hits a relevant page fault, KVM will +install the MMIO SPTE without first zapping the shadow-present SPTE. + + ------------[ cut here ]------------ + is_shadow_present_pte(*sptep) + WARNING: arch/x86/kvm/mmu/mmu.c:484 at mark_mmio_spte+0xb2/0xc0 [kvm], CPU#0: vmx_ept_stale_r/4292 + Modules linked in: kvm_intel kvm irqbypass + CPU: 0 UID: 1000 PID: 4292 Comm: vmx_ept_stale_r Not tainted 7.0.0-rc2-eafebd2d2ab0-sink-vm #319 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + RIP: 0010:mark_mmio_spte+0xb2/0xc0 [kvm] + Call Trace: + + mmu_set_spte+0x237/0x440 [kvm] + ept_page_fault+0x535/0x7f0 [kvm] + kvm_mmu_do_page_fault+0xee/0x1f0 [kvm] + kvm_mmu_page_fault+0x8d/0x620 [kvm] + vmx_handle_exit+0x18c/0x5a0 [kvm_intel] + kvm_arch_vcpu_ioctl_run+0xc55/0x1c20 [kvm] + kvm_vcpu_ioctl+0x2d5/0x980 [kvm] + __x64_sys_ioctl+0x8a/0xd0 + do_syscall_64+0xb5/0x730 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + RIP: 0033:0x47fa3f + + ---[ end trace 0000000000000000 ]--- + +Reported-by: Alexander Bulekov +Debugged-by: Alexander Bulekov +Suggested-by: Fred Griffoul +Fixes: a54aa15c6bda3 ("KVM: x86/mmu: Handle MMIO SPTEs directly in mmu_set_spte()") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +[ replaced `kvm_flush_remote_tlbs_gfn()` with `kvm_flush_remote_tlbs_with_address()` and omitted `pf_mmio_spte_created` stat counter ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/mmu/mmu.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -2717,11 +2717,6 @@ static int mmu_set_spte(struct kvm_vcpu + pgprintk("%s: spte %llx write_fault %d gfn %llx\n", __func__, + *sptep, write_fault, gfn); + +- if (unlikely(is_noslot_pfn(pfn))) { +- mark_mmio_spte(vcpu, sptep, gfn, pte_access); +- return RET_PF_EMULATE; +- } +- + if (is_shadow_present_pte(*sptep)) { + /* + * If we overwrite a PTE page pointer with a 2MB PMD, unlink +@@ -2743,6 +2738,14 @@ static int mmu_set_spte(struct kvm_vcpu + was_rmapped = 1; + } + ++ if (unlikely(is_noslot_pfn(pfn))) { ++ mark_mmio_spte(vcpu, sptep, gfn, pte_access); ++ if (flush) ++ kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, ++ KVM_PAGES_PER_HPAGE(level)); ++ return RET_PF_EMULATE; ++ } ++ + set_spte_ret = set_spte(vcpu, sptep, pte_access, level, gfn, pfn, + speculative, true, host_writable); + if (set_spte_ret & SET_SPTE_WRITE_PROTECTED_PT) { diff --git a/queue-5.15/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch b/queue-5.15/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch new file mode 100644 index 0000000000..e464c4c2d4 --- /dev/null +++ b/queue-5.15/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch @@ -0,0 +1,101 @@ +From stable+bounces-231432-greg=kroah.com@vger.kernel.org Tue Mar 31 16:28:45 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 10:25:47 -0400 +Subject: mm/huge_memory: fix folio isn't locked in softleaf_to_folio() +To: stable@vger.kernel.org +Cc: Jinjiang Tu , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (Oracle)" , Barry Song , Kefeng Wang , Liam Howlett , Michal Hocko , Mike Rapoport , Nanyong Sun , Ryan Roberts , Suren Baghdasaryan , Vlastimil Babka , Andrew Morton , Sasha Levin +Message-ID: <20260331142547.2463775-1-sashal@kernel.org> + +From: Jinjiang Tu + +[ Upstream commit 4c5e7f0fcd592801c9cc18f29f80fbee84eb8669 ] + +On arm64 server, we found folio that get from migration entry isn't locked +in softleaf_to_folio(). This issue triggers when mTHP splitting and +zap_nonpresent_ptes() races, and the root cause is lack of memory barrier +in softleaf_to_folio(). The race is as follows: + + CPU0 CPU1 + +deferred_split_scan() zap_nonpresent_ptes() + lock folio + split_folio() + unmap_folio() + change ptes to migration entries + __split_folio_to_order() softleaf_to_folio() + set flags(including PG_locked) for tail pages folio = pfn_folio(softleaf_to_pfn(entry)) + smp_wmb() VM_WARN_ON_ONCE(!folio_test_locked(folio)) + prep_compound_page() for tail pages + +In __split_folio_to_order(), smp_wmb() guarantees page flags of tail pages +are visible before the tail page becomes non-compound. smp_wmb() should +be paired with smp_rmb() in softleaf_to_folio(), which is missed. As a +result, if zap_nonpresent_ptes() accesses migration entry that stores tail +pfn, softleaf_to_folio() may see the updated compound_head of tail page +before page->flags. + +This issue will trigger VM_WARN_ON_ONCE() in pfn_swap_entry_folio() +because of the race between folio split and zap_nonpresent_ptes() +leading to a folio incorrectly undergoing modification without a folio +lock being held. + +This is a BUG_ON() before commit 93976a20345b ("mm: eliminate further +swapops predicates"), which in merged in v6.19-rc1. + +To fix it, add missing smp_rmb() if the softleaf entry is migration entry +in softleaf_to_folio() and softleaf_to_page(). + +[tujinjiang@huawei.com: update function name and comments] + Link: https://lkml.kernel.org/r/20260321075214.3305564-1-tujinjiang@huawei.com +Link: https://lkml.kernel.org/r/20260319012541.4158561-1-tujinjiang@huawei.com +Fixes: e9b61f19858a ("thp: reintroduce split_huge_page()") +Signed-off-by: Jinjiang Tu +Acked-by: David Hildenbrand (Arm) +Reviewed-by: Lorenzo Stoakes (Oracle) +Cc: Barry Song +Cc: Kefeng Wang +Cc: Liam Howlett +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Nanyong Sun +Cc: Ryan Roberts +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +[ adapted fix from leafops.h softleaf_to_page()/softleaf_to_folio() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/swapops.h | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/include/linux/swapops.h ++++ b/include/linux/swapops.h +@@ -251,11 +251,21 @@ static inline struct page *pfn_swap_entr + { + struct page *p = pfn_to_page(swp_offset(entry)); + +- /* +- * Any use of migration entries may only occur while the +- * corresponding page is locked +- */ +- BUG_ON(is_migration_entry(entry) && !PageLocked(p)); ++ if (is_migration_entry(entry)) { ++ /* ++ * Ensure we do not race with split, which might alter tail ++ * pages into new folios and thus result in observing an ++ * unlocked folio. ++ * This matches the write barrier in __split_folio_to_order(). ++ */ ++ smp_rmb(); ++ ++ /* ++ * Any use of migration entries may only occur while the ++ * corresponding page is locked ++ */ ++ BUG_ON(!PageLocked(p)); ++ } + + return p; + } diff --git a/queue-5.15/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch b/queue-5.15/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch new file mode 100644 index 0000000000..6808eba82e --- /dev/null +++ b/queue-5.15/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch @@ -0,0 +1,147 @@ +From stable+bounces-232613-greg=kroah.com@vger.kernel.org Wed Apr 1 02:02:43 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 20:02:38 -0400 +Subject: net: macb: Move devm_{free,request}_irq() out of spin lock area +To: stable@vger.kernel.org +Cc: "Kevin Hao" , "Théo Lebrun" , "Jakub Kicinski" , "Sasha Levin" +Message-ID: <20260401000238.3954205-1-sashal@kernel.org> + +From: Kevin Hao + +[ Upstream commit 317e49358ebbf6390fa439ef3c142f9239dd25fb ] + +The devm_free_irq() and devm_request_irq() functions should not be +executed in an atomic context. + +During device suspend, all userspace processes and most kernel threads +are frozen. Additionally, we flush all tx/rx status, disable all macb +interrupts, and halt rx operations. Therefore, it is safe to split the +region protected by bp->lock into two independent sections, allowing +devm_free_irq() and devm_request_irq() to run in a non-atomic context. +This modification resolves the following lockdep warning: + BUG: sleeping function called from invalid context at kernel/locking/mutex.c:591 + in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 501, name: rtcwake + preempt_count: 1, expected: 0 + RCU nest depth: 1, expected: 0 + 7 locks held by rtcwake/501: + #0: ffff0008038c3408 (sb_writers#5){.+.+}-{0:0}, at: vfs_write+0xf8/0x368 + #1: ffff0008049a5e88 (&of->mutex#2){+.+.}-{4:4}, at: kernfs_fop_write_iter+0xbc/0x1c8 + #2: ffff00080098d588 (kn->active#70){.+.+}-{0:0}, at: kernfs_fop_write_iter+0xcc/0x1c8 + #3: ffff800081c84888 (system_transition_mutex){+.+.}-{4:4}, at: pm_suspend+0x1ec/0x290 + #4: ffff0008009ba0f8 (&dev->mutex){....}-{4:4}, at: device_suspend+0x118/0x4f0 + #5: ffff800081d00458 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire+0x4/0x48 + #6: ffff0008031fb9e0 (&bp->lock){-.-.}-{3:3}, at: macb_suspend+0x144/0x558 + irq event stamp: 8682 + hardirqs last enabled at (8681): [] _raw_spin_unlock_irqrestore+0x44/0x88 + hardirqs last disabled at (8682): [] _raw_spin_lock_irqsave+0x38/0x98 + softirqs last enabled at (7322): [] handle_softirqs+0x52c/0x588 + softirqs last disabled at (7317): [] __do_softirq+0x20/0x2c + CPU: 1 UID: 0 PID: 501 Comm: rtcwake Not tainted 7.0.0-rc3-next-20260310-yocto-standard+ #125 PREEMPT + Hardware name: ZynqMP ZCU102 Rev1.1 (DT) + Call trace: + show_stack+0x24/0x38 (C) + __dump_stack+0x28/0x38 + dump_stack_lvl+0x64/0x88 + dump_stack+0x18/0x24 + __might_resched+0x200/0x218 + __might_sleep+0x38/0x98 + __mutex_lock_common+0x7c/0x1378 + mutex_lock_nested+0x38/0x50 + free_irq+0x68/0x2b0 + devm_irq_release+0x24/0x38 + devres_release+0x40/0x80 + devm_free_irq+0x48/0x88 + macb_suspend+0x298/0x558 + device_suspend+0x218/0x4f0 + dpm_suspend+0x244/0x3a0 + dpm_suspend_start+0x50/0x78 + suspend_devices_and_enter+0xec/0x560 + pm_suspend+0x194/0x290 + state_store+0x110/0x158 + kobj_attr_store+0x1c/0x30 + sysfs_kf_write+0xa8/0xd0 + kernfs_fop_write_iter+0x11c/0x1c8 + vfs_write+0x248/0x368 + ksys_write+0x7c/0xf8 + __arm64_sys_write+0x28/0x40 + invoke_syscall+0x4c/0xe8 + el0_svc_common+0x98/0xf0 + do_el0_svc+0x28/0x40 + el0_svc+0x54/0x1e0 + el0t_64_sync_handler+0x84/0x130 + el0t_64_sync+0x198/0x1a0 + +Fixes: 558e35ccfe95 ("net: macb: WoL support for GEM type of Ethernet controller") +Cc: stable@vger.kernel.org +Reviewed-by: Théo Lebrun +Signed-off-by: Kevin Hao +Link: https://patch.msgid.link/20260318-macb-irq-v2-1-f1179768ab24@gmail.com +Signed-off-by: Jakub Kicinski +[ adapted WoL register writes to use MACB_BIT(MAG) instead of tmp variable ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/cadence/macb_main.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -4961,6 +4961,8 @@ static int __maybe_unused macb_suspend(s + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(queue, ISR, -1); + } ++ spin_unlock_irqrestore(&bp->lock, flags); ++ + /* Change interrupt handler and + * Enable WoL IRQ on queue 0 + */ +@@ -4972,11 +4974,12 @@ static int __maybe_unused macb_suspend(s + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } ++ spin_lock_irqsave(&bp->lock, flags); + queue_writel(bp->queues, IER, GEM_BIT(WOL)); + gem_writel(bp, WOL, MACB_BIT(MAG)); ++ spin_unlock_irqrestore(&bp->lock, flags); + } else { + err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt, + IRQF_SHARED, netdev->name, bp->queues); +@@ -4984,13 +4987,13 @@ static int __maybe_unused macb_suspend(s + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } ++ spin_lock_irqsave(&bp->lock, flags); + queue_writel(bp->queues, IER, MACB_BIT(WOL)); + macb_writel(bp, WOL, MACB_BIT(MAG)); ++ spin_unlock_irqrestore(&bp->lock, flags); + } +- spin_unlock_irqrestore(&bp->lock, flags); + + enable_irq_wake(bp->queues[0].irq); + } +@@ -5052,6 +5055,8 @@ static int __maybe_unused macb_resume(st + queue_readl(bp->queues, ISR); + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(bp->queues, ISR, -1); ++ spin_unlock_irqrestore(&bp->lock, flags); ++ + /* Replace interrupt handler on queue 0 */ + devm_free_irq(dev, bp->queues[0].irq, bp->queues); + err = devm_request_irq(dev, bp->queues[0].irq, macb_interrupt, +@@ -5060,10 +5065,8 @@ static int __maybe_unused macb_resume(st + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } +- spin_unlock_irqrestore(&bp->lock, flags); + + disable_irq_wake(bp->queues[0].irq); + diff --git a/queue-5.15/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch b/queue-5.15/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch new file mode 100644 index 0000000000..b9bd735cfa --- /dev/null +++ b/queue-5.15/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch @@ -0,0 +1,137 @@ +From stable+bounces-235831-greg=kroah.com@vger.kernel.org Sun Apr 12 18:57:53 2026 +From: Sasha Levin +Date: Sun, 12 Apr 2026 12:57:46 -0400 +Subject: net: rfkill: prevent unlimited numbers of rfkill events from being created +To: stable@vger.kernel.org +Cc: Greg Kroah-Hartman , Johannes Berg , Yuan Tan , Yifan Wu , Juefei Pu , Xin Liu , stable , Johannes Berg , Sasha Levin +Message-ID: <20260412165746.2348467-1-sashal@kernel.org> + +From: Greg Kroah-Hartman + +[ Upstream commit ea245d78dec594372e27d8c79616baf49e98a4a1 ] + +Userspace can create an unlimited number of rfkill events if the system +is so configured, while not consuming them from the rfkill file +descriptor, causing a potential out of memory situation. Prevent this +from bounding the number of pending rfkill events at a "large" number +(i.e. 1000) to prevent abuses like this. + +Cc: Johannes Berg +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Link: https://patch.msgid.link/2026033013-disfigure-scroll-e25e@gregkh +Signed-off-by: Johannes Berg +[ replaced `scoped_guard()` with explicit `mutex_lock()`/`mutex_unlock()` calls ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/rfkill/core.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +--- a/net/rfkill/core.c ++++ b/net/rfkill/core.c +@@ -72,11 +72,14 @@ struct rfkill_int_event { + struct rfkill_event_ext ev; + }; + ++/* Max rfkill events that can be "in-flight" for one data source */ ++#define MAX_RFKILL_EVENT 1000 + struct rfkill_data { + struct list_head list; + struct list_head events; + struct mutex mtx; + wait_queue_head_t read_wait; ++ u32 event_count; + bool input_handler; + u8 max_size; + }; +@@ -254,10 +257,12 @@ static void rfkill_global_led_trigger_un + } + #endif /* CONFIG_RFKILL_LEDS */ + +-static void rfkill_fill_event(struct rfkill_event_ext *ev, +- struct rfkill *rfkill, +- enum rfkill_operation op) ++static int rfkill_fill_event(struct rfkill_int_event *int_ev, ++ struct rfkill *rfkill, ++ struct rfkill_data *data, ++ enum rfkill_operation op) + { ++ struct rfkill_event_ext *ev = &int_ev->ev; + unsigned long flags; + + ev->idx = rfkill->idx; +@@ -270,6 +275,16 @@ static void rfkill_fill_event(struct rfk + RFKILL_BLOCK_SW_PREV)); + ev->hard_block_reasons = rfkill->hard_block_reasons; + spin_unlock_irqrestore(&rfkill->lock, flags); ++ ++ mutex_lock(&data->mtx); ++ if (data->event_count++ > MAX_RFKILL_EVENT) { ++ data->event_count--; ++ mutex_unlock(&data->mtx); ++ return -ENOSPC; ++ } ++ list_add_tail(&int_ev->list, &data->events); ++ mutex_unlock(&data->mtx); ++ return 0; + } + + static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op) +@@ -281,10 +296,10 @@ static void rfkill_send_events(struct rf + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) + continue; +- rfkill_fill_event(&ev->ev, rfkill, op); +- mutex_lock(&data->mtx); +- list_add_tail(&ev->list, &data->events); +- mutex_unlock(&data->mtx); ++ if (rfkill_fill_event(ev, rfkill, data, op)) { ++ kfree(ev); ++ continue; ++ } + wake_up_interruptible(&data->read_wait); + } + } +@@ -1149,7 +1164,6 @@ static int rfkill_fop_open(struct inode + init_waitqueue_head(&data->read_wait); + + mutex_lock(&rfkill_global_mutex); +- mutex_lock(&data->mtx); + /* + * start getting events from elsewhere but hold mtx to get + * startup events added first +@@ -1159,11 +1173,10 @@ static int rfkill_fop_open(struct inode + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) + goto free; +- rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); +- list_add_tail(&ev->list, &data->events); ++ if (rfkill_fill_event(ev, rfkill, data, RFKILL_OP_ADD)) ++ kfree(ev); + } + list_add(&data->list, &rfkill_fds); +- mutex_unlock(&data->mtx); + mutex_unlock(&rfkill_global_mutex); + + file->private_data = data; +@@ -1171,7 +1184,6 @@ static int rfkill_fop_open(struct inode + return stream_open(inode, file); + + free: +- mutex_unlock(&data->mtx); + mutex_unlock(&rfkill_global_mutex); + mutex_destroy(&data->mtx); + list_for_each_entry_safe(ev, tmp, &data->events, list) +@@ -1232,6 +1244,7 @@ static ssize_t rfkill_fop_read(struct fi + ret = -EFAULT; + + list_del(&ev->list); ++ data->event_count--; + kfree(ev); + out: + mutex_unlock(&data->mtx); diff --git a/queue-5.15/revert-mptcp-add-needs_id-for-netlink-appending-addr.patch b/queue-5.15/revert-mptcp-add-needs_id-for-netlink-appending-addr.patch new file mode 100644 index 0000000000..de91ecbffe --- /dev/null +++ b/queue-5.15/revert-mptcp-add-needs_id-for-netlink-appending-addr.patch @@ -0,0 +1,109 @@ +From stable+bounces-235866-greg=kroah.com@vger.kernel.org Mon Apr 13 00:56:25 2026 +From: Sasha Levin +Date: Sun, 12 Apr 2026 18:52:06 -0400 +Subject: Revert "mptcp: add needs_id for netlink appending addr" +To: stable@vger.kernel.org +Cc: "Matthieu Baerts (NGI0)" , Geliang Tang , Jakub Kicinski , Sasha Levin +Message-ID: <20260412225206.2462132-1-sashal@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +[ Upstream commit 8e2760eaab778494fc1fa257031e0e1799647f46 ] + +This commit was originally adding the ability to add MPTCP endpoints +with ID 0 by accident. The in-kernel PM, handling MPTCP endpoints at the +net namespace level, is not supposed to handle endpoints with such ID, +because this ID 0 is reserved to the initial subflow, as mentioned in +the MPTCPv1 protocol [1], a per-connection setting. + +Note that 'ip mptcp endpoint add id 0' stops early with an error, but +other tools might still request the in-kernel PM to create MPTCP +endpoints with this restricted ID 0. + +In other words, it was wrong to call the mptcp_pm_has_addr_attr_id +helper to check whether the address ID attribute is set: if it was set +to 0, a new MPTCP endpoint would be created with ID 0, which is not +expected, and might cause various issues later. + +Fixes: 584f38942626 ("mptcp: add needs_id for netlink appending addr") +Cc: stable@vger.kernel.org +Link: https://datatracker.ietf.org/doc/html/rfc8684#section-3.2-9 [1] +Reviewed-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260407-net-mptcp-revert-pm-needs-id-v2-1-7a25cbc324f8@kernel.org +Signed-off-by: Jakub Kicinski +[ adapted changes from pm_kernel.c to pm_netlink.c ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm_netlink.c | 24 +++++------------------- + 1 file changed, 5 insertions(+), 19 deletions(-) + +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -972,8 +972,7 @@ static bool address_use_port(struct mptc + } + + static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, +- struct mptcp_pm_addr_entry *entry, +- bool needs_id) ++ struct mptcp_pm_addr_entry *entry) + { + struct mptcp_pm_addr_entry *cur; + unsigned int addr_max; +@@ -1000,7 +999,7 @@ static int mptcp_pm_nl_append_new_local_ + goto out; + } + +- if (!entry->addr.id && needs_id) { ++ if (!entry->addr.id) { + find_next: + entry->addr.id = find_next_zero_bit(pernet->id_bitmap, + MAX_ADDR_ID + 1, +@@ -1011,7 +1010,7 @@ find_next: + } + } + +- if (!entry->addr.id && needs_id) ++ if (!entry->addr.id) + goto out; + + __set_bit(entry->addr.id, pernet->id_bitmap); +@@ -1152,7 +1151,7 @@ int mptcp_pm_nl_get_local_id(struct mptc + entry->ifindex = 0; + entry->flags = 0; + entry->lsk = NULL; +- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true); ++ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry); + if (ret < 0) + kfree(entry); + +@@ -1374,18 +1373,6 @@ next: + return 0; + } + +-static bool mptcp_pm_has_addr_attr_id(const struct nlattr *attr, +- struct genl_info *info) +-{ +- struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1]; +- +- if (!nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr, +- mptcp_pm_addr_policy, info->extack) && +- tb[MPTCP_PM_ADDR_ATTR_ID]) +- return true; +- return false; +-} +- + static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info) + { + struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; +@@ -1412,8 +1399,7 @@ static int mptcp_nl_cmd_add_addr(struct + return ret; + } + } +- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, +- !mptcp_pm_has_addr_attr_id(attr, info)); ++ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry); + if (ret < 0) { + GENL_SET_ERR_MSG(info, "too many addresses or duplicate one"); + if (entry->lsk) diff --git a/queue-5.15/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch b/queue-5.15/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch new file mode 100644 index 0000000000..e6202f381b --- /dev/null +++ b/queue-5.15/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch @@ -0,0 +1,148 @@ +From stable+bounces-232539-greg=kroah.com@vger.kernel.org Tue Mar 31 19:49:30 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 13:10:00 -0400 +Subject: scsi: target: tcm_loop: Drain commands in target_reset handler +To: stable@vger.kernel.org +Cc: Josef Bacik , "Martin K. Petersen" , Sasha Levin +Message-ID: <20260331171000.2814732-1-sashal@kernel.org> + +From: Josef Bacik + +[ Upstream commit 1333eee56cdf3f0cf67c6ab4114c2c9e0a952026 ] + +tcm_loop_target_reset() violates the SCSI EH contract: it returns SUCCESS +without draining any in-flight commands. The SCSI EH documentation +(scsi_eh.rst) requires that when a reset handler returns SUCCESS the driver +has made lower layers "forget about timed out scmds" and is ready for new +commands. Every other SCSI LLD (virtio_scsi, mpt3sas, ipr, scsi_debug, +mpi3mr) enforces this by draining or completing outstanding commands before +returning SUCCESS. + +Because tcm_loop_target_reset() doesn't drain, the SCSI EH reuses in-flight +scsi_cmnd structures for recovery commands (e.g. TUR) while the target core +still has async completion work queued for the old se_cmd. The memset in +queuecommand zeroes se_lun and lun_ref_active, causing +transport_lun_remove_cmd() to skip its percpu_ref_put(). The leaked LUN +reference prevents transport_clear_lun_ref() from completing, hanging +configfs LUN unlink forever in D-state: + + INFO: task rm:264 blocked for more than 122 seconds. + rm D 0 264 258 0x00004000 + Call Trace: + __schedule+0x3d0/0x8e0 + schedule+0x36/0xf0 + transport_clear_lun_ref+0x78/0x90 [target_core_mod] + core_tpg_remove_lun+0x28/0xb0 [target_core_mod] + target_fabric_port_unlink+0x50/0x60 [target_core_mod] + configfs_unlink+0x156/0x1f0 [configfs] + vfs_unlink+0x109/0x290 + do_unlinkat+0x1d5/0x2d0 + +Fix this by making tcm_loop_target_reset() actually drain commands: + + 1. Issue TMR_LUN_RESET via tcm_loop_issue_tmr() to drain all commands that + the target core knows about (those not yet CMD_T_COMPLETE). + + 2. Use blk_mq_tagset_busy_iter() to iterate all started requests and + flush_work() on each se_cmd — this drains any deferred completion work + for commands that already had CMD_T_COMPLETE set before the TMR (which + the TMR skips via __target_check_io_state()). This is the same pattern + used by mpi3mr, scsi_debug, and libsas to drain outstanding commands + during reset. + +Fixes: e0eb5d38b732 ("scsi: target: tcm_loop: Use block cmd allocator for se_cmds") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-6 +Signed-off-by: Josef Bacik +Link: https://patch.msgid.link/27011aa34c8f6b1b94d2e3cf5655b6d037f53428.1773706803.git.josef@toxicpanda.com +Signed-off-by: Martin K. Petersen +[ added `bool reserved` parameter to `tcm_loop_flush_work_iter()` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/loopback/tcm_loop.c | 52 ++++++++++++++++++++++++++++++++----- + 1 file changed, 46 insertions(+), 6 deletions(-) + +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -274,15 +275,27 @@ static int tcm_loop_device_reset(struct + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } + ++static bool tcm_loop_flush_work_iter(struct request *rq, void *data, bool reserved) ++{ ++ struct scsi_cmnd *sc = blk_mq_rq_to_pdu(rq); ++ struct tcm_loop_cmd *tl_cmd = scsi_cmd_priv(sc); ++ struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd; ++ ++ flush_work(&se_cmd->work); ++ return true; ++} ++ + static int tcm_loop_target_reset(struct scsi_cmnd *sc) + { + struct tcm_loop_hba *tl_hba; + struct tcm_loop_tpg *tl_tpg; ++ struct Scsi_Host *sh = sc->device->host; ++ int ret; + + /* + * Locate the tcm_loop_hba_t pointer + */ +- tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); ++ tl_hba = *(struct tcm_loop_hba **)shost_priv(sh); + if (!tl_hba) { + pr_err("Unable to perform device reset without active I_T Nexus\n"); + return FAILED; +@@ -291,11 +304,38 @@ static int tcm_loop_target_reset(struct + * Locate the tl_tpg pointer from TargetID in sc->device->id + */ + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; +- if (tl_tpg) { +- tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE; +- return SUCCESS; +- } +- return FAILED; ++ if (!tl_tpg) ++ return FAILED; ++ ++ /* ++ * Issue a LUN_RESET to drain all commands that the target core ++ * knows about. This handles commands not yet marked CMD_T_COMPLETE. ++ */ ++ ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, 0, TMR_LUN_RESET); ++ if (ret != TMR_FUNCTION_COMPLETE) ++ return FAILED; ++ ++ /* ++ * Flush any deferred target core completion work that may still be ++ * queued. Commands that already had CMD_T_COMPLETE set before the TMR ++ * are skipped by the TMR drain, but their async completion work ++ * (transport_lun_remove_cmd → percpu_ref_put, release_cmd → scsi_done) ++ * may still be pending in target_completion_wq. ++ * ++ * The SCSI EH will reuse in-flight scsi_cmnd structures for recovery ++ * commands (e.g. TUR) immediately after this handler returns SUCCESS — ++ * if deferred work is still pending, the memset in queuecommand would ++ * zero the se_cmd while the work accesses it, leaking the LUN ++ * percpu_ref and hanging configfs unlink forever. ++ * ++ * Use blk_mq_tagset_busy_iter() to find all started requests and ++ * flush_work() on each — the same pattern used by mpi3mr, scsi_debug, ++ * and other SCSI drivers to drain outstanding commands during reset. ++ */ ++ blk_mq_tagset_busy_iter(&sh->tag_set, tcm_loop_flush_work_iter, NULL); ++ ++ tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE; ++ return SUCCESS; + } + + static struct scsi_host_template tcm_loop_driver_template = { diff --git a/queue-5.15/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch b/queue-5.15/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch new file mode 100644 index 0000000000..59e105862f --- /dev/null +++ b/queue-5.15/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch @@ -0,0 +1,132 @@ +From stable+bounces-235864-greg=kroah.com@vger.kernel.org Mon Apr 13 00:00:13 2026 +From: Sasha Levin +Date: Sun, 12 Apr 2026 18:00:05 -0400 +Subject: seg6: separate dst_cache for input and output paths in seg6 lwtunnel +To: stable@vger.kernel.org +Cc: Andrea Mayer , Nicolas Dichtel , Justin Iurman , Jakub Kicinski , Sasha Levin +Message-ID: <20260412220005.2440027-1-sashal@kernel.org> + +From: Andrea Mayer + +[ Upstream commit c3812651b522fe8437ebb7063b75ddb95b571643 ] + +The seg6 lwtunnel uses a single dst_cache per encap route, shared +between seg6_input_core() and seg6_output_core(). These two paths +can perform the post-encap SID lookup in different routing contexts +(e.g., ip rules matching on the ingress interface, or VRF table +separation). Whichever path runs first populates the cache, and the +other reuses it blindly, bypassing its own lookup. + +Fix this by splitting the cache into cache_input and cache_output, +so each path maintains its own cached dst independently. + +Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels") +Cc: stable@vger.kernel.org +Signed-off-by: Andrea Mayer +Reviewed-by: Nicolas Dichtel +Reviewed-by: Justin Iurman +Link: https://patch.msgid.link/20260404004405.4057-2-andrea.mayer@uniroma2.it +Signed-off-by: Jakub Kicinski +[ added missing dst reference loop guard in seg6_output_core() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/seg6_iptunnel.c | 41 ++++++++++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 13 deletions(-) + +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -48,7 +48,8 @@ static size_t seg6_lwt_headroom(struct s + } + + struct seg6_lwt { +- struct dst_cache cache; ++ struct dst_cache cache_input; ++ struct dst_cache cache_output; + struct seg6_iptunnel_encap tuninfo[]; + }; + +@@ -486,7 +487,7 @@ static int seg6_input_core(struct net *n + slwt = seg6_lwt_lwtunnel(lwtst); + + local_bh_disable(); +- dst = dst_cache_get(&slwt->cache); ++ dst = dst_cache_get(&slwt->cache_input); + local_bh_enable(); + + err = seg6_do_srh(skb, dst); +@@ -504,7 +505,7 @@ static int seg6_input_core(struct net *n + /* cache only if we don't create a dst reference loop */ + if (!dst->error && lwtst != dst->lwtstate) { + local_bh_disable(); +- dst_cache_set_ip6(&slwt->cache, dst, ++ dst_cache_set_ip6(&slwt->cache_input, dst, + &ipv6_hdr(skb)->saddr); + local_bh_enable(); + } +@@ -563,7 +564,7 @@ static int seg6_output_core(struct net * + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + + local_bh_disable(); +- dst = dst_cache_get(&slwt->cache); ++ dst = dst_cache_get(&slwt->cache_output); + local_bh_enable(); + + err = seg6_do_srh(skb, dst); +@@ -587,9 +588,12 @@ static int seg6_output_core(struct net * + goto drop; + } + +- local_bh_disable(); +- dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr); +- local_bh_enable(); ++ /* cache only if we don't create a dst reference loop */ ++ if (orig_dst->lwtstate != dst->lwtstate) { ++ local_bh_disable(); ++ dst_cache_set_ip6(&slwt->cache_output, dst, &fl6.saddr); ++ local_bh_enable(); ++ } + + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); + if (unlikely(err)) +@@ -697,11 +701,13 @@ static int seg6_build_state(struct net * + + slwt = seg6_lwt_lwtunnel(newts); + +- err = dst_cache_init(&slwt->cache, GFP_ATOMIC); +- if (err) { +- kfree(newts); +- return err; +- } ++ err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC); ++ if (err) ++ goto err_free_newts; ++ ++ err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC); ++ if (err) ++ goto err_destroy_input; + + memcpy(&slwt->tuninfo, tuninfo, tuninfo_len); + +@@ -716,11 +722,20 @@ static int seg6_build_state(struct net * + *ts = newts; + + return 0; ++ ++err_destroy_input: ++ dst_cache_destroy(&slwt->cache_input); ++err_free_newts: ++ kfree(newts); ++ return err; + } + + static void seg6_destroy_state(struct lwtunnel_state *lwt) + { +- dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache); ++ struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwt); ++ ++ dst_cache_destroy(&slwt->cache_input); ++ dst_cache_destroy(&slwt->cache_output); + } + + static int seg6_fill_encap_info(struct sk_buff *skb, diff --git a/queue-5.15/series b/queue-5.15/series index 690e8ed5c5..0ad8b8a578 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -540,3 +540,29 @@ rxrpc-fix-reference-count-leak-in-rxrpc_server_keyring.patch rxrpc-fix-key-keyring-checks-in-setsockopt-rxrpc_security_key-keyring.patch netlink-add-nla-be16-32-types-to-minlen-array.patch xen-privcmd-unregister-xenstore-notifier-on-module-exit.patch +revert-mptcp-add-needs_id-for-netlink-appending-addr.patch +seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch +net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch +usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch +usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch +usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch +ext4-publish-jinode-after-initialization.patch +ext4-fix-the-might_sleep-warnings-in-kvfree.patch +ext4-fix-use-after-free-in-update_super_work-when-racing-with-umount.patch +xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch +dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch +dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch +kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch +net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch +scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch +mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch +x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch +tracing-fix-potential-deadlock-in-cpu-hotplug-with-osnoise.patch +ksmbd-fix-potencial-oob-in-get_file_all_info-for-compound-requests.patch +ksmbd-replace-hardcoded-hdr2_len-with-offsetof-in-smb2_calc_max_out_buf_len.patch +i2c-cp2615-replace-deprecated-strncpy-with-strscpy.patch +i2c-cp2615-fix-serial-string-null-deref-at-probe.patch +bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch +drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch +ksmbd-fix-refcount-leak-when-invalid-session-is-found-on-session-lookup.patch +ksmbd-fix-dangling-pointer-in-krb_authenticate.patch diff --git a/queue-5.15/tracing-fix-potential-deadlock-in-cpu-hotplug-with-osnoise.patch b/queue-5.15/tracing-fix-potential-deadlock-in-cpu-hotplug-with-osnoise.patch new file mode 100644 index 0000000000..7d0aa28982 --- /dev/null +++ b/queue-5.15/tracing-fix-potential-deadlock-in-cpu-hotplug-with-osnoise.patch @@ -0,0 +1,93 @@ +From stable+bounces-231276-greg=kroah.com@vger.kernel.org Mon Mar 30 23:07:45 2026 +From: Sasha Levin +Date: Mon, 30 Mar 2026 17:07:37 -0400 +Subject: tracing: Fix potential deadlock in cpu hotplug with osnoise +To: stable@vger.kernel.org +Cc: Luo Haiyang , mathieu.desnoyers@efficios.com, zhang.run@zte.com.cn, yang.tao172@zte.com.cn, ran.xiaokai@zte.com.cn, "Masami Hiramatsu (Google)" , "Steven Rostedt (Google)" , Sasha Levin +Message-ID: <20260330210737.1213194-1-sashal@kernel.org> + +From: Luo Haiyang + +[ Upstream commit 1f9885732248d22f788e4992c739a98c88ab8a55 ] + +The following sequence may leads deadlock in cpu hotplug: + + task1 task2 task3 + ----- ----- ----- + + mutex_lock(&interface_lock) + + [CPU GOING OFFLINE] + + cpus_write_lock(); + osnoise_cpu_die(); + kthread_stop(task3); + wait_for_completion(); + + osnoise_sleep(); + mutex_lock(&interface_lock); + + cpus_read_lock(); + + [DEAD LOCK] + +Fix by swap the order of cpus_read_lock() and mutex_lock(&interface_lock). + +Cc: stable@vger.kernel.org +Cc: +Cc: +Cc: +Cc: +Fixes: bce29ac9ce0bb ("trace: Add osnoise tracer") +Link: https://patch.msgid.link/20260326141953414bVSj33dAYktqp9Oiyizq8@zte.com.cn +Reviewed-by: Masami Hiramatsu (Google) +Signed-off-by: Luo Haiyang +Signed-off-by: Steven Rostedt (Google) +[ adapted guard() macros to lock/unlock calls ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_osnoise.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/kernel/trace/trace_osnoise.c ++++ b/kernel/trace/trace_osnoise.c +@@ -1620,8 +1620,8 @@ static void osnoise_hotplug_workfn(struc + if (!osnoise_busy) + goto out_unlock_trace; + +- mutex_lock(&interface_lock); + cpus_read_lock(); ++ mutex_lock(&interface_lock); + + if (!cpu_online(cpu)) + goto out_unlock; +@@ -1634,8 +1634,8 @@ static void osnoise_hotplug_workfn(struc + start_kthread(cpu); + + out_unlock: +- cpus_read_unlock(); + mutex_unlock(&interface_lock); ++ cpus_read_unlock(); + out_unlock_trace: + mutex_unlock(&trace_types_lock); + } +@@ -1772,16 +1772,16 @@ osnoise_cpus_write(struct file *filp, co + if (running) + osnoise_tracer_stop(tr); + +- mutex_lock(&interface_lock); + /* + * osnoise_cpumask is read by CPU hotplug operations. + */ + cpus_read_lock(); ++ mutex_lock(&interface_lock); + + cpumask_copy(&osnoise_cpumask, osnoise_cpumask_new); + +- cpus_read_unlock(); + mutex_unlock(&interface_lock); ++ cpus_read_unlock(); + + if (running) + osnoise_tracer_start(tr); diff --git a/queue-5.15/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch b/queue-5.15/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch new file mode 100644 index 0000000000..d7fa22c36a --- /dev/null +++ b/queue-5.15/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch @@ -0,0 +1,72 @@ +From stable+bounces-235808-greg=kroah.com@vger.kernel.org Sun Apr 12 14:00:10 2026 +From: Sasha Levin +Date: Sun, 12 Apr 2026 08:00:00 -0400 +Subject: usb: gadget: f_hid: move list and spinlock inits from bind to alloc +To: stable@vger.kernel.org +Cc: Michael Zimmermann , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260412120000.2096246-1-sashal@kernel.org> + +From: Michael Zimmermann + +[ Upstream commit 4e0a88254ad59f6c53a34bf5fa241884ec09e8b2 ] + +There was an issue when you did the following: +- setup and bind an hid gadget +- open /dev/hidg0 +- use the resulting fd in EPOLL_CTL_ADD +- unbind the UDC +- bind the UDC +- use the fd in EPOLL_CTL_DEL + +When CONFIG_DEBUG_LIST was enabled, a list_del corruption was reported +within remove_wait_queue (via ep_remove_wait_queue). After some +debugging I found out that the queues, which f_hid registers via +poll_wait were the problem. These were initialized using +init_waitqueue_head inside hidg_bind. So effectively, the bind function +re-initialized the queues while there were still items in them. + +The solution is to move the initialization from hidg_bind to hidg_alloc +to extend their lifetimes to the lifetime of the function instance. + +Additionally, I found many other possibly problematic init calls in the +bind function, which I moved as well. + +Signed-off-by: Michael Zimmermann +Cc: stable +Link: https://patch.msgid.link/20260331184844.2388761-1-sigmaepsilon92@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_hid.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -996,13 +996,8 @@ static int hidg_bind(struct usb_configur + if (status) + goto fail; + +- spin_lock_init(&hidg->write_spinlock); + hidg->write_pending = 1; + hidg->req = NULL; +- spin_lock_init(&hidg->read_spinlock); +- init_waitqueue_head(&hidg->write_queue); +- init_waitqueue_head(&hidg->read_queue); +- INIT_LIST_HEAD(&hidg->completed_out_req); + + /* create char device */ + cdev_init(&hidg->cdev, &f_hidg_fops); +@@ -1272,6 +1267,12 @@ static struct usb_function *hidg_alloc(s + mutex_lock(&opts->lock); + ++opts->refcnt; + ++ spin_lock_init(&hidg->write_spinlock); ++ spin_lock_init(&hidg->read_spinlock); ++ init_waitqueue_head(&hidg->write_queue); ++ init_waitqueue_head(&hidg->read_queue); ++ INIT_LIST_HEAD(&hidg->completed_out_req); ++ + device_initialize(&hidg->dev); + hidg->dev.release = hidg_release; + hidg->dev.class = hidg_class; diff --git a/queue-5.15/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch b/queue-5.15/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch new file mode 100644 index 0000000000..367cf71f47 --- /dev/null +++ b/queue-5.15/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch @@ -0,0 +1,80 @@ +From sashal@kernel.org Sat Apr 11 18:31:09 2026 +From: Sasha Levin +Date: Sat, 11 Apr 2026 12:31:06 -0400 +Subject: usb: gadget: u_ether: Fix race between gether_disconnect and eth_stop +To: stable@vger.kernel.org +Cc: Kuen-Han Tsai , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260411163106.807249-1-sashal@kernel.org> + +From: Kuen-Han Tsai + +[ Upstream commit e1eabb072c75681f78312c484ccfffb7430f206e ] + +A race condition between gether_disconnect() and eth_stop() leads to a +NULL pointer dereference. Specifically, if eth_stop() is triggered +concurrently while gether_disconnect() is tearing down the endpoints, +eth_stop() attempts to access the cleared endpoint descriptor, causing +the following NPE: + + Unable to handle kernel NULL pointer dereference + Call trace: + __dwc3_gadget_ep_enable+0x60/0x788 + dwc3_gadget_ep_enable+0x70/0xe4 + usb_ep_enable+0x60/0x15c + eth_stop+0xb8/0x108 + +Because eth_stop() crashes while holding the dev->lock, the thread +running gether_disconnect() fails to acquire the same lock and spins +forever, resulting in a hardlockup: + + Core - Debugging Information for Hardlockup core(7) + Call trace: + queued_spin_lock_slowpath+0x94/0x488 + _raw_spin_lock+0x64/0x6c + gether_disconnect+0x19c/0x1e8 + ncm_set_alt+0x68/0x1a0 + composite_setup+0x6a0/0xc50 + +The root cause is that the clearing of dev->port_usb in +gether_disconnect() is delayed until the end of the function. + +Move the clearing of dev->port_usb to the very beginning of +gether_disconnect() while holding dev->lock. This cuts off the link +immediately, ensuring eth_stop() will see dev->port_usb as NULL and +safely bail out. + +Fixes: 2b3d942c4878 ("usb ethernet gadget: split out network core") +Cc: stable +Signed-off-by: Kuen-Han Tsai +Link: https://patch.msgid.link/20260311-gether-disconnect-npe-v1-1-454966adf7c7@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/u_ether.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/usb/gadget/function/u_ether.c ++++ b/drivers/usb/gadget/function/u_ether.c +@@ -1173,6 +1173,10 @@ void gether_disconnect(struct gether *li + + DBG(dev, "%s\n", __func__); + ++ spin_lock(&dev->lock); ++ dev->port_usb = NULL; ++ spin_unlock(&dev->lock); ++ + netif_stop_queue(dev->net); + netif_carrier_off(dev->net); + +@@ -1210,10 +1214,6 @@ void gether_disconnect(struct gether *li + dev->header_len = 0; + dev->unwrap = NULL; + dev->wrap = NULL; +- +- spin_lock(&dev->lock); +- dev->port_usb = NULL; +- spin_unlock(&dev->lock); + } + EXPORT_SYMBOL_GPL(gether_disconnect); + diff --git a/queue-5.15/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch b/queue-5.15/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch new file mode 100644 index 0000000000..add0e2ac0c --- /dev/null +++ b/queue-5.15/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch @@ -0,0 +1,244 @@ +From sashal@kernel.org Sat Apr 11 16:09:51 2026 +From: Sasha Levin +Date: Sat, 11 Apr 2026 10:09:48 -0400 +Subject: usb: gadget: uvc: fix NULL pointer dereference during unbind race +To: stable@vger.kernel.org +Cc: Jimmy Hu , stable , Alan Stern , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260411140948.765851-1-sashal@kernel.org> + +From: Jimmy Hu + +[ Upstream commit eba2936bbe6b752a31725a9eb5c674ecbf21ee7d ] + +Commit b81ac4395bbe ("usb: gadget: uvc: allow for application to cleanly +shutdown") introduced two stages of synchronization waits totaling 1500ms +in uvc_function_unbind() to prevent several types of kernel panics. +However, this timing-based approach is insufficient during power +management (PM) transitions. + +When the PM subsystem starts freezing user space processes, the +wait_event_interruptible_timeout() is aborted early, which allows the +unbind thread to proceed and nullify the gadget pointer +(cdev->gadget = NULL): + +[ 814.123447][ T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind() +[ 814.178583][ T3173] PM: suspend entry (deep) +[ 814.192487][ T3173] Freezing user space processes +[ 814.197668][ T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind no clean disconnect, wait for release + +When the PM subsystem resumes or aborts the suspend and tasks are +restarted, the V4L2 release path is executed and attempts to access the +already nullified gadget pointer, triggering a kernel panic: + +[ 814.292597][ C0] PM: pm_system_irq_wakeup: 479 triggered dhdpcie_host_wake +[ 814.386727][ T3173] Restarting tasks ... +[ 814.403522][ T4558] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000030 +[ 814.404021][ T4558] pc : usb_gadget_deactivate+0x14/0xf4 +[ 814.404031][ T4558] lr : usb_function_deactivate+0x54/0x94 +[ 814.404078][ T4558] Call trace: +[ 814.404080][ T4558] usb_gadget_deactivate+0x14/0xf4 +[ 814.404083][ T4558] usb_function_deactivate+0x54/0x94 +[ 814.404087][ T4558] uvc_function_disconnect+0x1c/0x5c +[ 814.404092][ T4558] uvc_v4l2_release+0x44/0xac +[ 814.404095][ T4558] v4l2_release+0xcc/0x130 + +Address the race condition and NULL pointer dereference by: + +1. State Synchronization (flag + mutex) +Introduce a 'func_unbound' flag in struct uvc_device. This allows +uvc_function_disconnect() to safely skip accessing the nullified +cdev->gadget pointer. As suggested by Alan Stern, this flag is protected +by a new mutex (uvc->lock) to ensure proper memory ordering and prevent +instruction reordering or speculative loads. This mutex is also used to +protect 'func_connected' for consistent state management. + +2. Explicit Synchronization (completion) +Use a completion to synchronize uvc_function_unbind() with the +uvc_vdev_release() callback. This prevents Use-After-Free (UAF) by +ensuring struct uvc_device is freed after all video device resources +are released. + +Fixes: b81ac4395bbe ("usb: gadget: uvc: allow for application to cleanly shutdown") +Cc: stable +Suggested-by: Alan Stern +Suggested-by: Greg Kroah-Hartman +Signed-off-by: Jimmy Hu +Link: https://patch.msgid.link/20260320065427.1374555-1-hhhuuu@google.com +Signed-off-by: Greg Kroah-Hartman +[ replaced guard()/scoped_guard() macros ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_uvc.c | 46 ++++++++++++++++++++++++++++++--- + drivers/usb/gadget/function/uvc.h | 3 ++ + drivers/usb/gadget/function/uvc_v4l2.c | 13 +++++++-- + 3 files changed, 56 insertions(+), 6 deletions(-) + +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -393,6 +393,14 @@ uvc_function_disconnect(struct uvc_devic + { + int ret; + ++ mutex_lock(&uvc->lock); ++ if (uvc->func_unbound) { ++ dev_dbg(&uvc->vdev.dev, "skipping function deactivate (unbound)\n"); ++ mutex_unlock(&uvc->lock); ++ return; ++ } ++ mutex_unlock(&uvc->lock); ++ + if ((ret = usb_function_deactivate(&uvc->func)) < 0) + uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret); + } +@@ -411,6 +419,15 @@ static ssize_t function_name_show(struct + + static DEVICE_ATTR_RO(function_name); + ++static void uvc_vdev_release(struct video_device *vdev) ++{ ++ struct uvc_device *uvc = video_get_drvdata(vdev); ++ ++ /* Signal uvc_function_unbind() that the video device has been released */ ++ if (uvc->vdev_release_done) ++ complete(uvc->vdev_release_done); ++} ++ + static int + uvc_register_video(struct uvc_device *uvc) + { +@@ -422,7 +439,7 @@ uvc_register_video(struct uvc_device *uv + uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev; + uvc->vdev.fops = &uvc_v4l2_fops; + uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops; +- uvc->vdev.release = video_device_release_empty; ++ uvc->vdev.release = uvc_vdev_release; + uvc->vdev.vfl_dir = VFL_DIR_TX; + uvc->vdev.lock = &uvc->video.mutex; + uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; +@@ -596,6 +613,9 @@ uvc_function_bind(struct usb_configurati + int ret = -EINVAL; + + uvcg_info(f, "%s()\n", __func__); ++ mutex_lock(&uvc->lock); ++ uvc->func_unbound = false; ++ mutex_unlock(&uvc->lock); + + opts = fi_to_f_uvc_opts(f->fi); + /* Sanity check the streaming endpoint module parameters. +@@ -888,18 +908,25 @@ static void uvc_free(struct usb_function + static void uvc_function_unbind(struct usb_configuration *c, + struct usb_function *f) + { ++ DECLARE_COMPLETION_ONSTACK(vdev_release_done); + struct usb_composite_dev *cdev = c->cdev; + struct uvc_device *uvc = to_uvc(f); + long wait_ret = 1; ++ bool connected; + + uvcg_info(f, "%s()\n", __func__); ++ mutex_lock(&uvc->lock); ++ uvc->func_unbound = true; ++ uvc->vdev_release_done = &vdev_release_done; ++ connected = uvc->func_connected; ++ mutex_unlock(&uvc->lock); + + /* If we know we're connected via v4l2, then there should be a cleanup + * of the device from userspace either via UVC_EVENT_DISCONNECT or + * though the video device removal uevent. Allow some time for the + * application to close out before things get deleted. + */ +- if (uvc->func_connected) { ++ if (connected) { + uvcg_dbg(f, "waiting for clean disconnect\n"); + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, + uvc->func_connected == false, msecs_to_jiffies(500)); +@@ -910,8 +937,13 @@ static void uvc_function_unbind(struct u + video_unregister_device(&uvc->vdev); + v4l2_device_unregister(&uvc->v4l2_dev); + +- if (uvc->func_connected) { +- /* Wait for the release to occur to ensure there are no longer any ++ mutex_lock(&uvc->lock); ++ connected = uvc->func_connected; ++ mutex_unlock(&uvc->lock); ++ ++ if (connected) { ++ /* ++ * Wait for the release to occur to ensure there are no longer any + * pending operations that may cause panics when resources are cleaned + * up. + */ +@@ -921,6 +953,10 @@ static void uvc_function_unbind(struct u + uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret); + } + ++ /* Wait for the video device to be released */ ++ wait_for_completion(&vdev_release_done); ++ uvc->vdev_release_done = NULL; ++ + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); + kfree(uvc->control_buf); + +@@ -938,6 +974,8 @@ static struct usb_function *uvc_alloc(st + return ERR_PTR(-ENOMEM); + + mutex_init(&uvc->video.mutex); ++ mutex_init(&uvc->lock); ++ uvc->func_unbound = true; + uvc->state = UVC_STATE_DISCONNECTED; + init_waitqueue_head(&uvc->func_connected_queue); + opts = fi_to_f_uvc_opts(fi); +--- a/drivers/usb/gadget/function/uvc.h ++++ b/drivers/usb/gadget/function/uvc.h +@@ -130,6 +130,9 @@ struct uvc_device { + enum uvc_state state; + struct usb_function func; + struct uvc_video video; ++ struct completion *vdev_release_done; ++ struct mutex lock; /* protects func_unbound and func_connected */ ++ bool func_unbound; + bool func_connected; + wait_queue_head_t func_connected_queue; + +--- a/drivers/usb/gadget/function/uvc_v4l2.c ++++ b/drivers/usb/gadget/function/uvc_v4l2.c +@@ -234,12 +234,18 @@ uvc_v4l2_subscribe_event(struct v4l2_fh + if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) + return -EINVAL; + +- if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) ++ mutex_lock(&uvc->lock); ++ ++ if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) { ++ mutex_unlock(&uvc->lock); + return -EBUSY; ++ } + + ret = v4l2_event_subscribe(fh, sub, 2, NULL); +- if (ret < 0) ++ if (ret < 0) { ++ mutex_unlock(&uvc->lock); + return ret; ++ } + + if (sub->type == UVC_EVENT_SETUP) { + uvc->func_connected = true; +@@ -247,6 +253,7 @@ uvc_v4l2_subscribe_event(struct v4l2_fh + uvc_function_connect(uvc); + } + ++ mutex_unlock(&uvc->lock); + return 0; + } + +@@ -255,7 +262,9 @@ static void uvc_v4l2_disable(struct uvc_ + uvc_function_disconnect(uvc); + uvcg_video_enable(&uvc->video, 0); + uvcg_free_buffers(&uvc->video.queue); ++ mutex_lock(&uvc->lock); + uvc->func_connected = false; ++ mutex_unlock(&uvc->lock); + wake_up_interruptible(&uvc->func_connected_queue); + } + diff --git a/queue-5.15/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch b/queue-5.15/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch new file mode 100644 index 0000000000..cf92145b8f --- /dev/null +++ b/queue-5.15/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch @@ -0,0 +1,142 @@ +From stable+bounces-231413-greg=kroah.com@vger.kernel.org Tue Mar 31 14:21:10 2026 +From: Sasha Levin +Date: Tue, 31 Mar 2026 08:16:42 -0400 +Subject: x86/cpu: Enable FSGSBASE early in cpu_init_exception_handling() +To: stable@vger.kernel.org +Cc: Nikunj A Dadhania , Borislav Petkov , Sohil Mehta , stable@kernel.org, Sasha Levin +Message-ID: <20260331121642.2195682-1-sashal@kernel.org> + +From: Nikunj A Dadhania + +[ Upstream commit 05243d490bb7852a8acca7b5b5658019c7797a52 ] + +Move FSGSBASE enablement from identify_cpu() to cpu_init_exception_handling() +to ensure it is enabled before any exceptions can occur on both boot and +secondary CPUs. + +== Background == + +Exception entry code (paranoid_entry()) uses ALTERNATIVE patching based on +X86_FEATURE_FSGSBASE to decide whether to use RDGSBASE/WRGSBASE instructions +or the slower RDMSR/SWAPGS sequence for saving/restoring GSBASE. + +On boot CPU, ALTERNATIVE patching happens after enabling FSGSBASE in CR4. +When the feature is available, the code is permanently patched to use +RDGSBASE/WRGSBASE, which require CR4.FSGSBASE=1 to execute without triggering + +== Boot Sequence == + +Boot CPU (with CR pinning enabled): + trap_init() + cpu_init() <- Uses unpatched code (RDMSR/SWAPGS) + x2apic_setup() + ... + arch_cpu_finalize_init() + identify_boot_cpu() + identify_cpu() + cr4_set_bits(X86_CR4_FSGSBASE) # Enables the feature + # This becomes part of cr4_pinned_bits + ... + alternative_instructions() <- Patches code to use RDGSBASE/WRGSBASE + +Secondary CPUs (with CR pinning enabled): + start_secondary() + cr4_init() <- Code already patched, CR4.FSGSBASE=1 + set implicitly via cr4_pinned_bits + + cpu_init() <- exceptions work because FSGSBASE is + already enabled + +Secondary CPU (with CR pinning disabled): + start_secondary() + cr4_init() <- Code already patched, CR4.FSGSBASE=0 + cpu_init() + x2apic_setup() + rdmsrq(MSR_IA32_APICBASE) <- Triggers #VC in SNP guests + exc_vmm_communication() + paranoid_entry() <- Uses RDGSBASE with CR4.FSGSBASE=0 + (patched code) + ... + ap_starting() + identify_secondary_cpu() + identify_cpu() + cr4_set_bits(X86_CR4_FSGSBASE) <- Enables the feature, which is + too late + +== CR Pinning == + +Currently, for secondary CPUs, CR4.FSGSBASE is set implicitly through +CR-pinning: the boot CPU sets it during identify_cpu(), it becomes part of +cr4_pinned_bits, and cr4_init() applies those pinned bits to secondary CPUs. +This works but creates an undocumented dependency between cr4_init() and the +pinning mechanism. + +== Problem == + +Secondary CPUs boot after alternatives have been applied globally. They +execute already-patched paranoid_entry() code that uses RDGSBASE/WRGSBASE +instructions, which require CR4.FSGSBASE=1. Upcoming changes to CR pinning +behavior will break the implicit dependency, causing secondary CPUs to +generate #UD. + +This issue manifests itself on AMD SEV-SNP guests, where the rdmsrq() in +x2apic_setup() triggers a #VC exception early during cpu_init(). The #VC +handler (exc_vmm_communication()) executes the patched paranoid_entry() path. +Without CR4.FSGSBASE enabled, RDGSBASE instructions trigger #UD. + +== Fix == + +Enable FSGSBASE explicitly in cpu_init_exception_handling() before loading +exception handlers. This makes the dependency explicit and ensures both +boot and secondary CPUs have FSGSBASE enabled before paranoid_entry() +executes. + +Fixes: c82965f9e530 ("x86/entry/64: Handle FSGSBASE enabled paranoid entry/exit") +Reported-by: Borislav Petkov +Suggested-by: Sohil Mehta +Signed-off-by: Nikunj A Dadhania +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Sohil Mehta +Cc: +Link: https://patch.msgid.link/20260318075654.1792916-2-nikunj@amd.com +[ placed FSGSBASE enablement before load_current_idt() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/cpu/common.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1839,12 +1839,6 @@ static void identify_cpu(struct cpuinfo_ + setup_smap(c); + setup_umip(c); + +- /* Enable FSGSBASE instructions if available. */ +- if (cpu_has(c, X86_FEATURE_FSGSBASE)) { +- cr4_set_bits(X86_CR4_FSGSBASE); +- elf_hwcap2 |= HWCAP2_FSGSBASE; +- } +- + /* + * The vendor-specific functions might have changed features. + * Now we do "generic changes." +@@ -2220,6 +2214,18 @@ void cpu_init_exception_handling(void) + + load_TR_desc(); + ++ /* ++ * On CPUs with FSGSBASE support, paranoid_entry() uses ++ * ALTERNATIVE-patched RDGSBASE/WRGSBASE instructions. Secondary CPUs ++ * boot after alternatives are patched globally, so early exceptions ++ * execute patched code that depends on FSGSBASE. Enable the feature ++ * before any exceptions occur. ++ */ ++ if (cpu_feature_enabled(X86_FEATURE_FSGSBASE)) { ++ cr4_set_bits(X86_CR4_FSGSBASE); ++ elf_hwcap2 |= HWCAP2_FSGSBASE; ++ } ++ + /* Finally load the IDT */ + load_current_idt(); + } diff --git a/queue-5.15/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch b/queue-5.15/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch new file mode 100644 index 0000000000..547ed68e2d --- /dev/null +++ b/queue-5.15/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch @@ -0,0 +1,100 @@ +From stable+bounces-232950-greg=kroah.com@vger.kernel.org Thu Apr 2 11:26:28 2026 +From: Sasha Levin +Date: Thu, 2 Apr 2026 05:12:46 -0400 +Subject: xfs: save ailp before dropping the AIL lock in push callbacks +To: stable@vger.kernel.org +Cc: Yuto Ohnuki , syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com, "Darrick J. Wong" , Dave Chinner , Carlos Maiolino , Sasha Levin +Message-ID: <20260402091246.482124-1-sashal@kernel.org> + +From: Yuto Ohnuki + +[ Upstream commit 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 ] + +In xfs_inode_item_push() and xfs_qm_dquot_logitem_push(), the AIL lock +is dropped to perform buffer IO. Once the cluster buffer no longer +protects the log item from reclaim, the log item may be freed by +background reclaim or the dquot shrinker. The subsequent spin_lock() +call dereferences lip->li_ailp, which is a use-after-free. + +Fix this by saving the ailp pointer in a local variable while the AIL +lock is held and the log item is guaranteed to be valid. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Reviewed-by: Darrick J. Wong +Reviewed-by: Dave Chinner +Signed-off-by: Yuto Ohnuki +Signed-off-by: Carlos Maiolino +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_dquot_item.c | 9 +++++++-- + fs/xfs/xfs_inode_item.c | 9 +++++++-- + 2 files changed, 14 insertions(+), 4 deletions(-) + +--- a/fs/xfs/xfs_dquot_item.c ++++ b/fs/xfs/xfs_dquot_item.c +@@ -124,6 +124,7 @@ xfs_qm_dquot_logitem_push( + { + struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; + struct xfs_buf *bp = lip->li_buf; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -152,7 +153,7 @@ xfs_qm_dquot_logitem_push( + goto out_unlock; + } + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + error = xfs_qm_dqflush(dqp, &bp); + if (!error) { +@@ -162,7 +163,11 @@ xfs_qm_dquot_logitem_push( + } else if (error == -EAGAIN) + rval = XFS_ITEM_LOCKED; + +- spin_lock(&lip->li_ailp->ail_lock); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ ++ spin_lock(&ailp->ail_lock); + out_unlock: + xfs_dqunlock(dqp); + return rval; +--- a/fs/xfs/xfs_inode_item.c ++++ b/fs/xfs/xfs_inode_item.c +@@ -540,6 +540,7 @@ xfs_inode_item_push( + struct xfs_inode_log_item *iip = INODE_ITEM(lip); + struct xfs_inode *ip = iip->ili_inode; + struct xfs_buf *bp = lip->li_buf; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -555,7 +556,7 @@ xfs_inode_item_push( + if (!xfs_buf_trylock(bp)) + return XFS_ITEM_LOCKED; + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + /* + * We need to hold a reference for flushing the cluster buffer as it may +@@ -579,7 +580,11 @@ xfs_inode_item_push( + rval = XFS_ITEM_LOCKED; + } + +- spin_lock(&lip->li_ailp->ail_lock); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ ++ spin_lock(&ailp->ail_lock); + return rval; + } +