From: Greg Kroah-Hartman Date: Wed, 15 Jul 2026 15:32:39 +0000 (+0200) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dddf2820ab13bee695fea8b9f77b0ad679e2fb50;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch module-decompress-check-return-value-of-module_extend_max_pages.patch nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch riscv-mm-define-direct_map_physmem_end.patch tracing-prevent-out-of-bounds-read-in-glob-matching.patch --- diff --git a/queue-6.6/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch b/queue-6.6/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch new file mode 100644 index 0000000000..0f8c914099 --- /dev/null +++ b/queue-6.6/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch @@ -0,0 +1,79 @@ +From 3a1230e7b043c62737b05a3e9275ca83a43ad20a Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Fri, 12 Jun 2026 14:29:06 -0500 +Subject: exfat: bound uniname advance in exfat_find_dir_entry() + +From: Bryam Vargas + +commit 3a1230e7b043c62737b05a3e9275ca83a43ad20a upstream. + +In exfat_find_dir_entry(), each TYPE_EXTEND (file name) entry advances the +output pointer by a fixed amount while the loop guard only tracks the +accumulated name length: + + if (++order == 2) + uniname = p_uniname->name; + else + uniname += EXFAT_FILE_NAME_LEN; + len = exfat_extract_uni_name(ep, entry_uniname); + name_len += len; + unichar = *(uniname+len); + *(uniname+len) = 0x0; + +uniname grows by EXFAT_FILE_NAME_LEN (15) per name entry, but name_len +grows only by the actual extracted length, which is shorter when a name +fragment contains an early NUL. The only guard is +`name_len >= MAX_NAME_LENGTH`, so a crafted directory with many short +name fragments lets uniname run far past the +p_uniname->name[MAX_NAME_LENGTH + 3] buffer while name_len stays small, +causing an out-of-bounds read and write at *(uniname+len). + +The sibling extractor exfat_get_uniname_from_ext_entry() already stops +on a short fragment (the lockstep `len != EXFAT_FILE_NAME_LEN` guard +added in commit d42334578eba ("exfat: check if filename entries exceeds +max filename length")); exfat_find_dir_entry() never got the +equivalent. Track the per-entry write offset as a count and reject a +fragment once the offset, or the offset plus the extracted length, would +exceed MAX_NAME_LENGTH, before forming the output pointer. + +Fixes: ca06197382bd ("exfat: add directory operations") +Cc: stable@vger.kernel.org +Suggested-by: Namjae Jeon +Signed-off-by: Bryam Vargas +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/dir.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -1081,6 +1081,7 @@ rewind: + + if (entry_type == TYPE_EXTEND) { + unsigned short entry_uniname[16], unichar; ++ unsigned int offset; + + if (step != DIRENT_STEP_NAME || + name_len >= MAX_NAME_LENGTH) { +@@ -1089,13 +1090,15 @@ rewind: + continue; + } + +- if (++order == 2) +- uniname = p_uniname->name; +- else +- uniname += EXFAT_FILE_NAME_LEN; +- ++ offset = (++order - 2) * EXFAT_FILE_NAME_LEN; + len = exfat_extract_uni_name(ep, entry_uniname); + brelse(bh); ++ if (offset > MAX_NAME_LENGTH || ++ len > MAX_NAME_LENGTH - offset) { ++ step = DIRENT_STEP_FILE; ++ continue; ++ } ++ uniname = p_uniname->name + offset; + name_len += len; + + unichar = *(uniname+len); diff --git a/queue-6.6/module-decompress-check-return-value-of-module_extend_max_pages.patch b/queue-6.6/module-decompress-check-return-value-of-module_extend_max_pages.patch new file mode 100644 index 0000000000..f2856619cb --- /dev/null +++ b/queue-6.6/module-decompress-check-return-value-of-module_extend_max_pages.patch @@ -0,0 +1,48 @@ +From 786d2d84416a9a1c1a47b71a68d679d886284be2 Mon Sep 17 00:00:00 2001 +From: Andrii Kuchmenko +Date: Mon, 18 May 2026 17:32:33 +0300 +Subject: module: decompress: check return value of module_extend_max_pages() + +From: Andrii Kuchmenko + +commit 786d2d84416a9a1c1a47b71a68d679d886284be2 upstream. + +module_extend_max_pages() calls kvrealloc() internally and returns +-ENOMEM on allocation failure. The return value is never checked. + +If the initial allocation fails, info->pages remains NULL and +info->max_pages remains 0. Subsequent calls to module_get_next_page() +will attempt to dynamically grow the array by calling +module_extend_max_pages(info, 0) since info->used_pages is 0. This +results in kvrealloc(NULL, 0) returning ZERO_SIZE_PTR, which is treated +as a success, leading to a dereference of ZERO_SIZE_PTR and a kernel +oops. + +Fix: add the missing error check after module_extend_max_pages() and +return immediately on failure. This matches the pattern used by every +other kvrealloc() caller in the module loading path. + +Fixes: b1ae6dc41eaa ("module: add in-kernel support for decompressing") +Cc: Dmitry Torokhov +Cc: Luis Chamberlain +Cc: stable@vger.kernel.org +Signed-off-by: Andrii Kuchmenko +Reviewed-by: Christophe Leroy (CS GROUP) +[Sami: Corrected the analysis in the commit message.] +Signed-off-by: Sami Tolvanen +Signed-off-by: Greg Kroah-Hartman +--- + kernel/module/decompress.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/module/decompress.c ++++ b/kernel/module/decompress.c +@@ -307,6 +307,8 @@ int module_decompress(struct load_info * + */ + n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2; + error = module_extend_max_pages(info, n_pages); ++ if (error) ++ return error; + + data_size = MODULE_DECOMPRESS_FN(info, buf, size); + if (data_size < 0) { diff --git a/queue-6.6/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch b/queue-6.6/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch new file mode 100644 index 0000000000..adc8fadc47 --- /dev/null +++ b/queue-6.6/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch @@ -0,0 +1,48 @@ +From 5140f099ecd8a2f2808b7f7b720ee1bad8468974 Mon Sep 17 00:00:00 2001 +From: Benjamin Coddington +Date: Thu, 11 Jun 2026 17:02:15 -0400 +Subject: NFSv4: include MAY_WRITE in open permission mask for O_TRUNC + +From: Benjamin Coddington + +commit 5140f099ecd8a2f2808b7f7b720ee1bad8468974 upstream. + +POSIX requires write permission to truncate a file, so an open() that +specifies O_TRUNC must be authorized for write access regardless of the +O_ACCMODE access mode. + +nfs_open_permission_mask() builds the access mask passed to +nfs_may_open(), which is the local authorization gate for OPENs the +client serves itself from a cached write delegation via the +can_open_delegated() path in nfs4_try_open_cached(). The mask is +derived from O_ACCMODE alone, so an open(O_RDONLY | O_TRUNC) against a +file the caller cannot write requests only MAY_READ and passes the +local check. The OPEN is then satisfied locally and the truncation is +issued to the server as a SETATTR(size=0) over the delegation stateid, +which the server accepts under standard write-delegation semantics. +POSIX requires that this open fail with EACCES. + +Include MAY_WRITE in the mask whenever O_TRUNC is set so the local +check matches the access the server would have enforced. + +Suggested-by: Trond Myklebust +Fixes: af22f94ae02a ("NFSv4: Simplify _nfs4_do_access()") +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Coddington +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -3275,6 +3275,8 @@ static int nfs_open_permission_mask(int + mask |= MAY_READ; + if ((openflags & O_ACCMODE) != O_RDONLY) + mask |= MAY_WRITE; ++ if (openflags & O_TRUNC) ++ mask |= MAY_WRITE; + } + + return mask; diff --git a/queue-6.6/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch b/queue-6.6/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch new file mode 100644 index 0000000000..20fcae4c5d --- /dev/null +++ b/queue-6.6/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch @@ -0,0 +1,59 @@ +From fcba26efe5efc7441f5505f4ccc69791214b40be Mon Sep 17 00:00:00 2001 +From: Koichiro Den +Date: Wed, 4 Mar 2026 17:30:27 +0900 +Subject: NTB: epf: Fix request_irq() unwind in ntb_epf_init_isr() + +From: Koichiro Den + +commit fcba26efe5efc7441f5505f4ccc69791214b40be upstream. + +ntb_epf_init_isr() requests multiple MSI/MSI-X vectors in a loop. If +request_irq() fails part-way through, it jumps straight to +pci_free_irq_vectors() without freeing already requested IRQs. + +Fix the error path by freeing any successfully requested IRQs before +releasing the vectors. + +Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Bjorn Helgaas +Reviewed-by: Dave Jiang +Cc: stable@vger.kernel.org # v5.12+ +Link: https://patch.msgid.link/20260304083028.1391068-2-den@valinux.co.jp +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ntb/hw/epf/ntb_hw_epf.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/ntb/hw/epf/ntb_hw_epf.c ++++ b/drivers/ntb/hw/epf/ntb_hw_epf.c +@@ -357,7 +357,7 @@ static int ntb_epf_init_isr(struct ntb_e + 0, "ntb_epf", ndev); + if (ret) { + dev_err(dev, "Failed to request irq\n"); +- goto err_request_irq; ++ goto err_free_irq; + } + } + +@@ -367,16 +367,14 @@ static int ntb_epf_init_isr(struct ntb_e + argument | irq); + if (ret) { + dev_err(dev, "Failed to configure doorbell\n"); +- goto err_configure_db; ++ goto err_free_irq; + } + + return 0; + +-err_configure_db: +- for (i = 0; i < ndev->db_count + 1; i++) ++err_free_irq: ++ while (i--) + free_irq(pci_irq_vector(pdev, i), ndev); +- +-err_request_irq: + pci_free_irq_vectors(pdev); + + return ret; diff --git a/queue-6.6/riscv-mm-define-direct_map_physmem_end.patch b/queue-6.6/riscv-mm-define-direct_map_physmem_end.patch new file mode 100644 index 0000000000..6acb0207fd --- /dev/null +++ b/queue-6.6/riscv-mm-define-direct_map_physmem_end.patch @@ -0,0 +1,47 @@ +From f3336b48cf9d3f2d1fc78e3289c0ded2f00876ee Mon Sep 17 00:00:00 2001 +From: Vivian Wang +Date: Sat, 6 Jun 2026 20:17:54 -0600 +Subject: riscv: mm: Define DIRECT_MAP_PHYSMEM_END + +From: Vivian Wang + +commit f3336b48cf9d3f2d1fc78e3289c0ded2f00876ee upstream. + +On RISC-V, the actual mappable range of physical address space is +dependent on the current MMU mode i.e. satp_mode (See +Documentation/arch/riscv/vm-layout.rst). + +Define the DIRECT_MAP_PHYSMEM_END macro based on the existing virtual +address space layout macros to expose this information to +get_free_mem_region(). Otherwise, it returns a region that couldn't be +mapped, which breaks ZONE_DEVICE. + +Cc: stable@vger.kernel.org # v6.13+ +Tested-by: Han Gao # SG2044 +Signed-off-by: Vivian Wang +Link: https://patch.msgid.link/20260309-riscv-sparsemem-vmemmap-limits-v1-2-f40efe18e3cd@iscas.ac.cn +Signed-off-by: Paul Walmsley +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/include/asm/pgtable.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -86,6 +86,16 @@ + */ + #define vmemmap ((struct page *)VMEMMAP_START - vmemmap_start_pfn) + ++/* Needed to limit get_free_mem_region() */ ++#if defined(CONFIG_FLATMEM) ++#define DIRECT_MAP_PHYSMEM_END (phys_ram_base + KERN_VIRT_SIZE - 1) ++#elif defined(CONFIG_SPARSEMEM_VMEMMAP) ++#define DIRECT_MAP_PHYSMEM_END \ ++ ((vmemmap_start_pfn + VMEMMAP_SIZE / sizeof(struct page)) * PAGE_SIZE - 1) ++#elif defined(CONFIG_SPARSEMEM) ++/* DIRECT_MAP_PHYSMEM_END is not limited by VA space assignment in this case */ ++#endif ++ + #define PCI_IO_SIZE SZ_16M + #define PCI_IO_END VMEMMAP_START + #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) diff --git a/queue-6.6/series b/queue-6.6/series index 2211c0ef48..e4e4f2560f 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -293,3 +293,9 @@ spi-fsl-lpspi-replace-dmaengine_terminate_all-with-dmaengine_terminate_sync.patc spi-fsl-lpspi-terminate-the-rx-channel-on-tx-prepare-failure-path.patch edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch watchdog-apple-add-apple-t8103-wdt-compatible.patch +tracing-prevent-out-of-bounds-read-in-glob-matching.patch +nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch +riscv-mm-define-direct_map_physmem_end.patch +module-decompress-check-return-value-of-module_extend_max_pages.patch +exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch +ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch diff --git a/queue-6.6/tracing-prevent-out-of-bounds-read-in-glob-matching.patch b/queue-6.6/tracing-prevent-out-of-bounds-read-in-glob-matching.patch new file mode 100644 index 0000000000..8bac17da37 --- /dev/null +++ b/queue-6.6/tracing-prevent-out-of-bounds-read-in-glob-matching.patch @@ -0,0 +1,132 @@ +From 0a6070839b1ef276d5b05bedfb787743e140fb17 Mon Sep 17 00:00:00 2001 +From: Huihui Huang +Date: Wed, 1 Jul 2026 18:28:46 +0800 +Subject: tracing: Prevent out-of-bounds read in glob matching + +From: Huihui Huang + +commit 0a6070839b1ef276d5b05bedfb787743e140fb17 upstream. + +String event fields are not necessarily NUL-terminated, so the filter +predicate functions (filter_pred_string(), filter_pred_strloc() and +filter_pred_strrelloc()) pass the field length to the regex match +callbacks, and the length-aware matchers honour it. + +regex_match_glob() was the exception: it ignored the length and called +glob_match(), which scans the string until it hits a NUL byte. Some +string fields are not NUL-terminated. One example is the dynamic char +array of the xfs_* namespace tracepoints, which is copied without a +trailing NUL. For such a field, glob matching reads past the end of +the event field, causing a KASAN slab-out-of-bounds read in +glob_match(), reached via regex_match_glob() and filter_match_preds() +from the xfs_lookup tracepoint. + +Add a length-bounded glob_match_len() and use it from regex_match_glob() +so glob matching always stops at the field boundary. The matching loop +is factored into a shared helper so glob_match() keeps its behaviour. + +Fixes: 60f1d5e3bac4 ("ftrace: Support full glob matching") +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/da1aaf125fc3b63320b0c540fd6afa7c3d5b4f1a.1782836943.git.hhhuang@smu.edu.sg +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Zhengchuan Liang +Reported-by: Xin Liu +Assisted-by: Codex:GPT-5.4 +Signed-off-by: Huihui Huang +Signed-off-by: Ren Wei +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/glob.h | 1 + + kernel/trace/trace_events_filter.c | 6 ++---- + lib/glob.c | 31 +++++++++++++++++++++++++++++-- + 3 files changed, 32 insertions(+), 6 deletions(-) + +--- a/include/linux/glob.h ++++ b/include/linux/glob.h +@@ -6,5 +6,6 @@ + #include /* For __pure */ + + bool __pure glob_match(char const *pat, char const *str); ++bool __pure glob_match_len(char const *pat, char const *str, size_t len); + + #endif /* _LINUX_GLOB_H */ +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -1056,11 +1056,9 @@ static int regex_match_end(char *str, st + return 0; + } + +-static int regex_match_glob(char *str, struct regex *r, int len __maybe_unused) ++static int regex_match_glob(char *str, struct regex *r, int len) + { +- if (glob_match(r->pattern, str)) +- return 1; +- return 0; ++ return glob_match_len(r->pattern, str, len) ? 1 : 0; + } + + /** +--- a/lib/glob.c ++++ b/lib/glob.c +@@ -9,6 +9,9 @@ + MODULE_DESCRIPTION("glob(7) matching"); + MODULE_LICENSE("Dual MIT/GPL"); + ++static bool __pure glob_match_str(char const *pat, char const *str, ++ char const *str_end); ++ + /** + * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) + * @pat: Shell-style pattern to match, e.g. "*.[ch]". +@@ -39,6 +42,29 @@ MODULE_LICENSE("Dual MIT/GPL"); + */ + bool __pure glob_match(char const *pat, char const *str) + { ++ return glob_match_str(pat, str, NULL); ++} ++EXPORT_SYMBOL(glob_match); ++ ++/** ++ * glob_match_len - glob match against a length-bounded string ++ * @pat: Shell-style pattern to match. ++ * @str: String to match. Need not be NUL-terminated. ++ * @len: Number of bytes of @str that may be read. ++ * ++ * Like glob_match(), but @str is only read up to @len bytes, so it can be ++ * used on buffers that are not NUL-terminated (e.g. trace event fields). ++ * A NUL byte within @len still terminates the string. ++ */ ++bool __pure glob_match_len(char const *pat, char const *str, size_t len) ++{ ++ return glob_match_str(pat, str, str + len); ++} ++EXPORT_SYMBOL(glob_match_len); ++ ++static bool __pure glob_match_str(char const *pat, char const *str, ++ char const *str_end) ++{ + /* + * Backtrack to previous * on mismatch and retry starting one + * character later in the string. Because * matches all characters +@@ -53,9 +79,11 @@ bool __pure glob_match(char const *pat, + * on mismatch, or true after matching the trailing nul bytes. + */ + for (;;) { +- unsigned char c = *str++; ++ unsigned char c = (str_end && str >= str_end) ? '\0' : *str; + unsigned char d = *pat++; + ++ str++; ++ + switch (d) { + case '?': /* Wildcard: anything but nul */ + if (c == '\0') +@@ -120,4 +148,3 @@ backtrack: + } + } + } +-EXPORT_SYMBOL(glob_match);