From: Sasha Levin Date: Mon, 18 May 2026 19:20:26 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v6.6.141~69 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=ca326b7a113f47dd0fd28b4aeb67347b9161bce6;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/series b/queue-6.1/series index c2b5851e8e..ba4759019f 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -792,3 +792,5 @@ ice-pull-common-tasks-into-ice_vf_post_vsi_rebuild.patch ice-fix-null-pointer-dereference-in-ice_reset_all_vf.patch net-tls-fix-strparser-anchor-skb-leak-on-offload-rx-.patch net-sched-cls_flower-revert-unintended-changes.patch +smb-client-correctly-handle-errorcontextdata-as-a-fl.patch +smb-client-fix-oob-reads-parsing-symlink-error-respo.patch diff --git a/queue-6.1/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch b/queue-6.1/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch new file mode 100644 index 0000000000..573e285538 --- /dev/null +++ b/queue-6.1/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch @@ -0,0 +1,70 @@ +From 386af6dd1c3dc107c84bce2b47c3a0022106b9b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 19:52:51 +0800 +Subject: smb: client: correctly handle ErrorContextData as a flexible array + +From: Liang Jie + +[ Upstream commit 215b7f9ecb8d7c14d56febdcdd246f3579c32aba ] + +The `smb2_symlink_err_rsp` structure was previously defined with +`ErrorContextData` as a single `__u8` byte. However, the `ErrorContextData` +field is intended to be a variable-length array based on `ErrorDataLength`. +This mismatch leads to incorrect pointer arithmetic and potential memory +access issues when processing error contexts. + +Updates the `ErrorContextData` field to be a flexible array +(`__u8 ErrorContextData[]`). Additionally, it modifies the corresponding +casts in the `symlink_data()` function to properly handle the flexible +array, ensuring correct memory calculations and data handling. + +These changes improve the robustness of SMB2 symlink error processing. + +Signed-off-by: Liang Jie +Suggested-by: Tom Talpey +Signed-off-by: Steve French +[ Remove the __counted_by_le annotation in v6.1. ] +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 4 ++-- + fs/smb/client/smb2pdu.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index fe016144f3405..def2602ea0fb9 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -41,14 +41,14 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); + do { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { +- sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData; ++ sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; + } + cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n", + __func__, le32_to_cpu(p->ErrorId)); + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); +- p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len); ++ p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); + } while (p < end); + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { +diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h +index 2823526b66f7e..d12ca9c7e62bc 100644 +--- a/fs/smb/client/smb2pdu.h ++++ b/fs/smb/client/smb2pdu.h +@@ -79,7 +79,7 @@ struct smb2_symlink_err_rsp { + struct smb2_error_context_rsp { + __le32 ErrorDataLength; + __le32 ErrorId; +- __u8 ErrorContextData; /* ErrorDataLength long array */ ++ __u8 ErrorContextData[]; + } __packed; + + /* ErrorId values */ +-- +2.53.0 + diff --git a/queue-6.1/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch b/queue-6.1/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch new file mode 100644 index 0000000000..fece15f9c0 --- /dev/null +++ b/queue-6.1/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch @@ -0,0 +1,121 @@ +From 98ba2e2187acca9deb57ded9017da3f620f795bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 19:52:52 +0800 +Subject: smb: client: fix OOB reads parsing symlink error response + +From: Greg Kroah-Hartman + +[ Upstream commit 3df690bba28edec865cf7190be10708ad0ddd67e ] + +When a CREATE returns STATUS_STOPPED_ON_SYMLINK, smb2_check_message() +returns success without any length validation, leaving the symlink +parsers as the only defense against an untrusted server. + +symlink_data() walks SMB 3.1.1 error contexts with the loop test "p < +end", but reads p->ErrorId at offset 4 and p->ErrorDataLength at offset +0. When the server-controlled ErrorDataLength advances p to within 1-7 +bytes of end, the next iteration will read past it. When the matching +context is found, sym->SymLinkErrorTag is read at offset 4 from +p->ErrorContextData with no check that the symlink header itself fits. + +smb2_parse_symlink_response() then bounds-checks the substitute name +using SMB2_SYMLINK_STRUCT_SIZE as the offset of PathBuffer from +iov_base. That value is computed as sizeof(smb2_err_rsp) + +sizeof(smb2_symlink_err_rsp), which is correct only when +ErrorContextCount == 0. + +With at least one error context the symlink data sits 8 bytes deeper, +and each skipped non-matching context shifts it further by 8 + +ALIGN(ErrorDataLength, 8). The check is too short, allowing the +substitute name read to run past iov_len. The out-of-bound heap bytes +are UTF-16-decoded into the symlink target and returned to userspace via +readlink(2). + +Fix this all up by making the loops test require the full context header +to fit, rejecting sym if its header runs past end, and bound the +substitute name against the actual position of sym->PathBuffer rather +than a fixed offset. + +Because sub_offs and sub_len are 16bits, the pointer math will not +overflow here with the new greater-than. + +Cc: Ronnie Sahlberg +Cc: Shyam Prasad N +Cc: Tom Talpey +Cc: Bharath SM +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Cc: stable +Reviewed-by: Paulo Alcantara (Red Hat) +Assisted-by: gregkh_clanker_t1000 +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Steve French +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index def2602ea0fb9..43e38909e20bb 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -26,10 +26,11 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + { + struct smb2_err_rsp *err = iov->iov_base; + struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL); ++ u8 *end = (u8 *)err + iov->iov_len; + u32 len; + + if (err->ErrorContextCount) { +- struct smb2_error_context_rsp *p, *end; ++ struct smb2_error_context_rsp *p; + + len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp, + ErrorContextData) + +@@ -38,8 +39,7 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + return ERR_PTR(-EINVAL); + + p = (struct smb2_error_context_rsp *)err->ErrorData; +- end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); +- do { ++ while ((u8 *)p + sizeof(*p) <= end) { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { + sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; +@@ -49,14 +49,16 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); + p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); +- } while (p < end); ++ } + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { + sym = (struct smb2_symlink_err_rsp *)err->ErrorData; + } + +- if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || +- le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) ++ if (!IS_ERR(sym) && ++ ((u8 *)sym + sizeof(*sym) > end || ++ le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || ++ le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) + sym = ERR_PTR(-EINVAL); + + return sym; +@@ -81,8 +83,10 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec + print_len = le16_to_cpu(sym->PrintNameLength); + print_offs = le16_to_cpu(sym->PrintNameOffset); + +- if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len || +- iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len) ++ if ((char *)sym->PathBuffer + sub_offs + sub_len > ++ (char *)iov->iov_base + iov->iov_len || ++ (char *)sym->PathBuffer + print_offs + print_len > ++ (char *)iov->iov_base + iov->iov_len) + return -EINVAL; + + s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true, +-- +2.53.0 + diff --git a/queue-6.12/loongarch-kvm-compile-switch.s-directly-into-the-ker.patch b/queue-6.12/loongarch-kvm-compile-switch.s-directly-into-the-ker.patch new file mode 100644 index 0000000000..265daeeb96 --- /dev/null +++ b/queue-6.12/loongarch-kvm-compile-switch.s-directly-into-the-ker.patch @@ -0,0 +1,274 @@ +From 2c4f6457a37313f433e5599746844fa237e3ab5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 May 2026 17:18:55 +0800 +Subject: LoongArch: KVM: Compile switch.S directly into the kernel + +From: Xianglai Li + +commit 5203012fa6045aac4b69d4e7c212e16dcf38ef10 upstream. + +If we directly compile the switch.S file into the kernel, the address of +the kvm_exc_entry function will definitely be within the DMW memory area. +Therefore, we will no longer need to perform a copy relocation of the +kvm_exc_entry. + +So this patch compiles switch.S directly into the kernel, and then remove +the copy relocation execution logic for the kvm_exc_entry function. + +Signed-off-by: Xianglai Li +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/Kbuild | 2 +- + arch/loongarch/include/asm/asm-prototypes.h | 20 ++++++++++++ + arch/loongarch/include/asm/kvm_host.h | 3 -- + arch/loongarch/kvm/Makefile | 3 +- + arch/loongarch/kvm/main.c | 35 ++------------------- + arch/loongarch/kvm/switch.S | 19 ++++++++--- + 6 files changed, 40 insertions(+), 42 deletions(-) + +diff --git a/arch/loongarch/Kbuild b/arch/loongarch/Kbuild +index bfa21465d83af..604adaff2623a 100644 +--- a/arch/loongarch/Kbuild ++++ b/arch/loongarch/Kbuild +@@ -3,7 +3,7 @@ obj-y += mm/ + obj-y += net/ + obj-y += vdso/ + +-obj-$(CONFIG_KVM) += kvm/ ++obj-$(subst m,y,$(CONFIG_KVM)) += kvm/ + obj-$(CONFIG_BUILTIN_DTB) += boot/dts/ + + # for cleaning +diff --git a/arch/loongarch/include/asm/asm-prototypes.h b/arch/loongarch/include/asm/asm-prototypes.h +index 51f224bcfc654..50c66b2a817aa 100644 +--- a/arch/loongarch/include/asm/asm-prototypes.h ++++ b/arch/loongarch/include/asm/asm-prototypes.h +@@ -12,3 +12,23 @@ __int128_t __ashlti3(__int128_t a, int b); + __int128_t __ashrti3(__int128_t a, int b); + __int128_t __lshrti3(__int128_t a, int b); + #endif ++ ++struct kvm_run; ++struct kvm_vcpu; ++struct loongarch_fpu; ++ ++void kvm_exc_entry(void); ++int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu); ++ ++void kvm_save_fpu(struct loongarch_fpu *fpu); ++void kvm_restore_fpu(struct loongarch_fpu *fpu); ++ ++#ifdef CONFIG_CPU_HAS_LSX ++void kvm_save_lsx(struct loongarch_fpu *fpu); ++void kvm_restore_lsx(struct loongarch_fpu *fpu); ++#endif ++ ++#ifdef CONFIG_CPU_HAS_LASX ++void kvm_save_lasx(struct loongarch_fpu *fpu); ++void kvm_restore_lasx(struct loongarch_fpu *fpu); ++#endif +diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h +index d6bb72424027a..4f813fd89ac54 100644 +--- a/arch/loongarch/include/asm/kvm_host.h ++++ b/arch/loongarch/include/asm/kvm_host.h +@@ -73,7 +73,6 @@ struct kvm_context { + struct kvm_world_switch { + int (*exc_entry)(void); + int (*enter_guest)(struct kvm_run *run, struct kvm_vcpu *vcpu); +- unsigned long page_order; + }; + + #define MAX_PGTABLE_LEVELS 4 +@@ -317,8 +316,6 @@ void kvm_exc_entry(void); + int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu); + + extern unsigned long vpid_mask; +-extern const unsigned long kvm_exception_size; +-extern const unsigned long kvm_enter_guest_size; + extern struct kvm_world_switch *kvm_loongarch_ops; + + #define SW_GCSR (1 << 0) +diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile +index 2e188e8f14687..cbc27edfd1a27 100644 +--- a/arch/loongarch/kvm/Makefile ++++ b/arch/loongarch/kvm/Makefile +@@ -9,11 +9,12 @@ include $(srctree)/virt/kvm/Makefile.kvm + + obj-$(CONFIG_KVM) += kvm.o + ++obj-y += switch.o ++ + kvm-y += exit.o + kvm-y += interrupt.o + kvm-y += main.o + kvm-y += mmu.o +-kvm-y += switch.o + kvm-y += timer.o + kvm-y += tlb.o + kvm-y += vcpu.o +diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c +index 34fad2c29ee69..550ce2b4df70b 100644 +--- a/arch/loongarch/kvm/main.c ++++ b/arch/loongarch/kvm/main.c +@@ -320,8 +320,7 @@ void kvm_arch_disable_virtualization_cpu(void) + + static int kvm_loongarch_env_init(void) + { +- int cpu, order; +- void *addr; ++ int cpu; + struct kvm_context *context; + + vmcs = alloc_percpu(struct kvm_context); +@@ -337,30 +336,8 @@ static int kvm_loongarch_env_init(void) + return -ENOMEM; + } + +- /* +- * PGD register is shared between root kernel and kvm hypervisor. +- * So world switch entry should be in DMW area rather than TLB area +- * to avoid page fault reenter. +- * +- * In future if hardware pagetable walking is supported, we won't +- * need to copy world switch code to DMW area. +- */ +- order = get_order(kvm_exception_size + kvm_enter_guest_size); +- addr = (void *)__get_free_pages(GFP_KERNEL, order); +- if (!addr) { +- free_percpu(vmcs); +- vmcs = NULL; +- kfree(kvm_loongarch_ops); +- kvm_loongarch_ops = NULL; +- return -ENOMEM; +- } +- +- memcpy(addr, kvm_exc_entry, kvm_exception_size); +- memcpy(addr + kvm_exception_size, kvm_enter_guest, kvm_enter_guest_size); +- flush_icache_range((unsigned long)addr, (unsigned long)addr + kvm_exception_size + kvm_enter_guest_size); +- kvm_loongarch_ops->exc_entry = addr; +- kvm_loongarch_ops->enter_guest = addr + kvm_exception_size; +- kvm_loongarch_ops->page_order = order; ++ kvm_loongarch_ops->exc_entry = (void *)kvm_exc_entry; ++ kvm_loongarch_ops->enter_guest = (void *)kvm_enter_guest; + + vpid_mask = read_csr_gstat(); + vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT; +@@ -380,16 +357,10 @@ static int kvm_loongarch_env_init(void) + + static void kvm_loongarch_env_exit(void) + { +- unsigned long addr; +- + if (vmcs) + free_percpu(vmcs); + + if (kvm_loongarch_ops) { +- if (kvm_loongarch_ops->exc_entry) { +- addr = (unsigned long)kvm_loongarch_ops->exc_entry; +- free_pages(addr, kvm_loongarch_ops->page_order); +- } + kfree(kvm_loongarch_ops); + } + } +diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S +index 42c9fc99dc7e9..df8e5a705b714 100644 +--- a/arch/loongarch/kvm/switch.S ++++ b/arch/loongarch/kvm/switch.S +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -108,8 +109,13 @@ + * - is still in guest mode, such as pgd table/vmid registers etc, + * - will fix with hw page walk enabled in future + * load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to KVM_TEMP_KS ++ * ++ * PGD register is shared between root kernel and kvm hypervisor. ++ * So world switch entry should be in DMW area rather than TLB area ++ * to avoid page fault re-enter. + */ + .text ++ .p2align PAGE_SHIFT + .cfi_sections .debug_frame + SYM_CODE_START(kvm_exc_entry) + UNWIND_HINT_END_OF_STACK +@@ -198,8 +204,8 @@ ret_to_host: + kvm_restore_host_gpr a2 + jr ra + +-SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL) + SYM_CODE_END(kvm_exc_entry) ++EXPORT_SYMBOL_GPL(kvm_exc_entry) + + /* + * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu) +@@ -223,8 +229,8 @@ SYM_FUNC_START(kvm_enter_guest) + /* Save kvm_vcpu to kscratch */ + csrwr a1, KVM_VCPU_KS + kvm_switch_to_guest +-SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL) + SYM_FUNC_END(kvm_enter_guest) ++EXPORT_SYMBOL_GPL(kvm_enter_guest) + + SYM_FUNC_START(kvm_save_fpu) + fpu_save_csr a0 t1 +@@ -232,6 +238,7 @@ SYM_FUNC_START(kvm_save_fpu) + fpu_save_cc a0 t1 t2 + jr ra + SYM_FUNC_END(kvm_save_fpu) ++EXPORT_SYMBOL_GPL(kvm_save_fpu) + + SYM_FUNC_START(kvm_restore_fpu) + fpu_restore_double a0 t1 +@@ -239,6 +246,7 @@ SYM_FUNC_START(kvm_restore_fpu) + fpu_restore_cc a0 t1 t2 + jr ra + SYM_FUNC_END(kvm_restore_fpu) ++EXPORT_SYMBOL_GPL(kvm_restore_fpu) + + #ifdef CONFIG_CPU_HAS_LSX + SYM_FUNC_START(kvm_save_lsx) +@@ -247,6 +255,7 @@ SYM_FUNC_START(kvm_save_lsx) + lsx_save_data a0 t1 + jr ra + SYM_FUNC_END(kvm_save_lsx) ++EXPORT_SYMBOL_GPL(kvm_save_lsx) + + SYM_FUNC_START(kvm_restore_lsx) + lsx_restore_data a0 t1 +@@ -254,6 +263,7 @@ SYM_FUNC_START(kvm_restore_lsx) + fpu_restore_csr a0 t1 t2 + jr ra + SYM_FUNC_END(kvm_restore_lsx) ++EXPORT_SYMBOL_GPL(kvm_restore_lsx) + #endif + + #ifdef CONFIG_CPU_HAS_LASX +@@ -263,6 +273,7 @@ SYM_FUNC_START(kvm_save_lasx) + lasx_save_data a0 t1 + jr ra + SYM_FUNC_END(kvm_save_lasx) ++EXPORT_SYMBOL_GPL(kvm_save_lasx) + + SYM_FUNC_START(kvm_restore_lasx) + lasx_restore_data a0 t1 +@@ -270,10 +281,8 @@ SYM_FUNC_START(kvm_restore_lasx) + fpu_restore_csr a0 t1 t2 + jr ra + SYM_FUNC_END(kvm_restore_lasx) ++EXPORT_SYMBOL_GPL(kvm_restore_lasx) + #endif +- .section ".rodata" +-SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry) +-SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest) + + #ifdef CONFIG_CPU_HAS_LBT + STACK_FRAME_NON_STANDARD kvm_restore_fpu +-- +2.53.0 + diff --git a/queue-6.12/ntfs-d_compare-must-not-block.patch b/queue-6.12/ntfs-d_compare-must-not-block.patch new file mode 100644 index 0000000000..7ff74195e0 --- /dev/null +++ b/queue-6.12/ntfs-d_compare-must-not-block.patch @@ -0,0 +1,237 @@ +From 0e23ce2eb2e75e1cb41dd10ace264bd8d075743c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 12:21:30 +0800 +Subject: ntfs: ->d_compare() must not block + +From: Al Viro + +[ Upstream commit ca2a04e84af79596e5cd9cfe697d5122ec39c8ce ] + +... so don't use __getname() there. Switch it (and ntfs_d_hash(), while +we are at it) to kmalloc(PATH_MAX, GFP_NOWAIT). Yes, ntfs_d_hash() +almost certainly can do with smaller allocations, but let ntfs folks +deal with that - keep the allocation size as-is for now. + +Stop abusing names_cachep in ntfs, period - various uses of that thing +in there have nothing to do with pathnames; just use k[mz]alloc() and +be done with that. For now let's keep sizes as-in, but AFAICS none of +the users actually want PATH_MAX. + +Signed-off-by: Al Viro +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + fs/ntfs3/dir.c | 5 ++--- + fs/ntfs3/fsntfs.c | 4 ++-- + fs/ntfs3/inode.c | 13 ++++++------- + fs/ntfs3/namei.c | 17 ++++++++--------- + fs/ntfs3/xattr.c | 5 ++--- + 5 files changed, 20 insertions(+), 24 deletions(-) + +diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c +index 600e66035c1b7..522ebc14b1fbd 100644 +--- a/fs/ntfs3/dir.c ++++ b/fs/ntfs3/dir.c +@@ -425,8 +425,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) + if (!dir_emit_dots(file, ctx)) + return 0; + +- /* Allocate PATH_MAX bytes. */ +- name = __getname(); ++ name = kmalloc(PATH_MAX, GFP_KERNEL); + if (!name) + return -ENOMEM; + +@@ -504,7 +503,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) + + out: + +- __putname(name); ++ kfree(name); + put_indx_node(node); + + if (err == 1) { +diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c +index 37c5d9a1f77b7..5972f160e566e 100644 +--- a/fs/ntfs3/fsntfs.c ++++ b/fs/ntfs3/fsntfs.c +@@ -2670,7 +2670,7 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) + u32 uni_bytes; + struct ntfs_inode *ni = sbi->volume.ni; + /* Allocate PATH_MAX bytes. */ +- struct cpu_str *uni = __getname(); ++ struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL); + + if (!uni) + return -ENOMEM; +@@ -2714,6 +2714,6 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) + err = _ni_write_inode(&ni->vfs_inode, 0); + + out: +- __putname(uni); ++ kfree(uni); + return err; + } +\ No newline at end of file +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index 8113d47b0ceb9..b50c9dff327d2 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -1301,7 +1301,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, + fa |= FILE_ATTRIBUTE_READONLY; + + /* Allocate PATH_MAX bytes. */ +- new_de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ new_de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!new_de) { + err = -ENOMEM; + goto out1; +@@ -1713,7 +1713,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, + ntfs_mark_rec_free(sbi, ino, false); + + out2: +- __putname(new_de); ++ kfree(new_de); + kfree(rp); + + out1: +@@ -1734,7 +1734,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) + struct NTFS_DE *de; + + /* Allocate PATH_MAX bytes. */ +- de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -1748,7 +1748,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) + + err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de); + out: +- __putname(de); ++ kfree(de); + return err; + } + +@@ -1771,8 +1771,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) + if (ntfs_is_meta_file(sbi, ni->mi.rno)) + return -EINVAL; + +- /* Allocate PATH_MAX bytes. */ +- de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -1808,7 +1807,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) + + out: + ni_unlock(ni); +- __putname(de); ++ kfree(de); + return err; + } + +diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c +index 71a5a959a48cb..fa4f7d9f38454 100644 +--- a/fs/ntfs3/namei.c ++++ b/fs/ntfs3/namei.c +@@ -68,7 +68,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry, + u32 flags) + { + struct ntfs_inode *ni = ntfs_i(dir); +- struct cpu_str *uni = __getname(); ++ struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL); + struct inode *inode; + int err; + +@@ -85,7 +85,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry, + inode = dir_search_u(dir, uni, NULL); + ni_unlock(ni); + } +- __putname(uni); ++ kfree(uni); + } + + /* +@@ -287,8 +287,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir, + return err; + } + +- /* Allocate PATH_MAX bytes. */ +- de = __getname(); ++ de = kmalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -333,7 +332,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir, + ni_unlock(ni); + ni_unlock(dir_ni); + out: +- __putname(de); ++ kfree(de); + return err; + } + +@@ -391,7 +390,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) + /* + * Try slow way with current upcase table + */ +- uni = kmem_cache_alloc(names_cachep, GFP_NOWAIT); ++ uni = kmalloc(PATH_MAX, GFP_NOWAIT); + if (!uni) + return -ENOMEM; + +@@ -413,7 +412,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) + err = 0; + + out: +- kmem_cache_free(names_cachep, uni); ++ kfree(uni); + return err; + } + +@@ -452,7 +451,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, + * Try slow way with current upcase table + */ + sbi = dentry->d_sb->s_fs_info; +- uni1 = __getname(); ++ uni1 = kmalloc(PATH_MAX, GFP_NOWAIT); + if (!uni1) + return -ENOMEM; + +@@ -482,7 +481,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, + ret = !ntfs_cmp_names_cpu(uni1, uni2, sbi->upcase, false) ? 0 : 1; + + out: +- __putname(uni1); ++ kfree(uni1); + return ret; + } + +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index e0055dcf8fe38..6861c09d66d77 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -552,8 +552,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, + int err; + void *buf; + +- /* Allocate PATH_MAX bytes. */ +- buf = __getname(); ++ buf = kmalloc(PATH_MAX, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + +@@ -584,7 +583,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); + +- __putname(buf); ++ kfree(buf); + + return acl; + } +-- +2.53.0 + diff --git a/queue-6.12/pci-initialize-temporary-device-in-new_id_store.patch b/queue-6.12/pci-initialize-temporary-device-in-new_id_store.patch new file mode 100644 index 0000000000..1265b74ae5 --- /dev/null +++ b/queue-6.12/pci-initialize-temporary-device-in-new_id_store.patch @@ -0,0 +1,90 @@ +From b35fdb57b71f252594f947f8eb9f7045172cf202 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 23:43:27 +0000 +Subject: PCI: Initialize temporary device in new_id_store() + +From: Samiullah Khawaja + +[ Upstream commit f45a49a2380a47332817b7248c61a0ebbc6f0d00 ] + +When setting new_id of a PCI device driver using sysfs a lockdep splat +occurs. This is because new_id_store() builds a temporary pci_dev for +pci_match_device(), which calls device_match_driver_override(). That +depends on the driver_override.lock added by cb3d1049f4ea ("driver core: +generalize driver_override in struct device"). + +The new driver_override.lock was not initialized in the temporary pci_dev, +resulting in this lockdep splat. + +Initialize the temporary pci_dev to fix this. + +Repro: + + Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID: + + # echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id + + INFO: trying to register non-static key. + The code is fine but needs lockdep annotation, or maybe + you didn't initialize this object before use? + turning off the locking correctness validator. + CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 + Call Trace: + + dump_stack_lvl+0x5d/0x80 + register_lock_class+0x77e/0x790 + lock_acquire+0xbf/0x2e0 + pci_match_device+0x24/0x180 + new_id_store+0x189/0x1d0 + kernfs_fop_write_iter+0x14f/0x210 + vfs_write+0x263/0x5e0 + ksys_write+0x79/0xf0 + do_syscall_64+0x117/0xf80 + +Fixes: 10a4206a2401 ("PCI: use generic driver_override infrastructure") +Fixes: 8895d3bcb8ba ("PCI: Fail new_id for vendor/device values already built into driver") +Signed-off-by: Samiullah Khawaja +[bhelgaas: add commit log details and repro, trim backtrace] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Danilo Krummrich +Link: https://patch.msgid.link/20260505234327.716630-1-skhawaja@google.com +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-driver.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 860d80787d9b1..f0fbe45bfb9a1 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, + return NULL; + } + ++static void _pci_free_device(struct device *dev) ++{ ++ kfree(to_pci_dev(dev)); ++} ++ + /** + * new_id_store - sysfs frontend to pci_add_dynid() + * @driver: target device driver +@@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, + pdev->subsystem_vendor = subvendor; + pdev->subsystem_device = subdevice; + pdev->class = class; ++ pdev->dev.release = _pci_free_device; + ++ device_initialize(&pdev->dev); + if (pci_match_device(pdrv, pdev)) + retval = -EEXIST; + +- kfree(pdev); ++ put_device(&pdev->dev); + + if (retval) + return retval; +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 17c6b30e0c..1ce51fc347 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -592,3 +592,8 @@ net-tls-fix-strparser-anchor-skb-leak-on-offload-rx-.patch sfc-fix-error-code-in-efx_devlink_info_running_versi.patch net-sched-cls_flower-revert-unintended-changes.patch arm64-reserve-an-extra-page-for-early-kernel-mapping.patch +smb-client-correctly-handle-errorcontextdata-as-a-fl.patch +smb-client-fix-oob-reads-parsing-symlink-error-respo.patch +loongarch-kvm-compile-switch.s-directly-into-the-ker.patch +ntfs-d_compare-must-not-block.patch +pci-initialize-temporary-device-in-new_id_store.patch diff --git a/queue-6.12/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch b/queue-6.12/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch new file mode 100644 index 0000000000..34d17714c4 --- /dev/null +++ b/queue-6.12/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch @@ -0,0 +1,69 @@ +From 03006f2ccd83328ef85aeac5f3c74c6c43e2c22e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 16:14:00 +0800 +Subject: smb: client: correctly handle ErrorContextData as a flexible array + +From: Liang Jie + +[ Upstream commit 215b7f9ecb8d7c14d56febdcdd246f3579c32aba ] + +The `smb2_symlink_err_rsp` structure was previously defined with +`ErrorContextData` as a single `__u8` byte. However, the `ErrorContextData` +field is intended to be a variable-length array based on `ErrorDataLength`. +This mismatch leads to incorrect pointer arithmetic and potential memory +access issues when processing error contexts. + +Updates the `ErrorContextData` field to be a flexible array +(`__u8 ErrorContextData[]`). Additionally, it modifies the corresponding +casts in the `symlink_data()` function to properly handle the flexible +array, ensuring correct memory calculations and data handling. + +These changes improve the robustness of SMB2 symlink error processing. + +Signed-off-by: Liang Jie +Suggested-by: Tom Talpey +Signed-off-by: Steve French +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 4 ++-- + fs/smb/client/smb2pdu.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index b7ab18d4bedca..35d2933982d31 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -42,14 +42,14 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); + do { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { +- sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData; ++ sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; + } + cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n", + __func__, le32_to_cpu(p->ErrorId)); + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); +- p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len); ++ p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); + } while (p < end); + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { +diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h +index 076d9e83e1a04..3c09a58dfd073 100644 +--- a/fs/smb/client/smb2pdu.h ++++ b/fs/smb/client/smb2pdu.h +@@ -79,7 +79,7 @@ struct smb2_symlink_err_rsp { + struct smb2_error_context_rsp { + __le32 ErrorDataLength; + __le32 ErrorId; +- __u8 ErrorContextData; /* ErrorDataLength long array */ ++ __u8 ErrorContextData[] __counted_by_le(ErrorDataLength); + } __packed; + + /* ErrorId values */ +-- +2.53.0 + diff --git a/queue-6.12/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch b/queue-6.12/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch new file mode 100644 index 0000000000..4b9f8de565 --- /dev/null +++ b/queue-6.12/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch @@ -0,0 +1,121 @@ +From d858b502b9b417d46a858ba2beddc90d0fbae93d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 16:14:01 +0800 +Subject: smb: client: fix OOB reads parsing symlink error response + +From: Greg Kroah-Hartman + +[ Upstream commit 3df690bba28edec865cf7190be10708ad0ddd67e ] + +When a CREATE returns STATUS_STOPPED_ON_SYMLINK, smb2_check_message() +returns success without any length validation, leaving the symlink +parsers as the only defense against an untrusted server. + +symlink_data() walks SMB 3.1.1 error contexts with the loop test "p < +end", but reads p->ErrorId at offset 4 and p->ErrorDataLength at offset +0. When the server-controlled ErrorDataLength advances p to within 1-7 +bytes of end, the next iteration will read past it. When the matching +context is found, sym->SymLinkErrorTag is read at offset 4 from +p->ErrorContextData with no check that the symlink header itself fits. + +smb2_parse_symlink_response() then bounds-checks the substitute name +using SMB2_SYMLINK_STRUCT_SIZE as the offset of PathBuffer from +iov_base. That value is computed as sizeof(smb2_err_rsp) + +sizeof(smb2_symlink_err_rsp), which is correct only when +ErrorContextCount == 0. + +With at least one error context the symlink data sits 8 bytes deeper, +and each skipped non-matching context shifts it further by 8 + +ALIGN(ErrorDataLength, 8). The check is too short, allowing the +substitute name read to run past iov_len. The out-of-bound heap bytes +are UTF-16-decoded into the symlink target and returned to userspace via +readlink(2). + +Fix this all up by making the loops test require the full context header +to fit, rejecting sym if its header runs past end, and bound the +substitute name against the actual position of sym->PathBuffer rather +than a fixed offset. + +Because sub_offs and sub_len are 16bits, the pointer math will not +overflow here with the new greater-than. + +Cc: Ronnie Sahlberg +Cc: Shyam Prasad N +Cc: Tom Talpey +Cc: Bharath SM +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Cc: stable +Reviewed-by: Paulo Alcantara (Red Hat) +Assisted-by: gregkh_clanker_t1000 +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Steve French +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index 35d2933982d31..fd331a9f2f4d2 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -27,10 +27,11 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + { + struct smb2_err_rsp *err = iov->iov_base; + struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL); ++ u8 *end = (u8 *)err + iov->iov_len; + u32 len; + + if (err->ErrorContextCount) { +- struct smb2_error_context_rsp *p, *end; ++ struct smb2_error_context_rsp *p; + + len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp, + ErrorContextData) + +@@ -39,8 +40,7 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + return ERR_PTR(-EINVAL); + + p = (struct smb2_error_context_rsp *)err->ErrorData; +- end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); +- do { ++ while ((u8 *)p + sizeof(*p) <= end) { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { + sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; +@@ -50,14 +50,16 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); + p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); +- } while (p < end); ++ } + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { + sym = (struct smb2_symlink_err_rsp *)err->ErrorData; + } + +- if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || +- le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) ++ if (!IS_ERR(sym) && ++ ((u8 *)sym + sizeof(*sym) > end || ++ le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || ++ le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) + sym = ERR_PTR(-EINVAL); + + return sym; +@@ -82,8 +84,10 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec + print_len = le16_to_cpu(sym->PrintNameLength); + print_offs = le16_to_cpu(sym->PrintNameOffset); + +- if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len || +- iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len) ++ if ((char *)sym->PathBuffer + sub_offs + sub_len > ++ (char *)iov->iov_base + iov->iov_len || ++ (char *)sym->PathBuffer + print_offs + print_len > ++ (char *)iov->iov_base + iov->iov_len) + return -EINVAL; + + return smb2_parse_native_symlink(path, +-- +2.53.0 + diff --git a/queue-6.18/pci-initialize-temporary-device-in-new_id_store.patch b/queue-6.18/pci-initialize-temporary-device-in-new_id_store.patch new file mode 100644 index 0000000000..fd9ddad94a --- /dev/null +++ b/queue-6.18/pci-initialize-temporary-device-in-new_id_store.patch @@ -0,0 +1,90 @@ +From ae69809aa76d518c43401fd544becc26b5924e70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 23:43:27 +0000 +Subject: PCI: Initialize temporary device in new_id_store() + +From: Samiullah Khawaja + +[ Upstream commit f45a49a2380a47332817b7248c61a0ebbc6f0d00 ] + +When setting new_id of a PCI device driver using sysfs a lockdep splat +occurs. This is because new_id_store() builds a temporary pci_dev for +pci_match_device(), which calls device_match_driver_override(). That +depends on the driver_override.lock added by cb3d1049f4ea ("driver core: +generalize driver_override in struct device"). + +The new driver_override.lock was not initialized in the temporary pci_dev, +resulting in this lockdep splat. + +Initialize the temporary pci_dev to fix this. + +Repro: + + Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID: + + # echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id + + INFO: trying to register non-static key. + The code is fine but needs lockdep annotation, or maybe + you didn't initialize this object before use? + turning off the locking correctness validator. + CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 + Call Trace: + + dump_stack_lvl+0x5d/0x80 + register_lock_class+0x77e/0x790 + lock_acquire+0xbf/0x2e0 + pci_match_device+0x24/0x180 + new_id_store+0x189/0x1d0 + kernfs_fop_write_iter+0x14f/0x210 + vfs_write+0x263/0x5e0 + ksys_write+0x79/0xf0 + do_syscall_64+0x117/0xf80 + +Fixes: 10a4206a2401 ("PCI: use generic driver_override infrastructure") +Fixes: 8895d3bcb8ba ("PCI: Fail new_id for vendor/device values already built into driver") +Signed-off-by: Samiullah Khawaja +[bhelgaas: add commit log details and repro, trim backtrace] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Danilo Krummrich +Link: https://patch.msgid.link/20260505234327.716630-1-skhawaja@google.com +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-driver.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index fba07a700508f..f9ead94d5ebb6 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, + return NULL; + } + ++static void _pci_free_device(struct device *dev) ++{ ++ kfree(to_pci_dev(dev)); ++} ++ + /** + * new_id_store - sysfs frontend to pci_add_dynid() + * @driver: target device driver +@@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, + pdev->subsystem_vendor = subvendor; + pdev->subsystem_device = subdevice; + pdev->class = class; ++ pdev->dev.release = _pci_free_device; + ++ device_initialize(&pdev->dev); + if (pci_match_device(pdrv, pdev)) + retval = -EEXIST; + +- kfree(pdev); ++ put_device(&pdev->dev); + + if (retval) + return retval; +-- +2.53.0 + diff --git a/queue-6.18/revert-papr-hvpipe-convert-papr_hvpipe_dev_create_ha.patch b/queue-6.18/revert-papr-hvpipe-convert-papr_hvpipe_dev_create_ha.patch new file mode 100644 index 0000000000..51a8cb9915 --- /dev/null +++ b/queue-6.18/revert-papr-hvpipe-convert-papr_hvpipe_dev_create_ha.patch @@ -0,0 +1,84 @@ +From 0f8b51c97b32587e905353f2aa5b54f93dfe3d12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 11:13:17 -0400 +Subject: Revert "papr-hvpipe: convert papr_hvpipe_dev_create_handle() to + FD_PREPARE()" + +This reverts commit 09c15bbbed533903e600660ea09098b3b0524f48. + +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 39 +++++++++++++++----- + 1 file changed, 30 insertions(+), 9 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c +index 3d8672642c251..431f6a3da4c5a 100644 +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -484,7 +484,10 @@ static const struct file_operations papr_hvpipe_handle_ops = { + + static int papr_hvpipe_dev_create_handle(u32 srcID) + { +- struct hvpipe_source_info *src_info __free(kfree) = NULL; ++ struct hvpipe_source_info *src_info; ++ struct file *file; ++ long err; ++ int fd; + + spin_lock(&hvpipe_src_list_lock); + /* +@@ -508,13 +511,20 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) + src_info->tsk = current; + init_waitqueue_head(&src_info->recv_wqh); + +- FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, +- anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops, +- (void *)src_info, O_RDWR)); +- if (fdf.err) +- return fdf.err; ++ fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); ++ if (fd < 0) { ++ err = fd; ++ goto free_buf; ++ } ++ ++ file = anon_inode_getfile("[papr-hvpipe]", ++ &papr_hvpipe_handle_ops, (void *)src_info, ++ O_RDWR); ++ if (IS_ERR(file)) { ++ err = PTR_ERR(file); ++ goto free_fd; ++ } + +- retain_and_null_ptr(src_info); + spin_lock(&hvpipe_src_list_lock); + /* + * If two processes are executing ioctl() for the same +@@ -523,11 +533,22 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) + */ + if (hvpipe_find_source(srcID)) { + spin_unlock(&hvpipe_src_list_lock); +- return -EALREADY; ++ err = -EALREADY; ++ goto free_file; + } + list_add(&src_info->list, &hvpipe_src_list); + spin_unlock(&hvpipe_src_list_lock); +- return fd_publish(fdf); ++ ++ fd_install(fd, file); ++ return fd; ++ ++free_file: ++ fput(file); ++free_fd: ++ put_unused_fd(fd); ++free_buf: ++ kfree(src_info); ++ return err; + } + + /* +-- +2.53.0 + diff --git a/queue-6.18/revert-pseries-papr-hvpipe-fix-race-with-interrupt-h.patch b/queue-6.18/revert-pseries-papr-hvpipe-fix-race-with-interrupt-h.patch new file mode 100644 index 0000000000..2768476fe2 --- /dev/null +++ b/queue-6.18/revert-pseries-papr-hvpipe-fix-race-with-interrupt-h.patch @@ -0,0 +1,95 @@ +From 531e4b6ad8ea5fd07341014e175aaa3797847f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 11:13:17 -0400 +Subject: Revert "pseries/papr-hvpipe: Fix race with interrupt handler" + +This reverts commit 6542e180fa6e1c701aba446a555c65556e6fd1a5. + +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c +index a238db095b4ec..3d8672642c251 100644 +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -449,14 +449,13 @@ static int papr_hvpipe_handle_release(struct inode *inode, + struct file *file) + { + struct hvpipe_source_info *src_info; +- unsigned long flags; + + /* + * Hold the lock, remove source from src_list, reset the + * hvpipe status and release the lock to prevent any race + * with message event IRQ. + */ +- spin_lock_irqsave(&hvpipe_src_list_lock, flags); ++ spin_lock(&hvpipe_src_list_lock); + src_info = file->private_data; + list_del(&src_info->list); + file->private_data = NULL; +@@ -467,10 +466,10 @@ static int papr_hvpipe_handle_release(struct inode *inode, + */ + if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) { + src_info->hvpipe_status = 0; +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + hvpipe_rtas_recv_msg(NULL, 0); + } else +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + + kfree(src_info); + return 0; +@@ -486,21 +485,20 @@ static const struct file_operations papr_hvpipe_handle_ops = { + static int papr_hvpipe_dev_create_handle(u32 srcID) + { + struct hvpipe_source_info *src_info __free(kfree) = NULL; +- unsigned long flags; + +- spin_lock_irqsave(&hvpipe_src_list_lock, flags); ++ spin_lock(&hvpipe_src_list_lock); + /* + * Do not allow more than one process communicates with + * each source. + */ + src_info = hvpipe_find_source(srcID); + if (src_info) { +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + pr_err("pid(%d) is already using the source(%d)\n", + src_info->tsk->pid, srcID); + return -EALREADY; + } +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + + src_info = kzalloc(sizeof(*src_info), GFP_KERNEL_ACCOUNT); + if (!src_info) +@@ -517,18 +515,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) + return fdf.err; + + retain_and_null_ptr(src_info); +- spin_lock_irqsave(&hvpipe_src_list_lock, flags); ++ spin_lock(&hvpipe_src_list_lock); + /* + * If two processes are executing ioctl() for the same + * source ID concurrently, prevent the second process to + * acquire FD. + */ + if (hvpipe_find_source(srcID)) { +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + return -EALREADY; + } + list_add(&src_info->list, &hvpipe_src_list); +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ spin_unlock(&hvpipe_src_list_lock); + return fd_publish(fdf); + } + +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 5d0c3d2220..19ccc2e75c 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -857,3 +857,6 @@ net-sched-cls_flower-revert-unintended-changes.patch kselftest-arm64-include-asm-ptrace.h-for-user_gcs-de.patch arm64-reserve-an-extra-page-for-early-kernel-mapping.patch futex-drop-clone_thread-requirement-for-private-defa.patch +revert-pseries-papr-hvpipe-fix-race-with-interrupt-h.patch +revert-papr-hvpipe-convert-papr_hvpipe_dev_create_ha.patch +pci-initialize-temporary-device-in-new_id_store.patch diff --git a/queue-6.6/crypto-nx-fix-bounce-buffer-leaks-in-nx842_crypto_-a.patch b/queue-6.6/crypto-nx-fix-bounce-buffer-leaks-in-nx842_crypto_-a.patch new file mode 100644 index 0000000000..32fda4147e --- /dev/null +++ b/queue-6.6/crypto-nx-fix-bounce-buffer-leaks-in-nx842_crypto_-a.patch @@ -0,0 +1,54 @@ +From da6ad9122e59d3e4ce3ce0a17f829705f9af4e39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 23:16:39 -0400 +Subject: crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx + +From: Thorsten Blum + +[ Upstream commit adb3faf2db1a66d0f015b44ac909a32dfc7f2f9c ] + +The bounce buffers are allocated with __get_free_pages() using +BOUNCE_BUFFER_ORDER (order 2 = 4 pages), but both the allocation error +path and nx842_crypto_free_ctx() release the buffers with free_page(). +Use free_pages() with the matching order instead. + +Fixes: ed70b479c2c0 ("crypto: nx - add hardware 842 crypto comp alg") +Cc: stable@vger.kernel.org +Signed-off-by: Thorsten Blum +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/crypto/nx/nx-842.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c +index 82214cde2bcd9..3b82b6f67f8c4 100644 +--- a/drivers/crypto/nx/nx-842.c ++++ b/drivers/crypto/nx/nx-842.c +@@ -112,8 +112,8 @@ int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver) + ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); + if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) { + kfree(ctx->wmem); +- free_page((unsigned long)ctx->sbounce); +- free_page((unsigned long)ctx->dbounce); ++ free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); ++ free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); + return -ENOMEM; + } + +@@ -126,8 +126,8 @@ void nx842_crypto_exit(struct crypto_tfm *tfm) + struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); + + kfree(ctx->wmem); +- free_page((unsigned long)ctx->sbounce); +- free_page((unsigned long)ctx->dbounce); ++ free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); ++ free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); + } + EXPORT_SYMBOL_GPL(nx842_crypto_exit); + +-- +2.53.0 + diff --git a/queue-6.6/ntfs-d_compare-must-not-block.patch b/queue-6.6/ntfs-d_compare-must-not-block.patch new file mode 100644 index 0000000000..8f431d28d7 --- /dev/null +++ b/queue-6.6/ntfs-d_compare-must-not-block.patch @@ -0,0 +1,236 @@ +From f84da19c4b51418cf222dc9428d5a643970aeb17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 12:21:40 +0800 +Subject: ntfs: ->d_compare() must not block + +From: Al Viro + +[ Upstream commit ca2a04e84af79596e5cd9cfe697d5122ec39c8ce ] + +... so don't use __getname() there. Switch it (and ntfs_d_hash(), while +we are at it) to kmalloc(PATH_MAX, GFP_NOWAIT). Yes, ntfs_d_hash() +almost certainly can do with smaller allocations, but let ntfs folks +deal with that - keep the allocation size as-is for now. + +Stop abusing names_cachep in ntfs, period - various uses of that thing +in there have nothing to do with pathnames; just use k[mz]alloc() and +be done with that. For now let's keep sizes as-in, but AFAICS none of +the users actually want PATH_MAX. + +Signed-off-by: Al Viro +Signed-off-by: Li hongliang <1468888505@139.com> +--- + fs/ntfs3/dir.c | 5 ++--- + fs/ntfs3/fsntfs.c | 4 ++-- + fs/ntfs3/inode.c | 13 ++++++------- + fs/ntfs3/namei.c | 17 ++++++++--------- + fs/ntfs3/xattr.c | 5 ++--- + 5 files changed, 20 insertions(+), 24 deletions(-) + +diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c +index 6b93c909bdc9e..894fd44164b48 100644 +--- a/fs/ntfs3/dir.c ++++ b/fs/ntfs3/dir.c +@@ -425,8 +425,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) + if (!dir_emit_dots(file, ctx)) + return 0; + +- /* Allocate PATH_MAX bytes. */ +- name = __getname(); ++ name = kmalloc(PATH_MAX, GFP_KERNEL); + if (!name) + return -ENOMEM; + +@@ -504,7 +503,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) + + out: + +- __putname(name); ++ kfree(name); + put_indx_node(node); + + if (err == 1) { +diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c +index e17d4c1ba06f0..a38547bd12bb4 100644 +--- a/fs/ntfs3/fsntfs.c ++++ b/fs/ntfs3/fsntfs.c +@@ -2666,7 +2666,7 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) + struct ntfs_inode *ni = sbi->volume.ni; + const u8 max_ulen = 0x80; /* TODO: use attrdef to get maximum length */ + /* Allocate PATH_MAX bytes. */ +- struct cpu_str *uni = __getname(); ++ struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL); + + if (!uni) + return -ENOMEM; +@@ -2709,6 +2709,6 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) + err = _ni_write_inode(&ni->vfs_inode, 0); + + out: +- __putname(uni); ++ kfree(uni); + return err; + } +\ No newline at end of file +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index ce381eafd084e..787e15ba0ca40 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -1327,7 +1327,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, + fa |= FILE_ATTRIBUTE_READONLY; + + /* Allocate PATH_MAX bytes. */ +- new_de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ new_de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!new_de) { + err = -ENOMEM; + goto out1; +@@ -1733,7 +1733,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, + ntfs_mark_rec_free(sbi, ino, false); + + out2: +- __putname(new_de); ++ kfree(new_de); + kfree(rp); + + out1: +@@ -1756,7 +1756,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) + struct NTFS_DE *de; + + /* Allocate PATH_MAX bytes. */ +- de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -1770,7 +1770,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) + + err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de); + out: +- __putname(de); ++ kfree(de); + return err; + } + +@@ -1793,8 +1793,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) + if (ntfs_is_meta_file(sbi, ni->mi.rno)) + return -EINVAL; + +- /* Allocate PATH_MAX bytes. */ +- de = kmem_cache_zalloc(names_cachep, GFP_KERNEL); ++ de = kzalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -1830,7 +1829,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) + + out: + ni_unlock(ni); +- __putname(de); ++ kfree(de); + return err; + } + +diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c +index f5901c23ab937..1b0c075c14853 100644 +--- a/fs/ntfs3/namei.c ++++ b/fs/ntfs3/namei.c +@@ -68,7 +68,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry, + u32 flags) + { + struct ntfs_inode *ni = ntfs_i(dir); +- struct cpu_str *uni = __getname(); ++ struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL); + struct inode *inode; + int err; + +@@ -85,7 +85,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry, + inode = dir_search_u(dir, uni, NULL); + ni_unlock(ni); + } +- __putname(uni); ++ kfree(uni); + } + + /* +@@ -304,8 +304,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir, + return err; + } + +- /* Allocate PATH_MAX bytes. */ +- de = __getname(); ++ de = kmalloc(PATH_MAX, GFP_KERNEL); + if (!de) + return -ENOMEM; + +@@ -350,7 +349,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir, + ni_unlock(ni); + ni_unlock(dir_ni); + out: +- __putname(de); ++ kfree(de); + return err; + } + +@@ -497,7 +496,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) + /* + * Try slow way with current upcase table + */ +- uni = kmem_cache_alloc(names_cachep, GFP_NOWAIT); ++ uni = kmalloc(PATH_MAX, GFP_NOWAIT); + if (!uni) + return -ENOMEM; + +@@ -519,7 +518,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) + err = 0; + + out: +- kmem_cache_free(names_cachep, uni); ++ kfree(uni); + return err; + } + +@@ -558,7 +557,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, + * Try slow way with current upcase table + */ + sbi = dentry->d_sb->s_fs_info; +- uni1 = __getname(); ++ uni1 = kmalloc(PATH_MAX, GFP_NOWAIT); + if (!uni1) + return -ENOMEM; + +@@ -588,7 +587,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, + ret = !ntfs_cmp_names_cpu(uni1, uni2, sbi->upcase, false) ? 0 : 1; + + out: +- __putname(uni1); ++ kfree(uni1); + return ret; + } + +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index 72bceb8cd164b..a03b4bce5fbfd 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -551,8 +551,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, + int err; + void *buf; + +- /* Allocate PATH_MAX bytes. */ +- buf = __getname(); ++ buf = kmalloc(PATH_MAX, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + +@@ -583,7 +582,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); + +- __putname(buf); ++ kfree(buf); + + return acl; + } +-- +2.53.0 + diff --git a/queue-6.6/revert-crypto-nx-fix-bounce-buffer-leaks-in-nx842_cr.patch b/queue-6.6/revert-crypto-nx-fix-bounce-buffer-leaks-in-nx842_cr.patch new file mode 100644 index 0000000000..1a96f00e88 --- /dev/null +++ b/queue-6.6/revert-crypto-nx-fix-bounce-buffer-leaks-in-nx842_cr.patch @@ -0,0 +1,42 @@ +From aaeb5379fb0e73f0198390a850ef81d38400172d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 10:51:32 -0400 +Subject: Revert "crypto: nx - fix bounce buffer leaks in + nx842_crypto_{alloc,free}_ctx" + +This reverts commit 6923cde8dc1d501e79b312139819c88b54463803. + +Signed-off-by: Sasha Levin +--- + drivers/crypto/nx/nx-842.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c +index 1f5005fcd69a9..b950fcce8a9be 100644 +--- a/drivers/crypto/nx/nx-842.c ++++ b/drivers/crypto/nx/nx-842.c +@@ -116,8 +116,8 @@ void *nx842_crypto_alloc_ctx(struct nx842_driver *driver) + ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); + if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) { + kfree(ctx->wmem); +- free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); +- free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); ++ free_page((unsigned long)ctx->sbounce); ++ free_page((unsigned long)ctx->dbounce); + kfree(ctx); + return ERR_PTR(-ENOMEM); + } +@@ -131,8 +131,8 @@ void nx842_crypto_free_ctx(void *p) + struct nx842_crypto_ctx *ctx = p; + + kfree(ctx->wmem); +- free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); +- free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); ++ free_page((unsigned long)ctx->sbounce); ++ free_page((unsigned long)ctx->dbounce); + } + EXPORT_SYMBOL_GPL(nx842_crypto_free_ctx); + +-- +2.53.0 + diff --git a/queue-6.6/revert-crypto-nx-fix-context-leak-in-nx842_crypto_fr.patch b/queue-6.6/revert-crypto-nx-fix-context-leak-in-nx842_crypto_fr.patch new file mode 100644 index 0000000000..e0b9a1d4c1 --- /dev/null +++ b/queue-6.6/revert-crypto-nx-fix-context-leak-in-nx842_crypto_fr.patch @@ -0,0 +1,39 @@ +From f5a2d421a04e607edacac4b8313c8e610acbf624 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 10:51:32 -0400 +Subject: Revert "crypto: nx - fix context leak in nx842_crypto_free_ctx" + +This reverts commit b94588f5a69718be2c942f4a851125f655e4e819. + +Signed-off-by: Sasha Levin +--- + drivers/crypto/nx/nx-842.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c +index 8b1dc05df8c8d..1f5005fcd69a9 100644 +--- a/drivers/crypto/nx/nx-842.c ++++ b/drivers/crypto/nx/nx-842.c +@@ -115,7 +115,10 @@ void *nx842_crypto_alloc_ctx(struct nx842_driver *driver) + ctx->sbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); + ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER); + if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) { +- nx842_crypto_free_ctx(ctx); ++ kfree(ctx->wmem); ++ free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); ++ free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); ++ kfree(ctx); + return ERR_PTR(-ENOMEM); + } + +@@ -130,7 +133,6 @@ void nx842_crypto_free_ctx(void *p) + kfree(ctx->wmem); + free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER); + free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER); +- kfree(ctx); + } + EXPORT_SYMBOL_GPL(nx842_crypto_free_ctx); + +-- +2.53.0 + diff --git a/queue-6.6/revert-crypto-nx-migrate-to-scomp-api.patch b/queue-6.6/revert-crypto-nx-migrate-to-scomp-api.patch new file mode 100644 index 0000000000..b5438f8951 --- /dev/null +++ b/queue-6.6/revert-crypto-nx-migrate-to-scomp-api.patch @@ -0,0 +1,280 @@ +From d7b870865489aa1f5108c3383cf9b52fc79c48bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 10:51:32 -0400 +Subject: Revert "crypto: nx - Migrate to scomp API" + +This reverts commit 268ae55a4c4fbff3ff54f92a4642f497da814f49. + +Signed-off-by: Sasha Levin +--- + drivers/crypto/nx/nx-842.c | 33 ++++++++++++--------------- + drivers/crypto/nx/nx-842.h | 15 ++++++------ + drivers/crypto/nx/nx-common-powernv.c | 31 +++++++++++++------------ + drivers/crypto/nx/nx-common-pseries.c | 33 ++++++++++++++------------- + 4 files changed, 54 insertions(+), 58 deletions(-) + +diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c +index b950fcce8a9be..82214cde2bcd9 100644 +--- a/drivers/crypto/nx/nx-842.c ++++ b/drivers/crypto/nx/nx-842.c +@@ -101,13 +101,9 @@ static int update_param(struct nx842_crypto_param *p, + return 0; + } + +-void *nx842_crypto_alloc_ctx(struct nx842_driver *driver) ++int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver) + { +- struct nx842_crypto_ctx *ctx; +- +- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +- if (!ctx) +- return ERR_PTR(-ENOMEM); ++ struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); + + spin_lock_init(&ctx->lock); + ctx->driver = driver; +@@ -118,23 +114,22 @@ void *nx842_crypto_alloc_ctx(struct nx842_driver *driver) + kfree(ctx->wmem); + free_page((unsigned long)ctx->sbounce); + free_page((unsigned long)ctx->dbounce); +- kfree(ctx); +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + } + +- return ctx; ++ return 0; + } +-EXPORT_SYMBOL_GPL(nx842_crypto_alloc_ctx); ++EXPORT_SYMBOL_GPL(nx842_crypto_init); + +-void nx842_crypto_free_ctx(void *p) ++void nx842_crypto_exit(struct crypto_tfm *tfm) + { +- struct nx842_crypto_ctx *ctx = p; ++ struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); + + kfree(ctx->wmem); + free_page((unsigned long)ctx->sbounce); + free_page((unsigned long)ctx->dbounce); + } +-EXPORT_SYMBOL_GPL(nx842_crypto_free_ctx); ++EXPORT_SYMBOL_GPL(nx842_crypto_exit); + + static void check_constraints(struct nx842_constraints *c) + { +@@ -251,11 +246,11 @@ static int compress(struct nx842_crypto_ctx *ctx, + return update_param(p, slen, dskip + dlen); + } + +-int nx842_crypto_compress(struct crypto_scomp *tfm, ++int nx842_crypto_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, +- u8 *dst, unsigned int *dlen, void *pctx) ++ u8 *dst, unsigned int *dlen) + { +- struct nx842_crypto_ctx *ctx = pctx; ++ struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); + struct nx842_crypto_header *hdr = + container_of(&ctx->header, + struct nx842_crypto_header, hdr); +@@ -436,11 +431,11 @@ static int decompress(struct nx842_crypto_ctx *ctx, + return update_param(p, slen + padding, dlen); + } + +-int nx842_crypto_decompress(struct crypto_scomp *tfm, ++int nx842_crypto_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, +- u8 *dst, unsigned int *dlen, void *pctx) ++ u8 *dst, unsigned int *dlen) + { +- struct nx842_crypto_ctx *ctx = pctx; ++ struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm); + struct nx842_crypto_header *hdr; + struct nx842_crypto_param p; + struct nx842_constraints c = *ctx->driver->constraints; +diff --git a/drivers/crypto/nx/nx-842.h b/drivers/crypto/nx/nx-842.h +index 58137ffd3835b..25fa70b2112cf 100644 +--- a/drivers/crypto/nx/nx-842.h ++++ b/drivers/crypto/nx/nx-842.h +@@ -3,6 +3,7 @@ + #ifndef __NX_842_H__ + #define __NX_842_H__ + ++#include + #include + #include + #include +@@ -100,8 +101,6 @@ + #define LEN_ON_SIZE(pa, size) ((size) - ((pa) & ((size) - 1))) + #define LEN_ON_PAGE(pa) LEN_ON_SIZE(pa, PAGE_SIZE) + +-struct crypto_scomp; +- + static inline unsigned long nx842_get_pa(void *addr) + { + if (!is_vmalloc_addr(addr)) +@@ -180,13 +179,13 @@ struct nx842_crypto_ctx { + struct nx842_driver *driver; + }; + +-void *nx842_crypto_alloc_ctx(struct nx842_driver *driver); +-void nx842_crypto_free_ctx(void *ctx); +-int nx842_crypto_compress(struct crypto_scomp *tfm, ++int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver); ++void nx842_crypto_exit(struct crypto_tfm *tfm); ++int nx842_crypto_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, +- u8 *dst, unsigned int *dlen, void *ctx); +-int nx842_crypto_decompress(struct crypto_scomp *tfm, ++ u8 *dst, unsigned int *dlen); ++int nx842_crypto_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, +- u8 *dst, unsigned int *dlen, void *ctx); ++ u8 *dst, unsigned int *dlen); + + #endif /* __NX_842_H__ */ +diff --git a/drivers/crypto/nx/nx-common-powernv.c b/drivers/crypto/nx/nx-common-powernv.c +index fd0a98b2fb1b2..8c859872c1839 100644 +--- a/drivers/crypto/nx/nx-common-powernv.c ++++ b/drivers/crypto/nx/nx-common-powernv.c +@@ -9,7 +9,6 @@ + + #include "nx-842.h" + +-#include + #include + + #include +@@ -1032,21 +1031,23 @@ static struct nx842_driver nx842_powernv_driver = { + .decompress = nx842_powernv_decompress, + }; + +-static void *nx842_powernv_crypto_alloc_ctx(void) ++static int nx842_powernv_crypto_init(struct crypto_tfm *tfm) + { +- return nx842_crypto_alloc_ctx(&nx842_powernv_driver); ++ return nx842_crypto_init(tfm, &nx842_powernv_driver); + } + +-static struct scomp_alg nx842_powernv_alg = { +- .base.cra_name = "842", +- .base.cra_driver_name = "842-nx", +- .base.cra_priority = 300, +- .base.cra_module = THIS_MODULE, +- +- .alloc_ctx = nx842_powernv_crypto_alloc_ctx, +- .free_ctx = nx842_crypto_free_ctx, +- .compress = nx842_crypto_compress, +- .decompress = nx842_crypto_decompress, ++static struct crypto_alg nx842_powernv_alg = { ++ .cra_name = "842", ++ .cra_driver_name = "842-nx", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, ++ .cra_ctxsize = sizeof(struct nx842_crypto_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_init = nx842_powernv_crypto_init, ++ .cra_exit = nx842_crypto_exit, ++ .cra_u = { .compress = { ++ .coa_compress = nx842_crypto_compress, ++ .coa_decompress = nx842_crypto_decompress } } + }; + + static __init int nx_compress_powernv_init(void) +@@ -1106,7 +1107,7 @@ static __init int nx_compress_powernv_init(void) + nx842_powernv_exec = nx842_exec_vas; + } + +- ret = crypto_register_scomp(&nx842_powernv_alg); ++ ret = crypto_register_alg(&nx842_powernv_alg); + if (ret) { + nx_delete_coprocs(); + return ret; +@@ -1127,7 +1128,7 @@ static void __exit nx_compress_powernv_exit(void) + if (!nx842_ct) + vas_unregister_api_powernv(); + +- crypto_unregister_scomp(&nx842_powernv_alg); ++ crypto_unregister_alg(&nx842_powernv_alg); + + nx_delete_coprocs(); + } +diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c +index 0d26aafd08863..7e98f174f69b9 100644 +--- a/drivers/crypto/nx/nx-common-pseries.c ++++ b/drivers/crypto/nx/nx-common-pseries.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + + #include "nx-842.h" + #include "nx_csbcpb.h" /* struct nx_csbcpb */ +@@ -1009,21 +1008,23 @@ static struct nx842_driver nx842_pseries_driver = { + .decompress = nx842_pseries_decompress, + }; + +-static void *nx842_pseries_crypto_alloc_ctx(void) ++static int nx842_pseries_crypto_init(struct crypto_tfm *tfm) + { +- return nx842_crypto_alloc_ctx(&nx842_pseries_driver); ++ return nx842_crypto_init(tfm, &nx842_pseries_driver); + } + +-static struct scomp_alg nx842_pseries_alg = { +- .base.cra_name = "842", +- .base.cra_driver_name = "842-nx", +- .base.cra_priority = 300, +- .base.cra_module = THIS_MODULE, +- +- .alloc_ctx = nx842_pseries_crypto_alloc_ctx, +- .free_ctx = nx842_crypto_free_ctx, +- .compress = nx842_crypto_compress, +- .decompress = nx842_crypto_decompress, ++static struct crypto_alg nx842_pseries_alg = { ++ .cra_name = "842", ++ .cra_driver_name = "842-nx", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, ++ .cra_ctxsize = sizeof(struct nx842_crypto_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_init = nx842_pseries_crypto_init, ++ .cra_exit = nx842_crypto_exit, ++ .cra_u = { .compress = { ++ .coa_compress = nx842_crypto_compress, ++ .coa_decompress = nx842_crypto_decompress } } + }; + + static int nx842_probe(struct vio_dev *viodev, +@@ -1071,7 +1072,7 @@ static int nx842_probe(struct vio_dev *viodev, + if (ret) + goto error; + +- ret = crypto_register_scomp(&nx842_pseries_alg); ++ ret = crypto_register_alg(&nx842_pseries_alg); + if (ret) { + dev_err(&viodev->dev, "could not register comp alg: %d\n", ret); + goto error; +@@ -1119,7 +1120,7 @@ static void nx842_remove(struct vio_dev *viodev) + if (caps_feat) + sysfs_remove_group(&viodev->dev.kobj, &nxcop_caps_attr_group); + +- crypto_unregister_scomp(&nx842_pseries_alg); ++ crypto_unregister_alg(&nx842_pseries_alg); + + spin_lock_irqsave(&devdata_mutex, flags); + old_devdata = rcu_dereference_check(devdata, +@@ -1251,7 +1252,7 @@ static void __exit nx842_pseries_exit(void) + + vas_unregister_api_pseries(); + +- crypto_unregister_scomp(&nx842_pseries_alg); ++ crypto_unregister_alg(&nx842_pseries_alg); + + spin_lock_irqsave(&devdata_mutex, flags); + old_devdata = rcu_dereference_check(devdata, +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index 09433a9694..a98f40cde6 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -435,3 +435,10 @@ ice-fix-null-pointer-dereference-in-ice_reset_all_vf.patch net-tls-fix-strparser-anchor-skb-leak-on-offload-rx-.patch sfc-fix-error-code-in-efx_devlink_info_running_versi.patch net-sched-cls_flower-revert-unintended-changes.patch +ntfs-d_compare-must-not-block.patch +revert-crypto-nx-fix-context-leak-in-nx842_crypto_fr.patch +revert-crypto-nx-fix-bounce-buffer-leaks-in-nx842_cr.patch +revert-crypto-nx-migrate-to-scomp-api.patch +smb-client-correctly-handle-errorcontextdata-as-a-fl.patch +smb-client-fix-oob-reads-parsing-symlink-error-respo.patch +crypto-nx-fix-bounce-buffer-leaks-in-nx842_crypto_-a.patch diff --git a/queue-6.6/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch b/queue-6.6/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch new file mode 100644 index 0000000000..ae7eb69553 --- /dev/null +++ b/queue-6.6/smb-client-correctly-handle-errorcontextdata-as-a-fl.patch @@ -0,0 +1,70 @@ +From 90086608e52a1723e442f5945570fa6cd30917f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 16:15:53 +0800 +Subject: smb: client: correctly handle ErrorContextData as a flexible array + +From: Liang Jie + +[ Upstream commit 215b7f9ecb8d7c14d56febdcdd246f3579c32aba ] + +The `smb2_symlink_err_rsp` structure was previously defined with +`ErrorContextData` as a single `__u8` byte. However, the `ErrorContextData` +field is intended to be a variable-length array based on `ErrorDataLength`. +This mismatch leads to incorrect pointer arithmetic and potential memory +access issues when processing error contexts. + +Updates the `ErrorContextData` field to be a flexible array +(`__u8 ErrorContextData[]`). Additionally, it modifies the corresponding +casts in the `symlink_data()` function to properly handle the flexible +array, ensuring correct memory calculations and data handling. + +These changes improve the robustness of SMB2 symlink error processing. + +Signed-off-by: Liang Jie +Suggested-by: Tom Talpey +Signed-off-by: Steve French +[ Remove the __counted_by_le annotation in v6.6. ] +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 4 ++-- + fs/smb/client/smb2pdu.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index 4e7d5c612256d..3a5b62b298063 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -42,14 +42,14 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); + do { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { +- sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData; ++ sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; + } + cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n", + __func__, le32_to_cpu(p->ErrorId)); + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); +- p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len); ++ p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); + } while (p < end); + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { +diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h +index 076d9e83e1a04..2eb15f3a7fe66 100644 +--- a/fs/smb/client/smb2pdu.h ++++ b/fs/smb/client/smb2pdu.h +@@ -79,7 +79,7 @@ struct smb2_symlink_err_rsp { + struct smb2_error_context_rsp { + __le32 ErrorDataLength; + __le32 ErrorId; +- __u8 ErrorContextData; /* ErrorDataLength long array */ ++ __u8 ErrorContextData[]; + } __packed; + + /* ErrorId values */ +-- +2.53.0 + diff --git a/queue-6.6/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch b/queue-6.6/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch new file mode 100644 index 0000000000..9080c90460 --- /dev/null +++ b/queue-6.6/smb-client-fix-oob-reads-parsing-symlink-error-respo.patch @@ -0,0 +1,121 @@ +From 48c183078801f9db5f19f1e5f35f6e124163cd08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 16:15:54 +0800 +Subject: smb: client: fix OOB reads parsing symlink error response + +From: Greg Kroah-Hartman + +[ Upstream commit 3df690bba28edec865cf7190be10708ad0ddd67e ] + +When a CREATE returns STATUS_STOPPED_ON_SYMLINK, smb2_check_message() +returns success without any length validation, leaving the symlink +parsers as the only defense against an untrusted server. + +symlink_data() walks SMB 3.1.1 error contexts with the loop test "p < +end", but reads p->ErrorId at offset 4 and p->ErrorDataLength at offset +0. When the server-controlled ErrorDataLength advances p to within 1-7 +bytes of end, the next iteration will read past it. When the matching +context is found, sym->SymLinkErrorTag is read at offset 4 from +p->ErrorContextData with no check that the symlink header itself fits. + +smb2_parse_symlink_response() then bounds-checks the substitute name +using SMB2_SYMLINK_STRUCT_SIZE as the offset of PathBuffer from +iov_base. That value is computed as sizeof(smb2_err_rsp) + +sizeof(smb2_symlink_err_rsp), which is correct only when +ErrorContextCount == 0. + +With at least one error context the symlink data sits 8 bytes deeper, +and each skipped non-matching context shifts it further by 8 + +ALIGN(ErrorDataLength, 8). The check is too short, allowing the +substitute name read to run past iov_len. The out-of-bound heap bytes +are UTF-16-decoded into the symlink target and returned to userspace via +readlink(2). + +Fix this all up by making the loops test require the full context header +to fit, rejecting sym if its header runs past end, and bound the +substitute name against the actual position of sym->PathBuffer rather +than a fixed offset. + +Because sub_offs and sub_len are 16bits, the pointer math will not +overflow here with the new greater-than. + +Cc: Ronnie Sahlberg +Cc: Shyam Prasad N +Cc: Tom Talpey +Cc: Bharath SM +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Cc: stable +Reviewed-by: Paulo Alcantara (Red Hat) +Assisted-by: gregkh_clanker_t1000 +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Steve French +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index 3a5b62b298063..044512b77448c 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -27,10 +27,11 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + { + struct smb2_err_rsp *err = iov->iov_base; + struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL); ++ u8 *end = (u8 *)err + iov->iov_len; + u32 len; + + if (err->ErrorContextCount) { +- struct smb2_error_context_rsp *p, *end; ++ struct smb2_error_context_rsp *p; + + len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp, + ErrorContextData) + +@@ -39,8 +40,7 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + return ERR_PTR(-EINVAL); + + p = (struct smb2_error_context_rsp *)err->ErrorData; +- end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); +- do { ++ while ((u8 *)p + sizeof(*p) <= end) { + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { + sym = (struct smb2_symlink_err_rsp *)p->ErrorContextData; + break; +@@ -50,14 +50,16 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) + + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); + p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); +- } while (p < end); ++ } + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { + sym = (struct smb2_symlink_err_rsp *)err->ErrorData; + } + +- if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || +- le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) ++ if (!IS_ERR(sym) && ++ ((u8 *)sym + sizeof(*sym) > end || ++ le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || ++ le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) + sym = ERR_PTR(-EINVAL); + + return sym; +@@ -82,8 +84,10 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec + print_len = le16_to_cpu(sym->PrintNameLength); + print_offs = le16_to_cpu(sym->PrintNameOffset); + +- if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len || +- iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len) ++ if ((char *)sym->PathBuffer + sub_offs + sub_len > ++ (char *)iov->iov_base + iov->iov_len || ++ (char *)sym->PathBuffer + print_offs + print_len > ++ (char *)iov->iov_base + iov->iov_len) + return -EINVAL; + + return smb2_parse_native_symlink(path, +-- +2.53.0 + diff --git a/queue-7.0/pci-initialize-temporary-device-in-new_id_store.patch b/queue-7.0/pci-initialize-temporary-device-in-new_id_store.patch new file mode 100644 index 0000000000..97ef133bf9 --- /dev/null +++ b/queue-7.0/pci-initialize-temporary-device-in-new_id_store.patch @@ -0,0 +1,90 @@ +From 0652221d824374215411cc47dfa07888ab65f3f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 23:43:27 +0000 +Subject: PCI: Initialize temporary device in new_id_store() + +From: Samiullah Khawaja + +[ Upstream commit f45a49a2380a47332817b7248c61a0ebbc6f0d00 ] + +When setting new_id of a PCI device driver using sysfs a lockdep splat +occurs. This is because new_id_store() builds a temporary pci_dev for +pci_match_device(), which calls device_match_driver_override(). That +depends on the driver_override.lock added by cb3d1049f4ea ("driver core: +generalize driver_override in struct device"). + +The new driver_override.lock was not initialized in the temporary pci_dev, +resulting in this lockdep splat. + +Initialize the temporary pci_dev to fix this. + +Repro: + + Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID: + + # echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id + + INFO: trying to register non-static key. + The code is fine but needs lockdep annotation, or maybe + you didn't initialize this object before use? + turning off the locking correctness validator. + CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 + Call Trace: + + dump_stack_lvl+0x5d/0x80 + register_lock_class+0x77e/0x790 + lock_acquire+0xbf/0x2e0 + pci_match_device+0x24/0x180 + new_id_store+0x189/0x1d0 + kernfs_fop_write_iter+0x14f/0x210 + vfs_write+0x263/0x5e0 + ksys_write+0x79/0xf0 + do_syscall_64+0x117/0xf80 + +Fixes: 10a4206a2401 ("PCI: use generic driver_override infrastructure") +Fixes: 8895d3bcb8ba ("PCI: Fail new_id for vendor/device values already built into driver") +Signed-off-by: Samiullah Khawaja +[bhelgaas: add commit log details and repro, trim backtrace] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Danilo Krummrich +Link: https://patch.msgid.link/20260505234327.716630-1-skhawaja@google.com +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-driver.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index d10ece0889f0f..e3f59001785a1 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, + return NULL; + } + ++static void _pci_free_device(struct device *dev) ++{ ++ kfree(to_pci_dev(dev)); ++} ++ + /** + * new_id_store - sysfs frontend to pci_add_dynid() + * @driver: target device driver +@@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, + pdev->subsystem_vendor = subvendor; + pdev->subsystem_device = subdevice; + pdev->class = class; ++ pdev->dev.release = _pci_free_device; + ++ device_initialize(&pdev->dev); + if (pci_match_device(pdrv, pdev)) + retval = -EEXIST; + +- kfree(pdev); ++ put_device(&pdev->dev); + + if (retval) + return retval; +-- +2.53.0 + diff --git a/queue-7.0/series b/queue-7.0/series index c71b86957c..4a997294a1 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -1034,3 +1034,4 @@ net-sched-cls_flower-revert-unintended-changes.patch kselftest-arm64-include-asm-ptrace.h-for-user_gcs-de.patch arm64-reserve-an-extra-page-for-early-kernel-mapping.patch futex-drop-clone_thread-requirement-for-private-defa.patch +pci-initialize-temporary-device-in-new_id_store.patch