From: Greg Kroah-Hartman Date: Thu, 2 Jul 2026 13:57:44 +0000 (+0200) Subject: 7.1-stable patches X-Git-Tag: v5.10.260~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=004b239f24cca6d193a2611642319cf32e2f62ff;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches added patches: 9p-avoid-putting-oldfid-in-p9_client_walk-error-path.patch blk-cgroup-fix-uaf-in-__blkcg_rstat_flush.patch fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch fbdev-fix-fb_new_modelist-to-prevent-null-ptr-deref-in-fb_videomode_to_var.patch fbdev-modedb-fix-a-possible-uaf-in-fb_find_mode.patch fbdev-modedb-fix-misaligned-fields-in-the-1920x1080-60-mode.patch fbdev-omap2-fix-use-after-free-in-omapfb_mmap.patch fpga-region-fix-use-after-free-in-child_regions_with_firmware.patch gfs2-fix-use-after-free-in-gfs2_qd_dealloc.patch hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch i2c-core-fix-adapter-registration-race.patch irqchip-imgpdc-fix-resource-leak-add-missing-chained-handler-cleanup-on-remove.patch ksmbd-fix-out-of-bounds-read-in-smb_check_perm_dacl.patch kvm-svm-fix-page-overflow-in-sev_dbg_crypt-for-encrypt-path.patch kvm-x86-hyper-v-bound-the-bank-index-when-querying-sparse-banks.patch loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch nfs-prevent-resource-leak-in-nfs_alloc_server.patch nfsd-avoid-leaking-pre-allocated-openowner-on-unconfirmed-retry-race.patch nfsd-check-get_user-return-when-reading-princhashlen.patch nfsd-fix-dead-acl-conflict-guard-in-nfsd4_create.patch nfsd-fix-inverted-cp_ttl-check-in-async-copy-reaper.patch nfsd-fix-posix_acl-leak-and-ignored-error-in-nfsd4_create_file.patch nfsd-fix-posix_acl-leak-on-setacl-decode-failure.patch nfsd-fix-secinfo_no_name-decode-error-cleanup.patch nfsd-release-layout-stid-on-setlease-failure.patch nfsd-reset-write-verifier-on-deferred-writeback-errors.patch nfsv4-clear-exception-state-on-successful-mkdir-retry.patch nfsv4-flexfiles-reject-zero-filehandle-version-count.patch nfsv4-pnfs-reject-zero-length-r_addr-in-nfs4_decode_mp_ds_addr.patch ntfs-serialize-volume-label-accesses.patch ocfs2-reject-oversized-group-bitmap-descriptors.patch pnfs-fix-use-after-free-in-pnfs_update_layout.patch power-reset-linkstation-poweroff-fix-use-after-free-in-the-linkstation_poweroff_init.patch pwrseq-core-fix-use-after-free-in-pwrseq_debugfs_seq_next.patch riscv-kfence-call-mark_new_valid_map-for-kfence_unprotect.patch rpmsg-char-fix-use-after-free-on-probe-error-path.patch sched-mmcid-fix-oob-clear_bit-when-cid-is-mm_cid_unset-in-fixup-path.patch tipc-fix-slab-use-after-free-read-in-tipc_aead_decrypt_done.patch --- diff --git a/queue-7.1/9p-avoid-putting-oldfid-in-p9_client_walk-error-path.patch b/queue-7.1/9p-avoid-putting-oldfid-in-p9_client_walk-error-path.patch new file mode 100644 index 0000000000..ba00efbfd8 --- /dev/null +++ b/queue-7.1/9p-avoid-putting-oldfid-in-p9_client_walk-error-path.patch @@ -0,0 +1,54 @@ +From 1a3860d46e3eb47dbd60339783cdad7904486b9f Mon Sep 17 00:00:00 2001 +From: Yizhou Zhao +Date: Thu, 28 May 2026 13:39:16 +0800 +Subject: 9p: avoid putting oldfid in p9_client_walk() error path + +From: Yizhou Zhao + +commit 1a3860d46e3eb47dbd60339783cdad7904486b9f upstream. + +When p9_client_walk() is called with clone set to false, fid aliases +oldfid. If the walk subsequently fails after the request has been sent, +the error path jumps to clunk_fid, which currently calls p9_fid_put(fid) +unconditionally. + +This drops a reference to oldfid even though ownership of oldfid remains +with the caller. If this is the last reference, oldfid can be clunked and +destroyed while the caller still expects it to be valid. A later use or +put of oldfid can then trigger a use-after-free or refcount underflow. + +Fix this by only putting fid in the clunk_fid error path when it does not +alias oldfid, matching the existing guard in the error path below. + +This can be triggered when a multi-component walk is split into multiple +p9_client_walk() calls and a later non-cloning walk fails. A reproducer +and refcount warning logs are available on request. + +Fixes: b48dbb998d70 ("9p fid refcount: add p9_fid_get/put wrappers") +Cc: stable@vger.kernel.org +Reported-by: Yuxiang Yang +Reported-by: Ao Wang +Reported-by: Xuewei Feng +Reported-by: Qi Li +Reported-by: Ke Xu +Assisted-by: GLM 5.1 +Signed-off-by: Yizhou Zhao +Message-ID: <20260528053918.53550-1-zhaoyz24@mails.tsinghua.edu.cn> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + net/9p/client.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -1092,7 +1092,8 @@ struct p9_fid *p9_client_walk(struct p9_ + + clunk_fid: + kfree(wqids); +- p9_fid_put(fid); ++ if (fid != oldfid) ++ p9_fid_put(fid); + fid = NULL; + + error: diff --git a/queue-7.1/blk-cgroup-fix-uaf-in-__blkcg_rstat_flush.patch b/queue-7.1/blk-cgroup-fix-uaf-in-__blkcg_rstat_flush.patch new file mode 100644 index 0000000000..86691f6bf3 --- /dev/null +++ b/queue-7.1/blk-cgroup-fix-uaf-in-__blkcg_rstat_flush.patch @@ -0,0 +1,76 @@ +From 0ab5ee5a1badb58cbb2242617cb01a4972b1f2a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Thu, 5 Feb 2026 23:54:23 +0800 +Subject: blk-cgroup: fix UAF in __blkcg_rstat_flush() + +From: Michal Koutný + +commit 0ab5ee5a1badb58cbb2242617cb01a4972b1f2a2 upstream. + +When multiple blkgs in the same blkcg are released concurrently, +a use-after-free can occur. The race happens when one blkg's +__blkcg_rstat_flush() removes another blkg's iostat entries via +llist_del_all(). The second blkg sees an empty list and proceeds +to free itself while the first is still iterating over its entries. + +Move the flush from __blkg_release() (RCU callback) to blkg_release() +(before call_rcu). This ensures the RCU grace period waits for any +concurrent flush's rcu_read_lock() section to complete before freeing. + +Cc: stable@vger.kernel.org +Cc: Jay Shin +Cc: Tejun Heo +Cc: Waiman Long +Fixes: 20cb1c2fb756 ("blk-cgroup: Flush stats before releasing blkcg_gq") +Reported-by: coregee2000@gmail.com +Closes: https://lore.kernel.org/linux-block/CAHPqNmwT9oRpem3J3erS_W0uSQND47LGGSBsNxP8E6uSUish1w@mail.gmail.com/ +Signed-off-by: Ming Lei +Tested-by: Jose Fernandez (Anthropic) +Link: https://patch.msgid.link/20260205155425.342084-1-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-cgroup.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -164,20 +164,10 @@ static void blkg_free(struct blkcg_gq *b + static void __blkg_release(struct rcu_head *rcu) + { + struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head); +- struct blkcg *blkcg = blkg->blkcg; +- int cpu; + + #ifdef CONFIG_BLK_CGROUP_PUNT_BIO + WARN_ON(!bio_list_empty(&blkg->async_bios)); + #endif +- /* +- * Flush all the non-empty percpu lockless lists before releasing +- * us, given these stat belongs to us. +- * +- * blkg_stat_lock is for serializing blkg stat update +- */ +- for_each_possible_cpu(cpu) +- __blkcg_rstat_flush(blkcg, cpu); + + /* release the blkcg and parent blkg refs this blkg has been holding */ + css_put(&blkg->blkcg->css); +@@ -195,6 +185,17 @@ static void __blkg_release(struct rcu_he + static void blkg_release(struct percpu_ref *ref) + { + struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt); ++ struct blkcg *blkcg = blkg->blkcg; ++ int cpu; ++ ++ /* ++ * Flush all the non-empty percpu lockless lists before releasing ++ * us, given these stat belongs to us. ++ * ++ * blkg_stat_lock is for serializing blkg stat update ++ */ ++ for_each_possible_cpu(cpu) ++ __blkcg_rstat_flush(blkcg, cpu); + + call_rcu(&blkg->rcu_head, __blkg_release); + } diff --git a/queue-7.1/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch b/queue-7.1/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch new file mode 100644 index 0000000000..28804f36ed --- /dev/null +++ b/queue-7.1/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch @@ -0,0 +1,65 @@ +From 8fdc8c2057eea08d40ce2c8eed41ff9e451c65c2 Mon Sep 17 00:00:00 2001 +From: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Date: Fri, 26 Jun 2026 00:03:06 +0800 +Subject: fbdev: fbcon: fix out-of-bounds read in err_out of fbcon_do_set_font() + +From: Mingyu Wang <25181214217@stu.xidian.edu.cn> + +commit 8fdc8c2057eea08d40ce2c8eed41ff9e451c65c2 upstream. + +When fbcon_do_set_font() fails (e.g., due to a memory allocation failure +inside vc_resize() under heavy memory pressure), it jumps to the `err_out` +label to roll back the console state. However, the current rollback logic +forgets to restore the `hi_font` state, leading to a severe state machine +corruption. + +Earlier in the function, `set_vc_hi_font()` might be called to change +`vc->vc_hi_font_mask` and mutate the screen buffer. If `vc_resize()` +subsequently fails, the `err_out` path restores `vc_font.charcount` +but entirely skips rolling back the `vc_hi_font_mask` and the screen +buffer. + +This mismatch leaves the terminal in a desynchronized state. Because +`vc_hi_font_mask` remains set, the VT subsystem will still accept +character indices greater than 255 from userspace and write them to the +screen buffer. Subsequent rendering calls (e.g., `fbcon_putcs()`) will +then use these inflated indices to access the reverted, 256-character +font array, leading to a deterministic out-of-bounds read and potential +kernel memory disclosure. + +Fix this by adding the missing rollback logic for the `hi_font` mask +and screen buffer in the error path. + +Fixes: a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed") +Cc: stable@vger.kernel.org +Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Reviewed-by: Thomas Zimmermann +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/fbcon.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -2407,6 +2407,7 @@ static int fbcon_do_set_font(struct vc_d + int resize, ret, old_width, old_height, old_charcount; + font_data_t *old_fontdata = p->fontdata; + const u8 *old_data = vc->vc_font.data; ++ unsigned short old_hi_font_mask = vc->vc_hi_font_mask; + + font_data_get(data); + +@@ -2453,6 +2454,12 @@ err_out: + vc->vc_font.height = old_height; + vc->vc_font.charcount = old_charcount; + ++ /* Restore the hi_font state and screen buffer */ ++ if (old_hi_font_mask && !vc->vc_hi_font_mask) ++ set_vc_hi_font(vc, true); ++ else if (!old_hi_font_mask && vc->vc_hi_font_mask) ++ set_vc_hi_font(vc, false); ++ + font_data_put(data); + + return ret; diff --git a/queue-7.1/fbdev-fix-fb_new_modelist-to-prevent-null-ptr-deref-in-fb_videomode_to_var.patch b/queue-7.1/fbdev-fix-fb_new_modelist-to-prevent-null-ptr-deref-in-fb_videomode_to_var.patch new file mode 100644 index 0000000000..2c6c5498a5 --- /dev/null +++ b/queue-7.1/fbdev-fix-fb_new_modelist-to-prevent-null-ptr-deref-in-fb_videomode_to_var.patch @@ -0,0 +1,59 @@ +From 7f08fc10fa3d3366dc3af723970bd03d7d6d10e3 Mon Sep 17 00:00:00 2001 +From: Ian Bridges +Date: Wed, 24 Jun 2026 23:13:12 -0500 +Subject: fbdev: Fix fb_new_modelist to prevent null-ptr-deref in fb_videomode_to_var + +From: Ian Bridges + +commit 7f08fc10fa3d3366dc3af723970bd03d7d6d10e3 upstream. + +info->var, a framebuffer's current mode, is expected to have a matching +entry in info->modelist. var_to_display() relies on this and treats a +failed fb_match_mode() as "This should not happen". fb_set_var() keeps it +true by adding the mode to the list on every change, and +do_register_framebuffer() does the same at registration. + +store_modes() replaces the modelist from userspace. fb_new_modelist() +validates the new modes but does not check that info->var still has a +match. It relies on fbcon_new_modelist() to re-point consoles, but that +only handles consoles mapped to the framebuffer. With fbcon unbound there +are none, so info->var is left describing a mode that is no longer in the +list. + +A later console takeover runs var_to_display(), where fb_match_mode() +returns NULL and leaves fb_display[i].mode NULL. fbcon_switch() passes it +to display_to_var(), and fb_videomode_to_var() dereferences the NULL mode. + +Keep the current mode in the list in fb_new_modelist(), the same way +fb_set_var() does. + +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Ian Bridges +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/fbmem.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -734,6 +734,18 @@ int fb_new_modelist(struct fb_info *info + if (list_empty(&info->modelist)) + return 1; + ++ /* ++ * The new modelist may not contain the current mode (info->var), and ++ * fbcon_new_modelist() below only re-points consoles mapped to this ++ * framebuffer. Add the current mode here so info->var keeps a match ++ * even when fbcon is unbound. ++ */ ++ if (!fb_match_mode(&info->var, &info->modelist)) { ++ fb_var_to_videomode(&mode, &info->var); ++ if (fb_add_videomode(&mode, &info->modelist)) ++ return 1; ++ } ++ + fbcon_new_modelist(info); + + return 0; diff --git a/queue-7.1/fbdev-modedb-fix-a-possible-uaf-in-fb_find_mode.patch b/queue-7.1/fbdev-modedb-fix-a-possible-uaf-in-fb_find_mode.patch new file mode 100644 index 0000000000..a350830dd2 --- /dev/null +++ b/queue-7.1/fbdev-modedb-fix-a-possible-uaf-in-fb_find_mode.patch @@ -0,0 +1,61 @@ +From 85b6256469cebdac395e7447147e06b2e151014f Mon Sep 17 00:00:00 2001 +From: Tuo Li +Date: Wed, 10 Jun 2026 10:50:14 +0800 +Subject: fbdev: modedb: fix a possible UAF in fb_find_mode() + +From: Tuo Li + +commit 85b6256469cebdac395e7447147e06b2e151014f upstream. + +If mode_option is NULL, it is assigned from mode_option_buf: + + if (!mode_option) { + fb_get_options(NULL, &mode_option_buf); + mode_option = mode_option_buf; + } + +Later, name is assigned from mode_option: + + const char *name = mode_option; + +However, mode_option_buf is freed before name is no longer used: + + kfree(mode_option_buf); + +while name is still accessed by: + + if ((name_matches(db[i], name, namelen) || + +Since name aliases mode_option_buf, this may result in a +use-after-free. + +Fix this by extending the lifetime of mode_option_buf until the end of the +function by using scope-based resource management for cleanup. + +Signed-off-by: Tuo Li +Cc: stable@vger.kernel.org # v6.5+ +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/modedb.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/video/fbdev/core/modedb.c ++++ b/drivers/video/fbdev/core/modedb.c +@@ -626,7 +626,7 @@ int fb_find_mode(struct fb_var_screeninf + const struct fb_videomode *default_mode, + unsigned int default_bpp) + { +- char *mode_option_buf = NULL; ++ char *mode_option_buf __free(kfree) = NULL; + int i; + + /* Set up defaults */ +@@ -724,7 +724,6 @@ int fb_find_mode(struct fb_var_screeninf + res_specified = 1; + } + done: +- kfree(mode_option_buf); + if (cvt) { + struct fb_videomode cvt_mode; + int ret; diff --git a/queue-7.1/fbdev-modedb-fix-misaligned-fields-in-the-1920x1080-60-mode.patch b/queue-7.1/fbdev-modedb-fix-misaligned-fields-in-the-1920x1080-60-mode.patch new file mode 100644 index 0000000000..3815c0fb55 --- /dev/null +++ b/queue-7.1/fbdev-modedb-fix-misaligned-fields-in-the-1920x1080-60-mode.patch @@ -0,0 +1,46 @@ +From d894c48a57d78206e4df9c90d4acfaf39394806a Mon Sep 17 00:00:00 2001 +From: Steffen Persvold +Date: Fri, 12 Jun 2026 18:40:41 +0200 +Subject: fbdev: modedb: Fix misaligned fields in the 1920x1080-60 mode + +From: Steffen Persvold + +commit d894c48a57d78206e4df9c90d4acfaf39394806a upstream. + +The 1920x1080@60 modedb entry has one too many initializers before +its sync field: a stray "0" occupies the sync slot, which shifts the +remaining values by one field. The entry therefore decodes as +sync = 0, vmode = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT (0x3, +i.e. FB_VMODE_INTERLACED | FB_VMODE_DOUBLE), and flag = +FB_VMODE_NONINTERLACED, instead of the intended sync = positive H/V, +vmode = non-interlaced. + +fb_find_mode() then returns a 1920x1080 mode flagged as interlaced + +doublescan with active-low syncs. Drivers that honour var->vmode and +var->sync when programming display timing enable doublescan and the +wrong sync polarity, corrupting the output. + +Drop the stray initializer so sync and vmode hold their intended +values (positive H/V sync, non-interlaced), matching the adjacent +1920x1200 entry. + +Fixes: c8902258b2b8 ("fbdev: modedb: Add 1920x1080 at 60 Hz video mode") +Cc: stable@vger.kernel.org +Signed-off-by: Steffen Persvold +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/modedb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/video/fbdev/core/modedb.c ++++ b/drivers/video/fbdev/core/modedb.c +@@ -259,7 +259,7 @@ static const struct fb_videomode modedb[ + FB_VMODE_DOUBLE }, + + /* 1920x1080 @ 60 Hz, 67.3 kHz hsync */ +- { NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5, 0, ++ { NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED }, + diff --git a/queue-7.1/fbdev-omap2-fix-use-after-free-in-omapfb_mmap.patch b/queue-7.1/fbdev-omap2-fix-use-after-free-in-omapfb_mmap.patch new file mode 100644 index 0000000000..daefee3510 --- /dev/null +++ b/queue-7.1/fbdev-omap2-fix-use-after-free-in-omapfb_mmap.patch @@ -0,0 +1,74 @@ +From 7958e67375aa111522086286bba13cfc0816ce8d Mon Sep 17 00:00:00 2001 +From: Hongling Zeng +Date: Tue, 2 Jun 2026 16:54:21 +0800 +Subject: fbdev: omap2: fix use-after-free in omapfb_mmap + +From: Hongling Zeng + +commit 7958e67375aa111522086286bba13cfc0816ce8d upstream. + +omapfb_mmap() has a race condition with OMAPFB_SETUP_PLANE ioctl that +can lead to use-after-free: + +The fb_mmap() entry point holds mm_lock but not lock (fb_info->lock), +while ioctl handlers like OMAPFB_SETUP_PLANE hold lock but not mm_lock. +This allows concurrent execution. + +In omapfb_mmap(): +1. rg = omapfb_get_mem_region(ofbi->region); // Get old region ref +2. start = omapfb_get_region_paddr(ofbi); // Read from NEW region +3. len = fix->smem_len; // Read from NEW region +4. vm_iomap_memory(vma, start, len); // Map NEW region memory +5. atomic_inc(&rg->map_count); // Increment OLD region! + +Concurrently, OMAPFB_SETUP_PLANE can: +- Reassign ofbi->region = new_rg +- Update fix->smem_len +- OMAPFB_SETUP_MEM then checks NEW region's map_count (0!) and frees it + +This leaves userspace with a mapping to freed physical memory. + +The fix is to read all required values (start, len) from the same +region reference (rg) that will have its map_count incremented, +preventing the region from being freed while still mapped. + +Cc: stable@vger.kernel.org +Signed-off-by: Hongling Zeng +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/omap2/omapfb/omapfb-main.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c ++++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c +@@ -1099,7 +1099,11 @@ static int omapfb_mmap(struct fb_info *f + + rg = omapfb_get_mem_region(ofbi->region); + +- start = omapfb_get_region_paddr(ofbi); ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ start = rg->vrfb.paddr[0]; ++ else ++ start = rg->paddr; ++ + len = fix->smem_len; + + DBG("user mmap region start %lx, len %d, off %lx\n", start, len, +@@ -1109,6 +1113,8 @@ static int omapfb_mmap(struct fb_info *f + vma->vm_ops = &mmap_user_ops; + vma->vm_private_data = rg; + ++ atomic_inc(&rg->map_count); ++ + r = vm_iomap_memory(vma, start, len); + if (r) + goto error; +@@ -1121,6 +1127,7 @@ static int omapfb_mmap(struct fb_info *f + return 0; + + error: ++ atomic_dec(&rg->map_count); + omapfb_put_mem_region(rg); + + return r; diff --git a/queue-7.1/fpga-region-fix-use-after-free-in-child_regions_with_firmware.patch b/queue-7.1/fpga-region-fix-use-after-free-in-child_regions_with_firmware.patch new file mode 100644 index 0000000000..e5b52c912f --- /dev/null +++ b/queue-7.1/fpga-region-fix-use-after-free-in-child_regions_with_firmware.patch @@ -0,0 +1,39 @@ +From 54f3c5643ec523a04b6ec0e7c19eb10f5ebebdd3 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Wed, 8 Apr 2026 15:45:34 +0000 +Subject: fpga: region: fix use-after-free in child_regions_with_firmware() + +From: Wentao Liang + +commit 54f3c5643ec523a04b6ec0e7c19eb10f5ebebdd3 upstream. + +Move of_node_put(child_region) after the error print to avoid accessing +freed memory when pr_err() references child_region. + +Fixes: 0fa20cdfcc1f ("fpga: fpga-region: device tree control for FPGA") +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Liang +[ Yilun: Fix the Fixes tag ] +Reviewed-by: Xu Yilun +Link: https://lore.kernel.org/r/20260408154534.404327-1-vulab@iscas.ac.cn +Signed-off-by: Xu Yilun +Signed-off-by: Greg Kroah-Hartman +--- + drivers/fpga/of-fpga-region.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/fpga/of-fpga-region.c ++++ b/drivers/fpga/of-fpga-region.c +@@ -168,11 +168,10 @@ static int child_regions_with_firmware(s + fpga_region_of_match); + } + +- of_node_put(child_region); +- + if (ret) + pr_err("firmware-name not allowed in child FPGA region: %pOF", + child_region); ++ of_node_put(child_region); + + return ret; + } diff --git a/queue-7.1/gfs2-fix-use-after-free-in-gfs2_qd_dealloc.patch b/queue-7.1/gfs2-fix-use-after-free-in-gfs2_qd_dealloc.patch new file mode 100644 index 0000000000..50b58437d6 --- /dev/null +++ b/queue-7.1/gfs2-fix-use-after-free-in-gfs2_qd_dealloc.patch @@ -0,0 +1,48 @@ +From f9c9ec2c319f843b70ecdf939d48b52d189bc081 Mon Sep 17 00:00:00 2001 +From: Tristan Madani +Date: Fri, 1 May 2026 11:02:03 +0000 +Subject: gfs2: fix use-after-free in gfs2_qd_dealloc + +From: Tristan Madani + +commit f9c9ec2c319f843b70ecdf939d48b52d189bc081 upstream. + +gfs2_qd_dealloc(), called as an RCU callback from gfs2_qd_dispose(), +accesses the superblock object sdp through qd->qd_sbd after freeing qd. +It does so to decrement sd_quota_count and wake up sd_kill_wait. + +However, by the time the RCU callback runs, gfs2_put_super() may have +already freed sdp via free_sbd(). This can happen when +gfs2_quota_cleanup() is called during unmount: it disposes of quota +objects via call_rcu() and then waits on sd_kill_wait with a 60-second +timeout. If the timeout expires, or if gfs2_gl_hash_clear() triggers +additional qd_put() calls that schedule more RCU callbacks after the +wait completes, gfs2_put_super() will proceed to free the superblock +while RCU callbacks referencing it are still pending. + +Add an rcu_barrier() before free_sbd() in gfs2_put_super() to ensure +all pending RCU callbacks (including gfs2_qd_dealloc) have completed +before the superblock is freed. + +Fixes: a475c5dd16e5 ("gfs2: Free quota data objects synchronously") +Reported-by: syzbot+42a37bf8045847d8f9d2@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=42a37bf8045847d8f9d2 +Tested-by: syzbot+42a37bf8045847d8f9d2@syzkaller.appspotmail.com +Cc: stable@vger.kernel.org +Signed-off-by: Tristan Madani +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/super.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -643,6 +643,7 @@ restart: + gfs2_delete_debugfs_file(sdp); + + gfs2_sys_fs_del(sdp); ++ rcu_barrier(); + free_sbd(sdp); + } + diff --git a/queue-7.1/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch b/queue-7.1/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch new file mode 100644 index 0000000000..ed1a06d625 --- /dev/null +++ b/queue-7.1/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch @@ -0,0 +1,109 @@ +From c78a4e41ab5ead6193ad8a2dd92e8906bae659fa Mon Sep 17 00:00:00 2001 +From: Fan Wu +Date: Wed, 17 Jun 2026 02:05:18 +0000 +Subject: hdlc_ppp: sync per-proto timers before freeing hdlc state + +From: Fan Wu + +commit c78a4e41ab5ead6193ad8a2dd92e8906bae659fa upstream. + +Each PPP control protocol (LCP/IPCP/IPV6CP) embedded in struct ppp +registers a timer via timer_setup(). That struct ppp is the +hdlc->state allocation, which detach_hdlc_protocol() frees with kfree() +in both teardown paths: unregister_hdlc_device() and the re-attach inside +attach_hdlc_protocol(). + +The ppp proto never registered a .detach callback, so +detach_hdlc_protocol() performs no timer synchronization before the +kfree(). The only cancel, timer_delete(&proto->timer) in ppp_cp_event(), +is partial (it does not wait for a running callback) and only runs on the +->CLOSED transition; ppp_stop()/ppp_close() do not sync either. A +ppp_timer callback already executing (blocked on ppp->lock) survives the +kfree and then dereferences proto->state / ppp->lock in freed memory, +leading to a use-after-free. + +Fix this by adding a .detach helper that calls timer_shutdown_sync() on +every per-proto timer. detach_hdlc_protocol() invokes proto->detach(dev) +before kfree(hdlc->state), so timer_shutdown_sync() +now runs on both free paths. +timer_shutdown_sync() is used instead of timer_delete_sync() because the +keepalive path re-arms the timer through add_timer()/mod_timer() and +shutdown blocks any re-activation during teardown. + +Initialize the per-protocol timers in ppp_ioctl() when the protocol is +attached, and remove the now-redundant timer_setup() from ppp_start(), so +that the timers are initialized exactly once at attach time and +ppp_timer_release() never operates on uninitialized timer_list +structures. attach_hdlc_protocol() uses kmalloc() (not kzalloc), so +struct ppp's protos[i].timer is uninitialized garbage until the first +timer_setup(); without this init-at-attach, attaching the PPP protocol +without ever bringing the device up would leave timer_shutdown_sync() +operating on uninitialized memory in .detach. Moving the init out of +ppp_start() (which only runs on NETDEV_UP) into the attach path makes the +initialization unconditional and avoids initializing the same timer_list +twice. + +This bug was found by static analysis. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Fan Wu +Link: https://patch.msgid.link/20260617020518.116319-1-fanwu01@zju.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wan/hdlc_ppp.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/net/wan/hdlc_ppp.c ++++ b/drivers/net/wan/hdlc_ppp.c +@@ -619,7 +619,6 @@ static void ppp_start(struct net_device + struct proto *proto = &ppp->protos[i]; + + proto->dev = dev; +- timer_setup(&proto->timer, ppp_timer, 0); + proto->state = CLOSED; + } + ppp->protos[IDX_LCP].pid = PID_LCP; +@@ -639,6 +638,15 @@ static void ppp_close(struct net_device + ppp_tx_flush(); + } + ++static void ppp_timer_release(struct net_device *dev) ++{ ++ struct ppp *ppp = get_ppp(dev); ++ int i; ++ ++ for (i = 0; i < IDX_COUNT; i++) ++ timer_shutdown_sync(&ppp->protos[i].timer); ++} ++ + static struct hdlc_proto proto = { + .start = ppp_start, + .stop = ppp_stop, +@@ -647,6 +655,7 @@ static struct hdlc_proto proto = { + .ioctl = ppp_ioctl, + .netif_rx = ppp_rx, + .module = THIS_MODULE, ++ .detach = ppp_timer_release, + }; + + static const struct header_ops ppp_header_ops = { +@@ -657,7 +666,7 @@ static int ppp_ioctl(struct net_device * + { + hdlc_device *hdlc = dev_to_hdlc(dev); + struct ppp *ppp; +- int result; ++ int i, result; + + switch (ifs->type) { + case IF_GET_PROTO: +@@ -685,6 +694,8 @@ static int ppp_ioctl(struct net_device * + return result; + + ppp = get_ppp(dev); ++ for (i = 0; i < IDX_COUNT; i++) ++ timer_setup(&ppp->protos[i].timer, ppp_timer, 0); + spin_lock_init(&ppp->lock); + ppp->req_timeout = 2; + ppp->cr_retries = 10; diff --git a/queue-7.1/i2c-core-fix-adapter-registration-race.patch b/queue-7.1/i2c-core-fix-adapter-registration-race.patch new file mode 100644 index 0000000000..3800e57955 --- /dev/null +++ b/queue-7.1/i2c-core-fix-adapter-registration-race.patch @@ -0,0 +1,61 @@ +From ba14d7cf2fe7284610a29854bdff22b2537d3ce6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 11 May 2026 16:37:12 +0200 +Subject: i2c: core: fix adapter registration race + +From: Johan Hovold + +commit ba14d7cf2fe7284610a29854bdff22b2537d3ce6 upstream. + +Adapters can be looked up based on their id using i2c_get_adapter() +which takes a reference to the embedded struct device. + +Make sure that the adapter (including its struct device) has been +initialised before adding it to the IDR to avoid accessing uninitialised +data which could, for example, lead to NULL-pointer dereferences or +use-after-free. + +Note that the i2c-dev chardev, which is registered from a bus notifier, +currently uses i2c_get_adapter() so the adapter needs to be added to the +IDR before registration. + +Fixes: 6e13e6418418 ("i2c: Add i2c_add_numbered_adapter()") +Cc: stable@vger.kernel.org # 2.6.22 +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1569,6 +1569,10 @@ static int i2c_register_adapter(struct i + pm_suspend_ignore_children(&adap->dev, true); + pm_runtime_enable(&adap->dev); + ++ mutex_lock(&core_lock); ++ idr_replace(&i2c_adapter_idr, adap, adap->nr); ++ mutex_unlock(&core_lock); ++ + res = device_add(&adap->dev); + if (res) { + pr_err("adapter '%s': can't register device (%d)\n", adap->name, res); +@@ -1627,7 +1631,7 @@ static int __i2c_add_numbered_adapter(st + int id; + + mutex_lock(&core_lock); +- id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, GFP_KERNEL); ++ id = idr_alloc(&i2c_adapter_idr, NULL, adap->nr, adap->nr + 1, GFP_KERNEL); + mutex_unlock(&core_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; +@@ -1661,7 +1665,7 @@ int i2c_add_adapter(struct i2c_adapter * + } + + mutex_lock(&core_lock); +- id = idr_alloc(&i2c_adapter_idr, adapter, ++ id = idr_alloc(&i2c_adapter_idr, NULL, + __i2c_first_dynamic_bus_num, 0, GFP_KERNEL); + mutex_unlock(&core_lock); + if (WARN(id < 0, "couldn't get idr")) diff --git a/queue-7.1/irqchip-imgpdc-fix-resource-leak-add-missing-chained-handler-cleanup-on-remove.patch b/queue-7.1/irqchip-imgpdc-fix-resource-leak-add-missing-chained-handler-cleanup-on-remove.patch new file mode 100644 index 0000000000..95168655f8 --- /dev/null +++ b/queue-7.1/irqchip-imgpdc-fix-resource-leak-add-missing-chained-handler-cleanup-on-remove.patch @@ -0,0 +1,64 @@ +From 37738fdf2ab1e504d1c63ce5bc0aeb6452d8f057 Mon Sep 17 00:00:00 2001 +From: Qingshuang Fu +Date: Thu, 18 Jun 2026 10:13:52 +0800 +Subject: irqchip/imgpdc: Fix resource leak, add missing chained handler cleanup on remove + +From: Qingshuang Fu + +commit 37738fdf2ab1e504d1c63ce5bc0aeb6452d8f057 upstream. + +The driver allocates domain generic chips using +irq_alloc_domain_generic_chips() during probe and sets up chained +handlers using irq_set_chained_handler_and_data(). However, on driver +removal, the generic chips are not freed and the chained handlers are +not removed. + +The generic chips remain on the global gc_list and may later be accessed by +generic interrupt chip suspend, resume, or shutdown callbacks after the +driver has been removed, potentially resulting in a use-after-free and +kernel crash. + +The chained handlers that were installed in probe for peripheral and +syswake interrupts are also left dangling, which can lead to spurious +interrupts accessing freed memory. + +Fix these issues by: + + - Setting IRQ_DOMAIN_FLAG_DESTROY_GC flag in domain->flags, so the + core code automatically removes generic chips when irq_domain_remove() + is called + + - Clearing all chained handlers with NULL in pdc_intc_remove() + +Fixes: b6ef9161e43a ("irq-imgpdc: add ImgTec PDC irqchip driver") +Signed-off-by: Qingshuang Fu +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260618021352.661773-1-fffsqian@163.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/irqchip/irq-imgpdc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/irqchip/irq-imgpdc.c ++++ b/drivers/irqchip/irq-imgpdc.c +@@ -378,6 +378,7 @@ static int pdc_intc_probe(struct platfor + dev_err(&pdev->dev, "cannot add IRQ domain\n"); + return -ENOMEM; + } ++ priv->domain->flags |= IRQ_DOMAIN_FLAG_DESTROY_GC; + + /* + * Set up 2 generic irq chips with 2 chip types. +@@ -465,6 +466,11 @@ static void pdc_intc_remove(struct platf + { + struct pdc_intc_priv *priv = platform_get_drvdata(pdev); + ++ for (unsigned int i = 0; i < priv->nr_perips; ++i) ++ irq_set_chained_handler_and_data(priv->perip_irqs[i], NULL, NULL); ++ ++ irq_set_chained_handler_and_data(priv->syswake_irq, NULL, NULL); ++ + irq_domain_remove(priv->domain); + } + diff --git a/queue-7.1/ksmbd-fix-out-of-bounds-read-in-smb_check_perm_dacl.patch b/queue-7.1/ksmbd-fix-out-of-bounds-read-in-smb_check_perm_dacl.patch new file mode 100644 index 0000000000..eafeee729f --- /dev/null +++ b/queue-7.1/ksmbd-fix-out-of-bounds-read-in-smb_check_perm_dacl.patch @@ -0,0 +1,62 @@ +From 1ef06004ed4bd6d3ed8c840d9d1a376b66d4935b Mon Sep 17 00:00:00 2001 +From: Hem Parekh +Date: Tue, 2 Jun 2026 16:56:46 -0700 +Subject: ksmbd: fix out-of-bounds read in smb_check_perm_dacl() + +From: Hem Parekh + +commit 1ef06004ed4bd6d3ed8c840d9d1a376b66d4935b upstream. + +The permission-check ACE walk in smb_check_perm_dacl() validates the ACE +header size and caps sid.num_subauth at SID_MAX_SUB_AUTHORITIES, but it +never checks that ace->size is actually large enough to contain +num_subauth sub-authorities before compare_sids() dereferences them. + +CIFS_SID_BASE_SIZE covers the SID header up to but excluding the +sub_auth[] array, and offsetof(struct smb_ace, sid) is the ACE header, +so the existing guards only guarantee the 8-byte SID base, i.e. zero +sub-authorities. compare_sids() then reads ace->sid.sub_auth[i] for +i < min(local_sid->num_subauth, ace->sid.num_subauth). The local +comparison SIDs (sid_everyone, sid_unix_NFS_mode, and the id_to_sid() +result) always have at least one sub-authority, and an attacker controls +the ACE revision and authority bytes (which lie within the in-bounds SID +base), so they can match one of those SIDs and force the sub_auth read. + +A crafted ACE with size == 16 and num_subauth >= 1 placed at the tail of +the security descriptor therefore causes a heap out-of-bounds read of up +to SID_MAX_SUB_AUTHORITIES * sizeof(__le32) bytes past the pntsd +allocation. The security descriptor is loaded by ksmbd_vfs_get_sd_xattr() +into a buffer sized exactly to the on-disk data (kzalloc(sd_size) in +ndr_decode_v4_ntacl()), so the read lands past the allocation. The +malformed descriptor can be stored verbatim via SMB2_SET_INFO (the DACL +is not normalised before being written to the security.NTACL xattr) and +the read fires on a subsequent SMB2_CREATE access check, making this +reachable by an authenticated client on a share that uses ACL xattrs. + +Add the missing num_subauth-versus-ace_size check, mirroring the +identical guards already present in the sibling parsers parse_dacl() and +smb_inherit_dacl(). + +Fixes: d07b26f39246 ("ksmbd: require minimum ACE size in smb_check_perm_dacl()") +Cc: stable@vger.kernel.org +Signed-off-by: Hem Parekh +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smbacl.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/smb/server/smbacl.c ++++ b/fs/smb/server/smbacl.c +@@ -1477,7 +1477,9 @@ int smb_check_perm_dacl(struct ksmbd_con + break; + aces_size -= ace_size; + +- if (ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES) ++ if (ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || ++ ace_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE + ++ sizeof(__le32) * ace->sid.num_subauth) + break; + + if (!compare_sids(&sid, &ace->sid) || diff --git a/queue-7.1/kvm-svm-fix-page-overflow-in-sev_dbg_crypt-for-encrypt-path.patch b/queue-7.1/kvm-svm-fix-page-overflow-in-sev_dbg_crypt-for-encrypt-path.patch new file mode 100644 index 0000000000..0715644726 --- /dev/null +++ b/queue-7.1/kvm-svm-fix-page-overflow-in-sev_dbg_crypt-for-encrypt-path.patch @@ -0,0 +1,93 @@ +From 78ee2d50185a037b3d2452a97f3dad69c3f7f389 Mon Sep 17 00:00:00 2001 +From: Ashutosh Desai +Date: Fri, 1 May 2026 13:35:32 -0700 +Subject: KVM: SVM: Fix page overflow in sev_dbg_crypt() for ENCRYPT path + +From: Ashutosh Desai + +commit 78ee2d50185a037b3d2452a97f3dad69c3f7f389 upstream. + +In sev_dbg_crypt(), the per-iteration transfer length is bounded by +the source page offset (PAGE_SIZE - s_off) but not by the destination +page offset (PAGE_SIZE - d_off). When d_off > s_off, the encrypt +path (__sev_dbg_encrypt_user) performs a read-modify-write using a +single-page intermediate buffer (dst_tpage): + + 1. __sev_dbg_decrypt() expands the size to round_up(len + (d_off & 15), 16) + before issuing the PSP command. If len + (d_off & 15) > PAGE_SIZE, + the PSP writes beyond the end of the 4096-byte dst_tpage allocation. + + 2. The subsequent memcpy()/copy_from_user() into + page_address(dst_tpage) + (d_off & 15) of 'len' bytes overflows + by up to 15 bytes under the same condition. + +Trigger example: s_off = 0, d_off = 1, debug.len = PAGE_SIZE - +the PSP is instructed to write round_up(4097, 16) = 4112 bytes to +a 4096-byte buffer. + +Fix by also bounding len by (PAGE_SIZE - d_off), the same check that +sev_send_update_data() already performs for its single-page guest +region. + + ================================================================== + BUG: KASAN: slab-use-after-free in sev_dbg_crypt+0x993/0xd10 [kvm_amd] + Write of size 4095 at addr ff110062293bb009 by task sev_dbg_test/228214 + + CPU: 96 UID: 0 PID: 228214 Comm: sev_dbg_test Tainted: G U W 7.0.0-smp--5ce9b0c48211-dbg #156 PREEMPTLAZY + Tainted: [U]=USER, [W]=WARN + Hardware name: Google Astoria/astoria, BIOS 0.20250817.1-0 08/25/2025 + Call Trace: + + dump_stack_lvl+0x54/0x70 + print_report+0xbc/0x260 + kasan_report+0xa2/0xd0 + kasan_check_range+0x25f/0x2c0 + __asan_memcpy+0x40/0x70 + sev_dbg_crypt+0x993/0xd10 [kvm_amd] + sev_mem_enc_ioctl+0x33c/0x450 [kvm_amd] + kvm_vm_ioctl+0x65d/0x6d0 [kvm] + __se_sys_ioctl+0xb2/0x100 + do_syscall_64+0xe8/0x870 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + + + The buggy address belongs to the physical page: + page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x7fe72b6a0 pfn:0x62293bb + memcg:ff11000112827d82 + flags: 0x1400000000000000(node=1|zone=1) + raw: 1400000000000000 0000000000000000 dead000000000122 0000000000000000 + raw: 00000007fe72b6a0 0000000000000000 00000001ffffffff ff11000112827d82 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ff110062293bbf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ff110062293bbf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ff110062293bc000: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc + ^ + ff110062293bc080: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc + ff110062293bc100: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc + ================================================================== + Disabling lock debugging due to kernel taint + +Fixes: 24f41fb23a39 ("KVM: SVM: Add support for SEV DEBUG_DECRYPT command") +Fixes: 7d1594f5d94b ("KVM: SVM: Add support for SEV DEBUG_ENCRYPT command") +Cc: stable@vger.kernel.org +Signed-off-by: Ashutosh Desai +[sean: add sample KASAN splat, Fixes, and stable@] +Link: https://patch.msgid.link/20260501203537.2120074-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/sev.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/kvm/svm/sev.c ++++ b/arch/x86/kvm/svm/sev.c +@@ -1396,6 +1396,7 @@ static int sev_dbg_crypt(struct kvm *kvm + s_off = vaddr & ~PAGE_MASK; + d_off = dst_vaddr & ~PAGE_MASK; + len = min_t(size_t, (PAGE_SIZE - s_off), size); ++ len = min_t(size_t, len, PAGE_SIZE - d_off); + + if (dec) + ret = __sev_dbg_decrypt_user(kvm, diff --git a/queue-7.1/kvm-x86-hyper-v-bound-the-bank-index-when-querying-sparse-banks.patch b/queue-7.1/kvm-x86-hyper-v-bound-the-bank-index-when-querying-sparse-banks.patch new file mode 100644 index 0000000000..07dbcd898e --- /dev/null +++ b/queue-7.1/kvm-x86-hyper-v-bound-the-bank-index-when-querying-sparse-banks.patch @@ -0,0 +1,91 @@ +From 4721f8160f17554b003e8928bb61e6c9b2fe92a3 Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Sat, 6 Jun 2026 23:44:52 +0900 +Subject: KVM: x86: hyper-v: Bound the bank index when querying sparse banks + +From: Hyunwoo Kim + +commit 4721f8160f17554b003e8928bb61e6c9b2fe92a3 upstream. + +When checking if a VP ID is included in a sparse bank set, explicitly check +that the ID can actually be contained in a sparse bank (the TLFS allows for +a maximum of 64 banks of 64 vCPUs each). When handling a paravirtual TLB +flush for L2, the VP ID is copied verbatim from the enlightened VMCS, +without any bounds check, i.e. isn't guaranteed to be under the limit of +4096. + +Failure to check the bounds of the VP ID leads to an out-of-bounds read +when testing the sparse bank, and super strictly speaking could lead to KVM +performing an unnecessary TLB flush for an L2 vCPU. + + ================================================================== + BUG: KASAN: use-after-free in hv_is_vp_in_sparse_set+0x85/0x100 [kvm] + Read of size 8 at addr ffff88811ba5f598 by task hyperv_evmcs/2802 + + CPU: 12 UID: 1000 PID: 2802 Comm: hyperv_evmcs Not tainted 7.1.0-rc2 #7 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + Call Trace: + + dump_stack_lvl+0x51/0x60 + print_report+0xcb/0x5d0 + kasan_report+0xb4/0xe0 + kasan_check_range+0x35/0x1b0 + hv_is_vp_in_sparse_set+0x85/0x100 [kvm] + kvm_hv_flush_tlb+0xe9e/0x16c0 [kvm] + kvm_hv_hypercall+0xe6b/0x1e60 [kvm] + vmx_handle_exit+0x485/0x1b60 [kvm_intel] + kvm_arch_vcpu_ioctl_run+0x22e3/0x5070 [kvm] + kvm_vcpu_ioctl+0x5d0/0x10c0 [kvm] + __x64_sys_ioctl+0x129/0x1a0 + do_syscall_64+0xb9/0xcf0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + RIP: 0033:0x7f0e62d1a9bf + + + The buggy address belongs to the physical page: + page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffffffffffffffff pfn:0x11ba5f + flags: 0x4000000000000000(zone=1) + raw: 4000000000000000 0000000000000000 00000000ffffffff 0000000000000000 + raw: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffff88811ba5f480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88811ba5f500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + >ffff88811ba5f580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ^ + ffff88811ba5f600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88811ba5f680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ================================================================== + Disabling lock debugging due to kernel taint + +Opportunistically add a compile time assertion to ensure the maximum number +of sparse banks exactly matches the number of possible bits in the passed +in mask. + +Cc: stable@vger.kernel.org +Fixes: c58a318f6090 ("KVM: x86: hyper-v: L2 TLB flush") +Signed-off-by: Hyunwoo Kim +Reviewed-by: Vitaly Kuznetsov +Link: https://patch.msgid.link/aiQyZIJtO-2Aj_xN@v4bel +[sean: add KASAN splat, drop comment, add assert, massage changelog] +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/hyperv.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -1839,6 +1839,11 @@ static bool hv_is_vp_in_sparse_set(u32 v + int valid_bit_nr = vp_id / HV_VCPUS_PER_SPARSE_BANK; + unsigned long sbank; + ++ BUILD_BUG_ON(BITS_PER_TYPE(valid_bank_mask) != HV_MAX_SPARSE_VCPU_BANKS); ++ ++ if (valid_bit_nr >= HV_MAX_SPARSE_VCPU_BANKS) ++ return false; ++ + if (!test_bit(valid_bit_nr, (unsigned long *)&valid_bank_mask)) + return false; + diff --git a/queue-7.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/queue-7.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..aea6abd667 --- /dev/null +++ b/queue-7.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,60 @@ +From f2539c56c74691e7a88af6372ba2b48c06ed2fe4 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Thu, 25 Jun 2026 13:03:49 +0800 +Subject: LoongArch: Report dying CPU to RCU in stop_this_cpu() + +From: Huacai Chen + +commit f2539c56c74691e7a88af6372ba2b48c06ed2fe4 upstream. + +This is a port of MIPS commit 9f3f3bdc6d9dac1 ("MIPS: smp: report dying +CPU to RCU in stop_this_cpu()"). smp_send_stop() parks all secondary +CPUs in stop_this_cpu(). And the function marks the CPU offline for the +scheduler via set_cpu_online(false) but never informs RCU, so RCU keeps +expecting a quiescent state from CPUs that are now spinning forever with +interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. However, since commit +91840be8f710370 ("irq_work: Fix use-after-free in irq_work_single() on +PREEMPT_RT"), irq_work_sync() calls synchronize_rcu() on architectures +without an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() +returns false. Any irq_work_sync() issued in the reboot/shutdown/halt +path after smp_send_stop() then blocks on a grace period that can never +complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue needs some hacks to reproduce, and it was not noticed on +LoongArch because arch_irq_work_has_interrupt() usually returns true. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring +the generic CPU-hotplug offline path, so RCU stops waiting on the parked +CPUs and grace periods can still complete. LoongArch shuts down all CPUs +here without going through the CPU-hotplug mechanism, so this report is +not otherwise issued. + +Cc: +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +Reviewed-by: Guo Ren +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kernel/smp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/loongarch/kernel/smp.c ++++ b/arch/loongarch/kernel/smp.c +@@ -705,6 +705,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcutree_report_cpu_dead(); + while (true); + } + diff --git a/queue-7.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/queue-7.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..a58903208f --- /dev/null +++ b/queue-7.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,71 @@ +From 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Mon, 8 Jun 2026 09:37:29 +0000 +Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu() + +From: Jonas Jelonek + +commit 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 upstream. + +smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function +marks the CPU offline for the scheduler via set_cpu_online(false) but +never informs RCU, so RCU keeps expecting a quiescent state from CPUs +that are now spinning forever with interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. Since commit +91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +however, irq_work_sync() calls synchronize_rcu() on architectures without +an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns +false. That is the asm-generic default used by MIPS. Any irq_work_sync() +issued in the reboot/shutdown path after smp_send_stop() then blocks on +a grace period that can never complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue was noticed on several Realtek MIPS switch SoCs (MIPS +interAptiv) and came up during kernel bump downstream in OpenWrt from +6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable +branch. The patch also has been backported all the way back to 6.1. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the +generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs +and grace periods can still complete. MIPS shuts down all CPUs here +without going through the CPU-hotplug mechanism, so this report is not +otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug +offline path is not unprecedented: arm64 does the same in cpu_die_early(). +There it is an exception for a CPU that was coming online and is aborting +bringup, rather than the default shutdown action as on MIPS. + +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +CC: stable@vger.kernel.org +Signed-off-by: Jonas Jelonek +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kernel/smp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcutree_report_cpu_dead(); + while (1); + } + diff --git a/queue-7.1/nfs-prevent-resource-leak-in-nfs_alloc_server.patch b/queue-7.1/nfs-prevent-resource-leak-in-nfs_alloc_server.patch new file mode 100644 index 0000000000..41481d80db --- /dev/null +++ b/queue-7.1/nfs-prevent-resource-leak-in-nfs_alloc_server.patch @@ -0,0 +1,33 @@ +From d189f224308c8ac3feeea8e442c99922bd18f1b2 Mon Sep 17 00:00:00 2001 +From: Markus Elfring +Date: Sun, 14 Jun 2026 09:56:35 +0200 +Subject: NFS: Prevent resource leak in nfs_alloc_server() + +From: Markus Elfring + +commit d189f224308c8ac3feeea8e442c99922bd18f1b2 upstream. + +It was overlooked to call ida_free() after a failed nfs_alloc_iostats() call. +Thus add the missed function call in an if branch. + +Fixes: 1c7251187dc067a6d460cf33ca67da9c1dd87807 ("NFS: add superblock sysfs entries") +Cc: stable@vger.kernel.org +Reported-by: Christophe Jaillet +Closes: https://lore.kernel.org/linux-nfs/1c8e10c9-def7-4f0d-8aa1-23c8035a38c8@wanadoo.fr/ +Signed-off-by: Markus Elfring +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/nfs/client.c ++++ b/fs/nfs/client.c +@@ -1074,6 +1074,7 @@ struct nfs_server *nfs_alloc_server(void + + server->io_stats = nfs_alloc_iostats(); + if (!server->io_stats) { ++ ida_free(&s_sysfs_ids, server->s_sysfs_id); + kfree(server); + return NULL; + } diff --git a/queue-7.1/nfsd-avoid-leaking-pre-allocated-openowner-on-unconfirmed-retry-race.patch b/queue-7.1/nfsd-avoid-leaking-pre-allocated-openowner-on-unconfirmed-retry-race.patch new file mode 100644 index 0000000000..d487aaf567 --- /dev/null +++ b/queue-7.1/nfsd-avoid-leaking-pre-allocated-openowner-on-unconfirmed-retry-race.patch @@ -0,0 +1,46 @@ +From 57aee7a35bb12753057c5b65d72d1f46c0e95b07 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Fri, 22 May 2026 10:36:14 -0400 +Subject: nfsd: avoid leaking pre-allocated openowner on unconfirmed retry race + +From: Jeff Layton + +commit 57aee7a35bb12753057c5b65d72d1f46c0e95b07 upstream. + +When find_or_alloc_open_stateowner() encounters an unconfirmed owner, it +calls release_openowner() and sets oo = NULL. Control then falls through +past the `if (oo)` guard -- which would have freed any pre-allocated +`new` -- and unconditionally executes `new = alloc_stateowner(...)`. If +`new` was already allocated on a prior iteration, the pointer is +silently overwritten and the previous allocation (slab object + owner +name buffer) is leaked. + +This requires a race: two NFSv4.0 OPEN threads with the same owner +string, where a concurrent thread inserts a new unconfirmed owner into +the hash between retry iterations. The window is narrow but repeatable +under adversarial conditions. + +Fix by adding `goto retry` after `oo = NULL` so the already-allocated +`new` is reused on the next iteration rather than overwritten. + +Reported-by: Chris Mason +Fixes: 23df17788c62 ("nfsd: perform all find_openstateowner_str calls in the one place.") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -5169,6 +5169,7 @@ retry: + /* Replace unconfirmed owners without checking for replay. */ + release_openowner(oo); + oo = NULL; ++ goto retry; + } + if (oo) { + if (new) diff --git a/queue-7.1/nfsd-check-get_user-return-when-reading-princhashlen.patch b/queue-7.1/nfsd-check-get_user-return-when-reading-princhashlen.patch new file mode 100644 index 0000000000..2c798dc142 --- /dev/null +++ b/queue-7.1/nfsd-check-get_user-return-when-reading-princhashlen.patch @@ -0,0 +1,47 @@ +From e186fa1c057f5eccb22afb1e83e34c0627085868 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dominik=20Wo=C5=BAniak?= +Date: Thu, 21 May 2026 17:46:56 +0200 +Subject: nfsd: check get_user() return when reading princhashlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dominik Woźniak + +commit e186fa1c057f5eccb22afb1e83e34c0627085868 upstream. + +In __cld_pipe_inprogress_downcall(), the get_user() that reads +princhashlen from the userspace cld_msg_v2 buffer does not check its +return value. A failing copy leaves princhashlen with uninitialised +stack contents, which are then used to drive memdup_user() and stored +as princhash.len on the resulting reclaim record. The other get_user() +calls in this function all check the return; only this one is missed, +which is most likely a copy-paste oversight from when v2 upcalls were +introduced. + +Mirror the existing pattern used a few lines above for namelen. +namecopy is declared with __free(kfree) so the early return cleans up +the already-allocated buffer automatically. + +Fixes: 6ee95d1c8991 ("nfsd: add support for upcall version 2") +Cc: stable@vger.kernel.org +Signed-off-by: Dominik Woźniak +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4recover.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -718,7 +718,8 @@ __cld_pipe_inprogress_downcall(const str + return PTR_ERR(namecopy); + name.data = namecopy; + name.len = namelen; +- get_user(princhashlen, &ci->cc_princhash.cp_len); ++ if (get_user(princhashlen, &ci->cc_princhash.cp_len)) ++ return -EFAULT; + if (princhashlen > 0) { + princhashcopy = memdup_user( + &ci->cc_princhash.cp_data, diff --git a/queue-7.1/nfsd-fix-dead-acl-conflict-guard-in-nfsd4_create.patch b/queue-7.1/nfsd-fix-dead-acl-conflict-guard-in-nfsd4_create.patch new file mode 100644 index 0000000000..7bf39c2b2f --- /dev/null +++ b/queue-7.1/nfsd-fix-dead-acl-conflict-guard-in-nfsd4_create.patch @@ -0,0 +1,49 @@ +From a60f25a800846ab8e5a13f8a9d05111f2aee55a7 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 21 May 2026 07:50:21 -0400 +Subject: nfsd: fix dead ACL conflict guard in nfsd4_create + +From: Jeff Layton + +commit a60f25a800846ab8e5a13f8a9d05111f2aee55a7 upstream. + +nfsd4_create() steals create->cr_dpacl/cr_pacl into the local +nfsd_attrs via the designated initializer, then immediately sets the +source pointers to NULL. The subsequent conflict guard tests the +already-nilled source fields, making it permanently dead code: + + if (create->cr_acl) { + if (create->cr_dpacl || create->cr_pacl) /* always false */ + +When a client encodes both FATTR4_WORD0_ACL and +FATTR4_WORD2_POSIX_{DEFAULT,ACCESS}_ACL in the same CREATE fattr +bitmap, nfsd4_acl_to_attr() overwrites attrs.na_pacl/na_dpacl without +releasing the originals, leaking two posix_acl slab objects per +request. Repeated requests cause unbounded slab exhaustion. + +Fix by checking attrs.na_dpacl/na_pacl (the stolen values) instead of +the nilled create->cr_dpacl/cr_pacl, matching the correct pattern +already used in nfsd4_setattr(). + +Reported-by: Chris Mason +Assisted-by: kres:claude-opus-4-6 +Fixes: d2ca50606f5f ("NFSD: Add support for POSIX draft ACLs for file creation") +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -840,7 +840,7 @@ nfsd4_create(struct svc_rqst *rqstp, str + goto out_aftermask; + + if (create->cr_acl) { +- if (create->cr_dpacl || create->cr_pacl) { ++ if (attrs.na_dpacl || attrs.na_pacl) { + status = nfserr_inval; + goto out_aftermask; + } diff --git a/queue-7.1/nfsd-fix-inverted-cp_ttl-check-in-async-copy-reaper.patch b/queue-7.1/nfsd-fix-inverted-cp_ttl-check-in-async-copy-reaper.patch new file mode 100644 index 0000000000..258c9afc6b --- /dev/null +++ b/queue-7.1/nfsd-fix-inverted-cp_ttl-check-in-async-copy-reaper.patch @@ -0,0 +1,45 @@ +From 0150459b05490b88b7e7378a31550a9e07b5517c Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 21 May 2026 09:25:40 -0400 +Subject: nfsd: fix inverted cp_ttl check in async copy reaper + +From: Jeff Layton + +commit 0150459b05490b88b7e7378a31550a9e07b5517c upstream. + +nfsd4_async_copy_reaper() is supposed to keep completed async copy +state around for NFSD_COPY_INITIAL_TTL (10) laundromat ticks so +that OFFLOAD_STATUS can report the result, then reap the state once +the countdown expires. + +The TTL predicate is inverted: `if (--copy->cp_ttl)` is true while +ticks remain and false when the counter reaches zero. This causes +the copy to be reaped on the very first tick (cp_ttl goes from 10 +to 9, which is non-zero) instead of after all 10 ticks elapse. +Once reaped, OFFLOAD_STATUS returns NFS4ERR_BAD_STATEID because +the copy state has already been freed. + +Fix by negating the test so that cleanup runs when the TTL expires. + +Fixes: aa0ebd21df9c ("NFSD: Add nfsd4_copy time-to-live") +Cc: stable@vger.kernel.org +Reported-by: Chris Mason +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1470,7 +1470,7 @@ void nfsd4_async_copy_reaper(struct nfsd + list_for_each_safe(pos, next, &clp->async_copies) { + copy = list_entry(pos, struct nfsd4_copy, copies); + if (test_bit(NFSD4_COPY_F_OFFLOAD_DONE, ©->cp_flags)) { +- if (--copy->cp_ttl) { ++ if (!--copy->cp_ttl) { + list_del_init(©->copies); + list_add(©->copies, &reaplist); + } diff --git a/queue-7.1/nfsd-fix-posix_acl-leak-and-ignored-error-in-nfsd4_create_file.patch b/queue-7.1/nfsd-fix-posix_acl-leak-and-ignored-error-in-nfsd4_create_file.patch new file mode 100644 index 0000000000..ca105ca3fc --- /dev/null +++ b/queue-7.1/nfsd-fix-posix_acl-leak-and-ignored-error-in-nfsd4_create_file.patch @@ -0,0 +1,86 @@ +From 24c975bbdd564d7d0ad90294bfa69729830345de Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 21 May 2026 12:37:33 -0400 +Subject: nfsd: fix posix_acl leak and ignored error in nfsd4_create_file + +From: Jeff Layton + +commit 24c975bbdd564d7d0ad90294bfa69729830345de upstream. + +nfsd4_create_file() has two bugs in its ACL handling: + +The return value of nfsd4_acl_to_attr() is silently discarded. When +the NFSv4-to-POSIX ACL conversion fails (e.g., -EINVAL for +unsupported ACE types), the file is created without any ACL and the +client receives NFS4_OK. This violates RFC 7530/8881 which require +the server to reject unsupported attributes on CREATE. + +When start_creating() fails after ACL attributes have been populated +in attrs (either via nfsd4_acl_to_attr or via ownership transfer from +open->op_dpacl/op_pacl), the function jumps to out_write which skips +nfsd_attrs_free(). The posix_acl allocations are leaked. A client +can trigger this repeatedly with OPEN(CREATE), ACL attributes, and an +invalid filename (e.g., longer than NAME_MAX). + +Fix both by capturing the nfsd4_acl_to_attr() return value and by +changing the early error paths to jump to out instead of out_write. +Initialize child to ERR_PTR(-EINVAL) so that end_creating() is safe +to call even if start_creating() was never reached. + +Reported-by: Chris Mason +Fixes: 7ab96df840e6 ("VFS/nfsd/cachefiles/ovl: add start_creating() and end_creating()") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4proc.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -253,7 +253,7 @@ nfsd4_create_file(struct svc_rqst *rqstp + .na_iattr = iap, + .na_seclabel = &open->op_label, + }; +- struct dentry *parent, *child; ++ struct dentry *parent, *child = ERR_PTR(-EINVAL); + __u32 v_mtime, v_atime; + struct inode *inode; + __be32 status; +@@ -277,10 +277,14 @@ nfsd4_create_file(struct svc_rqst *rqstp + if (open->op_acl) { + if (open->op_dpacl || open->op_pacl) { + status = nfserr_inval; +- goto out_write; ++ goto out; ++ } ++ if (is_create_with_attrs(open)) { ++ status = nfsd4_acl_to_attr(NF4REG, open->op_acl, ++ &attrs); ++ if (status) ++ goto out; + } +- if (is_create_with_attrs(open)) +- nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs); + } else if (is_create_with_attrs(open)) { + /* The dpacl and pacl will get released by nfsd_attrs_free(). */ + attrs.na_dpacl = open->op_dpacl; +@@ -293,7 +297,7 @@ nfsd4_create_file(struct svc_rqst *rqstp + &QSTR_LEN(open->op_fname, open->op_fnamelen)); + if (IS_ERR(child)) { + status = nfserrno(PTR_ERR(child)); +- goto out_write; ++ goto out; + } + + if (d_really_is_negative(child)) { +@@ -407,7 +411,6 @@ set_attr: + out: + end_creating(child); + nfsd_attrs_free(&attrs); +-out_write: + fh_drop_write(fhp); + return status; + } diff --git a/queue-7.1/nfsd-fix-posix_acl-leak-on-setacl-decode-failure.patch b/queue-7.1/nfsd-fix-posix_acl-leak-on-setacl-decode-failure.patch new file mode 100644 index 0000000000..70d4cc5de7 --- /dev/null +++ b/queue-7.1/nfsd-fix-posix_acl-leak-on-setacl-decode-failure.patch @@ -0,0 +1,131 @@ +From 0853ac544c590880d797b04daa33fcb72b6be0e1 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 21 May 2026 13:51:43 -0400 +Subject: nfsd: fix posix_acl leak on SETACL decode failure + +From: Jeff Layton + +commit 0853ac544c590880d797b04daa33fcb72b6be0e1 upstream. + +nfsaclsvc_decode_setaclargs() and nfs3svc_decode_setaclargs() each +call nfs_stream_decode_acl() twice, first for NFS_ACL and then for +NFS_DFACL. Each successful call transfers ownership of a freshly +allocated posix_acl into argp->acl_access or argp->acl_default. If +the first call succeeds but the second fails, the decoder returns +false and argp->acl_access is left dangling. + +ACLPROC2_SETACL.pc_release was wired to nfssvc_release_attrstat and +ACLPROC3_SETACL.pc_release was wired to nfs3svc_release_fhandle. +Both only call fh_put() and have no knowledge of the ACL fields on +argp. The posix_acl_release() pairs sat at the out: labels inside +nfsacld_proc_setacl() and nfsd3_proc_setacl(), but svc_process() +skips pc_func when pc_decode returns false, so that cleanup is +unreachable on decode failure: + + svc_process_common() + pc_decode() /* decode_setaclargs: false */ + /* pc_func skipped */ + pc_release() /* fh_put only -- ACLs leaked */ + +The orphaned posix_acl is leaked for the lifetime of the server. + +Fix by adding nfsaclsvc_release_setacl() and nfs3svc_release_setacl(), +which release both argp->acl_access and argp->acl_default in addition +to fh_put(), and wiring them as pc_release for their respective SETACL +procedures. pc_release runs on every path svc_process() takes after +decode, including decode failure, so the posix_acl_release() pairs are +removed from the proc functions' out: labels to keep ownership in one +place. This matches the existing release_getacl() pattern used by +the sibling GETACL procedures. + +Fixes: a257cdd0e217 ("[PATCH] NFSD: Add server support for NFSv3 ACLs.") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-7 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs2acl.c | 17 ++++++++++++----- + fs/nfsd/nfs3acl.c | 17 ++++++++++++----- + 2 files changed, 24 insertions(+), 10 deletions(-) + +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -131,10 +131,7 @@ static __be32 nfsacld_proc_setacl(struct + resp->status = fh_getattr(fh, &resp->stat); + + out: +- /* argp->acl_{access,default} may have been allocated in +- nfssvc_decode_setaclargs. */ +- posix_acl_release(argp->acl_access); +- posix_acl_release(argp->acl_default); ++ /* argp->acl_{access,default} are released in nfsaclsvc_release_setacl. */ + return rpc_success; + + out_drop_lock: +@@ -310,6 +307,16 @@ static void nfsaclsvc_release_access(str + fh_put(&resp->fh); + } + ++static void nfsaclsvc_release_setacl(struct svc_rqst *rqstp) ++{ ++ struct nfsd3_setaclargs *argp = rqstp->rq_argp; ++ struct nfsd_attrstat *resp = rqstp->rq_resp; ++ ++ fh_put(&resp->fh); ++ posix_acl_release(argp->acl_access); ++ posix_acl_release(argp->acl_default); ++} ++ + #define ST 1 /* status*/ + #define AT 21 /* attributes */ + #define pAT (1+AT) /* post attributes - conditional */ +@@ -343,7 +350,7 @@ static const struct svc_procedure nfsd_a + .pc_func = nfsacld_proc_setacl, + .pc_decode = nfsaclsvc_decode_setaclargs, + .pc_encode = nfssvc_encode_attrstatres, +- .pc_release = nfssvc_release_attrstat, ++ .pc_release = nfsaclsvc_release_setacl, + .pc_argsize = sizeof(struct nfsd3_setaclargs), + .pc_argzero = sizeof(struct nfsd3_setaclargs), + .pc_ressize = sizeof(struct nfsd_attrstat), +--- a/fs/nfsd/nfs3acl.c ++++ b/fs/nfsd/nfs3acl.c +@@ -118,10 +118,7 @@ out_drop_lock: + out_errno: + resp->status = nfserrno(error); + out: +- /* argp->acl_{access,default} may have been allocated in +- nfs3svc_decode_setaclargs. */ +- posix_acl_release(argp->acl_access); +- posix_acl_release(argp->acl_default); ++ /* argp->acl_{access,default} are released in nfs3svc_release_setacl. */ + return rpc_success; + } + +@@ -223,6 +220,16 @@ static void nfs3svc_release_getacl(struc + posix_acl_release(resp->acl_default); + } + ++static void nfs3svc_release_setacl(struct svc_rqst *rqstp) ++{ ++ struct nfsd3_setaclargs *argp = rqstp->rq_argp; ++ struct nfsd3_attrstat *resp = rqstp->rq_resp; ++ ++ fh_put(&resp->fh); ++ posix_acl_release(argp->acl_access); ++ posix_acl_release(argp->acl_default); ++} ++ + #define ST 1 /* status*/ + #define AT 21 /* attributes */ + #define pAT (1+AT) /* post attributes - conditional */ +@@ -256,7 +263,7 @@ static const struct svc_procedure nfsd_a + .pc_func = nfsd3_proc_setacl, + .pc_decode = nfs3svc_decode_setaclargs, + .pc_encode = nfs3svc_encode_setaclres, +- .pc_release = nfs3svc_release_fhandle, ++ .pc_release = nfs3svc_release_setacl, + .pc_argsize = sizeof(struct nfsd3_setaclargs), + .pc_argzero = sizeof(struct nfsd3_setaclargs), + .pc_ressize = sizeof(struct nfsd3_attrstat), diff --git a/queue-7.1/nfsd-fix-secinfo_no_name-decode-error-cleanup.patch b/queue-7.1/nfsd-fix-secinfo_no_name-decode-error-cleanup.patch new file mode 100644 index 0000000000..08909b3d64 --- /dev/null +++ b/queue-7.1/nfsd-fix-secinfo_no_name-decode-error-cleanup.patch @@ -0,0 +1,48 @@ +From 9e18e83b8846a5c3fe13fc8a464b4865d33996c6 Mon Sep 17 00:00:00 2001 +From: Guannan Wang +Date: Thu, 21 May 2026 16:03:32 +0800 +Subject: NFSD: Fix SECINFO_NO_NAME decode error cleanup + +From: Guannan Wang + +commit 9e18e83b8846a5c3fe13fc8a464b4865d33996c6 upstream. + +nfsd4_decode_secinfo_no_name() currently initializes sin_exp after +decoding sin_style. If the XDR stream is truncated, the decoder returns +nfserr_bad_xdr before sin_exp is initialized. + +Since commit 3fdc54646234 ("NFSD: Reduce amount of struct +nfsd4_compoundargs that needs clearing"), the inline iops array is not +cleared between RPC calls. A failed SECINFO_NO_NAME decode can therefore +leave sin_exp holding stale union contents from a previous operation. + +The error response path still invokes nfsd4_secinfo_no_name_release(), +which calls exp_put() on a non-NULL sin_exp. + +Initialize sin_exp before the first failable decode step, matching +nfsd4_decode_secinfo(). + +Fixes: 3fdc54646234 ("NFSD: Reduce amount of struct nfsd4_compoundargs that needs clearing") +Cc: stable@vger.kernel.org +Signed-off-by: Guannan Wang +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4xdr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2008,10 +2008,11 @@ static __be32 nfsd4_decode_secinfo_no_na + union nfsd4_op_u *u) + { + struct nfsd4_secinfo_no_name *sin = &u->secinfo_no_name; ++ ++ sin->sin_exp = NULL; + if (xdr_stream_decode_u32(argp->xdr, &sin->sin_style) < 0) + return nfserr_bad_xdr; + +- sin->sin_exp = NULL; + return nfs_ok; + } + diff --git a/queue-7.1/nfsd-release-layout-stid-on-setlease-failure.patch b/queue-7.1/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..6eb5b4fabb --- /dev/null +++ b/queue-7.1/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,84 @@ +From 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 Mon Sep 17 00:00:00 2001 +From: Chris Mason +Date: Mon, 18 May 2026 13:16:36 -0700 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4layouts.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -264,10 +264,12 @@ nfsd4_alloc_layout_stateid(struct nfsd4_ + ls->ls_file = find_any_file(fp); + BUG_ON(!ls->ls_file); + ++ ls->ls_fenced = false; ++ ls->ls_fence_delay = 0; ++ INIT_DELAYED_WORK(&ls->ls_fence_work, nfsd4_layout_fence_worker); ++ + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +@@ -280,10 +282,6 @@ nfsd4_alloc_layout_stateid(struct nfsd4_ + list_add(&ls->ls_perfile, &fp->fi_lo_states); + spin_unlock(&fp->fi_lock); + +- ls->ls_fenced = false; +- ls->ls_fence_delay = 0; +- INIT_DELAYED_WORK(&ls->ls_fence_work, nfsd4_layout_fence_worker); +- + trace_nfsd_layoutstate_alloc(&ls->ls_stid.sc_stateid); + return ls; + } diff --git a/queue-7.1/nfsd-reset-write-verifier-on-deferred-writeback-errors.patch b/queue-7.1/nfsd-reset-write-verifier-on-deferred-writeback-errors.patch new file mode 100644 index 0000000000..16ba67ad58 --- /dev/null +++ b/queue-7.1/nfsd-reset-write-verifier-on-deferred-writeback-errors.patch @@ -0,0 +1,63 @@ +From 2090b05803faab8a9fa62fbff871007862cac1b7 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Fri, 22 May 2026 12:44:19 -0400 +Subject: nfsd: reset write verifier on deferred writeback errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton + +commit 2090b05803faab8a9fa62fbff871007862cac1b7 upstream. + +nfsd_vfs_write() and nfsd_commit() both call filemap_check_wb_err() to +detect deferred writeback errors, but neither rotates the server's write +verifier (nn->writeverf) when this check fails. Every other +durable-storage-failure path in these functions calls +commit_reset_write_verifier() before returning an error. + +The missing rotation means clients holding UNSTABLE write data under the +current verifier will COMMIT, receive the unchanged verifier back, and +conclude their data is durable — silently dropping data that failed +writeback. This violates the UNSTABLE+COMMIT durability contract +(RFC 1813 §3.3.7, RFC 8881 §18.32). + +Add commit_reset_write_verifier() calls at both filemap_check_wb_err() +error sites, matching the pattern used by adjacent error paths in the +same functions. The helper already filters -EAGAIN and -ESTALE +internally, so the calls are unconditionally safe. + +Reported-by: Chris Mason +Fixes: 555dbf1a9aac ("nfsd: Replace use of rwsem with errseq_t") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/vfs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1508,8 +1508,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s + nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); +- if (host_err < 0) ++ if (host_err < 0) { ++ commit_reset_write_verifier(nn, rqstp, host_err); + goto out_nfserr; ++ } + + if (stable && fhp->fh_use_wgather) { + host_err = wait_for_concurrent_writes(file); +@@ -1689,6 +1691,8 @@ nfsd_commit(struct svc_rqst *rqstp, stru + nfsd_copy_write_verifier(verf, nn); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); ++ if (err2 < 0) ++ commit_reset_write_verifier(nn, rqstp, err2); + err = nfserrno(err2); + break; + case -EINVAL: diff --git a/queue-7.1/nfsv4-clear-exception-state-on-successful-mkdir-retry.patch b/queue-7.1/nfsv4-clear-exception-state-on-successful-mkdir-retry.patch new file mode 100644 index 0000000000..24bae0f2c3 --- /dev/null +++ b/queue-7.1/nfsv4-clear-exception-state-on-successful-mkdir-retry.patch @@ -0,0 +1,82 @@ +From 238e9b51aa29f48b6243212a3b75c8e48d6b96fd Mon Sep 17 00:00:00 2001 +From: Igor Raits +Date: Wed, 29 Apr 2026 12:49:38 +0200 +Subject: NFSv4: clear exception state on successful mkdir retry +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Igor Raits + +commit 238e9b51aa29f48b6243212a3b75c8e48d6b96fd upstream. + +After a server returns NFS4ERR_DELAY for an NFSv4 CREATE issued by +mkdir(2), the client correctly waits and retries. When the retry +succeeds, however, mkdir(2) can still surface -EEXIST to userspace +even though the directory was just created on the server. + +Reproducer (random 16-hex names so collisions are not the cause) +against an in-kernel Linux nfsd; reproduces under both NFSv4.0 and +NFSv4.2: + + N=2000000; base=/var/gdc/export + for ((i=1; i<=N; i++)); do + d=$base/$(openssl rand -hex 8) + mkdir "$d" 2>/dev/null || echo "$(date +%T) failed loop=$i $d" + rmdir "$d" 2>/dev/null + done + +Failures cluster at the cadence at which the server-side auth/export +cache refresh path causes nfsd to return NFS4ERR_DELAY for CREATE. + +A wire trace of one failure (the three CREATE RPCs all come from a +single mkdir(2), generated by the do-while in nfs4_proc_mkdir()): + + client -> server CREATE name=... -> NFS4ERR_DELAY + ~100 ms later + client -> server CREATE name=... -> NFS4_OK (dir created) + ~80 us later + client -> server CREATE name=... -> NFS4ERR_EXIST (correct) + +Since commit dd862da61e91 ("nfs: fix incorrect handling of large-number +NFS errors in nfs4_do_mkdir()"), nfs4_handle_exception() is called only +when _nfs4_proc_mkdir() returned an error. That gate breaks retry-state +hygiene: nfs4_do_handle_exception() resets exception.{delay,recovering, +retry} to 0 on entry, so calling it on success is what previously +cleared the retry flag set by the preceding NFS4ERR_DELAY iteration. +With the gate in place, exception.retry stays at 1 after the successful +retry, the loop runs once more, and the resulting CREATE for an +already-created name yields NFS4ERR_EXIST -> -EEXIST to userspace. + +Drop the conditional and call nfs4_handle_exception() unconditionally, +matching every other do-while in fs/nfs/nfs4proc.c (nfs4_proc_symlink(), +nfs4_proc_link(), etc.). The dentry/status separation introduced by +that commit is preserved. + +Fixes: dd862da61e91 ("nfs: fix incorrect handling of large-number NFS errors in nfs4_do_mkdir()") +Reported-and-tested-by: Jan Čípa +Closes: https://lore.kernel.org/linux-nfs/CA+9S74hSp_tJu2Ffe2BPNC2T25gfkhgjjDkdgSsF5c2rnJq_wA@mail.gmail.com/ +Reviewed-by: NeilBrown +Cc: stable@vger.kernel.org +Signed-off-by: Igor Raits +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/nfs4proc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -5302,10 +5302,9 @@ static struct dentry *nfs4_proc_mkdir(st + do { + alias = _nfs4_proc_mkdir(dir, dentry, sattr, label, &err); + trace_nfs4_mkdir(dir, &dentry->d_name, err); ++ err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception); + if (err) +- alias = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), +- err, +- &exception)); ++ alias = ERR_PTR(err); + } while (exception.retry); + nfs4_label_release_security(label); + diff --git a/queue-7.1/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch b/queue-7.1/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch new file mode 100644 index 0000000000..da92ab7438 --- /dev/null +++ b/queue-7.1/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch @@ -0,0 +1,54 @@ +From 2c6bb3c40bc24f6aa8dfbe6fe98c3ad6389203f2 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Wed, 13 May 2026 12:26:56 -0400 +Subject: NFSv4/flexfiles: reject zero filehandle version count + +From: Michael Bommarito + +commit 2c6bb3c40bc24f6aa8dfbe6fe98c3ad6389203f2 upstream. + +ff_layout_alloc_lseg() decodes the filehandle-version array count +from the flexfiles layout body. The value is used as the count for +kzalloc_objs(), and the current code only rejects NULL. + +A zero count yields ZERO_SIZE_PTR, which can be stored in +dss_info->fh_versions even though later flexfiles paths assume that at +least one filehandle version exists. + +Reject fh_count == 0 before the allocation, matching the existing zero +version_count validation in the flexfiles GETDEVICEINFO parser. + +A QEMU/KASAN run with a malformed flexfiles layout hit: + + KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017] + RIP: 0010:ff_layout_encode_ff_layoutupdate.isra.0+0x15f/0x750 + ff_layout_encode_layoutreturn+0x683/0x970 + nfs4_xdr_enc_layoutreturn+0x278/0x3a0 + Kernel panic - not syncing: Fatal exception + +The patched kernel rejects the malformed layout without KASAN/oops/panic, +and a valid fh_count=1 regression still opens, reads, and unmounts cleanly. + +Cc: stable@vger.kernel.org +Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -551,6 +551,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_ + if (!p) + goto out_err_free; + fh_count = be32_to_cpup(p); ++ if (fh_count == 0) { ++ rc = -EINVAL; ++ goto out_err_free; ++ } + + dss_info->fh_versions = + kzalloc_objs(struct nfs_fh, fh_count, gfp_flags); diff --git a/queue-7.1/nfsv4-pnfs-reject-zero-length-r_addr-in-nfs4_decode_mp_ds_addr.patch b/queue-7.1/nfsv4-pnfs-reject-zero-length-r_addr-in-nfs4_decode_mp_ds_addr.patch new file mode 100644 index 0000000000..115979c157 --- /dev/null +++ b/queue-7.1/nfsv4-pnfs-reject-zero-length-r_addr-in-nfs4_decode_mp_ds_addr.patch @@ -0,0 +1,56 @@ +From 41fe0f7b84f0cb822ae10ab08592996a592b2a25 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Wed, 27 May 2026 12:30:35 -0400 +Subject: NFSv4/pNFS: reject zero-length r_addr in nfs4_decode_mp_ds_addr + +From: Michael Bommarito + +commit 41fe0f7b84f0cb822ae10ab08592996a592b2a25 upstream. + +nfs4_decode_mp_ds_addr() decodes the r_netid and r_addr opaques of a +netaddr4 from a GETDEVICEINFO multipath-DS body, then immediately +calls strrchr(buf, '.') to locate the port separator. Both decodes +use xdr_stream_decode_string_dup(), and the current code checks only +"nlen < 0" / "rlen < 0" before dereferencing the returned string. + +When the on-wire opaque has length zero, xdr_stream_decode_opaque_inline() +returns 0 and xdr_stream_decode_string_dup() falls through to its +"*str = NULL; return ret" tail, leaving buf NULL with a return value +of 0. The "< 0" check does not catch this, and the next line is +strrchr(NULL, '.'), a kernel NULL pointer dereference reachable from +any pNFS-flexfile client mounted against a malicious or compromised +metadata server. + +Reject the zero-length cases explicitly so the decoder fails with +-EBADMSG (treated as a malformed GETDEVICEINFO body) instead of +panicking the client. + +Cc: stable@vger.kernel.org +Fixes: 6b7f3cf96364 ("nfs41: pull decode_ds_addr from file layout to generic pnfs") +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/pnfs_nfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/nfs/pnfs_nfs.c ++++ b/fs/nfs/pnfs_nfs.c +@@ -1075,14 +1075,14 @@ nfs4_decode_mp_ds_addr(struct net *net, + /* r_netid */ + nlen = xdr_stream_decode_string_dup(xdr, &netid, XDR_MAX_NETOBJ, + gfp_flags); +- if (unlikely(nlen < 0)) ++ if (unlikely(nlen <= 0)) + goto out_err; + + /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */ + /* port is ".ABC.DEF", 8 chars max */ + rlen = xdr_stream_decode_string_dup(xdr, &buf, INET6_ADDRSTRLEN + + IPV6_SCOPE_ID_LEN + 8, gfp_flags); +- if (unlikely(rlen < 0)) ++ if (unlikely(rlen <= 0)) + goto out_free_netid; + + /* replace port '.' with '-' */ diff --git a/queue-7.1/ntfs-serialize-volume-label-accesses.patch b/queue-7.1/ntfs-serialize-volume-label-accesses.patch new file mode 100644 index 0000000000..bf7dd55830 --- /dev/null +++ b/queue-7.1/ntfs-serialize-volume-label-accesses.patch @@ -0,0 +1,110 @@ +From e9e50ce4f13dc721014af622613409455c734942 Mon Sep 17 00:00:00 2001 +From: Hyunchul Lee +Date: Tue, 2 Jun 2026 13:53:24 +0900 +Subject: ntfs: serialize volume label accesses + +From: Hyunchul Lee + +commit e9e50ce4f13dc721014af622613409455c734942 upstream. + +Protect vol->volume_label with a mutex and snaphost the label before +copy_to_user. This prevent a use-after-free when FS_IOC_SETFSLABEL +replaces the vol->volume_label and FS_IOC_GETTSLABEL reads it +concurrently. + +Cc: stable@vger.kernel.org # v7.1 +Signed-off-by: Hyunchul Lee +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs/file.c | 17 +++++++++++++---- + fs/ntfs/super.c | 19 +++++++++++++------ + fs/ntfs/volume.h | 2 ++ + 3 files changed, 28 insertions(+), 10 deletions(-) + +--- a/fs/ntfs/file.c ++++ b/fs/ntfs/file.c +@@ -707,12 +707,21 @@ static int ntfs_ioctl_get_volume_label(s + { + struct ntfs_volume *vol = NTFS_SB(file_inode(filp)->i_sb); + char __user *buf = (char __user *)arg; ++ char label[FSLABEL_MAX]; ++ ssize_t len; + ++ mutex_lock(&vol->volume_label_lock); + if (!vol->volume_label) { +- if (copy_to_user(buf, "", 1)) +- return -EFAULT; +- } else if (copy_to_user(buf, vol->volume_label, +- MIN(FSLABEL_MAX, strlen(vol->volume_label) + 1))) ++ label[0] = '\0'; ++ len = 0; ++ } else { ++ len = strscpy(label, vol->volume_label, sizeof(label)); ++ if (len == -E2BIG) ++ len = FSLABEL_MAX - 1; ++ } ++ mutex_unlock(&vol->volume_label_lock); ++ ++ if (copy_to_user(buf, label, len + 1)) + return -EFAULT; + return 0; + } +--- a/fs/ntfs/super.c ++++ b/fs/ntfs/super.c +@@ -460,17 +460,23 @@ int ntfs_write_volume_label(struct ntfs_ + ret = ntfs_resident_attr_record_add(vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0, + (u8 *)uname, uname_len * sizeof(__le16), 0); + out: +- mutex_unlock(&vol_ni->mrec_lock); +- kvfree(uname); +- + if (ret >= 0) { +- kfree(vol->volume_label); ++ char *old_label; ++ ++ mutex_lock(&vol->volume_label_lock); ++ old_label = vol->volume_label; + vol->volume_label = new_label; ++ mutex_unlock(&vol->volume_label_lock); ++ ++ kfree(old_label); + mark_inode_dirty_sync(vol->vol_ino); + ret = 0; +- } else { +- kfree(new_label); + } ++ mutex_unlock(&vol_ni->mrec_lock); ++ kvfree(uname); ++ ++ if (ret < 0) ++ kfree(new_label); + return ret; + } + +@@ -2631,6 +2637,7 @@ static int ntfs_init_fs_context(struct f + NVolSetCaseSensitive(vol); + init_rwsem(&vol->mftbmp_lock); + init_rwsem(&vol->lcnbmp_lock); ++ mutex_init(&vol->volume_label_lock); + + fc->s_fs_info = vol; + fc->ops = &ntfs_context_ops; +--- a/fs/ntfs/volume.h ++++ b/fs/ntfs/volume.h +@@ -72,6 +72,7 @@ + * @vol_flags: Volume flags. + * @major_ver: Ntfs major version of volume. + * @minor_ver: Ntfs minor version of volume. ++ * @volume_label_lock: protects @volume_label. + * @volume_label: volume label. + * @root_ino: The VFS inode of the root directory. + * @secure_ino: The VFS inode of $Secure (NTFS3.0+ only, otherwise NULL). +@@ -133,6 +134,7 @@ struct ntfs_volume { + struct inode *logfile_ino; + struct inode *lcnbmp_ino; + struct rw_semaphore lcnbmp_lock; ++ struct mutex volume_label_lock; + struct inode *vol_ino; + __le16 vol_flags; + u8 major_ver; diff --git a/queue-7.1/ocfs2-reject-oversized-group-bitmap-descriptors.patch b/queue-7.1/ocfs2-reject-oversized-group-bitmap-descriptors.patch new file mode 100644 index 0000000000..2d4bc9a8ae --- /dev/null +++ b/queue-7.1/ocfs2-reject-oversized-group-bitmap-descriptors.patch @@ -0,0 +1,128 @@ +From 9bd541e09dffff27e5bec0f9f45b0228173a5375 Mon Sep 17 00:00:00 2001 +From: Zhang Cen +Date: Sun, 24 May 2026 19:12:48 +0800 +Subject: ocfs2: reject oversized group bitmap descriptors + +From: Zhang Cen + +commit 9bd541e09dffff27e5bec0f9f45b0228173a5375 upstream. + +ocfs2_validate_gd_parent() only bounds bg_bits against the parent +allocator's chain geometry. A malicious descriptor can still claim a +bg_size/bg_bits pair that exceeds the bitmap bytes that physically fit in +the group descriptor block, so later bitmap scans and bit updates can run +past bg_bitmap. + +Add a physical-cap check based on ocfs2_group_bitmap_size() for the parent +allocator type and reject descriptors whose bg_size or bg_bits exceed that +capacity. Keep the existing chain geometry check so both the on-disk +bitmap layout and the allocator metadata must agree before the descriptor +is used. + +Validation reproduced this kernel report: +KASAN use-after-free in _find_next_bit+0x7f/0xc0 +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 (?:?) + print_report+0xd0/0x630 (?:?) + _find_next_bit+0x7f/0xc0 (?:?) + srso_alias_return_thunk+0x5/0xfbef5 (?:?) + __virt_addr_valid+0x188/0x2f0 (?:?) + kasan_report+0xe4/0x120 (?:?) + ocfs2_find_max_contig_free_bits+0x35/0x70 (fs/ocfs2/suballoc.c:1375) + ocfs2_block_group_set_bits+0x472/0x4b0 (fs/ocfs2/suballoc.c:1457) + ocfs2_cluster_group_search+0x16b/0x440 (fs/ocfs2/suballoc.c:86) + ocfs2_bg_discontig_fix_result+0x1ef/0x230 (fs/ocfs2/suballoc.c:1786) + ocfs2_search_chain+0x8f8/0x10a0 (fs/ocfs2/suballoc.c:1886) + get_page_from_freelist+0x70e/0x2370 (?:?) + lock_release+0xc6/0x290 (?:?) + do_raw_spin_unlock+0x9a/0x100 (?:?) + kasan_unpoison+0x27/0x60 (?:?) + __bfs+0x147/0x240 (?:?) + get_page_from_freelist+0x83d/0x2370 (?:?) + ocfs2_claim_suballoc_bits+0x38c/0xe70 (fs/ocfs2/suballoc.c:96) + sched_domains_numa_masks_clear+0x70/0xd0 (?:?) + check_irq_usage+0xe8/0xb70 (?:?) + __ocfs2_claim_clusters+0x18d/0x4c0 (fs/ocfs2/suballoc.c:2497) + check_path+0x24/0x50 (?:?) + rcu_is_watching+0x20/0x50 (?:?) + check_prev_add+0xfd/0xd00 (?:?) + ocfs2_add_clusters_in_btree+0x17d/0x810 (fs/ocfs2/suballoc.c:?) + __folio_batch_add_and_move+0x1f5/0x3d0 (?:?) + ocfs2_add_inode_data+0xd9/0x120 (fs/ocfs2/suballoc.c:?) + filemap_add_folio+0x105/0x1f0 (?:?) + ocfs2_write_begin_nolock+0x29f7/0x2f80 (fs/ocfs2/suballoc.c:3043) + ocfs2_read_inode_block+0xb5/0x110 (fs/ocfs2/suballoc.c:?) + down_write+0xf5/0x180 (?:?) + ocfs2_write_begin+0x180/0x240 (fs/ocfs2/suballoc.c:?) + __mark_inode_dirty+0x758/0x9a0 (?:?) + inode_to_bdi+0x41/0x90 (?:?) + balance_dirty_pages_ratelimited_flags+0xf8/0x1d0 (?:?) + generic_perform_write+0x252/0x440 (?:?) + mnt_put_write_access_file+0x16/0x70 (?:?) + file_update_time_flags+0xe4/0x200 (?:?) + ocfs2_file_write_iter+0x80a/0x1320 (fs/ocfs2/suballoc.c:?) + lock_acquire+0x184/0x2f0 (?:?) + ksys_write+0xd2/0x170 (?:?) + apparmor_file_permission+0xf5/0x310 (?:?) + read_zero+0x8d/0x140 (?:?) + lock_is_held_type+0x8f/0x100 (?:?) + +Link: https://lore.kernel.org/20260524111248.1429884-1-rollkingzzc@gmail.com +Fixes: ccd979bdbce9 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Zhang Cen +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Heming Zhao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/suballoc.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/fs/ocfs2/suballoc.c ++++ b/fs/ocfs2/suballoc.c +@@ -231,8 +231,16 @@ static int ocfs2_validate_gd_parent(stru + int resize) + { + unsigned int max_bits; ++ unsigned int max_bitmap_bits; ++ unsigned int max_bitmap_size; ++ int suballocator; + struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; + ++ suballocator = le64_to_cpu(di->i_blkno) != OCFS2_SB(sb)->bitmap_blkno; ++ max_bitmap_size = ocfs2_group_bitmap_size(sb, suballocator, ++ OCFS2_SB(sb)->s_feature_incompat); ++ max_bitmap_bits = max_bitmap_size * 8; ++ + if (di->i_blkno != gd->bg_parent_dinode) { + do_error("Group descriptor #%llu has bad parent pointer (%llu, expected %llu)\n", + (unsigned long long)bh->b_blocknr, +@@ -240,6 +248,20 @@ static int ocfs2_validate_gd_parent(stru + (unsigned long long)le64_to_cpu(di->i_blkno)); + } + ++ if (le16_to_cpu(gd->bg_size) > max_bitmap_size) { ++ do_error("Group descriptor #%llu has bitmap size %u but physical max of %u\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(gd->bg_size), ++ max_bitmap_size); ++ } ++ ++ if (le16_to_cpu(gd->bg_bits) > max_bitmap_bits) { ++ do_error("Group descriptor #%llu has bit count %u but physical max of %u\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(gd->bg_bits), ++ max_bitmap_bits); ++ } ++ + max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc); + if (le16_to_cpu(gd->bg_bits) > max_bits) { + do_error("Group descriptor #%llu has bit count of %u\n", diff --git a/queue-7.1/pnfs-fix-use-after-free-in-pnfs_update_layout.patch b/queue-7.1/pnfs-fix-use-after-free-in-pnfs_update_layout.patch new file mode 100644 index 0000000000..4a6fc25020 --- /dev/null +++ b/queue-7.1/pnfs-fix-use-after-free-in-pnfs_update_layout.patch @@ -0,0 +1,41 @@ +From 13e198a90ca4050f4bee8a3f23680389a6563ccc Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Mon, 18 May 2026 13:10:36 +0000 +Subject: pNFS: Fix use-after-free in pnfs_update_layout() + +From: Wentao Liang + +commit 13e198a90ca4050f4bee8a3f23680389a6563ccc upstream. + +When hitting the NFS_LAYOUT_RETURN branch in pnfs_update_layout(), +the code calls pnfs_prepare_to_retry_layoutget(lo). If it succeeds, +pnfs_put_layout_hdr(lo) is called before trace_pnfs_update_layout(), +which still references 'lo'. This results in a use-after-free when the +tracepoint accesses lo's fields. + +Fix this by moving the tracepoint call before pnfs_put_layout_hdr(lo). + +Fixes: 2c8d5fc37fe2 ("pNFS: Stricter ordering of layoutget and layoutreturn") +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Liang +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/pnfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -2229,11 +2229,11 @@ lookup_again: + dprintk("%s wait for layoutreturn\n", __func__); + lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo)); + if (!IS_ERR(lseg)) { +- pnfs_put_layout_hdr(lo); + dprintk("%s retrying\n", __func__); + trace_pnfs_update_layout(ino, pos, count, iomode, lo, + lseg, + PNFS_UPDATE_LAYOUT_RETRY); ++ pnfs_put_layout_hdr(lo); + goto lookup_again; + } + trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, diff --git a/queue-7.1/power-reset-linkstation-poweroff-fix-use-after-free-in-the-linkstation_poweroff_init.patch b/queue-7.1/power-reset-linkstation-poweroff-fix-use-after-free-in-the-linkstation_poweroff_init.patch new file mode 100644 index 0000000000..ac2cca1614 --- /dev/null +++ b/queue-7.1/power-reset-linkstation-poweroff-fix-use-after-free-in-the-linkstation_poweroff_init.patch @@ -0,0 +1,36 @@ +From 8eec545cde69e46e9a1d2b7d915ce4f5df85b3bd Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Tue, 7 Apr 2026 07:30:25 +0000 +Subject: power: reset: linkstation-poweroff: fix use-after-free in the linkstation_poweroff_init() + +From: Wentao Liang + +commit 8eec545cde69e46e9a1d2b7d915ce4f5df85b3bd upstream. + +Move of_node_put(dn) after the of_match_node() call, which still needs +the node pointer. The node reference is correctly released after use. + +Fixes: e2f471efe1d6 ("power: reset: linkstation-poweroff: prepare for new devices") +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Liang +Link: https://patch.msgid.link/20260407073025.271865-1-vulab@iscas.ac.cn +Signed-off-by: Sebastian Reichel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/reset/linkstation-poweroff.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/power/reset/linkstation-poweroff.c ++++ b/drivers/power/reset/linkstation-poweroff.c +@@ -163,10 +163,10 @@ static int __init linkstation_poweroff_i + dn = of_find_matching_node(NULL, ls_poweroff_of_match); + if (!dn) + return -ENODEV; +- of_node_put(dn); + + match = of_match_node(ls_poweroff_of_match, dn); + cfg = match->data; ++ of_node_put(dn); + + dn = of_find_node_by_name(NULL, cfg->mdio_node_name); + if (!dn) diff --git a/queue-7.1/pwrseq-core-fix-use-after-free-in-pwrseq_debugfs_seq_next.patch b/queue-7.1/pwrseq-core-fix-use-after-free-in-pwrseq_debugfs_seq_next.patch new file mode 100644 index 0000000000..41d19c07e0 --- /dev/null +++ b/queue-7.1/pwrseq-core-fix-use-after-free-in-pwrseq_debugfs_seq_next.patch @@ -0,0 +1,85 @@ +From 257595adf9dac15ae1edd9d07753fbc576a7583d Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Tue, 16 Jun 2026 15:10:49 +0000 +Subject: pwrseq: core: fix use-after-free in pwrseq_debugfs_seq_next() + +From: Wentao Liang + +commit 257595adf9dac15ae1edd9d07753fbc576a7583d upstream. + +pwrseq_debugfs_seq_next() declares 'next' with __free(put_device), +which causes put_device() to be called on the returned pointer when +the variable goes out of scope. This results in a use-after-free +since the seq_file framework receives a pointer whose reference has +already been dropped. + +Simply removing __free(put_device) would fix the UAF but would leak +the reference acquired by bus_find_next_device(), as stop() only +calls up_read(&pwrseq_sem) and never releases the device reference. + +Fix this by making the reference counting consistent across all +seq_file callbacks, matching the standard pattern used by PCI and +SCSI: + +- start(): use get_device() so it returns a referenced pointer. +- next(): explicitly put_device(curr) to release the previous + device's reference (no NULL check needed - the seq_file framework + only calls next() while the previous return was non-NULL). +- stop(): put_device(data) to release the last iterated device's + reference, with a NULL guard since stop() may be called with NULL + when start() returned NULL or next() reached end-of-sequence. + +Cc: stable@vger.kernel.org +Fixes: 249ebf3f65f8 ("power: sequencing: implement the pwrseq core") +Signed-off-by: Wentao Liang +Link: https://patch.msgid.link/20260616151049.1705503-1-vulab@iscas.ac.cn +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/sequencing/core.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/power/sequencing/core.c ++++ b/drivers/power/sequencing/core.c +@@ -989,8 +989,9 @@ static void *pwrseq_debugfs_seq_start(st + ctx.index = *pos; + + /* +- * We're holding the lock for the entire printout so no need to fiddle +- * with device reference count. ++ * Hold the lock for the entire printout to prevent device removal. ++ * Reference counts are managed by start()/next()/stop() as required ++ * by the seq_file contract. + */ + down_read(&pwrseq_sem); + +@@ -998,7 +999,7 @@ static void *pwrseq_debugfs_seq_start(st + if (!ctx.index) + return NULL; + +- return ctx.dev; ++ return get_device(ctx.dev); + } + + static void *pwrseq_debugfs_seq_next(struct seq_file *seq, void *data, +@@ -1008,8 +1009,9 @@ static void *pwrseq_debugfs_seq_next(str + + ++*pos; + +- struct device *next __free(put_device) = +- bus_find_next_device(&pwrseq_bus, curr); ++ struct device *next = bus_find_next_device(&pwrseq_bus, curr); ++ ++ put_device(curr); + return next; + } + +@@ -1058,6 +1060,8 @@ static int pwrseq_debugfs_seq_show(struc + + static void pwrseq_debugfs_seq_stop(struct seq_file *seq, void *data) + { ++ if (data) ++ put_device(data); + up_read(&pwrseq_sem); + } + diff --git a/queue-7.1/riscv-kfence-call-mark_new_valid_map-for-kfence_unprotect.patch b/queue-7.1/riscv-kfence-call-mark_new_valid_map-for-kfence_unprotect.patch new file mode 100644 index 0000000000..5c7c9d4235 --- /dev/null +++ b/queue-7.1/riscv-kfence-call-mark_new_valid_map-for-kfence_unprotect.patch @@ -0,0 +1,77 @@ +From 8d6c8c40e733b3fcaf92fed0a078bba2f6941a3b Mon Sep 17 00:00:00 2001 +From: Vivian Wang +Date: Tue, 3 Mar 2026 13:29:46 +0800 +Subject: riscv: kfence: Call mark_new_valid_map() for kfence_unprotect() + +From: Vivian Wang + +commit 8d6c8c40e733b3fcaf92fed0a078bba2f6941a3b upstream. + +In kfence_protect_page(), which kfence_unprotect() calls, we cannot send +IPIs to other CPUs to ask them to flush TLB. This may lead to those CPUs +spuriously faulting on a recently allocated kfence object despite it +being valid, leading to false positive use-after-free reports. + +Fix this by calling mark_new_valid_map() so that the page fault handling +code path notices the spurious fault and flushes TLB then retries the +access. + +Update the comment in handle_exception to indicate that +new_valid_map_cpus_check also handles kfence_unprotect() spurious +faults. + +Note that kfence_protect() has the same stale TLB entries problem, but +that leads to false negatives, which is fine with kfence. + +Cc: stable@vger.kernel.org +Reported-by: Yanko Kaneti +Fixes: b3431a8bb336 ("riscv: Fix IPIs usage in kfence_protect_page()") +Signed-off-by: Vivian Wang +Link: https://patch.msgid.link/20260303-handle-kfence-protect-spurious-fault-v2-2-f80d8354d79d@iscas.ac.cn +Signed-off-by: Paul Walmsley +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/include/asm/kfence.h | 7 +++++-- + arch/riscv/kernel/entry.S | 6 ++++-- + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- a/arch/riscv/include/asm/kfence.h ++++ b/arch/riscv/include/asm/kfence.h +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + static inline bool arch_kfence_init_pool(void) +@@ -17,10 +18,12 @@ static inline bool kfence_protect_page(u + { + pte_t *pte = virt_to_kpte(addr); + +- if (protect) ++ if (protect) { + set_pte(pte, __pte(pte_val(ptep_get(pte)) & ~_PAGE_PRESENT)); +- else ++ } else { + set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT)); ++ mark_new_valid_map(); ++ } + + preempt_disable(); + local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE); +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -136,8 +136,10 @@ SYM_CODE_START(handle_exception) + + #ifdef CONFIG_64BIT + /* +- * The RISC-V kernel does not eagerly emit a sfence.vma after each +- * new vmalloc mapping, which may result in exceptions: ++ * The RISC-V kernel does not flush TLBs on all CPUS after each new ++ * vmalloc mapping or kfence_unprotect(), which may result in ++ * exceptions: ++ * + * - if the uarch caches invalid entries, the new mapping would not be + * observed by the page table walker and an invalidation is needed. + * - if the uarch does not cache invalid entries, a reordered access diff --git a/queue-7.1/rpmsg-char-fix-use-after-free-on-probe-error-path.patch b/queue-7.1/rpmsg-char-fix-use-after-free-on-probe-error-path.patch new file mode 100644 index 0000000000..ab83661437 --- /dev/null +++ b/queue-7.1/rpmsg-char-fix-use-after-free-on-probe-error-path.patch @@ -0,0 +1,81 @@ +From 1ff3f528e67d20e2b1483dcaba899dc7832b2e6b Mon Sep 17 00:00:00 2001 +From: Yuho Choi +Date: Mon, 1 Jun 2026 14:32:47 -0400 +Subject: rpmsg: char: Fix use-after-free on probe error path + +From: Yuho Choi + +commit 1ff3f528e67d20e2b1483dcaba899dc7832b2e6b upstream. + +rpmsg_chrdev_probe() stores the newly allocated eptdev in the default +endpoint's priv pointer before calling rpmsg_chrdev_eptdev_add(). If +rpmsg_chrdev_eptdev_add() then fails, its error path frees eptdev while +the default endpoint may still dispatch callbacks with the stale priv +pointer. + +Avoid publishing eptdev through the default endpoint until +rpmsg_chrdev_eptdev_add() succeeds. Messages received before the priv +pointer is published should be ignored by rpmsg_ept_cb(). Flow-control +updates can hit rpmsg_ept_flow_cb() in the same window, so make both +callbacks return success when priv is NULL. + +Fixes: bc69d1066569 ("rpmsg: char: Introduce the "rpmsg-raw" channel") +Signed-off-by: Yuho Choi +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20260601183247.1962010-1-dbgh9129@gmail.com +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rpmsg/rpmsg_char.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/rpmsg/rpmsg_char.c ++++ b/drivers/rpmsg/rpmsg_char.c +@@ -104,6 +104,9 @@ static int rpmsg_ept_cb(struct rpmsg_dev + struct rpmsg_eptdev *eptdev = priv; + struct sk_buff *skb; + ++ if (!eptdev) ++ return 0; ++ + skb = alloc_skb(len, GFP_ATOMIC); + if (!skb) + return -ENOMEM; +@@ -124,6 +127,9 @@ static int rpmsg_ept_flow_cb(struct rpms + { + struct rpmsg_eptdev *eptdev = priv; + ++ if (!eptdev) ++ return 0; ++ + eptdev->remote_flow_restricted = enable; + eptdev->remote_flow_updated = true; + +@@ -490,6 +496,7 @@ static int rpmsg_chrdev_probe(struct rpm + struct rpmsg_channel_info chinfo; + struct rpmsg_eptdev *eptdev; + struct device *dev = &rpdev->dev; ++ int ret; + + memcpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); + chinfo.src = rpdev->src; +@@ -502,13 +509,17 @@ static int rpmsg_chrdev_probe(struct rpm + /* Set the default_ept to the rpmsg device endpoint */ + eptdev->default_ept = rpdev->ept; + ++ ret = rpmsg_chrdev_eptdev_add(eptdev, chinfo); ++ ++ if (ret) ++ return ret; + /* + * The rpmsg_ept_cb uses *priv parameter to get its rpmsg_eptdev context. +- * Storedit in default_ept *priv field. ++ * Stored it in default_ept *priv field. + */ + eptdev->default_ept->priv = eptdev; + +- return rpmsg_chrdev_eptdev_add(eptdev, chinfo); ++ return 0; + } + + static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev) diff --git a/queue-7.1/sched-mmcid-fix-oob-clear_bit-when-cid-is-mm_cid_unset-in-fixup-path.patch b/queue-7.1/sched-mmcid-fix-oob-clear_bit-when-cid-is-mm_cid_unset-in-fixup-path.patch new file mode 100644 index 0000000000..93a3e595ec --- /dev/null +++ b/queue-7.1/sched-mmcid-fix-oob-clear_bit-when-cid-is-mm_cid_unset-in-fixup-path.patch @@ -0,0 +1,88 @@ +From de3ab9bd3133899efb92e4cd05ba4203e58fc0a3 Mon Sep 17 00:00:00 2001 +From: Rik van Riel +Date: Tue, 16 Jun 2026 16:38:17 -0400 +Subject: sched/mmcid: Fix OOB clear_bit when CID is MM_CID_UNSET in fixup path + +From: Rik van Riel + +commit de3ab9bd3133899efb92e4cd05ba4203e58fc0a3 upstream. + +In mm_cid_fixup_cpus_to_tasks(), when rq->curr has the target mm and +mm_cid.active is set, the CID is checked with cid_in_transit() before +setting the transition bit. In per-CPU mode a newly forked or exec'd +task can be running with mm_cid.cid == MM_CID_UNSET because CIDs are +assigned lazily on schedule-in. With cid_in_transit() the guard passes +for MM_CID_UNSET (no transit bit), converts it to MM_CID_UNSET | +MM_CID_TRANSIT and stores it back; later mm_cid_schedout() feeds this +to clear_bit() with MM_CID_UNSET as the bit number, triggering an +out-of-bounds write. + +Symptoms: this is genuine memory corruption, but a bounded out-of-bounds +write, not an arbitrary one. MM_CID_UNSET is the fixed sentinel BIT(31), +so once the bad value reaches mm_cid_schedout() the cid_from_transit_cid() +strip leaves MM_CID_UNSET, which fails the "cid < max_cids" convergence +test and falls into mm_drop_cid() -> clear_bit(MM_CID_UNSET, +mm_cidmask(mm)). The cid bitmap is embedded in the mm_struct slab object +(after cpu_bitmap and mm_cpus_allowed) and is only num_possible_cpus() +bits wide, so clearing bit 31 is a deterministic OOB bit-clear at a +fixed offset of 2^31 / 8 == 256 MiB past the bitmap base. The address is +not attacker-influenced (fixed sentinel -> fixed offset) and the op only +clears a single bit; what sits 256 MiB further along the direct map is +whatever kernel object happens to live there, so this corrupts one bit of +unpredictable kernel memory -- it is not an arbitrary-address or +arbitrary-value write. + +It triggers only in per-CPU CID mode, when a CPU is running an active +task of the target mm whose cid is still MM_CID_UNSET -- the +fork()/execve() window before that task's next schedule-in assigns it a +real CID -- and a per-CPU -> per-task fixup walks over it (the mode +fallback driven by a thread exit, sched_mm_cid_exit(), or by the deferred +max_cids recompute in mm_cid_work_fn()). + +In practice syzkaller surfaced it as a KASAN use-after-free reported in +__schedule -> mm_cid_switch_to, where the offending clear_bit() is inlined +via mm_cid_schedout() -> mm_drop_cid(). + +Guard the transition-bit assignment against MM_CID_UNSET, in addition to +the existing cid_in_transit() check, so the bit is only set on a genuine +task-owned CID. A CPU-owned (MM_CID_ONCPU) CID of a running active task +is handled by the cid_on_cpu(pcp->cid) branch above and never reaches +this path, so excluding MM_CID_UNSET (and the already-transitioning case) +is sufficient. + +Fixes: fbd0e71dc370 ("sched/mmcid: Provide CID ownership mode fixup functions") +Signed-off-by: Rik van Riel +Signed-off-by: Thomas Gleixner +Assisted-by: Claude:claude-opus-4-8 syzkaller +Reviewed-by: Mathieu Desnoyers +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260616203818.1516263-1-riel@surriel.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/core.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -10880,8 +10880,19 @@ static void mm_cid_fixup_cpus_to_tasks(s + } else if (rq->curr->mm == mm && rq->curr->mm_cid.active) { + unsigned int cid = rq->curr->mm_cid.cid; + +- /* Ensure it has the transition bit set */ +- if (!cid_in_transit(cid)) { ++ /* ++ * Set the transition bit only on a genuine task-owned ++ * CID. A running active task can legitimately have ++ * MM_CID_UNSET here: in per-CPU mode CIDs are assigned ++ * lazily on schedule-in, so the fork()/execve() window ++ * leaves the task active with no owned CID. Setting the ++ * transition bit on MM_CID_UNSET would later feed ++ * clear_bit() an out-of-bounds bit number via ++ * mm_cid_schedout(), so exclude it. A CPU-owned ++ * (MM_CID_ONCPU) CID is handled by the cid_on_cpu() ++ * branch above and never reaches here. ++ */ ++ if (cid != MM_CID_UNSET && !cid_in_transit(cid)) { + cid = cid_to_transit_cid(cid); + rq->curr->mm_cid.cid = cid; + pcp->cid = cid; diff --git a/queue-7.1/series b/queue-7.1/series index 5b7049de95..ec4214421e 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -77,3 +77,42 @@ exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch crypto-nx-fix-nx_crypto_ctx_exit-argument.patch +gfs2-fix-use-after-free-in-gfs2_qd_dealloc.patch +pwrseq-core-fix-use-after-free-in-pwrseq_debugfs_seq_next.patch +hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch +blk-cgroup-fix-uaf-in-__blkcg_rstat_flush.patch +tipc-fix-slab-use-after-free-read-in-tipc_aead_decrypt_done.patch +loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch +pnfs-fix-use-after-free-in-pnfs_update_layout.patch +sched-mmcid-fix-oob-clear_bit-when-cid-is-mm_cid_unset-in-fixup-path.patch +irqchip-imgpdc-fix-resource-leak-add-missing-chained-handler-cleanup-on-remove.patch +fpga-region-fix-use-after-free-in-child_regions_with_firmware.patch +rpmsg-char-fix-use-after-free-on-probe-error-path.patch +ocfs2-reject-oversized-group-bitmap-descriptors.patch +9p-avoid-putting-oldfid-in-p9_client_walk-error-path.patch +mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch +kvm-x86-hyper-v-bound-the-bank-index-when-querying-sparse-banks.patch +kvm-svm-fix-page-overflow-in-sev_dbg_crypt-for-encrypt-path.patch +power-reset-linkstation-poweroff-fix-use-after-free-in-the-linkstation_poweroff_init.patch +riscv-kfence-call-mark_new_valid_map-for-kfence_unprotect.patch +ntfs-serialize-volume-label-accesses.patch +fbdev-fix-fb_new_modelist-to-prevent-null-ptr-deref-in-fb_videomode_to_var.patch +fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch +fbdev-omap2-fix-use-after-free-in-omapfb_mmap.patch +fbdev-modedb-fix-a-possible-uaf-in-fb_find_mode.patch +fbdev-modedb-fix-misaligned-fields-in-the-1920x1080-60-mode.patch +i2c-core-fix-adapter-registration-race.patch +nfsd-release-layout-stid-on-setlease-failure.patch +nfsd-fix-secinfo_no_name-decode-error-cleanup.patch +nfsd-fix-posix_acl-leak-on-setacl-decode-failure.patch +nfsd-fix-inverted-cp_ttl-check-in-async-copy-reaper.patch +nfsd-fix-posix_acl-leak-and-ignored-error-in-nfsd4_create_file.patch +nfsd-check-get_user-return-when-reading-princhashlen.patch +nfsd-fix-dead-acl-conflict-guard-in-nfsd4_create.patch +nfsd-avoid-leaking-pre-allocated-openowner-on-unconfirmed-retry-race.patch +nfsd-reset-write-verifier-on-deferred-writeback-errors.patch +nfsv4-flexfiles-reject-zero-filehandle-version-count.patch +nfsv4-pnfs-reject-zero-length-r_addr-in-nfs4_decode_mp_ds_addr.patch +nfsv4-clear-exception-state-on-successful-mkdir-retry.patch +nfs-prevent-resource-leak-in-nfs_alloc_server.patch +ksmbd-fix-out-of-bounds-read-in-smb_check_perm_dacl.patch diff --git a/queue-7.1/tipc-fix-slab-use-after-free-read-in-tipc_aead_decrypt_done.patch b/queue-7.1/tipc-fix-slab-use-after-free-read-in-tipc_aead_decrypt_done.patch new file mode 100644 index 0000000000..5ac16dbdea --- /dev/null +++ b/queue-7.1/tipc-fix-slab-use-after-free-read-in-tipc_aead_decrypt_done.patch @@ -0,0 +1,124 @@ +From bda3348872a2ef0d19f2df6aa8cb5025adce2f20 Mon Sep 17 00:00:00 2001 +From: Doruk Tan Ozturk +Date: Wed, 17 Jun 2026 09:58:18 +0200 +Subject: tipc: fix slab-use-after-free Read in tipc_aead_decrypt_done + +From: Doruk Tan Ozturk + +commit bda3348872a2ef0d19f2df6aa8cb5025adce2f20 upstream. + +tipc_aead_decrypt() goes straight from tipc_bearer_hold(b) to +crypto_aead_decrypt(req) without taking a reference on the netns, unlike +the encrypt path. When crypto_aead_decrypt() is offloaded asynchronously +(e.g. the SIMD aead wrapper queuing to cryptd), the cryptd worker runs +tipc_aead_decrypt_done() later. If the bearer's netns is torn down in the +meantime, cleanup_net() -> tipc_exit_net() -> tipc_crypto_stop() frees the +per-netns tipc_crypto, and the completion then reads it: +tipc_aead_decrypt_done() dereferences aead->crypto->stats and +aead->crypto->net, and tipc_crypto_rcv_complete() dereferences +aead->crypto->aead[] and the node table -- reading freed memory. + +Decoded KASAN splat (v7.1-rc7, CONFIG_KASAN_INLINE + TIPC + TIPC_CRYPTO): + + BUG: KASAN: slab-use-after-free in tipc_aead_decrypt_done (net/tipc/crypto.c:999) + Read of size 8 at addr ffff8881056258a8 by task kworker/u16:2/51 + Workqueue: events_unbound + Call Trace: + tipc_aead_decrypt_done (net/tipc/crypto.c:999) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + + Allocated by task 169: + __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) + tipc_crypto_start (net/tipc/crypto.c:1502) + tipc_init_net (net/tipc/core.c:72) + ops_init (net/core/net_namespace.c:137) + setup_net (net/core/net_namespace.c:446) + copy_net_ns (net/core/net_namespace.c:579) + create_new_namespaces (kernel/nsproxy.c:132) + __x64_sys_unshare (kernel/fork.c:3316) + do_syscall_64 (arch/x86/entry/syscall_64.c:63) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + + Freed by task 8: + kfree (mm/slub.c:6566) + tipc_exit_net (net/tipc/core.c:119) + cleanup_net (net/core/net_namespace.c:704) + process_one_work (kernel/workqueue.c:3314) + kthread (kernel/kthread.c:436) + +This is the same class of bug that commit e279024617134 ("net/tipc: fix +slab-use-after-free Read in tipc_aead_encrypt_done") fixed for the encrypt +side. The encrypt path takes maybe_get_net(aead->crypto->net) before +crypto_aead_encrypt() and drops it with put_net() on the synchronous +return paths and in tipc_aead_encrypt_done(); the -EINPROGRESS/-EBUSY +return keeps the reference for the async callback to release. The decrypt +path was left without the equivalent guard. + +Mirror the encrypt-side fix on the decrypt path: take a net reference +before crypto_aead_decrypt() (failing with -ENODEV and the matching +bearer put if it cannot be acquired), keep it across the +-EINPROGRESS/-EBUSY async return, and drop it with put_net() on the +synchronous success/error return and at the end of +tipc_aead_decrypt_done(). + +Reproduced under KASAN on v7.1-rc7: a UDP bearer with a cluster key is +flooded with crafted encrypted frames from an unknown peer (driving the +cluster-key decrypt path) while the bearer's netns is repeatedly torn +down. The completion must run asynchronously to outlive +tipc_crypto_stop(); on x86 the stock aesni gcm(aes) now decrypts +synchronously, so the async path was exercised via cryptd offload. The +unguarded aead->crypto dereference in tipc_aead_decrypt_done() is the +unpatched upstream path; tipc_aead_decrypt() still lacks +maybe_get_net(aead->crypto->net), so the completion can outlive the free +on any config where crypto_aead_decrypt() goes async. + +Found by 0sec automated security-research tooling (https://0sec.ai). + +Fixes: fc1b6d6de220 ("tipc: introduce TIPC encryption & authentication") +Cc: stable@vger.kernel.org +Signed-off-by: Doruk Tan Ozturk +Reviewed-by: Alexander Lobakin +Reviewed-by: Tung Nguyen +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260617075818.37431-1-doruk@0sec.ai +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/crypto.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/net/tipc/crypto.c ++++ b/net/tipc/crypto.c +@@ -941,12 +941,20 @@ static int tipc_aead_decrypt(struct net + goto exit; + } + ++ /* Get net to avoid freed tipc_crypto when delete namespace */ ++ if (!maybe_get_net(net)) { ++ tipc_bearer_put(b); ++ rc = -ENODEV; ++ goto exit; ++ } ++ + /* Now, do decrypt */ + rc = crypto_aead_decrypt(req); + if (rc == -EINPROGRESS || rc == -EBUSY) + return rc; + + tipc_bearer_put(b); ++ put_net(net); + + exit: + kfree(ctx); +@@ -984,6 +992,7 @@ static void tipc_aead_decrypt_done(void + } + + tipc_bearer_put(b); ++ put_net(net); + } + + static inline int tipc_ehdr_size(struct tipc_ehdr *ehdr)