From: Greg Kroah-Hartman Date: Tue, 8 Apr 2025 10:18:32 +0000 (+0200) Subject: 6.14-stable patches X-Git-Tag: v5.4.292~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bfc4d2783f4d46cf5115a84e5d0bc11c24475392;p=thirdparty%2Fkernel%2Fstable-queue.git 6.14-stable patches added patches: arm64-don-t-call-null-in-do_compat_alignment_fixup.patch exec-fix-the-racy-usage-of-fs_struct-in_exec.patch exfat-fix-potential-wrong-error-return-from-get_block.patch exfat-fix-random-stack-corruption-after-get_block.patch ext4-don-t-over-report-free-space-or-inodes-in-statvfs.patch ext4-fix-oob-read-when-checking-dotdot-dir.patch jfs-add-index-corruption-check-to-dt_getpage.patch jfs-fix-slab-out-of-bounds-read-in-ea_get.patch ksmbd-add-bounds-check-for-create-lease-context.patch ksmbd-add-bounds-check-for-durable-handle-context.patch ksmbd-fix-null-pointer-dereference-in-alloc_preauth_hash.patch ksmbd-fix-overflow-in-dacloffset-bounds-check.patch ksmbd-fix-session-use-after-free-in-multichannel-connection.patch ksmbd-fix-use-after-free-in-ksmbd_sessions_deregister.patch ksmbd-validate-zero-num_subauth-before-sub_auth-is-accessed.patch kvm-svm-don-t-change-target-vcpu-state-on-ap-creation-vmgexit-error.patch media-streamzap-fix-race-between-device-disconnection-and-urb-callback.patch media-vimc-skip-.s_stream-for-stopped-entities.patch mm-gup-reject-foll_split_pmd-with-hugetlb-vmas.patch mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch mm-zswap-fix-crypto_free_acomp-deadlock-in-zswap_cpu_comp_dead.patch mmc-omap-fix-memory-leak-in-mmc_omap_new_slot.patch mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qcom_ice_get.patch mmc-sdhci-omap-disable-mmc_cap_aggressive_pm-for-emmc-sd.patch mmc-sdhci-pxav3-set-need_rsp_busy-capability.patch nfsd-add-a-kconfig-setting-to-enable-delegated-timestamps.patch nfsd-allow-sc_status_freeable-when-searching-via-nfs4_lookup_stateid.patch nfsd-don-t-ignore-the-return-code-of-svc_proc_register.patch nfsd-fix-management-of-listener-transports.patch nfsd-never-return-nfs4err_file_open-when-removing-a-directory.patch nfsd-nfsd_unlink-clobbers-non-zero-status-returned-from-fh_fill_pre_attrs.patch nfsd-put-dl_stid-if-fail-to-queue-dl_recall.patch nfsd-skip-sending-cb_recall_any-when-the-backchannel-isn-t-up.patch pci-bwctrl-fix-null-pointer-dereference-on-bus-number-exhaustion.patch remove-unnecessary-firmware-version-check-for-gc-v9_4_2.patch tracing-ensure-module-defining-synth-event-cannot-be-unloaded-while-tracing.patch tracing-fix-synth-event-printk-format-for-str-fields.patch tracing-fix-use-after-free-in-print_graph_function_flags-during-tracer-switching.patch tracing-osnoise-fix-possible-recursive-locking-for-cpus_read_lock.patch tracing-verify-event-formats-that-have-p.patch wifi-mt76-mt7921-fix-kernel-panic-due-to-null-pointer-dereference.patch --- diff --git a/queue-6.14/arm64-don-t-call-null-in-do_compat_alignment_fixup.patch b/queue-6.14/arm64-don-t-call-null-in-do_compat_alignment_fixup.patch new file mode 100644 index 0000000000..aabdc323ef --- /dev/null +++ b/queue-6.14/arm64-don-t-call-null-in-do_compat_alignment_fixup.patch @@ -0,0 +1,75 @@ +From c28f31deeacda307acfee2f18c0ad904e5123aac Mon Sep 17 00:00:00 2001 +From: Angelos Oikonomopoulos +Date: Tue, 1 Apr 2025 10:51:50 +0200 +Subject: arm64: Don't call NULL in do_compat_alignment_fixup() + +From: Angelos Oikonomopoulos + +commit c28f31deeacda307acfee2f18c0ad904e5123aac upstream. + +do_alignment_t32_to_handler() only fixes up alignment faults for +specific instructions; it returns NULL otherwise (e.g. LDREX). When +that's the case, signal to the caller that it needs to proceed with the +regular alignment fault handling (i.e. SIGBUS). Without this patch, the +kernel panics: + + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 + Mem abort info: + ESR = 0x0000000086000006 + EC = 0x21: IABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x06: level 2 translation fault + user pgtable: 4k pages, 48-bit VAs, pgdp=00000800164aa000 + [0000000000000000] pgd=0800081fdbd22003, p4d=0800081fdbd22003, pud=08000815d51c6003, pmd=0000000000000000 + Internal error: Oops: 0000000086000006 [#1] SMP + Modules linked in: cfg80211 rfkill xt_nat xt_tcpudp xt_conntrack nft_chain_nat xt_MASQUERADE nf_nat nf_conntrack_netlink nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xfrm_user xfrm_algo xt_addrtype nft_compat br_netfilter veth nvme_fa> + libcrc32c crc32c_generic raid0 multipath linear dm_mod dax raid1 md_mod xhci_pci nvme xhci_hcd nvme_core t10_pi usbcore igb crc64_rocksoft crc64 crc_t10dif crct10dif_generic crct10dif_ce crct10dif_common usb_common i2c_algo_bit i2c> + CPU: 2 PID: 3932954 Comm: WPEWebProcess Not tainted 6.1.0-31-arm64 #1 Debian 6.1.128-1 + Hardware name: GIGABYTE MP32-AR1-00/MP32-AR1-00, BIOS F18v (SCP: 1.08.20211002) 12/01/2021 + pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : 0x0 + lr : do_compat_alignment_fixup+0xd8/0x3dc + sp : ffff80000f973dd0 + x29: ffff80000f973dd0 x28: ffff081b42526180 x27: 0000000000000000 + x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 + x23: 0000000000000004 x22: 0000000000000000 x21: 0000000000000001 + x20: 00000000e8551f00 x19: ffff80000f973eb0 x18: 0000000000000000 + x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 + x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 + x11: 0000000000000000 x10: 0000000000000000 x9 : ffffaebc949bc488 + x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000 + x5 : 0000000000400000 x4 : 0000fffffffffffe x3 : 0000000000000000 + x2 : ffff80000f973eb0 x1 : 00000000e8551f00 x0 : 0000000000000001 + Call trace: + 0x0 + do_alignment_fault+0x40/0x50 + do_mem_abort+0x4c/0xa0 + el0_da+0x48/0xf0 + el0t_32_sync_handler+0x110/0x140 + el0t_32_sync+0x190/0x194 + Code: bad PC value + ---[ end trace 0000000000000000 ]--- + +Signed-off-by: Angelos Oikonomopoulos +Fixes: 3fc24ef32d3b ("arm64: compat: Implement misalignment fixups for multiword loads") +Cc: # 6.1.x +Reviewed-by: Anshuman Khandual +Link: https://lore.kernel.org/r/20250401085150.148313-1-angelos@igalia.com +Signed-off-by: Catalin Marinas +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/compat_alignment.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/kernel/compat_alignment.c ++++ b/arch/arm64/kernel/compat_alignment.c +@@ -368,6 +368,8 @@ int do_compat_alignment_fixup(unsigned l + return 1; + } + ++ if (!handler) ++ return 1; + type = handler(addr, instr, regs); + + if (type == TYPE_ERROR || type == TYPE_FAULT) diff --git a/queue-6.14/exec-fix-the-racy-usage-of-fs_struct-in_exec.patch b/queue-6.14/exec-fix-the-racy-usage-of-fs_struct-in_exec.patch new file mode 100644 index 0000000000..2e66283b7c --- /dev/null +++ b/queue-6.14/exec-fix-the-racy-usage-of-fs_struct-in_exec.patch @@ -0,0 +1,89 @@ +From af7bb0d2ca459f15cb5ca604dab5d9af103643f0 Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 24 Mar 2025 17:00:03 +0100 +Subject: exec: fix the racy usage of fs_struct->in_exec + +From: Oleg Nesterov + +commit af7bb0d2ca459f15cb5ca604dab5d9af103643f0 upstream. + +check_unsafe_exec() sets fs->in_exec under cred_guard_mutex, then execve() +paths clear fs->in_exec lockless. This is fine if exec succeeds, but if it +fails we have the following race: + + T1 sets fs->in_exec = 1, fails, drops cred_guard_mutex + + T2 sets fs->in_exec = 1 + + T1 clears fs->in_exec + + T2 continues with fs->in_exec == 0 + +Change fs/exec.c to clear fs->in_exec with cred_guard_mutex held. + +Reported-by: syzbot+1c486d0b62032c82a968@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67dc67f0.050a0220.25ae54.001f.GAE@google.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Oleg Nesterov +Link: https://lore.kernel.org/r/20250324160003.GA8878@redhat.com +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/exec.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1229,13 +1229,12 @@ int begin_new_exec(struct linux_binprm * + */ + bprm->point_of_no_return = true; + +- /* +- * Make this the only thread in the thread group. +- */ ++ /* Make this the only thread in the thread group */ + retval = de_thread(me); + if (retval) + goto out; +- ++ /* see the comment in check_unsafe_exec() */ ++ current->fs->in_exec = 0; + /* + * Cancel any io_uring activity across execve + */ +@@ -1497,6 +1496,8 @@ static void free_bprm(struct linux_binpr + } + free_arg_pages(bprm); + if (bprm->cred) { ++ /* in case exec fails before de_thread() succeeds */ ++ current->fs->in_exec = 0; + mutex_unlock(¤t->signal->cred_guard_mutex); + abort_creds(bprm->cred); + } +@@ -1618,6 +1619,10 @@ static void check_unsafe_exec(struct lin + * suid exec because the differently privileged task + * will be able to manipulate the current directory, etc. + * It would be nice to force an unshare instead... ++ * ++ * Otherwise we set fs->in_exec = 1 to deny clone(CLONE_FS) ++ * from another sub-thread until de_thread() succeeds, this ++ * state is protected by cred_guard_mutex we hold. + */ + n_fs = 1; + spin_lock(&p->fs->lock); +@@ -1862,7 +1867,6 @@ static int bprm_execve(struct linux_binp + + sched_mm_cid_after_execve(current); + /* execve succeeded */ +- current->fs->in_exec = 0; + current->in_execve = 0; + rseq_execve(current); + user_events_execve(current); +@@ -1881,7 +1885,6 @@ out: + force_fatal_sig(SIGSEGV); + + sched_mm_cid_after_execve(current); +- current->fs->in_exec = 0; + current->in_execve = 0; + + return retval; diff --git a/queue-6.14/exfat-fix-potential-wrong-error-return-from-get_block.patch b/queue-6.14/exfat-fix-potential-wrong-error-return-from-get_block.patch new file mode 100644 index 0000000000..0c325b38f7 --- /dev/null +++ b/queue-6.14/exfat-fix-potential-wrong-error-return-from-get_block.patch @@ -0,0 +1,35 @@ +From 59c30e31425833385e6644ad33151420e37eabe1 Mon Sep 17 00:00:00 2001 +From: Sungjong Seo +Date: Wed, 26 Mar 2025 23:48:48 +0900 +Subject: exfat: fix potential wrong error return from get_block + +From: Sungjong Seo + +commit 59c30e31425833385e6644ad33151420e37eabe1 upstream. + +If there is no error, get_block() should return 0. However, when bh_read() +returns 1, get_block() also returns 1 in the same manner. + +Let's set err to 0, if there is no error from bh_read() + +Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength") +Cc: stable@vger.kernel.org +Signed-off-by: Sungjong Seo +Reviewed-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -391,6 +391,8 @@ static int exfat_get_block(struct inode + /* Zero unwritten part of a block */ + memset(bh_result->b_data + size, 0, + bh_result->b_size - size); ++ ++ err = 0; + } else { + /* + * The range has not been written, clear the mapped flag diff --git a/queue-6.14/exfat-fix-random-stack-corruption-after-get_block.patch b/queue-6.14/exfat-fix-random-stack-corruption-after-get_block.patch new file mode 100644 index 0000000000..6258ab4a8d --- /dev/null +++ b/queue-6.14/exfat-fix-random-stack-corruption-after-get_block.patch @@ -0,0 +1,127 @@ +From 1bb7ff4204b6d4927e982cd256286c09ed4fd8ca Mon Sep 17 00:00:00 2001 +From: Sungjong Seo +Date: Fri, 21 Mar 2025 15:34:42 +0900 +Subject: exfat: fix random stack corruption after get_block + +From: Sungjong Seo + +commit 1bb7ff4204b6d4927e982cd256286c09ed4fd8ca upstream. + +When get_block is called with a buffer_head allocated on the stack, such +as do_mpage_readpage, stack corruption due to buffer_head UAF may occur in +the following race condition situation. + + +mpage_read_folio + <> + do_mpage_readpage + exfat_get_block + bh_read + __bh_read + get_bh(bh) + submit_bh + wait_on_buffer + ... + end_buffer_read_sync + __end_buffer_read_notouch + unlock_buffer + <> + ... + ... + ... + ... +<> + . + . +another_function + <> + put_bh(bh) + atomic_dec(bh->b_count) + * stack corruption here * + +This patch returns -EAGAIN if a folio does not have buffers when bh_read +needs to be called. By doing this, the caller can fallback to functions +like block_read_full_folio(), create a buffer_head in the folio, and then +call get_block again. + +Let's do not call bh_read() with on-stack buffer_head. + +Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength") +Cc: stable@vger.kernel.org +Tested-by: Yeongjin Gil +Signed-off-by: Sungjong Seo +Reviewed-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/inode.c | 39 +++++++++++++++++++++++++++++++++------ + 1 file changed, 33 insertions(+), 6 deletions(-) + +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -344,7 +344,8 @@ static int exfat_get_block(struct inode + * The block has been partially written, + * zero the unwritten part and map the block. + */ +- loff_t size, off, pos; ++ loff_t size, pos; ++ void *addr; + + max_blocks = 1; + +@@ -355,17 +356,41 @@ static int exfat_get_block(struct inode + if (!bh_result->b_folio) + goto done; + ++ /* ++ * No buffer_head is allocated. ++ * (1) bmap: It's enough to fill bh_result without I/O. ++ * (2) read: The unwritten part should be filled with 0 ++ * If a folio does not have any buffers, ++ * let's returns -EAGAIN to fallback to ++ * per-bh IO like block_read_full_folio(). ++ */ ++ if (!folio_buffers(bh_result->b_folio)) { ++ err = -EAGAIN; ++ goto done; ++ } ++ + pos = EXFAT_BLK_TO_B(iblock, sb); + size = ei->valid_size - pos; +- off = pos & (PAGE_SIZE - 1); ++ addr = folio_address(bh_result->b_folio) + ++ offset_in_folio(bh_result->b_folio, pos); + +- folio_set_bh(bh_result, bh_result->b_folio, off); ++ /* Check if bh->b_data points to proper addr in folio */ ++ if (bh_result->b_data != addr) { ++ exfat_fs_error_ratelimit(sb, ++ "b_data(%p) != folio_addr(%p)", ++ bh_result->b_data, addr); ++ err = -EINVAL; ++ goto done; ++ } ++ ++ /* Read a block */ + err = bh_read(bh_result, 0); + if (err < 0) +- goto unlock_ret; ++ goto done; + +- folio_zero_segment(bh_result->b_folio, off + size, +- off + sb->s_blocksize); ++ /* Zero unwritten part of a block */ ++ memset(bh_result->b_data + size, 0, ++ bh_result->b_size - size); + } else { + /* + * The range has not been written, clear the mapped flag +@@ -376,6 +401,8 @@ static int exfat_get_block(struct inode + } + done: + bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); ++ if (err < 0) ++ clear_buffer_mapped(bh_result); + unlock_ret: + mutex_unlock(&sbi->s_lock); + return err; diff --git a/queue-6.14/ext4-don-t-over-report-free-space-or-inodes-in-statvfs.patch b/queue-6.14/ext4-don-t-over-report-free-space-or-inodes-in-statvfs.patch new file mode 100644 index 0000000000..b7e2a107b8 --- /dev/null +++ b/queue-6.14/ext4-don-t-over-report-free-space-or-inodes-in-statvfs.patch @@ -0,0 +1,69 @@ +From f87d3af7419307ae26e705a2b2db36140db367a2 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 14 Mar 2025 00:38:42 -0400 +Subject: ext4: don't over-report free space or inodes in statvfs + +From: Theodore Ts'o + +commit f87d3af7419307ae26e705a2b2db36140db367a2 upstream. + +This fixes an analogus bug that was fixed in xfs in commit +4b8d867ca6e2 ("xfs: don't over-report free space or inodes in +statvfs") where statfs can report misleading / incorrect information +where project quota is enabled, and the free space is less than the +remaining quota. + +This commit will resolve a test failure in generic/762 which tests for +this bug. + +Cc: stable@kernel.org +Fixes: 689c958cbe6b ("ext4: add project quota support") +Signed-off-by: Theodore Ts'o +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -6813,22 +6813,29 @@ static int ext4_statfs_project(struct su + dquot->dq_dqb.dqb_bhardlimit); + limit >>= sb->s_blocksize_bits; + +- if (limit && buf->f_blocks > limit) { ++ if (limit) { ++ uint64_t remaining = 0; ++ + curblock = (dquot->dq_dqb.dqb_curspace + + dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits; +- buf->f_blocks = limit; +- buf->f_bfree = buf->f_bavail = +- (buf->f_blocks > curblock) ? +- (buf->f_blocks - curblock) : 0; ++ if (limit > curblock) ++ remaining = limit - curblock; ++ ++ buf->f_blocks = min(buf->f_blocks, limit); ++ buf->f_bfree = min(buf->f_bfree, remaining); ++ buf->f_bavail = min(buf->f_bavail, remaining); + } + + limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit, + dquot->dq_dqb.dqb_ihardlimit); +- if (limit && buf->f_files > limit) { +- buf->f_files = limit; +- buf->f_ffree = +- (buf->f_files > dquot->dq_dqb.dqb_curinodes) ? +- (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0; ++ if (limit) { ++ uint64_t remaining = 0; ++ ++ if (limit > dquot->dq_dqb.dqb_curinodes) ++ remaining = limit - dquot->dq_dqb.dqb_curinodes; ++ ++ buf->f_files = min(buf->f_files, limit); ++ buf->f_ffree = min(buf->f_ffree, remaining); + } + + spin_unlock(&dquot->dq_dqb_lock); diff --git a/queue-6.14/ext4-fix-oob-read-when-checking-dotdot-dir.patch b/queue-6.14/ext4-fix-oob-read-when-checking-dotdot-dir.patch new file mode 100644 index 0000000000..65e715c546 --- /dev/null +++ b/queue-6.14/ext4-fix-oob-read-when-checking-dotdot-dir.patch @@ -0,0 +1,100 @@ +From d5e206778e96e8667d3bde695ad372c296dc9353 Mon Sep 17 00:00:00 2001 +From: "Acs, Jakub" +Date: Thu, 20 Mar 2025 15:46:49 +0000 +Subject: ext4: fix OOB read when checking dotdot dir + +From: Acs, Jakub + +commit d5e206778e96e8667d3bde695ad372c296dc9353 upstream. + +Mounting a corrupted filesystem with directory which contains '.' dir +entry with rec_len == block size results in out-of-bounds read (later +on, when the corrupted directory is removed). + +ext4_empty_dir() assumes every ext4 directory contains at least '.' +and '..' as directory entries in the first data block. It first loads +the '.' dir entry, performs sanity checks by calling ext4_check_dir_entry() +and then uses its rec_len member to compute the location of '..' dir +entry (in ext4_next_entry). It assumes the '..' dir entry fits into the +same data block. + +If the rec_len of '.' is precisely one block (4KB), it slips through the +sanity checks (it is considered the last directory entry in the data +block) and leaves "struct ext4_dir_entry_2 *de" point exactly past the +memory slot allocated to the data block. The following call to +ext4_check_dir_entry() on new value of de then dereferences this pointer +which results in out-of-bounds mem access. + +Fix this by extending __ext4_check_dir_entry() to check for '.' dir +entries that reach the end of data block. Make sure to ignore the phony +dir entries for checksum (by checking name_len for non-zero). + +Note: This is reported by KASAN as use-after-free in case another +structure was recently freed from the slot past the bound, but it is +really an OOB read. + +This issue was found by syzkaller tool. + +Call Trace: +[ 38.594108] BUG: KASAN: slab-use-after-free in __ext4_check_dir_entry+0x67e/0x710 +[ 38.594649] Read of size 2 at addr ffff88802b41a004 by task syz-executor/5375 +[ 38.595158] +[ 38.595288] CPU: 0 UID: 0 PID: 5375 Comm: syz-executor Not tainted 6.14.0-rc7 #1 +[ 38.595298] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 +[ 38.595304] Call Trace: +[ 38.595308] +[ 38.595311] dump_stack_lvl+0xa7/0xd0 +[ 38.595325] print_address_description.constprop.0+0x2c/0x3f0 +[ 38.595339] ? __ext4_check_dir_entry+0x67e/0x710 +[ 38.595349] print_report+0xaa/0x250 +[ 38.595359] ? __ext4_check_dir_entry+0x67e/0x710 +[ 38.595368] ? kasan_addr_to_slab+0x9/0x90 +[ 38.595378] kasan_report+0xab/0xe0 +[ 38.595389] ? __ext4_check_dir_entry+0x67e/0x710 +[ 38.595400] __ext4_check_dir_entry+0x67e/0x710 +[ 38.595410] ext4_empty_dir+0x465/0x990 +[ 38.595421] ? __pfx_ext4_empty_dir+0x10/0x10 +[ 38.595432] ext4_rmdir.part.0+0x29a/0xd10 +[ 38.595441] ? __dquot_initialize+0x2a7/0xbf0 +[ 38.595455] ? __pfx_ext4_rmdir.part.0+0x10/0x10 +[ 38.595464] ? __pfx___dquot_initialize+0x10/0x10 +[ 38.595478] ? down_write+0xdb/0x140 +[ 38.595487] ? __pfx_down_write+0x10/0x10 +[ 38.595497] ext4_rmdir+0xee/0x140 +[ 38.595506] vfs_rmdir+0x209/0x670 +[ 38.595517] ? lookup_one_qstr_excl+0x3b/0x190 +[ 38.595529] do_rmdir+0x363/0x3c0 +[ 38.595537] ? __pfx_do_rmdir+0x10/0x10 +[ 38.595544] ? strncpy_from_user+0x1ff/0x2e0 +[ 38.595561] __x64_sys_unlinkat+0xf0/0x130 +[ 38.595570] do_syscall_64+0x5b/0x180 +[ 38.595583] entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Fixes: ac27a0ec112a0 ("[PATCH] ext4: initial copy of files from ext3") +Signed-off-by: Jakub Acs +Cc: Theodore Ts'o +Cc: Andreas Dilger +Cc: linux-ext4@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: Mahmoud Adam +Cc: stable@vger.kernel.org +Cc: security@kernel.org +Link: https://patch.msgid.link/b3ae36a6794c4a01944c7d70b403db5b@amazon.de +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/dir.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -104,6 +104,9 @@ int __ext4_check_dir_entry(const char *f + else if (unlikely(le32_to_cpu(de->inode) > + le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) + error_msg = "inode out of bounds"; ++ else if (unlikely(next_offset == size && de->name_len == 1 && ++ de->name[0] == '.')) ++ error_msg = "'.' directory cannot be the last in data block"; + else + return 0; + diff --git a/queue-6.14/jfs-add-index-corruption-check-to-dt_getpage.patch b/queue-6.14/jfs-add-index-corruption-check-to-dt_getpage.patch new file mode 100644 index 0000000000..a859c17902 --- /dev/null +++ b/queue-6.14/jfs-add-index-corruption-check-to-dt_getpage.patch @@ -0,0 +1,62 @@ +From a8dfb2168906944ea61acfc87846b816eeab882d Mon Sep 17 00:00:00 2001 +From: Roman Smirnov +Date: Wed, 26 Feb 2025 11:25:22 +0300 +Subject: jfs: add index corruption check to DT_GETPAGE() + +From: Roman Smirnov + +commit a8dfb2168906944ea61acfc87846b816eeab882d upstream. + +If the file system is corrupted, the header.stblindex variable +may become greater than 127. Because of this, an array access out +of bounds may occur: + +------------[ cut here ]------------ +UBSAN: array-index-out-of-bounds in fs/jfs/jfs_dtree.c:3096:10 +index 237 is out of range for type 'struct dtslot[128]' +CPU: 0 UID: 0 PID: 5822 Comm: syz-executor740 Not tainted 6.13.0-rc4-syzkaller-00110-g4099a71718b0 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:231 [inline] + __ubsan_handle_out_of_bounds+0x121/0x150 lib/ubsan.c:429 + dtReadFirst+0x622/0xc50 fs/jfs/jfs_dtree.c:3096 + dtReadNext fs/jfs/jfs_dtree.c:3147 [inline] + jfs_readdir+0x9aa/0x3c50 fs/jfs/jfs_dtree.c:2862 + wrap_directory_iterator+0x91/0xd0 fs/readdir.c:65 + iterate_dir+0x571/0x800 fs/readdir.c:108 + __do_sys_getdents64 fs/readdir.c:403 [inline] + __se_sys_getdents64+0x1e2/0x4b0 fs/readdir.c:389 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +---[ end trace ]--- + +Add a stblindex check for corruption. + +Reported-by: syzbot +Closes: https://syzkaller.appspot.com/bug?extid=9120834fc227768625ba +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Roman Smirnov +Signed-off-by: Dave Kleikamp +Signed-off-by: Greg Kroah-Hartman +--- + fs/jfs/jfs_dtree.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/jfs/jfs_dtree.c ++++ b/fs/jfs/jfs_dtree.c +@@ -117,7 +117,8 @@ do { \ + if (!(RC)) { \ + if (((P)->header.nextindex > \ + (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \ +- ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT))) { \ ++ ((BN) && (((P)->header.maxslot > DTPAGEMAXSLOT) || \ ++ ((P)->header.stblindex >= DTPAGEMAXSLOT)))) { \ + BT_PUTPAGE(MP); \ + jfs_error((IP)->i_sb, \ + "DT_GETPAGE: dtree page corrupt\n"); \ diff --git a/queue-6.14/jfs-fix-slab-out-of-bounds-read-in-ea_get.patch b/queue-6.14/jfs-fix-slab-out-of-bounds-read-in-ea_get.patch new file mode 100644 index 0000000000..3bbc1fee8a --- /dev/null +++ b/queue-6.14/jfs-fix-slab-out-of-bounds-read-in-ea_get.patch @@ -0,0 +1,93 @@ +From fdf480da5837c23b146c4743c18de97202fcab37 Mon Sep 17 00:00:00 2001 +From: Qasim Ijaz +Date: Thu, 13 Feb 2025 21:05:53 +0000 +Subject: jfs: fix slab-out-of-bounds read in ea_get() + +From: Qasim Ijaz + +commit fdf480da5837c23b146c4743c18de97202fcab37 upstream. + +During the "size_check" label in ea_get(), the code checks if the extended +attribute list (xattr) size matches ea_size. If not, it logs +"ea_get: invalid extended attribute" and calls print_hex_dump(). + +Here, EALIST_SIZE(ea_buf->xattr) returns 4110417968, which exceeds +INT_MAX (2,147,483,647). Then ea_size is clamped: + + int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr)); + +Although clamp_t aims to bound ea_size between 0 and 4110417968, the upper +limit is treated as an int, causing an overflow above 2^31 - 1. This leads +"size" to wrap around and become negative (-184549328). + +The "size" is then passed to print_hex_dump() (called "len" in +print_hex_dump()), it is passed as type size_t (an unsigned +type), this is then stored inside a variable called +"int remaining", which is then assigned to "int linelen" which +is then passed to hex_dump_to_buffer(). In print_hex_dump() +the for loop, iterates through 0 to len-1, where len is +18446744073525002176, calling hex_dump_to_buffer() +on each iteration: + + for (i = 0; i < len; i += rowsize) { + linelen = min(remaining, rowsize); + remaining -= rowsize; + + hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, + linebuf, sizeof(linebuf), ascii); + + ... + } + +The expected stopping condition (i < len) is effectively broken +since len is corrupted and very large. This eventually leads to +the "ptr+i" being passed to hex_dump_to_buffer() to get closer +to the end of the actual bounds of "ptr", eventually an out of +bounds access is done in hex_dump_to_buffer() in the following +for loop: + + for (j = 0; j < len; j++) { + if (linebuflen < lx + 2) + goto overflow2; + ch = ptr[j]; + ... + } + +To fix this we should validate "EALIST_SIZE(ea_buf->xattr)" +before it is utilised. + +Reported-by: syzbot +Tested-by: syzbot +Closes: https://syzkaller.appspot.com/bug?extid=4e6e7e4279d046613bc5 +Fixes: d9f9d96136cb ("jfs: xattr: check invalid xattr size more strictly") +Cc: stable@vger.kernel.org +Signed-off-by: Qasim Ijaz +Signed-off-by: Dave Kleikamp +Signed-off-by: Greg Kroah-Hartman +--- + fs/jfs/xattr.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/fs/jfs/xattr.c ++++ b/fs/jfs/xattr.c +@@ -559,11 +559,16 @@ static int ea_get(struct inode *inode, s + + size_check: + if (EALIST_SIZE(ea_buf->xattr) != ea_size) { +- int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr)); ++ if (unlikely(EALIST_SIZE(ea_buf->xattr) > INT_MAX)) { ++ printk(KERN_ERR "ea_get: extended attribute size too large: %u > INT_MAX\n", ++ EALIST_SIZE(ea_buf->xattr)); ++ } else { ++ int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr)); + +- printk(KERN_ERR "ea_get: invalid extended attribute\n"); +- print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, +- ea_buf->xattr, size, 1); ++ printk(KERN_ERR "ea_get: invalid extended attribute\n"); ++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, ++ ea_buf->xattr, size, 1); ++ } + ea_release(inode, ea_buf); + rc = -EIO; + goto clean_up; diff --git a/queue-6.14/ksmbd-add-bounds-check-for-create-lease-context.patch b/queue-6.14/ksmbd-add-bounds-check-for-create-lease-context.patch new file mode 100644 index 0000000000..e2af98e604 --- /dev/null +++ b/queue-6.14/ksmbd-add-bounds-check-for-create-lease-context.patch @@ -0,0 +1,46 @@ +From bab703ed8472aa9d109c5f8c1863921533363dae Mon Sep 17 00:00:00 2001 +From: Norbert Szetei +Date: Sat, 15 Mar 2025 12:19:28 +0900 +Subject: ksmbd: add bounds check for create lease context + +From: Norbert Szetei + +commit bab703ed8472aa9d109c5f8c1863921533363dae upstream. + +Add missing bounds check for create lease context. + +Cc: stable@vger.kernel.org +Reported-by: Norbert Szetei +Tested-by: Norbert Szetei +Signed-off-by: Norbert Szetei +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/oplock.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -1505,6 +1505,10 @@ struct lease_ctx_info *parse_lease_state + if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) { + struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; + ++ if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) < ++ sizeof(struct create_lease_v2) - 4) ++ return NULL; ++ + memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); + lreq->req_state = lc->lcontext.LeaseState; + lreq->flags = lc->lcontext.LeaseFlags; +@@ -1517,6 +1521,10 @@ struct lease_ctx_info *parse_lease_state + } else { + struct create_lease *lc = (struct create_lease *)cc; + ++ if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) < ++ sizeof(struct create_lease)) ++ return NULL; ++ + memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); + lreq->req_state = lc->lcontext.LeaseState; + lreq->flags = lc->lcontext.LeaseFlags; diff --git a/queue-6.14/ksmbd-add-bounds-check-for-durable-handle-context.patch b/queue-6.14/ksmbd-add-bounds-check-for-durable-handle-context.patch new file mode 100644 index 0000000000..a5dc7fc4bb --- /dev/null +++ b/queue-6.14/ksmbd-add-bounds-check-for-durable-handle-context.patch @@ -0,0 +1,65 @@ +From 542027e123fc0bfd61dd59e21ae0ee4ef2101b29 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Fri, 14 Mar 2025 18:21:47 +0900 +Subject: ksmbd: add bounds check for durable handle context + +From: Namjae Jeon + +commit 542027e123fc0bfd61dd59e21ae0ee4ef2101b29 upstream. + +Add missing bounds check for durable handle context. + +Cc: stable@vger.kernel.org +Reported-by: Norbert Szetei +Tested-by: Norbert Szetei +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smb2pdu.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2704,6 +2704,13 @@ static int parse_durable_handle_context( + goto out; + } + ++ if (le16_to_cpu(context->DataOffset) + ++ le32_to_cpu(context->DataLength) < ++ sizeof(struct create_durable_reconn_v2_req)) { ++ err = -EINVAL; ++ goto out; ++ } ++ + recon_v2 = (struct create_durable_reconn_v2_req *)context; + persistent_id = recon_v2->Fid.PersistentFileId; + dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); +@@ -2737,6 +2744,13 @@ static int parse_durable_handle_context( + goto out; + } + ++ if (le16_to_cpu(context->DataOffset) + ++ le32_to_cpu(context->DataLength) < ++ sizeof(struct create_durable_reconn_req)) { ++ err = -EINVAL; ++ goto out; ++ } ++ + recon = (struct create_durable_reconn_req *)context; + persistent_id = recon->Data.Fid.PersistentFileId; + dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); +@@ -2761,6 +2775,13 @@ static int parse_durable_handle_context( + err = -EINVAL; + goto out; + } ++ ++ if (le16_to_cpu(context->DataOffset) + ++ le32_to_cpu(context->DataLength) < ++ sizeof(struct create_durable_req_v2)) { ++ err = -EINVAL; ++ goto out; ++ } + + durable_v2_blob = + (struct create_durable_req_v2 *)context; diff --git a/queue-6.14/ksmbd-fix-null-pointer-dereference-in-alloc_preauth_hash.patch b/queue-6.14/ksmbd-fix-null-pointer-dereference-in-alloc_preauth_hash.patch new file mode 100644 index 0000000000..2f854ca583 --- /dev/null +++ b/queue-6.14/ksmbd-fix-null-pointer-dereference-in-alloc_preauth_hash.patch @@ -0,0 +1,130 @@ +From c8b5b7c5da7d0c31c9b7190b4a7bba5281fc4780 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 2 Apr 2025 09:11:23 +0900 +Subject: ksmbd: fix null pointer dereference in alloc_preauth_hash() + +From: Namjae Jeon + +commit c8b5b7c5da7d0c31c9b7190b4a7bba5281fc4780 upstream. + +The Client send malformed smb2 negotiate request. ksmbd return error +response. Subsequently, the client can send smb2 session setup even +thought conn->preauth_info is not allocated. +This patch add KSMBD_SESS_NEED_SETUP status of connection to ignore +session setup request if smb2 negotiate phase is not complete. + +Cc: stable@vger.kernel.org +Tested-by: Steve French +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-26505 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/connection.h | 11 +++++++++++ + fs/smb/server/mgmt/user_session.c | 4 ++-- + fs/smb/server/smb2pdu.c | 14 +++++++++++--- + 3 files changed, 24 insertions(+), 5 deletions(-) + +--- a/fs/smb/server/connection.h ++++ b/fs/smb/server/connection.h +@@ -27,6 +27,7 @@ enum { + KSMBD_SESS_EXITING, + KSMBD_SESS_NEED_RECONNECT, + KSMBD_SESS_NEED_NEGOTIATE, ++ KSMBD_SESS_NEED_SETUP, + KSMBD_SESS_RELEASING + }; + +@@ -187,6 +188,11 @@ static inline bool ksmbd_conn_need_negot + return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE; + } + ++static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn) ++{ ++ return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP; ++} ++ + static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn) + { + return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT; +@@ -217,6 +223,11 @@ static inline void ksmbd_conn_set_need_n + WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE); + } + ++static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn) ++{ ++ WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP); ++} ++ + static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn) + { + WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT); +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -374,13 +374,13 @@ void destroy_previous_session(struct ksm + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); + err = ksmbd_conn_wait_idle_sess_id(conn, id); + if (err) { +- ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); ++ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); + goto out; + } + + ksmbd_destroy_file_table(&prev_sess->file_table); + prev_sess->state = SMB2_SESSION_EXPIRED; +- ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); ++ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); + ksmbd_launch_ksmbd_durable_scavenger(); + out: + up_write(&conn->session_lock); +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -1249,7 +1249,7 @@ int smb2_handle_negotiate(struct ksmbd_w + } + + conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); +- ksmbd_conn_set_need_negotiate(conn); ++ ksmbd_conn_set_need_setup(conn); + + err_out: + ksmbd_conn_unlock(conn); +@@ -1271,6 +1271,9 @@ static int alloc_preauth_hash(struct ksm + if (sess->Preauth_HashValue) + return 0; + ++ if (!conn->preauth_info) ++ return -ENOMEM; ++ + sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue, + PREAUTH_HASHVALUE_SIZE, KSMBD_DEFAULT_GFP); + if (!sess->Preauth_HashValue) +@@ -1674,6 +1677,11 @@ int smb2_sess_setup(struct ksmbd_work *w + + ksmbd_debug(SMB, "Received smb2 session setup request\n"); + ++ if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) { ++ work->send_no_response = 1; ++ return rc; ++ } ++ + WORK_BUFFERS(work, req, rsp); + + rsp->StructureSize = cpu_to_le16(9); +@@ -1909,7 +1917,7 @@ out_err: + if (try_delay) { + ksmbd_conn_set_need_reconnect(conn); + ssleep(5); +- ksmbd_conn_set_need_negotiate(conn); ++ ksmbd_conn_set_need_setup(conn); + } + } + smb2_set_err_rsp(work); +@@ -2243,7 +2251,7 @@ int smb2_session_logoff(struct ksmbd_wor + ksmbd_free_user(sess->user); + sess->user = NULL; + } +- ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); ++ ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP); + + rsp->StructureSize = cpu_to_le16(4); + err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp)); diff --git a/queue-6.14/ksmbd-fix-overflow-in-dacloffset-bounds-check.patch b/queue-6.14/ksmbd-fix-overflow-in-dacloffset-bounds-check.patch new file mode 100644 index 0000000000..f9a13aa400 --- /dev/null +++ b/queue-6.14/ksmbd-fix-overflow-in-dacloffset-bounds-check.patch @@ -0,0 +1,75 @@ +From beff0bc9d69bc8e733f9bca28e2d3df5b3e10e42 Mon Sep 17 00:00:00 2001 +From: Norbert Szetei +Date: Sat, 29 Mar 2025 06:58:15 +0000 +Subject: ksmbd: fix overflow in dacloffset bounds check + +From: Norbert Szetei + +commit beff0bc9d69bc8e733f9bca28e2d3df5b3e10e42 upstream. + +The dacloffset field was originally typed as int and used in an +unchecked addition, which could overflow and bypass the existing +bounds check in both smb_check_perm_dacl() and smb_inherit_dacl(). + +This could result in out-of-bounds memory access and a kernel crash +when dereferencing the DACL pointer. + +This patch converts dacloffset to unsigned int and uses +check_add_overflow() to validate access to the DACL. + +Cc: stable@vger.kernel.org +Signed-off-by: Norbert Szetei +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smbacl.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/fs/smb/server/smbacl.c ++++ b/fs/smb/server/smbacl.c +@@ -1026,7 +1026,9 @@ int smb_inherit_dacl(struct ksmbd_conn * + struct dentry *parent = path->dentry->d_parent; + struct mnt_idmap *idmap = mnt_idmap(path->mnt); + int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size; +- int rc = 0, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size; ++ int rc = 0, pntsd_type, pntsd_size, acl_len, aces_size; ++ unsigned int dacloffset; ++ size_t dacl_struct_end; + u16 num_aces, ace_cnt = 0; + char *aces_base; + bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode); +@@ -1035,8 +1037,11 @@ int smb_inherit_dacl(struct ksmbd_conn * + parent, &parent_pntsd); + if (pntsd_size <= 0) + return -ENOENT; ++ + dacloffset = le32_to_cpu(parent_pntsd->dacloffset); +- if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) { ++ if (!dacloffset || ++ check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) || ++ dacl_struct_end > (size_t)pntsd_size) { + rc = -EINVAL; + goto free_parent_pntsd; + } +@@ -1240,7 +1245,9 @@ int smb_check_perm_dacl(struct ksmbd_con + struct smb_ntsd *pntsd = NULL; + struct smb_acl *pdacl; + struct posix_acl *posix_acls; +- int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset; ++ int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size; ++ unsigned int dacl_offset; ++ size_t dacl_struct_end; + struct smb_sid sid; + int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE); + struct smb_ace *ace; +@@ -1259,7 +1266,8 @@ int smb_check_perm_dacl(struct ksmbd_con + + dacl_offset = le32_to_cpu(pntsd->dacloffset); + if (!dacl_offset || +- (dacl_offset + sizeof(struct smb_acl) > pntsd_size)) ++ check_add_overflow(dacl_offset, sizeof(struct smb_acl), &dacl_struct_end) || ++ dacl_struct_end > (size_t)pntsd_size) + goto err_out; + + pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset)); diff --git a/queue-6.14/ksmbd-fix-session-use-after-free-in-multichannel-connection.patch b/queue-6.14/ksmbd-fix-session-use-after-free-in-multichannel-connection.patch new file mode 100644 index 0000000000..4892e9817c --- /dev/null +++ b/queue-6.14/ksmbd-fix-session-use-after-free-in-multichannel-connection.patch @@ -0,0 +1,110 @@ +From fa4cdb8cbca7d6cb6aa13e4d8d83d1103f6345db Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Thu, 27 Mar 2025 21:22:51 +0900 +Subject: ksmbd: fix session use-after-free in multichannel connection + +From: Namjae Jeon + +commit fa4cdb8cbca7d6cb6aa13e4d8d83d1103f6345db upstream. + +There is a race condition between session setup and +ksmbd_sessions_deregister. The session can be freed before the connection +is added to channel list of session. +This patch check reference count of session before freeing it. + +Cc: stable@vger.kernel.org +Reported-by: Sean Heelan +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/auth.c | 4 ++-- + fs/smb/server/mgmt/user_session.c | 14 ++++++++------ + fs/smb/server/smb2pdu.c | 7 ++++--- + 3 files changed, 14 insertions(+), 11 deletions(-) + +--- a/fs/smb/server/auth.c ++++ b/fs/smb/server/auth.c +@@ -1016,9 +1016,9 @@ static int ksmbd_get_encryption_key(stru + + ses_enc_key = enc ? sess->smb3encryptionkey : + sess->smb3decryptionkey; +- if (enc) +- ksmbd_user_session_get(sess); + memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); ++ if (!enc) ++ ksmbd_user_session_put(sess); + + return 0; + } +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -181,7 +181,7 @@ static void ksmbd_expire_session(struct + down_write(&sessions_table_lock); + down_write(&conn->session_lock); + xa_for_each(&conn->sessions, id, sess) { +- if (atomic_read(&sess->refcnt) == 0 && ++ if (atomic_read(&sess->refcnt) <= 1 && + (sess->state != SMB2_SESSION_VALID || + time_after(jiffies, + sess->last_active + SMB2_SESSION_TIMEOUT))) { +@@ -233,7 +233,8 @@ void ksmbd_sessions_deregister(struct ks + down_write(&conn->session_lock); + xa_erase(&conn->sessions, sess->id); + up_write(&conn->session_lock); +- ksmbd_session_destroy(sess); ++ if (atomic_dec_and_test(&sess->refcnt)) ++ ksmbd_session_destroy(sess); + } + } + } +@@ -252,7 +253,8 @@ void ksmbd_sessions_deregister(struct ks + if (xa_empty(&sess->ksmbd_chann_list)) { + xa_erase(&conn->sessions, sess->id); + hash_del(&sess->hlist); +- ksmbd_session_destroy(sess); ++ if (atomic_dec_and_test(&sess->refcnt)) ++ ksmbd_session_destroy(sess); + } + } + up_write(&conn->session_lock); +@@ -328,8 +330,8 @@ void ksmbd_user_session_put(struct ksmbd + + if (atomic_read(&sess->refcnt) <= 0) + WARN_ON(1); +- else +- atomic_dec(&sess->refcnt); ++ else if (atomic_dec_and_test(&sess->refcnt)) ++ ksmbd_session_destroy(sess); + } + + struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, +@@ -436,7 +438,7 @@ static struct ksmbd_session *__session_c + xa_init(&sess->rpc_handle_list); + sess->sequence_number = 1; + rwlock_init(&sess->tree_conns_lock); +- atomic_set(&sess->refcnt, 1); ++ atomic_set(&sess->refcnt, 2); + + ret = __init_smb2_session(sess); + if (ret) +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2235,13 +2235,14 @@ int smb2_session_logoff(struct ksmbd_wor + return -ENOENT; + } + +- ksmbd_destroy_file_table(&sess->file_table); + down_write(&conn->session_lock); + sess->state = SMB2_SESSION_EXPIRED; + up_write(&conn->session_lock); + +- ksmbd_free_user(sess->user); +- sess->user = NULL; ++ if (sess->user) { ++ ksmbd_free_user(sess->user); ++ sess->user = NULL; ++ } + ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); + + rsp->StructureSize = cpu_to_le16(4); diff --git a/queue-6.14/ksmbd-fix-use-after-free-in-ksmbd_sessions_deregister.patch b/queue-6.14/ksmbd-fix-use-after-free-in-ksmbd_sessions_deregister.patch new file mode 100644 index 0000000000..dc186dfc6a --- /dev/null +++ b/queue-6.14/ksmbd-fix-use-after-free-in-ksmbd_sessions_deregister.patch @@ -0,0 +1,36 @@ +From 15a9605f8d69dc85005b1a00c31a050b8625e1aa Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Sat, 22 Mar 2025 09:20:19 +0900 +Subject: ksmbd: fix use-after-free in ksmbd_sessions_deregister() + +From: Namjae Jeon + +commit 15a9605f8d69dc85005b1a00c31a050b8625e1aa upstream. + +In multichannel mode, UAF issue can occur in session_deregister +when the second channel sets up a session through the connection of +the first channel. session that is freed through the global session +table can be accessed again through ->sessions of connection. + +Cc: stable@vger.kernel.org +Reported-by: Norbert Szetei +Tested-by: Norbert Szetei +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/mgmt/user_session.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -230,6 +230,9 @@ void ksmbd_sessions_deregister(struct ks + if (!ksmbd_chann_del(conn, sess) && + xa_empty(&sess->ksmbd_chann_list)) { + hash_del(&sess->hlist); ++ down_write(&conn->session_lock); ++ xa_erase(&conn->sessions, sess->id); ++ up_write(&conn->session_lock); + ksmbd_session_destroy(sess); + } + } diff --git a/queue-6.14/ksmbd-validate-zero-num_subauth-before-sub_auth-is-accessed.patch b/queue-6.14/ksmbd-validate-zero-num_subauth-before-sub_auth-is-accessed.patch new file mode 100644 index 0000000000..748fc33edb --- /dev/null +++ b/queue-6.14/ksmbd-validate-zero-num_subauth-before-sub_auth-is-accessed.patch @@ -0,0 +1,37 @@ +From bf21e29d78cd2c2371023953d9c82dfef82ebb36 Mon Sep 17 00:00:00 2001 +From: Norbert Szetei +Date: Sat, 29 Mar 2025 16:06:01 +0000 +Subject: ksmbd: validate zero num_subauth before sub_auth is accessed + +From: Norbert Szetei + +commit bf21e29d78cd2c2371023953d9c82dfef82ebb36 upstream. + +Access psid->sub_auth[psid->num_subauth - 1] without checking +if num_subauth is non-zero leads to an out-of-bounds read. +This patch adds a validation step to ensure num_subauth != 0 +before sub_auth is accessed. + +Cc: stable@vger.kernel.org +Signed-off-by: Norbert Szetei +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smbacl.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/smb/server/smbacl.c ++++ b/fs/smb/server/smbacl.c +@@ -270,6 +270,11 @@ static int sid_to_id(struct mnt_idmap *i + return -EIO; + } + ++ if (psid->num_subauth == 0) { ++ pr_err("%s: zero subauthorities!\n", __func__); ++ return -EIO; ++ } ++ + if (sidtype == SIDOWNER) { + kuid_t uid; + uid_t id; diff --git a/queue-6.14/kvm-svm-don-t-change-target-vcpu-state-on-ap-creation-vmgexit-error.patch b/queue-6.14/kvm-svm-don-t-change-target-vcpu-state-on-ap-creation-vmgexit-error.patch new file mode 100644 index 0000000000..a987b46b47 --- /dev/null +++ b/queue-6.14/kvm-svm-don-t-change-target-vcpu-state-on-ap-creation-vmgexit-error.patch @@ -0,0 +1,78 @@ +From d26638bfcdfc5c8c4e085dc3f5976a0443abab3c Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Wed, 26 Feb 2025 17:25:35 -0800 +Subject: KVM: SVM: Don't change target vCPU state on AP Creation VMGEXIT error + +From: Sean Christopherson + +commit d26638bfcdfc5c8c4e085dc3f5976a0443abab3c upstream. + +If KVM rejects an AP Creation event, leave the target vCPU state as-is. +Nothing in the GHCB suggests the hypervisor is *allowed* to muck with vCPU +state on failure, let alone required to do so. Furthermore, kicking only +in the !ON_INIT case leads to divergent behavior, and even the "kick" case +is non-deterministic. + +E.g. if an ON_INIT request fails, the guest can successfully retry if the +fixed AP Creation request is made prior to sending INIT. And if a !ON_INIT +fails, the guest can successfully retry if the fixed AP Creation request is +handled before the target vCPU processes KVM's +KVM_REQ_UPDATE_PROTECTED_GUEST_STATE. + +Fixes: e366f92ea99e ("KVM: SEV: Support SEV-SNP AP Creation NAE event") +Cc: stable@vger.kernel.org +Reviewed-by: Tom Lendacky +Reviewed-by: Pankaj Gupta +Link: https://lore.kernel.org/r/20250227012541.3234589-5-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/sev.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/arch/x86/kvm/svm/sev.c ++++ b/arch/x86/kvm/svm/sev.c +@@ -3969,16 +3969,12 @@ static int sev_snp_ap_creation(struct vc + + /* + * The target vCPU is valid, so the vCPU will be kicked unless the +- * request is for CREATE_ON_INIT. For any errors at this stage, the +- * kick will place the vCPU in an non-runnable state. ++ * request is for CREATE_ON_INIT. + */ + kick = true; + + mutex_lock(&target_svm->sev_es.snp_vmsa_mutex); + +- target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE; +- target_svm->sev_es.snp_ap_waiting_for_reset = true; +- + /* Interrupt injection mode shouldn't change for AP creation */ + if (request < SVM_VMGEXIT_AP_DESTROY) { + u64 sev_features; +@@ -4024,20 +4020,23 @@ static int sev_snp_ap_creation(struct vc + target_svm->sev_es.snp_vmsa_gpa = svm->vmcb->control.exit_info_2; + break; + case SVM_VMGEXIT_AP_DESTROY: ++ target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE; + break; + default: + vcpu_unimpl(vcpu, "vmgexit: invalid AP creation request [%#x] from guest\n", + request); + ret = -EINVAL; +- break; ++ goto out; + } + +-out: ++ target_svm->sev_es.snp_ap_waiting_for_reset = true; ++ + if (kick) { + kvm_make_request(KVM_REQ_UPDATE_PROTECTED_GUEST_STATE, target_vcpu); + kvm_vcpu_kick(target_vcpu); + } + ++out: + mutex_unlock(&target_svm->sev_es.snp_vmsa_mutex); + + return ret; diff --git a/queue-6.14/media-streamzap-fix-race-between-device-disconnection-and-urb-callback.patch b/queue-6.14/media-streamzap-fix-race-between-device-disconnection-and-urb-callback.patch new file mode 100644 index 0000000000..83a2765423 --- /dev/null +++ b/queue-6.14/media-streamzap-fix-race-between-device-disconnection-and-urb-callback.patch @@ -0,0 +1,48 @@ +From f656cfbc7a293a039d6a0c7100e1c846845148c1 Mon Sep 17 00:00:00 2001 +From: Murad Masimov +Date: Mon, 13 Jan 2025 13:51:30 +0300 +Subject: media: streamzap: fix race between device disconnection and urb callback + +From: Murad Masimov + +commit f656cfbc7a293a039d6a0c7100e1c846845148c1 upstream. + +Syzkaller has reported a general protection fault at function +ir_raw_event_store_with_filter(). This crash is caused by a NULL pointer +dereference of dev->raw pointer, even though it is checked for NULL in +the same function, which means there is a race condition. It occurs due +to the incorrect order of actions in the streamzap_disconnect() function: +rc_unregister_device() is called before usb_kill_urb(). The dev->raw +pointer is freed and set to NULL in rc_unregister_device(), and only +after that usb_kill_urb() waits for in-progress requests to finish. + +If rc_unregister_device() is called while streamzap_callback() handler is +not finished, this can lead to accessing freed resources. Thus +rc_unregister_device() should be called after usb_kill_urb(). + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 8e9e60640067 ("V4L/DVB: staging/lirc: port lirc_streamzap to ir-core") +Cc: stable@vger.kernel.org +Reported-by: syzbot+34008406ee9a31b13c73@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=34008406ee9a31b13c73 +Signed-off-by: Murad Masimov +Signed-off-by: Sean Young +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/rc/streamzap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -385,8 +385,8 @@ static void streamzap_disconnect(struct + if (!sz) + return; + +- rc_unregister_device(sz->rdev); + usb_kill_urb(sz->urb_in); ++ rc_unregister_device(sz->rdev); + usb_free_urb(sz->urb_in); + usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); + diff --git a/queue-6.14/media-vimc-skip-.s_stream-for-stopped-entities.patch b/queue-6.14/media-vimc-skip-.s_stream-for-stopped-entities.patch new file mode 100644 index 0000000000..b697460a60 --- /dev/null +++ b/queue-6.14/media-vimc-skip-.s_stream-for-stopped-entities.patch @@ -0,0 +1,72 @@ +From 36cef585e2a31e4ddf33a004b0584a7a572246de Mon Sep 17 00:00:00 2001 +From: Nikita Zhandarovich +Date: Sun, 2 Mar 2025 17:58:25 +0300 +Subject: media: vimc: skip .s_stream() for stopped entities + +From: Nikita Zhandarovich + +commit 36cef585e2a31e4ddf33a004b0584a7a572246de upstream. + +Syzbot reported [1] a warning prompted by a check in call_s_stream() +that checks whether .s_stream() operation is warranted for unstarted +or stopped subdevs. + +Add a simple fix in vimc_streamer_pipeline_terminate() ensuring that +entities skip a call to .s_stream() unless they have been previously +properly started. + +[1] Syzbot report: +------------[ cut here ]------------ +WARNING: CPU: 0 PID: 5933 at drivers/media/v4l2-core/v4l2-subdev.c:460 call_s_stream+0x2df/0x350 drivers/media/v4l2-core/v4l2-subdev.c:460 +Modules linked in: +CPU: 0 UID: 0 PID: 5933 Comm: syz-executor330 Not tainted 6.13.0-rc2-syzkaller-00362-g2d8308bf5b67 #0 +... +Call Trace: + + vimc_streamer_pipeline_terminate+0x218/0x320 drivers/media/test-drivers/vimc/vimc-streamer.c:62 + vimc_streamer_pipeline_init drivers/media/test-drivers/vimc/vimc-streamer.c:101 [inline] + vimc_streamer_s_stream+0x650/0x9a0 drivers/media/test-drivers/vimc/vimc-streamer.c:203 + vimc_capture_start_streaming+0xa1/0x130 drivers/media/test-drivers/vimc/vimc-capture.c:256 + vb2_start_streaming+0x15f/0x5a0 drivers/media/common/videobuf2/videobuf2-core.c:1789 + vb2_core_streamon+0x2a7/0x450 drivers/media/common/videobuf2/videobuf2-core.c:2348 + vb2_streamon drivers/media/common/videobuf2/videobuf2-v4l2.c:875 [inline] + vb2_ioctl_streamon+0xf4/0x170 drivers/media/common/videobuf2/videobuf2-v4l2.c:1118 + __video_do_ioctl+0xaf0/0xf00 drivers/media/v4l2-core/v4l2-ioctl.c:3122 + video_usercopy+0x4d2/0x1620 drivers/media/v4l2-core/v4l2-ioctl.c:3463 + v4l2_ioctl+0x1ba/0x250 drivers/media/v4l2-core/v4l2-dev.c:366 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:906 [inline] + __se_sys_ioctl fs/ioctl.c:892 [inline] + __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f2b85c01b19 +... + +Reported-by: syzbot+5bcd7c809d365e14c4df@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=5bcd7c809d365e14c4df +Fixes: adc589d2a208 ("media: vimc: Add vimc-streamer for stream control") +Cc: stable@vger.kernel.org +Signed-off-by: Nikita Zhandarovich +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/test-drivers/vimc/vimc-streamer.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/media/test-drivers/vimc/vimc-streamer.c ++++ b/drivers/media/test-drivers/vimc/vimc-streamer.c +@@ -59,6 +59,12 @@ static void vimc_streamer_pipeline_termi + continue; + + sd = media_entity_to_v4l2_subdev(ved->ent); ++ /* ++ * Do not call .s_stream() to stop an already ++ * stopped/unstarted subdev. ++ */ ++ if (!v4l2_subdev_is_streaming(sd)) ++ continue; + v4l2_subdev_call(sd, video, s_stream, 0); + } + } diff --git a/queue-6.14/mm-gup-reject-foll_split_pmd-with-hugetlb-vmas.patch b/queue-6.14/mm-gup-reject-foll_split_pmd-with-hugetlb-vmas.patch new file mode 100644 index 0000000000..cb735705f7 --- /dev/null +++ b/queue-6.14/mm-gup-reject-foll_split_pmd-with-hugetlb-vmas.patch @@ -0,0 +1,249 @@ +From 8977752c8056a6a094a279004a49722da15bace3 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Mon, 10 Feb 2025 20:37:43 +0100 +Subject: mm/gup: reject FOLL_SPLIT_PMD with hugetlb VMAs + +From: David Hildenbrand + +commit 8977752c8056a6a094a279004a49722da15bace3 upstream. + +Patch series "mm: fixes for device-exclusive entries (hmm)", v2. + +Discussing the PageTail() call in make_device_exclusive_range() with +Willy, I recently discovered [1] that device-exclusive handling does not +properly work with THP, making the hmm-tests selftests fail if THPs are +enabled on the system. + +Looking into more details, I found that hugetlb is not properly fenced, +and I realized that something that was bugging me for longer -- how +device-exclusive entries interact with mapcounts -- completely breaks +migration/swapout/split/hwpoison handling of these folios while they have +device-exclusive PTEs. + +The program below can be used to allocate 1 GiB worth of pages and making +them device-exclusive on a kernel with CONFIG_TEST_HMM. + +Once they are device-exclusive, these folios cannot get swapped out +(proc$pid/smaps_rollup will always indicate 1 GiB RSS no matter how much +one forces memory reclaim), and when having a memory block onlined to +ZONE_MOVABLE, trying to offline it will loop forever and complain about +failed migration of a page that should be movable. + +# echo offline > /sys/devices/system/memory/memory136/state +# echo online_movable > /sys/devices/system/memory/memory136/state +# ./hmm-swap & +... wait until everything is device-exclusive +# echo offline > /sys/devices/system/memory/memory136/state +[ 285.193431][T14882] page: refcount:2 mapcount:0 mapping:0000000000000000 + index:0x7f20671f7 pfn:0x442b6a +[ 285.196618][T14882] memcg:ffff888179298000 +[ 285.198085][T14882] anon flags: 0x5fff0000002091c(referenced|uptodate| + dirty|active|owner_2|swapbacked|node=1|zone=3|lastcpupid=0x7ff) +[ 285.201734][T14882] raw: ... +[ 285.204464][T14882] raw: ... +[ 285.207196][T14882] page dumped because: migration failure +[ 285.209072][T14882] page_owner tracks the page as allocated +[ 285.210915][T14882] page last allocated via order 0, migratetype + Movable, gfp_mask 0x140dca(GFP_HIGHUSER_MOVABLE|__GFP_COMP|__GFP_ZERO), + id 14926, tgid 14926 (hmm-swap), ts 254506295376, free_ts 227402023774 +[ 285.216765][T14882] post_alloc_hook+0x197/0x1b0 +[ 285.218874][T14882] get_page_from_freelist+0x76e/0x3280 +[ 285.220864][T14882] __alloc_frozen_pages_noprof+0x38e/0x2740 +[ 285.223302][T14882] alloc_pages_mpol+0x1fc/0x540 +[ 285.225130][T14882] folio_alloc_mpol_noprof+0x36/0x340 +[ 285.227222][T14882] vma_alloc_folio_noprof+0xee/0x1a0 +[ 285.229074][T14882] __handle_mm_fault+0x2b38/0x56a0 +[ 285.230822][T14882] handle_mm_fault+0x368/0x9f0 +... + +This series fixes all issues I found so far. There is no easy way to fix +without a bigger rework/cleanup. I have a bunch of cleanups on top (some +previous sent, some the result of the discussion in v1) that I will send +out separately once this landed and I get to it. + +I wish we could just use some special present PROT_NONE PTEs instead of +these (non-present, non-none) fake-swap entries; but that just results in +the same problem we keep having (lack of spare PTE bits), and staring at +other similar fake-swap entries, that ship has sailed. + +With this series, make_device_exclusive() doesn't actually belong into +mm/rmap.c anymore, but I'll leave moving that for another day. + +I only tested this series with the hmm-tests selftests due to lack of HW, +so I'd appreciate some testing, especially if the interaction between two +GPUs wanting a device-exclusive entry works as expected. + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HMM_DMIRROR_EXCLUSIVE _IOWR('H', 0x05, struct hmm_dmirror_cmd) + +struct hmm_dmirror_cmd { + __u64 addr; + __u64 ptr; + __u64 npages; + __u64 cpages; + __u64 faults; +}; + +const size_t size = 1 * 1024 * 1024 * 1024ul; +const size_t chunk_size = 2 * 1024 * 1024ul; + +int main(void) +{ + struct hmm_dmirror_cmd cmd; + size_t cur_size; + int fd, ret; + char *addr, *mirror; + + fd = open("/dev/hmm_dmirror1", O_RDWR, 0); + if (fd < 0) { + perror("open failed\n"); + exit(1); + } + + addr = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (addr == MAP_FAILED) { + perror("mmap failed\n"); + exit(1); + } + madvise(addr, size, MADV_NOHUGEPAGE); + memset(addr, 1, size); + + mirror = malloc(chunk_size); + + for (cur_size = 0; cur_size < size; cur_size += chunk_size) { + cmd.addr = (uintptr_t)addr + cur_size; + cmd.ptr = (uintptr_t)mirror; + cmd.npages = chunk_size / getpagesize(); + ret = ioctl(fd, HMM_DMIRROR_EXCLUSIVE, &cmd); + if (ret) { + perror("ioctl failed\n"); + exit(1); + } + } + pause(); + return 0; +} + + +[1] https://lkml.kernel.org/r/25e02685-4f1d-47fa-be5b-01ff85bb0ce2@redhat.com + + +This patch (of 17): + +We only have two FOLL_SPLIT_PMD users. While uprobe refuses hugetlb +early, make_device_exclusive_range() can end up getting called on hugetlb +VMAs. + +Right now, this means that with a PMD-sized hugetlb page, we can end up +calling split_huge_pmd(), because pmd_trans_huge() also succeeds with +hugetlb PMDs. + +For example, using a modified hmm-test selftest one can trigger: + +[ 207.017134][T14945] ------------[ cut here ]------------ +[ 207.018614][T14945] kernel BUG at mm/page_table_check.c:87! +[ 207.019716][T14945] Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI +[ 207.021072][T14945] CPU: 3 UID: 0 PID: ... +[ 207.023036][T14945] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014 +[ 207.024834][T14945] RIP: 0010:page_table_check_clear.part.0+0x488/0x510 +[ 207.026128][T14945] Code: ... +[ 207.029965][T14945] RSP: 0018:ffffc9000cb8f348 EFLAGS: 00010293 +[ 207.031139][T14945] RAX: 0000000000000000 RBX: 00000000ffffffff RCX: ffffffff8249a0cd +[ 207.032649][T14945] RDX: ffff88811e883c80 RSI: ffffffff8249a357 RDI: ffff88811e883c80 +[ 207.034183][T14945] RBP: ffff888105c0a050 R08: 0000000000000005 R09: 0000000000000000 +[ 207.035688][T14945] R10: 00000000ffffffff R11: 0000000000000003 R12: 0000000000000001 +[ 207.037203][T14945] R13: 0000000000000200 R14: 0000000000000001 R15: dffffc0000000000 +[ 207.038711][T14945] FS: 00007f2783275740(0000) GS:ffff8881f4980000(0000) knlGS:0000000000000000 +[ 207.040407][T14945] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 207.041660][T14945] CR2: 00007f2782c00000 CR3: 0000000132356000 CR4: 0000000000750ef0 +[ 207.043196][T14945] PKRU: 55555554 +[ 207.043880][T14945] Call Trace: +[ 207.044506][T14945] +[ 207.045086][T14945] ? __die+0x51/0x92 +[ 207.045864][T14945] ? die+0x29/0x50 +[ 207.046596][T14945] ? do_trap+0x250/0x320 +[ 207.047430][T14945] ? do_error_trap+0xe7/0x220 +[ 207.048346][T14945] ? page_table_check_clear.part.0+0x488/0x510 +[ 207.049535][T14945] ? handle_invalid_op+0x34/0x40 +[ 207.050494][T14945] ? page_table_check_clear.part.0+0x488/0x510 +[ 207.051681][T14945] ? exc_invalid_op+0x2e/0x50 +[ 207.052589][T14945] ? asm_exc_invalid_op+0x1a/0x20 +[ 207.053596][T14945] ? page_table_check_clear.part.0+0x1fd/0x510 +[ 207.054790][T14945] ? page_table_check_clear.part.0+0x487/0x510 +[ 207.055993][T14945] ? page_table_check_clear.part.0+0x488/0x510 +[ 207.057195][T14945] ? page_table_check_clear.part.0+0x487/0x510 +[ 207.058384][T14945] __page_table_check_pmd_clear+0x34b/0x5a0 +[ 207.059524][T14945] ? __pfx___page_table_check_pmd_clear+0x10/0x10 +[ 207.060775][T14945] ? __pfx___mutex_unlock_slowpath+0x10/0x10 +[ 207.061940][T14945] ? __pfx___lock_acquire+0x10/0x10 +[ 207.062967][T14945] pmdp_huge_clear_flush+0x279/0x360 +[ 207.064024][T14945] split_huge_pmd_locked+0x82b/0x3750 +... + +Before commit 9cb28da54643 ("mm/gup: handle hugetlb in the generic +follow_page_mask code"), we would have ignored the flag; instead, let's +simply refuse the combination completely in check_vma_flags(): the caller +is likely not prepared to handle any hugetlb folios. + +We'll teach make_device_exclusive_range() separately to ignore any hugetlb +folios as a future-proof safety net. + +Link: https://lkml.kernel.org/r/20250210193801.781278-1-david@redhat.com +Link: https://lkml.kernel.org/r/20250210193801.781278-2-david@redhat.com +Fixes: 9cb28da54643 ("mm/gup: handle hugetlb in the generic follow_page_mask code") +Signed-off-by: David Hildenbrand +Reviewed-by: John Hubbard +Reviewed-by: Alistair Popple +Tested-by: Alistair Popple +Cc: Alex Shi +Cc: Danilo Krummrich +Cc: Dave Airlie +Cc: Jann Horn +Cc: Jason Gunthorpe +Cc: Jerome Glisse +Cc: Jonathan Corbet +Cc: Karol Herbst +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Lyude +Cc: "Masami Hiramatsu (Google)" +Cc: Oleg Nesterov +Cc: Pasha Tatashin +Cc: Peter Xu +Cc: Peter Zijlstra (Intel) +Cc: SeongJae Park +Cc: Vlastimil Babka +Cc: Yanteng Si +Cc: Simona Vetter +Cc: Barry Song +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/gup.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1283,6 +1283,9 @@ static int check_vma_flags(struct vm_are + if ((gup_flags & FOLL_LONGTERM) && vma_is_fsdax(vma)) + return -EOPNOTSUPP; + ++ if ((gup_flags & FOLL_SPLIT_PMD) && is_vm_hugetlb_page(vma)) ++ return -EOPNOTSUPP; ++ + if (vma_is_secretmem(vma)) + return -EFAULT; + diff --git a/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch b/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch new file mode 100644 index 0000000000..df9096820d --- /dev/null +++ b/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch @@ -0,0 +1,101 @@ +From 1b0449544c6482179ac84530b61fc192a6527bfd Mon Sep 17 00:00:00 2001 +From: Jinjiang Tu +Date: Tue, 18 Mar 2025 16:39:39 +0800 +Subject: mm/vmscan: don't try to reclaim hwpoison folio + +From: Jinjiang Tu + +commit 1b0449544c6482179ac84530b61fc192a6527bfd upstream. + +Syzkaller reports a bug as follows: + +Injecting memory failure for pfn 0x18b00e at process virtual address 0x20ffd000 +Memory failure: 0x18b00e: dirty swapcache page still referenced by 2 users +Memory failure: 0x18b00e: recovery action for dirty swapcache page: Failed +page: refcount:2 mapcount:0 mapping:0000000000000000 index:0x20ffd pfn:0x18b00e +memcg:ffff0000dd6d9000 +anon flags: 0x5ffffe00482011(locked|dirty|arch_1|swapbacked|hwpoison|node=0|zone=2|lastcpupid=0xfffff) +raw: 005ffffe00482011 dead000000000100 dead000000000122 ffff0000e232a7c9 +raw: 0000000000020ffd 0000000000000000 00000002ffffffff ffff0000dd6d9000 +page dumped because: VM_BUG_ON_FOLIO(!folio_test_uptodate(folio)) +------------[ cut here ]------------ +kernel BUG at mm/swap_state.c:184! +Internal error: Oops - BUG: 00000000f2000800 [#1] SMP +Modules linked in: +CPU: 0 PID: 60 Comm: kswapd0 Not tainted 6.6.0-gcb097e7de84e #3 +Hardware name: linux,dummy-virt (DT) +pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : add_to_swap+0xbc/0x158 +lr : add_to_swap+0xbc/0x158 +sp : ffff800087f37340 +x29: ffff800087f37340 x28: fffffc00052c0380 x27: ffff800087f37780 +x26: ffff800087f37490 x25: ffff800087f37c78 x24: ffff800087f377a0 +x23: ffff800087f37c50 x22: 0000000000000000 x21: fffffc00052c03b4 +x20: 0000000000000000 x19: fffffc00052c0380 x18: 0000000000000000 +x17: 296f696c6f662865 x16: 7461646f7470755f x15: 747365745f6f696c +x14: 6f6621284f494c4f x13: 0000000000000001 x12: ffff600036d8b97b +x11: 1fffe00036d8b97a x10: ffff600036d8b97a x9 : dfff800000000000 +x8 : 00009fffc9274686 x7 : ffff0001b6c5cbd3 x6 : 0000000000000001 +x5 : ffff0000c25896c0 x4 : 0000000000000000 x3 : 0000000000000000 +x2 : 0000000000000000 x1 : ffff0000c25896c0 x0 : 0000000000000000 +Call trace: + add_to_swap+0xbc/0x158 + shrink_folio_list+0x12ac/0x2648 + shrink_inactive_list+0x318/0x948 + shrink_lruvec+0x450/0x720 + shrink_node_memcgs+0x280/0x4a8 + shrink_node+0x128/0x978 + balance_pgdat+0x4f0/0xb20 + kswapd+0x228/0x438 + kthread+0x214/0x230 + ret_from_fork+0x10/0x20 + +I can reproduce this issue with the following steps: + +1) When a dirty swapcache page is isolated by reclaim process and the + page isn't locked, inject memory failure for the page. + me_swapcache_dirty() clears uptodate flag and tries to delete from lru, + but fails. Reclaim process will put the hwpoisoned page back to lru. + +2) The process that maps the hwpoisoned page exits, the page is deleted + the page will never be freed and will be in the lru forever. + +3) If we trigger a reclaim again and tries to reclaim the page, + add_to_swap() will trigger VM_BUG_ON_FOLIO due to the uptodate flag is + cleared. + +To fix it, skip the hwpoisoned page in shrink_folio_list(). Besides, the +hwpoison folio may not be unmapped by hwpoison_user_mappings() yet, unmap +it in shrink_folio_list(), otherwise the folio will fail to be unmaped by +hwpoison_user_mappings() since the folio isn't in lru list. + +Link: https://lkml.kernel.org/r/20250318083939.987651-3-tujinjiang@huawei.com +Signed-off-by: Jinjiang Tu +Acked-by: Miaohe Lin +Cc: David Hildenbrand +Cc: Kefeng Wang +Cc: Nanyong Sun +Cc: Naoya Horiguchi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/vmscan.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -1112,6 +1112,13 @@ retry: + if (!folio_trylock(folio)) + goto keep; + ++ if (folio_contain_hwpoisoned_page(folio)) { ++ unmap_poisoned_folio(folio, folio_pfn(folio), false); ++ folio_unlock(folio); ++ folio_put(folio); ++ continue; ++ } ++ + VM_BUG_ON_FOLIO(folio_test_active(folio), folio); + + nr_pages = folio_nr_pages(folio); diff --git a/queue-6.14/mm-zswap-fix-crypto_free_acomp-deadlock-in-zswap_cpu_comp_dead.patch b/queue-6.14/mm-zswap-fix-crypto_free_acomp-deadlock-in-zswap_cpu_comp_dead.patch new file mode 100644 index 0000000000..717ef7823b --- /dev/null +++ b/queue-6.14/mm-zswap-fix-crypto_free_acomp-deadlock-in-zswap_cpu_comp_dead.patch @@ -0,0 +1,117 @@ +From c11bcbc0a517acf69282c8225059b2a8ac5fe628 Mon Sep 17 00:00:00 2001 +From: Yosry Ahmed +Date: Wed, 26 Feb 2025 18:56:25 +0000 +Subject: mm: zswap: fix crypto_free_acomp() deadlock in zswap_cpu_comp_dead() + +From: Yosry Ahmed + +commit c11bcbc0a517acf69282c8225059b2a8ac5fe628 upstream. + +Currently, zswap_cpu_comp_dead() calls crypto_free_acomp() while holding +the per-CPU acomp_ctx mutex. crypto_free_acomp() then holds scomp_lock +(through crypto_exit_scomp_ops_async()). + +On the other hand, crypto_alloc_acomp_node() holds the scomp_lock (through +crypto_scomp_init_tfm()), and then allocates memory. If the allocation +results in reclaim, we may attempt to hold the per-CPU acomp_ctx mutex. + +The above dependencies can cause an ABBA deadlock. For example in the +following scenario: + +(1) Task A running on CPU #1: + crypto_alloc_acomp_node() + Holds scomp_lock + Enters reclaim + Reads per_cpu_ptr(pool->acomp_ctx, 1) + +(2) Task A is descheduled + +(3) CPU #1 goes offline + zswap_cpu_comp_dead(CPU #1) + Holds per_cpu_ptr(pool->acomp_ctx, 1)) + Calls crypto_free_acomp() + Waits for scomp_lock + +(4) Task A running on CPU #2: + Waits for per_cpu_ptr(pool->acomp_ctx, 1) // Read on CPU #1 + DEADLOCK + +Since there is no requirement to call crypto_free_acomp() with the per-CPU +acomp_ctx mutex held in zswap_cpu_comp_dead(), move it after the mutex is +unlocked. Also move the acomp_request_free() and kfree() calls for +consistency and to avoid any potential sublte locking dependencies in the +future. + +With this, only setting acomp_ctx fields to NULL occurs with the mutex +held. This is similar to how zswap_cpu_comp_prepare() only initializes +acomp_ctx fields with the mutex held, after performing all allocations +before holding the mutex. + +Opportunistically, move the NULL check on acomp_ctx so that it takes place +before the mutex dereference. + +Link: https://lkml.kernel.org/r/20250226185625.2672936-1-yosry.ahmed@linux.dev +Fixes: 12dcb0ef5406 ("mm: zswap: properly synchronize freeing resources during CPU hotunplug") +Signed-off-by: Herbert Xu +Co-developed-by: Herbert Xu +Signed-off-by: Yosry Ahmed +Reported-by: syzbot+1a517ccfcbc6a7ab0f82@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67bcea51.050a0220.bbfd1.0096.GAE@google.com/ +Acked-by: Herbert Xu +Reviewed-by: Chengming Zhou +Reviewed-by: Nhat Pham +Tested-by: Nhat Pham +Cc: David S. Miller +Cc: Eric Biggers +Cc: Johannes Weiner +Cc: Chris Murphy +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/zswap.c | 30 ++++++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 8 deletions(-) + +--- a/mm/zswap.c ++++ b/mm/zswap.c +@@ -881,18 +881,32 @@ static int zswap_cpu_comp_dead(unsigned + { + struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node); + struct crypto_acomp_ctx *acomp_ctx = per_cpu_ptr(pool->acomp_ctx, cpu); ++ struct acomp_req *req; ++ struct crypto_acomp *acomp; ++ u8 *buffer; ++ ++ if (IS_ERR_OR_NULL(acomp_ctx)) ++ return 0; + + mutex_lock(&acomp_ctx->mutex); +- if (!IS_ERR_OR_NULL(acomp_ctx)) { +- if (!IS_ERR_OR_NULL(acomp_ctx->req)) +- acomp_request_free(acomp_ctx->req); +- acomp_ctx->req = NULL; +- if (!IS_ERR_OR_NULL(acomp_ctx->acomp)) +- crypto_free_acomp(acomp_ctx->acomp); +- kfree(acomp_ctx->buffer); +- } ++ req = acomp_ctx->req; ++ acomp = acomp_ctx->acomp; ++ buffer = acomp_ctx->buffer; ++ acomp_ctx->req = NULL; ++ acomp_ctx->acomp = NULL; ++ acomp_ctx->buffer = NULL; + mutex_unlock(&acomp_ctx->mutex); + ++ /* ++ * Do the actual freeing after releasing the mutex to avoid subtle ++ * locking dependencies causing deadlocks. ++ */ ++ if (!IS_ERR_OR_NULL(req)) ++ acomp_request_free(req); ++ if (!IS_ERR_OR_NULL(acomp)) ++ crypto_free_acomp(acomp); ++ kfree(buffer); ++ + return 0; + } + diff --git a/queue-6.14/mmc-omap-fix-memory-leak-in-mmc_omap_new_slot.patch b/queue-6.14/mmc-omap-fix-memory-leak-in-mmc_omap_new_slot.patch new file mode 100644 index 0000000000..05c9d73716 --- /dev/null +++ b/queue-6.14/mmc-omap-fix-memory-leak-in-mmc_omap_new_slot.patch @@ -0,0 +1,65 @@ +From 3834a759afb817e23a7a2f09c2c9911b0ce5c588 Mon Sep 17 00:00:00 2001 +From: Miaoqian Lin +Date: Tue, 18 Mar 2025 22:02:25 +0800 +Subject: mmc: omap: Fix memory leak in mmc_omap_new_slot + +From: Miaoqian Lin + +commit 3834a759afb817e23a7a2f09c2c9911b0ce5c588 upstream. + +Add err_free_host label to properly pair mmc_alloc_host() with +mmc_free_host() in GPIO error paths. The allocated host memory was +leaked when GPIO lookups failed. + +Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") +Signed-off-by: Miaoqian Lin +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20250318140226.19650-1-linmq006@gmail.com +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/omap.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/mmc/host/omap.c ++++ b/drivers/mmc/host/omap.c +@@ -1272,19 +1272,25 @@ static int mmc_omap_new_slot(struct mmc_ + /* Check for some optional GPIO controls */ + slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd", + id, GPIOD_OUT_LOW); +- if (IS_ERR(slot->vsd)) +- return dev_err_probe(host->dev, PTR_ERR(slot->vsd), ++ if (IS_ERR(slot->vsd)) { ++ r = dev_err_probe(host->dev, PTR_ERR(slot->vsd), + "error looking up VSD GPIO\n"); ++ goto err_free_host; ++ } + slot->vio = devm_gpiod_get_index_optional(host->dev, "vio", + id, GPIOD_OUT_LOW); +- if (IS_ERR(slot->vio)) +- return dev_err_probe(host->dev, PTR_ERR(slot->vio), ++ if (IS_ERR(slot->vio)) { ++ r = dev_err_probe(host->dev, PTR_ERR(slot->vio), + "error looking up VIO GPIO\n"); ++ goto err_free_host; ++ } + slot->cover = devm_gpiod_get_index_optional(host->dev, "cover", + id, GPIOD_IN); +- if (IS_ERR(slot->cover)) +- return dev_err_probe(host->dev, PTR_ERR(slot->cover), ++ if (IS_ERR(slot->cover)) { ++ r = dev_err_probe(host->dev, PTR_ERR(slot->cover), + "error looking up cover switch GPIO\n"); ++ goto err_free_host; ++ } + + host->slots[id] = slot; + +@@ -1344,6 +1350,7 @@ err_remove_slot_name: + device_remove_file(&mmc->class_dev, &dev_attr_slot_name); + err_remove_host: + mmc_remove_host(mmc); ++err_free_host: + mmc_free_host(mmc); + return r; + } diff --git a/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qcom_ice_get.patch b/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qcom_ice_get.patch new file mode 100644 index 0000000000..40a60a82f5 --- /dev/null +++ b/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qcom_ice_get.patch @@ -0,0 +1,37 @@ +From cbef7442fba510b7eb229dcc9f39d3dde4a159a4 Mon Sep 17 00:00:00 2001 +From: Tudor Ambarus +Date: Fri, 17 Jan 2025 14:18:51 +0000 +Subject: mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get + +From: Tudor Ambarus + +commit cbef7442fba510b7eb229dcc9f39d3dde4a159a4 upstream. + +The driver leaks the device reference taken with +of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get(). + +Fixes: c7eed31e235c ("mmc: sdhci-msm: Switch to the new ICE API") +Cc: stable@vger.kernel.org +Signed-off-by: Tudor Ambarus +Reviewed-by: Krzysztof Kozlowski +Acked-by: Ulf Hansson +Reviewed-by: Abel Vesa +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-2-1ffa5b6884cb@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci-msm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -1873,7 +1873,7 @@ static int sdhci_msm_ice_init(struct sdh + if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) + return 0; + +- ice = of_qcom_ice_get(dev); ++ ice = devm_of_qcom_ice_get(dev); + if (ice == ERR_PTR(-EOPNOTSUPP)) { + dev_warn(dev, "Disabling inline encryption support\n"); + ice = NULL; diff --git a/queue-6.14/mmc-sdhci-omap-disable-mmc_cap_aggressive_pm-for-emmc-sd.patch b/queue-6.14/mmc-sdhci-omap-disable-mmc_cap_aggressive_pm-for-emmc-sd.patch new file mode 100644 index 0000000000..9dfbd0c2c2 --- /dev/null +++ b/queue-6.14/mmc-sdhci-omap-disable-mmc_cap_aggressive_pm-for-emmc-sd.patch @@ -0,0 +1,41 @@ +From 49d162635151d0dd04935070d7cf67137ab863aa Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Wed, 12 Mar 2025 13:17:12 +0100 +Subject: mmc: sdhci-omap: Disable MMC_CAP_AGGRESSIVE_PM for eMMC/SD + +From: Ulf Hansson + +commit 49d162635151d0dd04935070d7cf67137ab863aa upstream. + +We have received reports about cards can become corrupt related to the +aggressive PM support. Let's make a partial revert of the change that +enabled the feature. + +Reported-by: David Owens +Reported-by: Romain Naour +Reported-by: Robert Nelson +Tested-by: Robert Nelson +Fixes: 3edf588e7fe0 ("mmc: sdhci-omap: Allow SDIO card power off and enable aggressive PM") +Cc: stable@vger.kernel.org +Signed-off-by: Ulf Hansson +Acked-by: Adrian Hunter +Reviewed-by: Tony Lindgren +Link: https://lore.kernel.org/r/20250312121712.1168007-1-ulf.hansson@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci-omap.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mmc/host/sdhci-omap.c ++++ b/drivers/mmc/host/sdhci-omap.c +@@ -1339,8 +1339,8 @@ static int sdhci_omap_probe(struct platf + /* R1B responses is required to properly manage HW busy detection. */ + mmc->caps |= MMC_CAP_NEED_RSP_BUSY; + +- /* Allow card power off and runtime PM for eMMC/SD card devices */ +- mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_AGGRESSIVE_PM; ++ /* Enable SDIO card power off. */ ++ mmc->caps |= MMC_CAP_POWER_OFF_CARD; + + ret = sdhci_setup_host(host); + if (ret) diff --git a/queue-6.14/mmc-sdhci-pxav3-set-need_rsp_busy-capability.patch b/queue-6.14/mmc-sdhci-pxav3-set-need_rsp_busy-capability.patch new file mode 100644 index 0000000000..921d92bfa7 --- /dev/null +++ b/queue-6.14/mmc-sdhci-pxav3-set-need_rsp_busy-capability.patch @@ -0,0 +1,47 @@ +From a41fcca4b342811b473bbaa4b44f1d34d87fcce6 Mon Sep 17 00:00:00 2001 +From: Karel Balej +Date: Mon, 10 Mar 2025 15:07:04 +0100 +Subject: mmc: sdhci-pxav3: set NEED_RSP_BUSY capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Karel Balej + +commit a41fcca4b342811b473bbaa4b44f1d34d87fcce6 upstream. + +Set the MMC_CAP_NEED_RSP_BUSY capability for the sdhci-pxav3 host to +prevent conversion of R1B responses to R1. Without this, the eMMC card +in the samsung,coreprimevelte smartphone using the Marvell PXA1908 SoC +with this mmc host doesn't probe with the ETIMEDOUT error originating in +__mmc_poll_for_busy. + +Note that the other issues reported for this phone and host, namely +floods of "Tuning failed, falling back to fixed sampling clock" dmesg +messages for the eMMC and unstable SDIO are not mitigated by this +change. + +Link: https://lore.kernel.org/r/20200310153340.5593-1-ulf.hansson@linaro.org/ +Link: https://lore.kernel.org/r/D7204PWIGQGI.1FRFQPPIEE2P9@matfyz.cz/ +Link: https://lore.kernel.org/r/20250115-pxa1908-lkml-v14-0-847d24f3665a@skole.hr/ +Cc: stable@vger.kernel.org +Signed-off-by: Karel Balej +Acked-by: Adrian Hunter +Tested-by: Duje Mihanović +Link: https://lore.kernel.org/r/20250310140707.23459-1-balejk@matfyz.cz +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci-pxav3.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mmc/host/sdhci-pxav3.c ++++ b/drivers/mmc/host/sdhci-pxav3.c +@@ -399,6 +399,7 @@ static int sdhci_pxav3_probe(struct plat + if (!IS_ERR(pxa->clk_core)) + clk_prepare_enable(pxa->clk_core); + ++ host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; + /* enable 1/8V DDR capable */ + host->mmc->caps |= MMC_CAP_1_8V_DDR; + diff --git a/queue-6.14/nfsd-add-a-kconfig-setting-to-enable-delegated-timestamps.patch b/queue-6.14/nfsd-add-a-kconfig-setting-to-enable-delegated-timestamps.patch new file mode 100644 index 0000000000..ffd1140348 --- /dev/null +++ b/queue-6.14/nfsd-add-a-kconfig-setting-to-enable-delegated-timestamps.patch @@ -0,0 +1,79 @@ +From 26a80762153ba0dc98258b5e6d2e9741178c5114 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Tue, 11 Mar 2025 23:06:38 -0400 +Subject: NFSD: Add a Kconfig setting to enable delegated timestamps + +From: Chuck Lever + +commit 26a80762153ba0dc98258b5e6d2e9741178c5114 upstream. + +After three tries, we still see test failures with delegated +timestamps. Disable them by default, but leave the implementation +intact so that development can continue. + +Cc: stable@vger.kernel.org # v6.14 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/Kconfig | 12 +++++++++++- + fs/nfsd/nfs4state.c | 16 ++++++++++++++-- + 2 files changed, 25 insertions(+), 3 deletions(-) + +--- a/fs/nfsd/Kconfig ++++ b/fs/nfsd/Kconfig +@@ -172,6 +172,16 @@ config NFSD_LEGACY_CLIENT_TRACKING + recoverydir, or spawn a process directly using a usermodehelper + upcall. + +- These legacy client tracking methods have proven to be probelmatic ++ These legacy client tracking methods have proven to be problematic + and will be removed in the future. Say Y here if you need support + for them in the interim. ++ ++config NFSD_V4_DELEG_TIMESTAMPS ++ bool "Support delegated timestamps" ++ depends on NFSD_V4 ++ default n ++ help ++ NFSD implements delegated timestamps according to ++ draft-ietf-nfsv4-delstid-08 "Extending the Opening of Files". This ++ is currently an experimental feature and is therefore left disabled ++ by default. +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -5958,11 +5958,23 @@ nfsd4_verify_setuid_write(struct nfsd4_o + return 0; + } + ++#ifdef CONFIG_NFSD_V4_DELEG_TIMESTAMPS ++static bool nfsd4_want_deleg_timestamps(const struct nfsd4_open *open) ++{ ++ return open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS; ++} ++#else /* CONFIG_NFSD_V4_DELEG_TIMESTAMPS */ ++static bool nfsd4_want_deleg_timestamps(const struct nfsd4_open *open) ++{ ++ return false; ++} ++#endif /* CONFIG NFSD_V4_DELEG_TIMESTAMPS */ ++ + static struct nfs4_delegation * + nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + struct svc_fh *parent) + { +- bool deleg_ts = open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS; ++ bool deleg_ts = nfsd4_want_deleg_timestamps(open); + struct nfs4_client *clp = stp->st_stid.sc_client; + struct nfs4_file *fp = stp->st_stid.sc_file; + struct nfs4_clnt_odstate *odstate = stp->st_clnt_odstate; +@@ -6161,8 +6173,8 @@ static void + nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + struct svc_fh *currentfh) + { +- bool deleg_ts = open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS; + struct nfs4_openowner *oo = openowner(stp->st_stateowner); ++ bool deleg_ts = nfsd4_want_deleg_timestamps(open); + struct nfs4_client *clp = stp->st_stid.sc_client; + struct svc_fh *parent = NULL; + struct nfs4_delegation *dp; diff --git a/queue-6.14/nfsd-allow-sc_status_freeable-when-searching-via-nfs4_lookup_stateid.patch b/queue-6.14/nfsd-allow-sc_status_freeable-when-searching-via-nfs4_lookup_stateid.patch new file mode 100644 index 0000000000..dea14991d1 --- /dev/null +++ b/queue-6.14/nfsd-allow-sc_status_freeable-when-searching-via-nfs4_lookup_stateid.patch @@ -0,0 +1,58 @@ +From d1bc15b147d35b4cb7ca99a9a7d79d41ca342c13 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 13 Feb 2025 09:08:29 -0500 +Subject: nfsd: allow SC_STATUS_FREEABLE when searching via nfs4_lookup_stateid() + +From: Jeff Layton + +commit d1bc15b147d35b4cb7ca99a9a7d79d41ca342c13 upstream. + +The pynfs DELEG8 test fails when run against nfsd. It acquires a +delegation and then lets the lease time out. It then tries to use the +deleg stateid and expects to see NFS4ERR_DELEG_REVOKED, but it gets +bad NFS4ERR_BAD_STATEID instead. + +When a delegation is revoked, it's initially marked with +SC_STATUS_REVOKED, or SC_STATUS_ADMIN_REVOKED and later, it's marked +with the SC_STATUS_FREEABLE flag, which denotes that it is waiting for +s FREE_STATEID call. + +nfs4_lookup_stateid() accepts a statusmask that includes the status +flags that a found stateid is allowed to have. Currently, that mask +never includes SC_STATUS_FREEABLE, which means that revoked delegations +are (almost) never found. + +Add SC_STATUS_FREEABLE to the always-allowed status flags, and remove it +from nfsd4_delegreturn() since it's now always implied. + +Fixes: 8dd91e8d31fe ("nfsd: fix race between laundromat and free_stateid") +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -7051,7 +7051,7 @@ nfsd4_lookup_stateid(struct nfsd4_compou + */ + statusmask |= SC_STATUS_REVOKED; + +- statusmask |= SC_STATUS_ADMIN_REVOKED; ++ statusmask |= SC_STATUS_ADMIN_REVOKED | SC_STATUS_FREEABLE; + + if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) || + CLOSE_STATEID(stateid)) +@@ -7706,9 +7706,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp + if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) + return status; + +- status = nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, +- SC_STATUS_REVOKED | SC_STATUS_FREEABLE, +- &s, nn); ++ status = nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, SC_STATUS_REVOKED, &s, nn); + if (status) + goto out; + dp = delegstateid(s); diff --git a/queue-6.14/nfsd-don-t-ignore-the-return-code-of-svc_proc_register.patch b/queue-6.14/nfsd-don-t-ignore-the-return-code-of-svc_proc_register.patch new file mode 100644 index 0000000000..34c90c1ca1 --- /dev/null +++ b/queue-6.14/nfsd-don-t-ignore-the-return-code-of-svc_proc_register.patch @@ -0,0 +1,93 @@ +From 930b64ca0c511521f0abdd1d57ce52b2a6e3476b Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 6 Feb 2025 13:12:13 -0500 +Subject: nfsd: don't ignore the return code of svc_proc_register() + +From: Jeff Layton + +commit 930b64ca0c511521f0abdd1d57ce52b2a6e3476b upstream. + +Currently, nfsd_proc_stat_init() ignores the return value of +svc_proc_register(). If the procfile creation fails, then the kernel +will WARN when it tries to remove the entry later. + +Fix nfsd_proc_stat_init() to return the same type of pointer as +svc_proc_register(), and fix up nfsd_net_init() to check that and fail +the nfsd_net construction if it occurs. + +svc_proc_register() can fail if the dentry can't be allocated, or if an +identical dentry already exists. The second case is pretty unlikely in +the nfsd_net construction codepath, so if this happens, return -ENOMEM. + +Reported-by: syzbot+e34ad04f27991521104c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-nfs/67a47501.050a0220.19061f.05f9.GAE@google.com/ +Cc: stable@vger.kernel.org # v6.9 +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfsctl.c | 9 ++++++++- + fs/nfsd/stats.c | 4 ++-- + fs/nfsd/stats.h | 2 +- + 3 files changed, 11 insertions(+), 4 deletions(-) + +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -2204,8 +2204,14 @@ static __net_init int nfsd_net_init(stru + NFSD_STATS_COUNTERS_NUM); + if (retval) + goto out_repcache_error; ++ + memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); + nn->nfsd_svcstats.program = &nfsd_programs[0]; ++ if (!nfsd_proc_stat_init(net)) { ++ retval = -ENOMEM; ++ goto out_proc_error; ++ } ++ + for (i = 0; i < sizeof(nn->nfsd_versions); i++) + nn->nfsd_versions[i] = nfsd_support_version(i); + for (i = 0; i < sizeof(nn->nfsd4_minorversions); i++) +@@ -2215,13 +2221,14 @@ static __net_init int nfsd_net_init(stru + nfsd4_init_leases_net(nn); + get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key)); + seqlock_init(&nn->writeverf_lock); +- nfsd_proc_stat_init(net); + #if IS_ENABLED(CONFIG_NFS_LOCALIO) + spin_lock_init(&nn->local_clients_lock); + INIT_LIST_HEAD(&nn->local_clients); + #endif + return 0; + ++out_proc_error: ++ percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); + out_repcache_error: + nfsd_idmap_shutdown(net); + out_idmap_error: +--- a/fs/nfsd/stats.c ++++ b/fs/nfsd/stats.c +@@ -73,11 +73,11 @@ static int nfsd_show(struct seq_file *se + + DEFINE_PROC_SHOW_ATTRIBUTE(nfsd); + +-void nfsd_proc_stat_init(struct net *net) ++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net) + { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +- svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops); ++ return svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops); + } + + void nfsd_proc_stat_shutdown(struct net *net) +--- a/fs/nfsd/stats.h ++++ b/fs/nfsd/stats.h +@@ -10,7 +10,7 @@ + #include + #include + +-void nfsd_proc_stat_init(struct net *net); ++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net); + void nfsd_proc_stat_shutdown(struct net *net); + + static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn) diff --git a/queue-6.14/nfsd-fix-management-of-listener-transports.patch b/queue-6.14/nfsd-fix-management-of-listener-transports.patch new file mode 100644 index 0000000000..c1e64871f8 --- /dev/null +++ b/queue-6.14/nfsd-fix-management-of-listener-transports.patch @@ -0,0 +1,133 @@ +From d093c90892607be505e801469d6674459e69ab89 Mon Sep 17 00:00:00 2001 +From: Olga Kornievskaia +Date: Fri, 17 Jan 2025 11:32:58 -0500 +Subject: nfsd: fix management of listener transports + +From: Olga Kornievskaia + +commit d093c90892607be505e801469d6674459e69ab89 upstream. + +Currently, when no active threads are running, a root user using nfsdctl +command can try to remove a particular listener from the list of previously +added ones, then start the server by increasing the number of threads, +it leads to the following problem: + +[ 158.835354] refcount_t: addition on 0; use-after-free. +[ 158.835603] WARNING: CPU: 2 PID: 9145 at lib/refcount.c:25 refcount_warn_saturate+0x160/0x1a0 +[ 158.836017] Modules linked in: rpcrdma rdma_cm iw_cm ib_cm ib_core nfsd auth_rpcgss nfs_acl lockd grace overlay isofs uinput snd_seq_dummy snd_hrtimer nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 rfkill ip_set nf_tables qrtr sunrpc vfat fat uvcvideo videobuf2_vmalloc videobuf2_memops uvc videobuf2_v4l2 videodev videobuf2_common snd_hda_codec_generic mc e1000e snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hda_core snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd soundcore sg loop dm_multipath dm_mod nfnetlink vsock_loopback vmw_vsock_virtio_transport_common vmw_vsock_vmci_transport vmw_vmci vsock xfs libcrc32c crct10dif_ce ghash_ce vmwgfx sha2_ce sha256_arm64 sr_mod sha1_ce cdrom nvme drm_client_lib drm_ttm_helper ttm nvme_core drm_kms_helper nvme_auth drm fuse +[ 158.840093] CPU: 2 UID: 0 PID: 9145 Comm: nfsd Kdump: loaded Tainted: G B W 6.13.0-rc6+ #7 +[ 158.840624] Tainted: [B]=BAD_PAGE, [W]=WARN +[ 158.840802] Hardware name: VMware, Inc. VMware20,1/VBSA, BIOS VMW201.00V.24006586.BA64.2406042154 06/04/2024 +[ 158.841220] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) +[ 158.841563] pc : refcount_warn_saturate+0x160/0x1a0 +[ 158.841780] lr : refcount_warn_saturate+0x160/0x1a0 +[ 158.842000] sp : ffff800089be7d80 +[ 158.842147] x29: ffff800089be7d80 x28: ffff00008e68c148 x27: ffff00008e68c148 +[ 158.842492] x26: ffff0002e3b5c000 x25: ffff600011cd1829 x24: ffff00008653c010 +[ 158.842832] x23: ffff00008653c000 x22: 1fffe00011cd1829 x21: ffff00008653c028 +[ 158.843175] x20: 0000000000000002 x19: ffff00008653c010 x18: 0000000000000000 +[ 158.843505] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 +[ 158.843836] x14: 0000000000000000 x13: 0000000000000001 x12: ffff600050a26493 +[ 158.844143] x11: 1fffe00050a26492 x10: ffff600050a26492 x9 : dfff800000000000 +[ 158.844475] x8 : 00009fffaf5d9b6e x7 : ffff000285132493 x6 : 0000000000000001 +[ 158.844823] x5 : ffff000285132490 x4 : ffff600050a26493 x3 : ffff8000805e72bc +[ 158.845174] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff000098588000 +[ 158.845528] Call trace: +[ 158.845658] refcount_warn_saturate+0x160/0x1a0 (P) +[ 158.845894] svc_recv+0x58c/0x680 [sunrpc] +[ 158.846183] nfsd+0x1fc/0x348 [nfsd] +[ 158.846390] kthread+0x274/0x2f8 +[ 158.846546] ret_from_fork+0x10/0x20 +[ 158.846714] ---[ end trace 0000000000000000 ]--- + +nfsd_nl_listener_set_doit() would manipulate the list of transports of +server's sv_permsocks and close the specified listener but the other +list of transports (server's sp_xprts list) would not be changed leading +to the problem above. + +Instead, determined if the nfsdctl is trying to remove a listener, in +which case, delete all the existing listener transports and re-create +all-but-the-removed ones. + +Fixes: 16a471177496 ("NFSD: add listener-{set,get} netlink command") +Signed-off-by: Olga Kornievskaia +Reviewed-by: Jeff Layton +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfsctl.c | 44 +++++++++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 23 deletions(-) + +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -1917,6 +1917,7 @@ int nfsd_nl_listener_set_doit(struct sk_ + struct svc_serv *serv; + LIST_HEAD(permsocks); + struct nfsd_net *nn; ++ bool delete = false; + int err, rem; + + mutex_lock(&nfsd_mutex); +@@ -1977,34 +1978,28 @@ int nfsd_nl_listener_set_doit(struct sk_ + } + } + +- /* For now, no removing old sockets while server is running */ +- if (serv->sv_nrthreads && !list_empty(&permsocks)) { ++ /* ++ * If there are listener transports remaining on the permsocks list, ++ * it means we were asked to remove a listener. ++ */ ++ if (!list_empty(&permsocks)) { + list_splice_init(&permsocks, &serv->sv_permsocks); +- spin_unlock_bh(&serv->sv_lock); +- err = -EBUSY; +- goto out_unlock_mtx; ++ delete = true; + } ++ spin_unlock_bh(&serv->sv_lock); + +- /* Close the remaining sockets on the permsocks list */ +- while (!list_empty(&permsocks)) { +- xprt = list_first_entry(&permsocks, struct svc_xprt, xpt_list); +- list_move(&xprt->xpt_list, &serv->sv_permsocks); +- +- /* +- * Newly-created sockets are born with the BUSY bit set. Clear +- * it if there are no threads, since nothing can pick it up +- * in that case. +- */ +- if (!serv->sv_nrthreads) +- clear_bit(XPT_BUSY, &xprt->xpt_flags); +- +- set_bit(XPT_CLOSE, &xprt->xpt_flags); +- spin_unlock_bh(&serv->sv_lock); +- svc_xprt_close(xprt); +- spin_lock_bh(&serv->sv_lock); ++ /* Do not remove listeners while there are active threads. */ ++ if (serv->sv_nrthreads) { ++ err = -EBUSY; ++ goto out_unlock_mtx; + } + +- spin_unlock_bh(&serv->sv_lock); ++ /* ++ * Since we can't delete an arbitrary llist entry, destroy the ++ * remaining listeners and recreate the list. ++ */ ++ if (delete) ++ svc_xprt_destroy_all(serv, net); + + /* walk list of addrs again, open any that still don't exist */ + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { +@@ -2031,6 +2026,9 @@ int nfsd_nl_listener_set_doit(struct sk_ + + xprt = svc_find_listener(serv, xcl_name, net, sa); + if (xprt) { ++ if (delete) ++ WARN_ONCE(1, "Transport type=%s already exists\n", ++ xcl_name); + svc_xprt_put(xprt); + continue; + } diff --git a/queue-6.14/nfsd-never-return-nfs4err_file_open-when-removing-a-directory.patch b/queue-6.14/nfsd-never-return-nfs4err_file_open-when-removing-a-directory.patch new file mode 100644 index 0000000000..dc754ce115 --- /dev/null +++ b/queue-6.14/nfsd-never-return-nfs4err_file_open-when-removing-a-directory.patch @@ -0,0 +1,73 @@ +From 370345b4bd184a49ac68d6591801e5e3605b355a Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Sun, 26 Jan 2025 16:50:18 -0500 +Subject: NFSD: Never return NFS4ERR_FILE_OPEN when removing a directory + +From: Chuck Lever + +commit 370345b4bd184a49ac68d6591801e5e3605b355a upstream. + +RFC 8881 Section 18.25.4 paragraph 5 tells us that the server +should return NFS4ERR_FILE_OPEN only if the target object is an +opened file. This suggests that returning this status when removing +a directory will confuse NFS clients. + +This is a version-specific issue; nfsd_proc_remove/rmdir() and +nfsd3_proc_remove/rmdir() already return nfserr_access as +appropriate. + +Unfortunately there is no quick way for nfsd4_remove() to determine +whether the target object is a file or not, so the check is done in +in nfsd_unlink() for now. + +Reported-by: Trond Myklebust +Fixes: 466e16f0920f ("nfsd: check for EBUSY from vfs_rmdir/vfs_unink.") +Reviewed-by: Jeff Layton +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/vfs.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1931,9 +1931,17 @@ out: + return err; + } + +-/* +- * Unlink a file or directory +- * N.B. After this call fhp needs an fh_put ++/** ++ * nfsd_unlink - remove a directory entry ++ * @rqstp: RPC transaction context ++ * @fhp: the file handle of the parent directory to be modified ++ * @type: enforced file type of the object to be removed ++ * @fname: the name of directory entry to be removed ++ * @flen: length of @fname in octets ++ * ++ * After this call fhp needs an fh_put. ++ * ++ * Returns a generic NFS status code in network byte-order. + */ + __be32 + nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, +@@ -2007,10 +2015,14 @@ out_drop_write: + fh_drop_write(fhp); + out_nfserr: + if (host_err == -EBUSY) { +- /* name is mounted-on. There is no perfect +- * error status. ++ /* ++ * See RFC 8881 Section 18.25.4 para 4: NFSv4 REMOVE ++ * wants a status unique to the object type. + */ +- err = nfserr_file_open; ++ if (type != S_IFDIR) ++ err = nfserr_file_open; ++ else ++ err = nfserr_acces; + } + out: + return err != nfs_ok ? err : nfserrno(host_err); diff --git a/queue-6.14/nfsd-nfsd_unlink-clobbers-non-zero-status-returned-from-fh_fill_pre_attrs.patch b/queue-6.14/nfsd-nfsd_unlink-clobbers-non-zero-status-returned-from-fh_fill_pre_attrs.patch new file mode 100644 index 0000000000..ba85e81307 --- /dev/null +++ b/queue-6.14/nfsd-nfsd_unlink-clobbers-non-zero-status-returned-from-fh_fill_pre_attrs.patch @@ -0,0 +1,39 @@ +From d7d8e3169b56e7696559a2427c922c0d55debcec Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Sun, 26 Jan 2025 16:50:17 -0500 +Subject: NFSD: nfsd_unlink() clobbers non-zero status returned from fh_fill_pre_attrs() + +From: Chuck Lever + +commit d7d8e3169b56e7696559a2427c922c0d55debcec upstream. + +If fh_fill_pre_attrs() returns a non-zero status, the error flow +takes it through out_unlock, which then overwrites the returned +status code with + + err = nfserrno(host_err); + +Fixes: a332018a91c4 ("nfsd: handle failure to collect pre/post-op attrs more sanely") +Reviewed-by: Jeff Layton +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/vfs.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -2011,11 +2011,9 @@ out_nfserr: + * error status. + */ + err = nfserr_file_open; +- } else { +- err = nfserrno(host_err); + } + out: +- return err; ++ return err != nfs_ok ? err : nfserrno(host_err); + out_unlock: + inode_unlock(dirp); + goto out_drop_write; diff --git a/queue-6.14/nfsd-put-dl_stid-if-fail-to-queue-dl_recall.patch b/queue-6.14/nfsd-put-dl_stid-if-fail-to-queue-dl_recall.patch new file mode 100644 index 0000000000..f0bafa8340 --- /dev/null +++ b/queue-6.14/nfsd-put-dl_stid-if-fail-to-queue-dl_recall.patch @@ -0,0 +1,102 @@ +From 230ca758453c63bd38e4d9f4a21db698f7abada8 Mon Sep 17 00:00:00 2001 +From: Li Lingfeng +Date: Thu, 13 Feb 2025 22:42:20 +0800 +Subject: nfsd: put dl_stid if fail to queue dl_recall + +From: Li Lingfeng + +commit 230ca758453c63bd38e4d9f4a21db698f7abada8 upstream. + +Before calling nfsd4_run_cb to queue dl_recall to the callback_wq, we +increment the reference count of dl_stid. +We expect that after the corresponding work_struct is processed, the +reference count of dl_stid will be decremented through the callback +function nfsd4_cb_recall_release. +However, if the call to nfsd4_run_cb fails, the incremented reference +count of dl_stid will not be decremented correspondingly, leading to the +following nfs4_stid leak: +unreferenced object 0xffff88812067b578 (size 344): + comm "nfsd", pid 2761, jiffies 4295044002 (age 5541.241s) + hex dump (first 32 bytes): + 01 00 00 00 6b 6b 6b 6b b8 02 c0 e2 81 88 ff ff ....kkkk........ + 00 6b 6b 6b 6b 6b 6b 6b 00 00 00 00 ad 4e ad de .kkkkkkk.....N.. + backtrace: + kmem_cache_alloc+0x4b9/0x700 + nfsd4_process_open1+0x34/0x300 + nfsd4_open+0x2d1/0x9d0 + nfsd4_proc_compound+0x7a2/0xe30 + nfsd_dispatch+0x241/0x3e0 + svc_process_common+0x5d3/0xcc0 + svc_process+0x2a3/0x320 + nfsd+0x180/0x2e0 + kthread+0x199/0x1d0 + ret_from_fork+0x30/0x50 + ret_from_fork_asm+0x1b/0x30 +unreferenced object 0xffff8881499f4d28 (size 368): + comm "nfsd", pid 2761, jiffies 4295044005 (age 5541.239s) + hex dump (first 32 bytes): + 01 00 00 00 00 00 00 00 30 4d 9f 49 81 88 ff ff ........0M.I.... + 30 4d 9f 49 81 88 ff ff 20 00 00 00 01 00 00 00 0M.I.... ....... + backtrace: + kmem_cache_alloc+0x4b9/0x700 + nfs4_alloc_stid+0x29/0x210 + alloc_init_deleg+0x92/0x2e0 + nfs4_set_delegation+0x284/0xc00 + nfs4_open_delegation+0x216/0x3f0 + nfsd4_process_open2+0x2b3/0xee0 + nfsd4_open+0x770/0x9d0 + nfsd4_proc_compound+0x7a2/0xe30 + nfsd_dispatch+0x241/0x3e0 + svc_process_common+0x5d3/0xcc0 + svc_process+0x2a3/0x320 + nfsd+0x180/0x2e0 + kthread+0x199/0x1d0 + ret_from_fork+0x30/0x50 + ret_from_fork_asm+0x1b/0x30 +Fix it by checking the result of nfsd4_run_cb and call nfs4_put_stid if +fail to queue dl_recall. + +Cc: stable@vger.kernel.org +Signed-off-by: Li Lingfeng +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1050,6 +1050,12 @@ static struct nfs4_ol_stateid * nfs4_all + return openlockstateid(stid); + } + ++/* ++ * As the sc_free callback of deleg, this may be called by nfs4_put_stid ++ * in nfsd_break_one_deleg. ++ * Considering nfsd_break_one_deleg is called with the flc->flc_lock held, ++ * this function mustn't ever sleep. ++ */ + static void nfs4_free_deleg(struct nfs4_stid *stid) + { + struct nfs4_delegation *dp = delegstateid(stid); +@@ -5414,6 +5420,7 @@ static const struct nfsd4_callback_ops n + + static void nfsd_break_one_deleg(struct nfs4_delegation *dp) + { ++ bool queued; + /* + * We're assuming the state code never drops its reference + * without first removing the lease. Since we're in this lease +@@ -5422,7 +5429,10 @@ static void nfsd_break_one_deleg(struct + * we know it's safe to take a reference. + */ + refcount_inc(&dp->dl_stid.sc_count); +- WARN_ON_ONCE(!nfsd4_run_cb(&dp->dl_recall)); ++ queued = nfsd4_run_cb(&dp->dl_recall); ++ WARN_ON_ONCE(!queued); ++ if (!queued) ++ nfs4_put_stid(&dp->dl_stid); + } + + /* Called from break_lease() with flc_lock held. */ diff --git a/queue-6.14/nfsd-skip-sending-cb_recall_any-when-the-backchannel-isn-t-up.patch b/queue-6.14/nfsd-skip-sending-cb_recall_any-when-the-backchannel-isn-t-up.patch new file mode 100644 index 0000000000..bdda6f7d04 --- /dev/null +++ b/queue-6.14/nfsd-skip-sending-cb_recall_any-when-the-backchannel-isn-t-up.patch @@ -0,0 +1,60 @@ +From 8a388c1fabeb6606e16467b23242416c0dbeffad Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Tue, 14 Jan 2025 17:09:24 -0500 +Subject: NFSD: Skip sending CB_RECALL_ANY when the backchannel isn't up + +From: Chuck Lever + +commit 8a388c1fabeb6606e16467b23242416c0dbeffad upstream. + +NFSD sends CB_RECALL_ANY to clients when the server is low on +memory or that client has a large number of delegations outstanding. + +We've seen cases where NFSD attempts to send CB_RECALL_ANY requests +to disconnected clients, and gets confused. These calls never go +anywhere if a backchannel transport to the target client isn't +available. Before the server can send any backchannel operation, the +client has to connect first and then do a BIND_CONN_TO_SESSION. + +This patch doesn't address the root cause of the confusion, but +there's no need to queue up these optional operations if they can't +go anywhere. + +Fixes: 44df6f439a17 ("NFSD: add delegation reaper to react to low memory condition") +Reviewed-by: Jeff Layton +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -6882,14 +6882,19 @@ deleg_reaper(struct nfsd_net *nn) + spin_lock(&nn->client_lock); + list_for_each_safe(pos, next, &nn->client_lru) { + clp = list_entry(pos, struct nfs4_client, cl_lru); +- if (clp->cl_state != NFSD4_ACTIVE || +- list_empty(&clp->cl_delegations) || +- atomic_read(&clp->cl_delegs_in_recall) || +- test_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags) || +- (ktime_get_boottime_seconds() - +- clp->cl_ra_time < 5)) { ++ ++ if (clp->cl_state != NFSD4_ACTIVE) ++ continue; ++ if (list_empty(&clp->cl_delegations)) ++ continue; ++ if (atomic_read(&clp->cl_delegs_in_recall)) ++ continue; ++ if (test_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags)) ++ continue; ++ if (ktime_get_boottime_seconds() - clp->cl_ra_time < 5) ++ continue; ++ if (clp->cl_cb_state != NFSD4_CB_UP) + continue; +- } + list_add(&clp->cl_ra_cblist, &cblist); + + /* release in nfsd4_cb_recall_any_release */ diff --git a/queue-6.14/pci-bwctrl-fix-null-pointer-dereference-on-bus-number-exhaustion.patch b/queue-6.14/pci-bwctrl-fix-null-pointer-dereference-on-bus-number-exhaustion.patch new file mode 100644 index 0000000000..775e37a315 --- /dev/null +++ b/queue-6.14/pci-bwctrl-fix-null-pointer-dereference-on-bus-number-exhaustion.patch @@ -0,0 +1,75 @@ +From 667f053b05f00a007738cd7ed6fa1901de19dc7e Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Sat, 22 Mar 2025 19:52:08 +0100 +Subject: PCI/bwctrl: Fix NULL pointer dereference on bus number exhaustion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lukas Wunner + +commit 667f053b05f00a007738cd7ed6fa1901de19dc7e upstream. + +When BIOS neglects to assign bus numbers to PCI bridges, the kernel +attempts to correct that during PCI device enumeration. If it runs out +of bus numbers, no pci_bus is allocated and the "subordinate" pointer in +the bridge's pci_dev remains NULL. + +The PCIe bandwidth controller erroneously does not check for a NULL +subordinate pointer and dereferences it on probe. + +Bandwidth control of unusable devices below the bridge is of questionable +utility, so simply error out instead. This mirrors what PCIe hotplug does +since commit 62e4492c3063 ("PCI: Prevent NULL dereference during pciehp +probe"). + +The PCI core emits a message with KERN_INFO severity if it has run out of +bus numbers. PCIe hotplug emits an additional message with KERN_ERR +severity to inform the user that hotplug functionality is disabled at the +bridge. A similar message for bandwidth control does not seem merited, +given that its only purpose so far is to expose an up-to-date link speed +in sysfs and throttle the link speed on certain laptops with limited +Thermal Design Power. So error out silently. + +User-visible messages: + + pci 0000:16:02.0: bridge configuration invalid ([bus 00-00]), reconfiguring + [...] + pci_bus 0000:45: busn_res: [bus 45-74] end is updated to 74 + pci 0000:16:02.0: devices behind bridge are unusable because [bus 45-74] cannot be assigned for them + [...] + pcieport 0000:16:02.0: pciehp: Hotplug bridge without secondary bus, ignoring + [...] + BUG: kernel NULL pointer dereference + RIP: pcie_update_link_speed + pcie_bwnotif_enable + pcie_bwnotif_probe + pcie_port_probe_service + really_probe + +Fixes: 665745f27487 ("PCI/bwctrl: Re-add BW notification portdrv as PCIe BW controller") +Reported-by: Wouter Bijlsma +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219906 +Signed-off-by: Lukas Wunner +Signed-off-by: Krzysztof Wilczyński +Tested-by: Wouter Bijlsma +Cc: stable@vger.kernel.org # v6.13+ +Link: https://lore.kernel.org/r/3b6c8d973aedc48860640a9d75d20528336f1f3c.1742669372.git.lukas@wunner.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pcie/bwctrl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/pci/pcie/bwctrl.c ++++ b/drivers/pci/pcie/bwctrl.c +@@ -294,6 +294,10 @@ static int pcie_bwnotif_probe(struct pci + struct pci_dev *port = srv->port; + int ret; + ++ /* Can happen if we run out of bus numbers during enumeration. */ ++ if (!port->subordinate) ++ return -ENODEV; ++ + struct pcie_bwctrl_data *data = devm_kzalloc(&srv->device, + sizeof(*data), GFP_KERNEL); + if (!data) diff --git a/queue-6.14/remove-unnecessary-firmware-version-check-for-gc-v9_4_2.patch b/queue-6.14/remove-unnecessary-firmware-version-check-for-gc-v9_4_2.patch new file mode 100644 index 0000000000..ec85c804d1 --- /dev/null +++ b/queue-6.14/remove-unnecessary-firmware-version-check-for-gc-v9_4_2.patch @@ -0,0 +1,31 @@ +From 5b3c08ae9ed324743f5f7286940d45caeb656e6e Mon Sep 17 00:00:00 2001 +From: Candice Li +Date: Wed, 26 Mar 2025 13:41:01 +0800 +Subject: Remove unnecessary firmware version check for gc v9_4_2 + +From: Candice Li + +commit 5b3c08ae9ed324743f5f7286940d45caeb656e6e upstream. + +GC v9_4_2 uses a new versioning scheme for CP firmware, making +the warning ("CP firmware version too old, please update!") irrelevant. + +Signed-off-by: Candice Li +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -1269,6 +1269,7 @@ static void gfx_v9_0_check_fw_write_wait + adev->gfx.mec_fw_write_wait = false; + + if ((amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1)) && ++ (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)) && + ((adev->gfx.mec_fw_version < 0x000001a5) || + (adev->gfx.mec_feature_version < 46) || + (adev->gfx.pfp_fw_version < 0x000000b7) || diff --git a/queue-6.14/series b/queue-6.14/series index af625b34bd..15dd472b8f 100644 --- a/queue-6.14/series +++ b/queue-6.14/series @@ -690,3 +690,44 @@ acpi-video-handle-fetching-edid-as-acpi_type_package.patch arm-9443-1-require-linker-to-support-keep-within-overlay-for-dce.patch arm-9444-1-add-keep-keyword-to-arm_vectors.patch media-omap3isp-handle-arm-dma_iommu_mapping.patch +remove-unnecessary-firmware-version-check-for-gc-v9_4_2.patch +mmc-omap-fix-memory-leak-in-mmc_omap_new_slot.patch +mmc-sdhci-pxav3-set-need_rsp_busy-capability.patch +mmc-sdhci-omap-disable-mmc_cap_aggressive_pm-for-emmc-sd.patch +mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qcom_ice_get.patch +kvm-svm-don-t-change-target-vcpu-state-on-ap-creation-vmgexit-error.patch +ksmbd-add-bounds-check-for-durable-handle-context.patch +ksmbd-add-bounds-check-for-create-lease-context.patch +ksmbd-fix-use-after-free-in-ksmbd_sessions_deregister.patch +ksmbd-fix-session-use-after-free-in-multichannel-connection.patch +ksmbd-fix-overflow-in-dacloffset-bounds-check.patch +ksmbd-validate-zero-num_subauth-before-sub_auth-is-accessed.patch +ksmbd-fix-null-pointer-dereference-in-alloc_preauth_hash.patch +exfat-fix-random-stack-corruption-after-get_block.patch +exfat-fix-potential-wrong-error-return-from-get_block.patch +tracing-fix-use-after-free-in-print_graph_function_flags-during-tracer-switching.patch +tracing-ensure-module-defining-synth-event-cannot-be-unloaded-while-tracing.patch +tracing-fix-synth-event-printk-format-for-str-fields.patch +tracing-osnoise-fix-possible-recursive-locking-for-cpus_read_lock.patch +tracing-verify-event-formats-that-have-p.patch +mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch +mm-gup-reject-foll_split_pmd-with-hugetlb-vmas.patch +arm64-don-t-call-null-in-do_compat_alignment_fixup.patch +wifi-mt76-mt7921-fix-kernel-panic-due-to-null-pointer-dereference.patch +ext4-don-t-over-report-free-space-or-inodes-in-statvfs.patch +ext4-fix-oob-read-when-checking-dotdot-dir.patch +pci-bwctrl-fix-null-pointer-dereference-on-bus-number-exhaustion.patch +jfs-fix-slab-out-of-bounds-read-in-ea_get.patch +jfs-add-index-corruption-check-to-dt_getpage.patch +mm-zswap-fix-crypto_free_acomp-deadlock-in-zswap_cpu_comp_dead.patch +exec-fix-the-racy-usage-of-fs_struct-in_exec.patch +media-vimc-skip-.s_stream-for-stopped-entities.patch +media-streamzap-fix-race-between-device-disconnection-and-urb-callback.patch +nfsd-don-t-ignore-the-return-code-of-svc_proc_register.patch +nfsd-allow-sc_status_freeable-when-searching-via-nfs4_lookup_stateid.patch +nfsd-put-dl_stid-if-fail-to-queue-dl_recall.patch +nfsd-add-a-kconfig-setting-to-enable-delegated-timestamps.patch +nfsd-fix-management-of-listener-transports.patch +nfsd-nfsd_unlink-clobbers-non-zero-status-returned-from-fh_fill_pre_attrs.patch +nfsd-never-return-nfs4err_file_open-when-removing-a-directory.patch +nfsd-skip-sending-cb_recall_any-when-the-backchannel-isn-t-up.patch diff --git a/queue-6.14/tracing-ensure-module-defining-synth-event-cannot-be-unloaded-while-tracing.patch b/queue-6.14/tracing-ensure-module-defining-synth-event-cannot-be-unloaded-while-tracing.patch new file mode 100644 index 0000000000..1af23b5d6b --- /dev/null +++ b/queue-6.14/tracing-ensure-module-defining-synth-event-cannot-be-unloaded-while-tracing.patch @@ -0,0 +1,76 @@ +From 21581dd4e7ff6c07d0ab577e3c32b13a74b31522 Mon Sep 17 00:00:00 2001 +From: Douglas Raillard +Date: Tue, 18 Mar 2025 18:09:05 +0000 +Subject: tracing: Ensure module defining synth event cannot be unloaded while tracing + +From: Douglas Raillard + +commit 21581dd4e7ff6c07d0ab577e3c32b13a74b31522 upstream. + +Currently, using synth_event_delete() will fail if the event is being +used (tracing in progress), but that is normally done in the module exit +function. At that stage, failing is problematic as returning a non-zero +status means the module will become locked (impossible to unload or +reload again). + +Instead, ensure the module exit function does not get called in the +first place by increasing the module refcnt when the event is enabled. + +Cc: stable@vger.kernel.org +Cc: Mathieu Desnoyers +Fixes: 35ca5207c2d11 ("tracing: Add synthetic event command generation functions") +Link: https://lore.kernel.org/20250318180906.226841-1-douglas.raillard@arm.com +Signed-off-by: Douglas Raillard +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events_synth.c | 30 +++++++++++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -852,6 +852,34 @@ static struct trace_event_fields synth_e + {} + }; + ++static int synth_event_reg(struct trace_event_call *call, ++ enum trace_reg type, void *data) ++{ ++ struct synth_event *event = container_of(call, struct synth_event, call); ++ ++ switch (type) { ++ case TRACE_REG_REGISTER: ++ case TRACE_REG_PERF_REGISTER: ++ if (!try_module_get(event->mod)) ++ return -EBUSY; ++ break; ++ default: ++ break; ++ } ++ ++ int ret = trace_event_reg(call, type, data); ++ ++ switch (type) { ++ case TRACE_REG_UNREGISTER: ++ case TRACE_REG_PERF_UNREGISTER: ++ module_put(event->mod); ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ + static int register_synth_event(struct synth_event *event) + { + struct trace_event_call *call = &event->call; +@@ -881,7 +909,7 @@ static int register_synth_event(struct s + goto out; + } + call->flags = TRACE_EVENT_FL_TRACEPOINT; +- call->class->reg = trace_event_reg; ++ call->class->reg = synth_event_reg; + call->class->probe = trace_event_raw_event_synth; + call->data = event; + call->tp = event->tp; diff --git a/queue-6.14/tracing-fix-synth-event-printk-format-for-str-fields.patch b/queue-6.14/tracing-fix-synth-event-printk-format-for-str-fields.patch new file mode 100644 index 0000000000..73c0d12465 --- /dev/null +++ b/queue-6.14/tracing-fix-synth-event-printk-format-for-str-fields.patch @@ -0,0 +1,41 @@ +From 4d38328eb442dc06aec4350fd9594ffa6488af02 Mon Sep 17 00:00:00 2001 +From: Douglas Raillard +Date: Tue, 25 Mar 2025 16:52:02 +0000 +Subject: tracing: Fix synth event printk format for str fields + +From: Douglas Raillard + +commit 4d38328eb442dc06aec4350fd9594ffa6488af02 upstream. + +The printk format for synth event uses "%.*s" to print string fields, +but then only passes the pointer part as var arg. + +Replace %.*s with %s as the C string is guaranteed to be null-terminated. + +The output in print fmt should never have been updated as __get_str() +handles the string limit because it can access the length of the string in +the string meta data that is saved in the ring buffer. + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Fixes: 8db4d6bfbbf92 ("tracing: Change synthetic event string format to limit printed length") +Link: https://lore.kernel.org/20250325165202.541088-1-douglas.raillard@arm.com +Signed-off-by: Douglas Raillard +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events_synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -305,7 +305,7 @@ static const char *synth_field_fmt(char + else if (strcmp(type, "gfp_t") == 0) + fmt = "%x"; + else if (synth_field_is_string(type)) +- fmt = "%.*s"; ++ fmt = "%s"; + else if (synth_field_is_stack(type)) + fmt = "%s"; + diff --git a/queue-6.14/tracing-fix-use-after-free-in-print_graph_function_flags-during-tracer-switching.patch b/queue-6.14/tracing-fix-use-after-free-in-print_graph_function_flags-during-tracer-switching.patch new file mode 100644 index 0000000000..eb9745eecc --- /dev/null +++ b/queue-6.14/tracing-fix-use-after-free-in-print_graph_function_flags-during-tracer-switching.patch @@ -0,0 +1,93 @@ +From 7f81f27b1093e4895e87b74143c59c055c3b1906 Mon Sep 17 00:00:00 2001 +From: Tengda Wu +Date: Thu, 20 Mar 2025 12:21:37 +0000 +Subject: tracing: Fix use-after-free in print_graph_function_flags during tracer switching + +From: Tengda Wu + +commit 7f81f27b1093e4895e87b74143c59c055c3b1906 upstream. + +Kairui reported a UAF issue in print_graph_function_flags() during +ftrace stress testing [1]. This issue can be reproduced if puting a +'mdelay(10)' after 'mutex_unlock(&trace_types_lock)' in s_start(), +and executing the following script: + + $ echo function_graph > current_tracer + $ cat trace > /dev/null & + $ sleep 5 # Ensure the 'cat' reaches the 'mdelay(10)' point + $ echo timerlat > current_tracer + +The root cause lies in the two calls to print_graph_function_flags +within print_trace_line during each s_show(): + + * One through 'iter->trace->print_line()'; + * Another through 'event->funcs->trace()', which is hidden in + print_trace_fmt() before print_trace_line returns. + +Tracer switching only updates the former, while the latter continues +to use the print_line function of the old tracer, which in the script +above is print_graph_function_flags. + +Moreover, when switching from the 'function_graph' tracer to the +'timerlat' tracer, s_start only calls graph_trace_close of the +'function_graph' tracer to free 'iter->private', but does not set +it to NULL. This provides an opportunity for 'event->funcs->trace()' +to use an invalid 'iter->private'. + +To fix this issue, set 'iter->private' to NULL immediately after +freeing it in graph_trace_close(), ensuring that an invalid pointer +is not passed to other tracers. Additionally, clean up the unnecessary +'iter->private = NULL' during each 'cat trace' when using wakeup and +irqsoff tracers. + + [1] https://lore.kernel.org/all/20231112150030.84609-1-ryncsn@gmail.com/ + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Cc: Zheng Yejian +Link: https://lore.kernel.org/20250320122137.23635-1-wutengda@huaweicloud.com +Fixes: eecb91b9f98d ("tracing: Fix memleak due to race between current_tracer and trace") +Closes: https://lore.kernel.org/all/CAMgjq7BW79KDSCyp+tZHjShSzHsScSiJxn5ffskp-QzVM06fxw@mail.gmail.com/ +Reported-by: Kairui Song +Signed-off-by: Tengda Wu +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_functions_graph.c | 1 + + kernel/trace/trace_irqsoff.c | 2 -- + kernel/trace/trace_sched_wakeup.c | 2 -- + 3 files changed, 1 insertion(+), 4 deletions(-) + +--- a/kernel/trace/trace_functions_graph.c ++++ b/kernel/trace/trace_functions_graph.c +@@ -1511,6 +1511,7 @@ void graph_trace_close(struct trace_iter + if (data) { + free_percpu(data->cpu_data); + kfree(data); ++ iter->private = NULL; + } + } + +--- a/kernel/trace/trace_irqsoff.c ++++ b/kernel/trace/trace_irqsoff.c +@@ -250,8 +250,6 @@ static void irqsoff_trace_open(struct tr + { + if (is_graph(iter->tr)) + graph_trace_open(iter); +- else +- iter->private = NULL; + } + + static void irqsoff_trace_close(struct trace_iterator *iter) +--- a/kernel/trace/trace_sched_wakeup.c ++++ b/kernel/trace/trace_sched_wakeup.c +@@ -188,8 +188,6 @@ static void wakeup_trace_open(struct tra + { + if (is_graph(iter->tr)) + graph_trace_open(iter); +- else +- iter->private = NULL; + } + + static void wakeup_trace_close(struct trace_iterator *iter) diff --git a/queue-6.14/tracing-osnoise-fix-possible-recursive-locking-for-cpus_read_lock.patch b/queue-6.14/tracing-osnoise-fix-possible-recursive-locking-for-cpus_read_lock.patch new file mode 100644 index 0000000000..e725465ac2 --- /dev/null +++ b/queue-6.14/tracing-osnoise-fix-possible-recursive-locking-for-cpus_read_lock.patch @@ -0,0 +1,75 @@ +From 7e6b3fcc9c5294aeafed0dbe1a09a1bc899bd0f2 Mon Sep 17 00:00:00 2001 +From: Ran Xiaokai +Date: Fri, 21 Mar 2025 09:52:49 +0000 +Subject: tracing/osnoise: Fix possible recursive locking for cpus_read_lock() + +From: Ran Xiaokai + +commit 7e6b3fcc9c5294aeafed0dbe1a09a1bc899bd0f2 upstream. + +Lockdep reports this deadlock log: + +osnoise: could not start sampling thread +============================================ +WARNING: possible recursive locking detected +-------------------------------------------- + CPU0 + ---- + lock(cpu_hotplug_lock); + lock(cpu_hotplug_lock); + + Call Trace: + + print_deadlock_bug+0x282/0x3c0 + __lock_acquire+0x1610/0x29a0 + lock_acquire+0xcb/0x2d0 + cpus_read_lock+0x49/0x120 + stop_per_cpu_kthreads+0x7/0x60 + start_kthread+0x103/0x120 + osnoise_hotplug_workfn+0x5e/0x90 + process_one_work+0x44f/0xb30 + worker_thread+0x33e/0x5e0 + kthread+0x206/0x3b0 + ret_from_fork+0x31/0x50 + ret_from_fork_asm+0x11/0x20 + + +This is the deadlock scenario: +osnoise_hotplug_workfn() + guard(cpus_read_lock)(); // first lock call + start_kthread(cpu) + if (IS_ERR(kthread)) { + stop_per_cpu_kthreads(); { + cpus_read_lock(); // second lock call. Cause the AA deadlock + } + } + +It is not necessary to call stop_per_cpu_kthreads() which stops osnoise +kthread for every other CPUs in the system if a failure occurs during +hotplug of a certain CPU. +For start_per_cpu_kthreads(), if the start_kthread() call fails, +this function calls stop_per_cpu_kthreads() to handle the error. +Therefore, similarly, there is no need to call stop_per_cpu_kthreads() +again within start_kthread(). +So just remove stop_per_cpu_kthreads() from start_kthread to solve this issue. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/20250321095249.2739397-1-ranxiaokai627@163.com +Fixes: c8895e271f79 ("trace/osnoise: Support hotplug operations") +Signed-off-by: Ran Xiaokai +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_osnoise.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/kernel/trace/trace_osnoise.c ++++ b/kernel/trace/trace_osnoise.c +@@ -2032,7 +2032,6 @@ static int start_kthread(unsigned int cp + + if (IS_ERR(kthread)) { + pr_err(BANNER "could not start sampling thread\n"); +- stop_per_cpu_kthreads(); + return -ENOMEM; + } + diff --git a/queue-6.14/tracing-verify-event-formats-that-have-p.patch b/queue-6.14/tracing-verify-event-formats-that-have-p.patch new file mode 100644 index 0000000000..80118841c1 --- /dev/null +++ b/queue-6.14/tracing-verify-event-formats-that-have-p.patch @@ -0,0 +1,86 @@ +From ea8d7647f9ddf1f81e2027ed305299797299aa03 Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Thu, 27 Mar 2025 19:53:11 -0400 +Subject: tracing: Verify event formats that have "%*p.." + +From: Steven Rostedt + +commit ea8d7647f9ddf1f81e2027ed305299797299aa03 upstream. + +The trace event verifier checks the formats of trace events to make sure +that they do not point at memory that is not in the trace event itself or +in data that will never be freed. If an event references data that was +allocated when the event triggered and that same data is freed before the +event is read, then the kernel can crash by reading freed memory. + +The verifier runs at boot up (or module load) and scans the print formats +of the events and checks their arguments to make sure that dereferenced +pointers are safe. If the format uses "%*p.." the verifier will ignore it, +and that could be dangerous. Cover this case as well. + +Also add to the sample code a use case of "%*pbl". + +Link: https://lore.kernel.org/all/bcba4d76-2c3f-4d11-baf0-02905db953dd@oracle.com/ + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Fixes: 5013f454a352c ("tracing: Add check of trace event print fmts for dereferencing pointers") +Link: https://lore.kernel.org/20250327195311.2d89ec66@gandalf.local.home +Reported-by: Libo Chen +Reviewed-by: Libo Chen +Tested-by: Libo Chen +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events.c | 7 +++++++ + samples/trace_events/trace-events-sample.h | 8 ++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -470,6 +470,7 @@ static void test_event_printk(struct tra + case '%': + continue; + case 'p': ++ do_pointer: + /* Find dereferencing fields */ + switch (fmt[i + 1]) { + case 'B': case 'R': case 'r': +@@ -498,6 +499,12 @@ static void test_event_printk(struct tra + continue; + if (fmt[i + j] == '*') { + star = true; ++ /* Handle %*pbl case */ ++ if (!j && fmt[i + 1] == 'p') { ++ arg++; ++ i++; ++ goto do_pointer; ++ } + continue; + } + if ((fmt[i + j] == 's')) { +--- a/samples/trace_events/trace-events-sample.h ++++ b/samples/trace_events/trace-events-sample.h +@@ -319,7 +319,8 @@ TRACE_EVENT(foo_bar, + __assign_cpumask(cpum, cpumask_bits(mask)); + ), + +- TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, ++ TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s [%d] %*pbl", ++ __entry->foo, __entry->bar, + + /* + * Notice here the use of some helper functions. This includes: +@@ -370,7 +371,10 @@ TRACE_EVENT(foo_bar, + + __get_str(str), __get_str(lstr), + __get_bitmask(cpus), __get_cpumask(cpum), +- __get_str(vstr)) ++ __get_str(vstr), ++ __get_dynamic_array_len(cpus), ++ __get_dynamic_array_len(cpus), ++ __get_dynamic_array(cpus)) + ); + + /* diff --git a/queue-6.14/wifi-mt76-mt7921-fix-kernel-panic-due-to-null-pointer-dereference.patch b/queue-6.14/wifi-mt76-mt7921-fix-kernel-panic-due-to-null-pointer-dereference.patch new file mode 100644 index 0000000000..1aeb3a19af --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7921-fix-kernel-panic-due-to-null-pointer-dereference.patch @@ -0,0 +1,76 @@ +From adc3fd2a2277b7cc0b61692463771bf9bd298036 Mon Sep 17 00:00:00 2001 +From: Ming Yen Hsieh +Date: Tue, 18 Feb 2025 11:33:42 +0800 +Subject: wifi: mt76: mt7921: fix kernel panic due to null pointer dereference + +From: Ming Yen Hsieh + +commit adc3fd2a2277b7cc0b61692463771bf9bd298036 upstream. + +Address a kernel panic caused by a null pointer dereference in the +`mt792x_rx_get_wcid` function. The issue arises because the `deflink` structure +is not properly initialized with the `sta` context. This patch ensures that the +`deflink` structure is correctly linked to the `sta` context, preventing the +null pointer dereference. + + BUG: kernel NULL pointer dereference, address: 0000000000000400 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 0 P4D 0 + Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI + CPU: 0 UID: 0 PID: 470 Comm: mt76-usb-rx phy Not tainted 6.12.13-gentoo-dist #1 + Hardware name: /AMD HUDSON-M1, BIOS 4.6.4 11/15/2011 + RIP: 0010:mt792x_rx_get_wcid+0x48/0x140 [mt792x_lib] + RSP: 0018:ffffa147c055fd98 EFLAGS: 00010202 + RAX: 0000000000000000 RBX: ffff8e9ecb652000 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff8e9ecb652000 + RBP: 0000000000000685 R08: ffff8e9ec6570000 R09: 0000000000000000 + R10: ffff8e9ecd2ca000 R11: ffff8e9f22a217c0 R12: 0000000038010119 + R13: 0000000080843801 R14: ffff8e9ec6570000 R15: ffff8e9ecb652000 + FS: 0000000000000000(0000) GS:ffff8e9f22a00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000400 CR3: 000000000d2ea000 CR4: 00000000000006f0 + Call Trace: + + ? __die_body.cold+0x19/0x27 + ? page_fault_oops+0x15a/0x2f0 + ? search_module_extables+0x19/0x60 + ? search_bpf_extables+0x5f/0x80 + ? exc_page_fault+0x7e/0x180 + ? asm_exc_page_fault+0x26/0x30 + ? mt792x_rx_get_wcid+0x48/0x140 [mt792x_lib] + mt7921_queue_rx_skb+0x1c6/0xaa0 [mt7921_common] + mt76u_alloc_queues+0x784/0x810 [mt76_usb] + ? __pfx___mt76_worker_fn+0x10/0x10 [mt76] + __mt76_worker_fn+0x4f/0x80 [mt76] + kthread+0xd2/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x34/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + ---[ end trace 0000000000000000 ]--- + +Reported-by: Nick Morrow +Closes: https://github.com/morrownr/USB-WiFi/issues/577 +Cc: stable@vger.kernel.org +Fixes: 90c10286b176 ("wifi: mt76: mt7925: Update mt792x_rx_get_wcid for per-link STA") +Signed-off-by: Ming Yen Hsieh +Tested-by: Salah Coronya +Link: https://patch.msgid.link/20250218033343.1999648-1-mingyen.hsieh@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -811,6 +811,7 @@ int mt7921_mac_sta_add(struct mt76_dev * + msta->deflink.wcid.phy_idx = mvif->bss_conf.mt76.band_idx; + msta->deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta->deflink.last_txs = jiffies; ++ msta->deflink.sta = msta; + + ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); + if (ret)