From: Greg Kroah-Hartman Date: Wed, 15 Jul 2026 15:18:22 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffe6a2b4155cda55ce1296e624f0b4478027ffa3;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.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 perf-aux-fix-page-uaf-in-map_range.patch riscv-mm-define-direct_map_physmem_end.patch riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.patch selftests-mm-fix-and-speedup-droppable-test.patch selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch tracing-prevent-out-of-bounds-read-in-glob-matching.patch --- diff --git a/queue-6.18/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch b/queue-6.18/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch new file mode 100644 index 0000000000..71efcddbd5 --- /dev/null +++ b/queue-6.18/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch @@ -0,0 +1,62 @@ +From 65dfde57d1e29ce2b76fc23dd565eccd5c0bc0f0 Mon Sep 17 00:00:00 2001 +From: Ricardo Robaina +Date: Thu, 2 Jul 2026 11:04:11 -0300 +Subject: audit: fix potential integer overflow in audit_log_n_hex() + +From: Ricardo Robaina + +commit 65dfde57d1e29ce2b76fc23dd565eccd5c0bc0f0 upstream. + +The function calculates new_len as len << 1 for hex encoding. This +has two overflow risks: the shift itself can overflow when len is +large, and the result can be truncated when assigned to new_len +(declared as int) from the size_t calculation. + +Fix by using check_shl_overflow() to catch shift overflow and +changing new_len and loop counter i to size_t to prevent truncation. + +Cc: stable@vger.kernel.org +Fixes: 168b7173959f ("AUDIT: Clean up logging of untrusted strings") +Reviewed-by: Richard Guy Briggs +Signed-off-by: Ricardo Robaina +[PM: remove vertical whitspace noise] +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + kernel/audit.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + + #include + +@@ -2075,7 +2076,8 @@ void audit_log_format(struct audit_buffe + void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, + size_t len) + { +- int i, avail, new_len; ++ int avail; ++ size_t i, new_len; + unsigned char *ptr; + struct sk_buff *skb; + +@@ -2085,7 +2087,12 @@ void audit_log_n_hex(struct audit_buffer + BUG_ON(!ab->skb); + skb = ab->skb; + avail = skb_tailroom(skb); +- new_len = len<<1; ++ ++ if (check_shl_overflow(len, 1, &new_len)) { ++ audit_log_format(ab, "?"); ++ return; ++ } ++ + if (new_len >= avail) { + /* Round the buffer request up to the next multiple */ + new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); diff --git a/queue-6.18/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch b/queue-6.18/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch new file mode 100644 index 0000000000..ec05e10dce --- /dev/null +++ b/queue-6.18/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 +@@ -1083,6 +1083,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) { +@@ -1091,13 +1092,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.18/mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch b/queue-6.18/mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch new file mode 100644 index 0000000000..59efd24695 --- /dev/null +++ b/queue-6.18/mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch @@ -0,0 +1,102 @@ +From e187bc02f8fa4226d62814592cf064ee4557c470 Mon Sep 17 00:00:00 2001 +From: Pedro Falcato +Date: Thu, 25 Jun 2026 16:38:53 +0100 +Subject: mm: do file ownership checks with the proper mount idmap + +From: Pedro Falcato + +commit e187bc02f8fa4226d62814592cf064ee4557c470 upstream. + +Ever since idmapped mounts were introduced, inode ownership checks (for +side-channel protection) in mincore() and madvise(MADV_PAGEOUT) were done +against the nop_mnt_idmap, which completely ignores the file's mount's +idmap. This results in odd edgecases like: + +1) mount/bind-mount with an idmap userA:userB:1 +2) userB runs an owner_or_capable() check on file that is owned by userA +on-disk/in-memory, but owned by userB after idmap translation +3) owner_or_capable() mysteriously fails as the correct idmap wasn't supplied + +In the case of mincore/madvise MADV_PAGEOUT, this is usually benign, +because file_permission(file, MAY_WRITE) will probably succeed, as it uses +the proper idmap internally, but it does not need to be the case on e.g a +0444 file where even the owner itself doesn't have permissions to write to +it. + +Since this is clearly not trivial to get right, introduce a +file_owner_or_capable() that can carry the correct semantics, and switch +the various users in mm to it. + +The issue was found by manual code inspection & an off-list discussion +with Jan Kara. + +Link: https://lore.kernel.org/20260625153853.913949-1-pfalcato@suse.de +Fixes: 9caccd41541a ("fs: introduce MOUNT_ATTR_IDMAP") +Signed-off-by: Pedro Falcato +Reviewed-by: Jan Kara +Reviewed-by: Christian Brauner (Amutable) +Acked-by: David Hildenbrand (Arm) +Cc: Al Viro +Cc: Jann Horn +Cc: Liam R. Howlett +Cc: Matthew Wilcox (Oracle) +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/fs.h | 5 +++++ + mm/filemap.c | 2 +- + mm/madvise.c | 3 +-- + mm/mincore.c | 3 +-- + 4 files changed, 8 insertions(+), 5 deletions(-) + +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2852,6 +2852,11 @@ static inline struct mnt_idmap *file_mnt + return mnt_idmap(file->f_path.mnt); + } + ++static inline bool file_owner_or_capable(const struct file *file) ++{ ++ return inode_owner_or_capable(file_mnt_idmap(file), file_inode(file)); ++} ++ + /** + * is_idmapped_mnt - check whether a mount is mapped + * @mnt: the mount to check +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -4620,7 +4620,7 @@ static inline bool can_do_cachestat(stru + { + if (f->f_mode & FMODE_WRITE) + return true; +- if (inode_owner_or_capable(file_mnt_idmap(f), file_inode(f))) ++ if (file_owner_or_capable(f)) + return true; + return file_permission(f, MAY_WRITE) == 0; + } +--- a/mm/madvise.c ++++ b/mm/madvise.c +@@ -338,8 +338,7 @@ static inline bool can_do_file_pageout(s + * otherwise we'd be including shared non-exclusive mappings, which + * opens a side channel. + */ +- return inode_owner_or_capable(&nop_mnt_idmap, +- file_inode(vma->vm_file)) || ++ return file_owner_or_capable(vma->vm_file) || + file_permission(vma->vm_file, MAY_WRITE) == 0; + } + +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -214,8 +214,7 @@ static inline bool can_do_mincore(struct + * for writing; otherwise we'd be including shared non-exclusive + * mappings, which opens a side channel. + */ +- return inode_owner_or_capable(&nop_mnt_idmap, +- file_inode(vma->vm_file)) || ++ return file_owner_or_capable(vma->vm_file) || + file_permission(vma->vm_file, MAY_WRITE) == 0; + } + diff --git a/queue-6.18/mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch b/queue-6.18/mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch new file mode 100644 index 0000000000..cfe58888a2 --- /dev/null +++ b/queue-6.18/mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch @@ -0,0 +1,72 @@ +From d86c9e971af2315119a78c564a802fafcebf1b6b Mon Sep 17 00:00:00 2001 +From: Anthony Yznaga +Date: Wed, 15 Apr 2026 20:39:37 -0700 +Subject: mm: fix mmap errno value when MAP_DROPPABLE is not supported + +From: Anthony Yznaga + +commit d86c9e971af2315119a78c564a802fafcebf1b6b upstream. + +Patch series "fix MAP_DROPPABLE not supported errno", v4. + +Mark Brown reported seeing a regression in -next on 32 bit arm with the +mlock selftests. Before exiting and marking the tests failed, the +following message was logged after an attempt to create a MAP_DROPPABLE +mapping: + +Bail out! mmap error: Unknown error 524 + +It turns out error 524 is ENOTSUPP which is an error that userspace is not +supposed to see, but it indicates in this instance that MAP_DROPPABLE is +not supported. + +The first patch changes the errno returned to EOPNOTSUPP. The second +patch is a second version of a prior patch to introduce selftests to +verify locking behavior with droppable mappings with the additional change +to skip the tests when MAP_DROPPABLE is not supported. The third patch +fixes the MAP_DROPPABLE selftest so that it is run by the framework and +skips if MAP_DROPPABLE is not supported. + + +This patch (of 3): + +On configs where MAP_DROPPABLE is not supported (currently any 32-bit +config except for PPC32), mmap fails with errno set to ENOTSUPP. However, +ENOTSUPP is not a standard error value that userspace knows about. The +acceptable userspace-visible errno to use is EOPNOTSUPP. checkpatch.pl +has a warning to this effect. + +Link: https://lore.kernel.org/20260416033939.49981-1-anthony.yznaga@oracle.com +Link: https://lore.kernel.org/20260416033939.49981-2-anthony.yznaga@oracle.com +Fixes: 9651fcedf7b9 ("mm: add MAP_DROPPABLE for designating always lazily freeable mappings") +Signed-off-by: Anthony Yznaga +Acked-by: David Hildenbrand (Arm) +Acked-by: Vlastimil Babka (SUSE) +Reported-by: Mark Brown +Reviewed-by: Pedro Falcato +Reviewed-by: Lorenzo Stoakes (Oracle) +Cc: Jann Horn +Cc: Jason A. Donenfeld +Cc: Liam Howlett +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/mmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -502,7 +502,7 @@ unsigned long do_mmap(struct file *file, + break; + case MAP_DROPPABLE: + if (VM_DROPPABLE == VM_NONE) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + /* + * A locked or stack area makes no sense to be droppable. + * diff --git a/queue-6.18/mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch b/queue-6.18/mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch new file mode 100644 index 0000000000..d8718cd9e2 --- /dev/null +++ b/queue-6.18/mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch @@ -0,0 +1,125 @@ +From ffd017237cfe99e6e5602ab14179b0e6878a0840 Mon Sep 17 00:00:00 2001 +From: Ketan +Date: Tue, 23 Jun 2026 02:48:04 +0530 +Subject: mm: page_ext: add count limit to page_ext_iter_next to prevent invalid PFN access + +From: Ketan + +commit ffd017237cfe99e6e5602ab14179b0e6878a0840 upstream. + +The page_ext iteration API does not validate if the PFN still belongs to a +valid section while advancing the iterator. When dynamically adding +memory in the hotplug path, it can lead to a NULL pointer dereference +during page_ext_lookup at the boundary of the last valid section when +iterator count equals __pgcount. + +The for_each_page_ext() macro calls page_ext_iter_next() as its loop +increment. for_each_page_ext() does a "__page_ext = +page_ext_iter_next(&__iter)" at the end. This causes page_ext_iter_next() +to increment iter->index past __pgcount and call page_ext_lookup(start_pfn ++ __pgcount). During memory hotplug (online), the PFN at start_pfn + +__pgcount may belong to a section that has not yet been initialized, +causing page_ext_lookup() to trigger a NULL pointer dereference. + +[ 14.555124][ T846] Call trace: +[ 14.555125][ T846] lookup_page_ext+0x6c/0x108 (P) +[ 14.555127][ T846] page_ext_lookup+0x30/0x3c +[ 14.555129][ T846] __reset_page_owner+0x11c/0x260 +[ 14.571201][ T846] __free_pages_ok+0x5e8/0x8e0 +[ 14.571204][ T846] __free_pages_core+0x78/0xf0 +[ 14.571206][ T846] generic_online_page+0x14/0x24 +[ 14.597782][ T846] online_pages+0x178/0x30c +[ 14.597784][ T846] memory_block_change_state+0x284/0x32c +[ 14.597787][ T846] memory_subsys_online+0x4c/0x64 +[ 14.597789][ T846] device_online+0x88/0xb0 +[ 14.597791][ T846] online_memory_block+0x30/0x40 +[ 14.597793][ T846] walk_memory_blocks+0xac/0xe8 +[ 14.597794][ T846] add_memory_resource+0x280/0x298 +[ 14.656161][ T846] add_memory+0x60/0x98 + +Move the iteration boundary enforcement inside the iterator functions, so +callers cannot inadvertently access beyond the requested range. + +Link: https://lore.kernel.org/20260623-page_ext-v3-1-a89799a5367c@oss.qualcomm.com +Fixes: 9039b9096ea2 ("mm: page_ext: add an iteration API for page extensions") +Signed-off-by: Ketan Kishore +Suggested-by: David Hildenbrand +Suggested-by: Matthew Wilcox +Acked-by: Zi Yan +Acked-by: David Hildenbrand (Arm) +Cc: Brendan Jackman +Cc: Johannes Weiner +Cc: Liam R. Howlett +Cc: Lorenzo Stoakes +Cc: Luiz Capitulino +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/page_ext.h | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/include/linux/page_ext.h ++++ b/include/linux/page_ext.h +@@ -119,14 +119,18 @@ struct page_ext_iter { + * page_ext_iter_begin() - Prepare for iterating through page extensions. + * @iter: page extension iterator. + * @pfn: PFN of the page we're interested in. ++ * @count: maximum number of page extensions to return. + * + * Must be called with RCU read lock taken. + * + * Return: NULL if no page_ext exists for this page. + */ + static inline struct page_ext *page_ext_iter_begin(struct page_ext_iter *iter, +- unsigned long pfn) ++ unsigned long pfn, unsigned long count) + { ++ if (!count) ++ return NULL; ++ + iter->index = 0; + iter->start_pfn = pfn; + iter->page_ext = page_ext_lookup(pfn); +@@ -137,19 +141,22 @@ static inline struct page_ext *page_ext_ + /** + * page_ext_iter_next() - Get next page extension + * @iter: page extension iterator. ++ * @count: maximum number of page extensions to return. + * + * Must be called with RCU read lock taken. + * + * Return: NULL if no next page_ext exists. + */ +-static inline struct page_ext *page_ext_iter_next(struct page_ext_iter *iter) ++static inline struct page_ext *page_ext_iter_next(struct page_ext_iter *iter, ++ unsigned long count) + { + unsigned long pfn; + + if (WARN_ON_ONCE(!iter->page_ext)) + return NULL; + +- iter->index++; ++ if (++iter->index >= count) ++ return NULL; + pfn = iter->start_pfn + iter->index; + + if (page_ext_iter_next_fast_possible(pfn)) +@@ -182,9 +189,9 @@ static inline struct page_ext *page_ext_ + * IMPORTANT: must be called with RCU read lock taken. + */ + #define for_each_page_ext(__page, __pgcount, __page_ext, __iter) \ +- for (__page_ext = page_ext_iter_begin(&__iter, page_to_pfn(__page));\ +- __page_ext && __iter.index < __pgcount; \ +- __page_ext = page_ext_iter_next(&__iter)) ++ for (__page_ext = page_ext_iter_begin(&__iter, page_to_pfn(__page), __pgcount); \ ++ __page_ext; \ ++ __page_ext = page_ext_iter_next(&__iter, __pgcount)) + + #else /* !CONFIG_PAGE_EXTENSION */ + struct page_ext; diff --git a/queue-6.18/module-decompress-check-return-value-of-module_extend_max_pages.patch b/queue-6.18/module-decompress-check-return-value-of-module_extend_max_pages.patch new file mode 100644 index 0000000000..f2856619cb --- /dev/null +++ b/queue-6.18/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.18/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch b/queue-6.18/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch new file mode 100644 index 0000000000..b61935d465 --- /dev/null +++ b/queue-6.18/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 +@@ -3302,6 +3302,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.18/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch b/queue-6.18/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch new file mode 100644 index 0000000000..20fcae4c5d --- /dev/null +++ b/queue-6.18/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.18/perf-aux-fix-page-uaf-in-map_range.patch b/queue-6.18/perf-aux-fix-page-uaf-in-map_range.patch new file mode 100644 index 0000000000..5d44799127 --- /dev/null +++ b/queue-6.18/perf-aux-fix-page-uaf-in-map_range.patch @@ -0,0 +1,57 @@ +From 5948aaf64f81f217a25dcc2bf6c0779bca19566c Mon Sep 17 00:00:00 2001 +From: Lee Jia Jie +Date: Thu, 9 Jul 2026 21:56:19 +0800 +Subject: perf/aux: Fix page UAF in map_range() + +From: Lee Jia Jie + +commit 5948aaf64f81f217a25dcc2bf6c0779bca19566c upstream. + +map_range() reads rb->aux_pages[], rb->aux_nr_pages and rb->aux_pgoff via +perf_mmap_to_page() while holding only event->mmap_mutex. Those fields are +serialized by rb->aux_mutex, and mmap_mutex is per event. + +Thus, two events sharing one rb via PERF_EVENT_IOC_SET_OUTPUT can race +rb_alloc_aux() with map_range(), leading to a page-UAF scenario as follows: + + CPU 0 CPU 1 + ===== ===== + rb_alloc_aux() map_range() + [1]: allocate rb->aux_pages[0] + [2]: rb->aux_nr_pages++ + [3]: perf_mmap_to_page() + returns rb->aux_pages[0] + [4]: map it as VM_PFNMAP + [5]: rb->aux_pgoff = 1 + + munmap the page + [6]: free rb->aux_pages[0] + +Pages mapped as VM_PFNMAP have no refcount protection, so CPU 1 holds a +mapping to a freed physical frame. + +Fix this by taking rb->aux_mutex across the page walk in map_range(). + +Fixes: b709eb872e19 ("perf: map pages in advance") +Signed-off-by: Lee Jia Jie +Signed-off-by: Ingo Molnar +Cc: stable@vger.kernel.org +Cc: Peter Zijlstra +Cc: Arnaldo Carvalho de Melo +Cc: Namhyung Kim +Signed-off-by: Greg Kroah-Hartman +--- + kernel/events/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6879,6 +6879,8 @@ static int map_range(struct perf_buffer + int err = 0; + unsigned long pagenum; + ++ guard(mutex)(&rb->aux_mutex); ++ + /* + * We map this as a VM_PFNMAP VMA. + * diff --git a/queue-6.18/riscv-mm-define-direct_map_physmem_end.patch b/queue-6.18/riscv-mm-define-direct_map_physmem_end.patch new file mode 100644 index 0000000000..43d200051a --- /dev/null +++ b/queue-6.18/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 +@@ -93,6 +93,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.18/riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch b/queue-6.18/riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch new file mode 100644 index 0000000000..54fa25ee1c --- /dev/null +++ b/queue-6.18/riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch @@ -0,0 +1,43 @@ +From 1b2c6b56a9fa0dcbef461039937de22b1cbecc7d Mon Sep 17 00:00:00 2001 +From: Vivian Wang +Date: Tue, 3 Mar 2026 13:29:49 +0800 +Subject: riscv: mm: Unconditionally sfence.vma for spurious fault + +From: Vivian Wang + +commit 1b2c6b56a9fa0dcbef461039937de22b1cbecc7d upstream. + +Svvptc does not guarantee that it's safe to just return here. Since we +have already cleared our bit, if, theoretically, the bounded timeframe +for the accessed page to become valid still hasn't happened after sret, +we could fault again and actually crash. + +Hopefully, these spurious faults should be rare enough that this is an +acceptable slowdown. + +Cc: stable@vger.kernel.org +Fixes: 503638e0babf ("riscv: Stop emitting preventive sfence.vma for new vmalloc mappings") +Signed-off-by: Vivian Wang +Link: https://patch.msgid.link/20260303-handle-kfence-protect-spurious-fault-v2-5-f80d8354d79d@iscas.ac.cn +Signed-off-by: Paul Walmsley +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/kernel/entry.S | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -75,8 +75,11 @@ + /* Atomically reset the current cpu bit in new_vmalloc */ + amoxor.d a0, a1, (a0) + +- /* Only emit a sfence.vma if the uarch caches invalid entries */ +- ALTERNATIVE("sfence.vma", "nop", 0, RISCV_ISA_EXT_SVVPTC, 1) ++ /* ++ * A sfence.vma is required here. Even if we had Svvptc, there's no ++ * guarantee that after returning we wouldn't just fault again. ++ */ ++ sfence.vma + + REG_L a0, TASK_TI_A0(tp) + REG_L a1, TASK_TI_A1(tp) diff --git a/queue-6.18/rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.patch b/queue-6.18/rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.patch new file mode 100644 index 0000000000..316bd515cf --- /dev/null +++ b/queue-6.18/rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.patch @@ -0,0 +1,60 @@ +From b48bd16eb9fc57a463a337ca148516cdf3212d61 Mon Sep 17 00:00:00 2001 +From: Gabriele Monaco +Date: Wed, 10 Jun 2026 11:04:29 +0200 +Subject: rqspinlock: Fix order in raw_res_spin_(un)lock_irq to allow schedule + +From: Gabriele Monaco + +commit b48bd16eb9fc57a463a337ca148516cdf3212d61 upstream. + +raw_res_spin_unlock_irqrestore() calls raw_res_spin_unlock() and then +restores interrupts, this means preemption is enabled when interrupts +are still disabled (as part of raw_res_spin_unlock()) so this cannot +trigger an actual preemption. +This is inconsistent with other spinlock implementations +(raw_spin_unlock_irqrestore() and bpf_res_spin_unlock_irqrestore() +itself). + +Adjust the macro to ensure interrupts are enabled before enabling +preemption, allowing to schedule at that point. Make the same +modification in the error path of raw_res_spin_lock_irqsave(). + +Fixes: 101acd2e78b1 ("rqspinlock: Add macros for rqspinlock usage") +Cc: stable@vger.kernel.org +Acked-by: Arnd Bergmann # asm-generic +Acked-by: Waiman Long +Acked-by: Kumar Kartikeya Dwivedi +Signed-off-by: Gabriele Monaco +Link: https://lore.kernel.org/r/20260610090431.32427-1-gmonaco@redhat.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + include/asm-generic/rqspinlock.h | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/include/asm-generic/rqspinlock.h ++++ b/include/asm-generic/rqspinlock.h +@@ -243,12 +243,20 @@ static __always_inline void res_spin_unl + ({ \ + int __ret; \ + local_irq_save(flags); \ +- __ret = raw_res_spin_lock(lock); \ +- if (__ret) \ ++ preempt_disable(); \ ++ __ret = res_spin_lock(lock); \ ++ if (__ret) { \ + local_irq_restore(flags); \ ++ preempt_enable(); \ ++ } \ + __ret; \ + }) + +-#define raw_res_spin_unlock_irqrestore(lock, flags) ({ raw_res_spin_unlock(lock); local_irq_restore(flags); }) ++#define raw_res_spin_unlock_irqrestore(lock, flags) \ ++ ({ \ ++ res_spin_unlock(lock); \ ++ local_irq_restore(flags); \ ++ preempt_enable(); \ ++ }) + + #endif /* __ASM_GENERIC_RQSPINLOCK_H */ diff --git a/queue-6.18/selftests-mm-fix-and-speedup-droppable-test.patch b/queue-6.18/selftests-mm-fix-and-speedup-droppable-test.patch new file mode 100644 index 0000000000..451ae62eee --- /dev/null +++ b/queue-6.18/selftests-mm-fix-and-speedup-droppable-test.patch @@ -0,0 +1,126 @@ +From cc13a7a618fe8354f16d74c06aaf9565a68e9ebd Mon Sep 17 00:00:00 2001 +From: "David Hildenbrand (Arm)" +Date: Thu, 11 Jun 2026 12:01:55 +0200 +Subject: selftests: mm: fix and speedup "droppable" test + +From: David Hildenbrand (Arm) + +commit cc13a7a618fe8354f16d74c06aaf9565a68e9ebd upstream. + +The droppable test currently relies on creating memory pressure in a child +process to trigger dropping the droppable pages. + +That not only takes a long time on some machines (allocating and filling +all that memory), on large machines this will not work as we hardcode the +area size to 134217728 bytes. + +... further, we rely on timeouts to detect that memory was not dropped, +which is really suboptimal. + +Instead, let's just use MADV_PAGEOUT on a 2 MiB region. MADV_PAGEOUT +works with droppable memory even without swap. + +There is the low chance of MADV_PAGEOUT failing to drop a page because of +speculative references. We'll wait 1s and retry 10 times to rule that +unlikely case out as best as we can. + +On a machine without swap: + + $ ./droppable + TAP version 13 + 1..1 + ok 1 madvise(MADV_PAGEOUT) behavior + # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 + +Link: https://lore.kernel.org/20260611-droppable_test-v1-1-b6a73d99f658@kernel.org +Fixes: 9651fcedf7b9 ("mm: add MAP_DROPPABLE for designating always lazily freeable mappings") +Signed-off-by: David Hildenbrand (Arm) +Reported-by: Aishwarya TCV +Tested-by: Sarthak Sharma +Tested-by: Lance Yang +Reviewed-by: Dev Jain +Reviewed-by: SeongJae Park +Tested-by: Lorenzo Stoakes +Reviewed-by: Lorenzo Stoakes +Reviewed-by: Jason A. Donenfeld +Cc: Anthony Yznaga +Cc: Liam R. Howlett +Cc: Mark Brown +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/mm/droppable.c | 46 ++++++++++++++++++--------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +--- a/tools/testing/selftests/mm/droppable.c ++++ b/tools/testing/selftests/mm/droppable.c +@@ -17,10 +17,10 @@ + + int main(int argc, char *argv[]) + { +- size_t alloc_size = 134217728; +- size_t page_size = getpagesize(); ++ const size_t alloc_size = 2 * 1024 * 1024; ++ int retry_count = 10; ++ bool dropped; + void *alloc; +- pid_t child; + + ksft_print_header(); + ksft_set_plan(1); +@@ -28,26 +28,32 @@ int main(int argc, char *argv[]) + alloc = mmap(0, alloc_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0); + assert(alloc != MAP_FAILED); + memset(alloc, 'A', alloc_size); +- for (size_t i = 0; i < alloc_size; i += page_size) +- assert(*(uint8_t *)(alloc + i)); + +- child = fork(); +- assert(child >= 0); +- if (!child) { +- for (;;) +- *(char *)malloc(page_size) = 'B'; +- } +- +- for (bool done = false; !done;) { +- for (size_t i = 0; i < alloc_size; i += page_size) { +- if (!*(uint8_t *)(alloc + i)) { +- done = true; +- break; ++ while (retry_count--) { ++ if (madvise(alloc, alloc_size, MADV_PAGEOUT)) { ++ if (errno == EINVAL) { ++ ksft_test_result_skip("madvise(MADV_PAGEOUT) not supported\n"); ++ exit(KSFT_SKIP); + } ++ ksft_test_result_fail("madvise(MADV_PAGEOUT) error: %s\n", strerror(errno)); ++ exit(KSFT_FAIL); + } ++ ++ dropped = memchr(alloc, 'A', alloc_size) == NULL; ++ ++ /* ++ * Speculative reference can temporarily prevent some ++ * pages from getting dropped. So sleep and retry. ++ * ++ * If a page is not droppable for 10s, something ++ * is seriously messed up and we want to fail. ++ */ ++ if (dropped) ++ break; ++ sleep(1); + } +- kill(child, SIGTERM); + +- ksft_test_result_pass("MAP_DROPPABLE: PASS\n"); +- exit(KSFT_PASS); ++ ksft_test_result(dropped, "madvise(MADV_PAGEOUT) behavior\n"); ++ ++ ksft_finished(); + } diff --git a/queue-6.18/selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch b/queue-6.18/selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch new file mode 100644 index 0000000000..453c140edf --- /dev/null +++ b/queue-6.18/selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch @@ -0,0 +1,88 @@ +From dccf636bf1e68c3fda92f0c9e1018ab7e0ac8b2c Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Sun, 28 Jun 2026 18:11:18 +0800 +Subject: selftests/mm: pagemap_ioctl: use the correct page size for transact_test() + +From: Zenghui Yu + +commit dccf636bf1e68c3fda92f0c9e1018ab7e0ac8b2c upstream. + +There are several places in transact_test() where we use the hardcoded +0x1000 (4k) as page size, which is not always correct for architectures +supporting multiple page sizes. + +Switch to use the correct page size. Otherwise ./ksft_pagemap.sh on a +16k-page-size arm64 box fails with + + $ ./ksft_pagemap.sh + [...] + # ok 96 mprotect_tests Both pages written after remap and mprotect + # ok 97 mprotect_tests Clear and make the pages written + # Bail out! ioctl failed + # # Planned tests != run tests (117 != 97) + # # Totals: pass:97 fail:0 xfail:0 xpass:0 skip:0 error:0 + # [FAIL] + not ok 1 pagemap_ioctl # exit=1 + # SUMMARY: PASS=0 SKIP=0 FAIL=1 + 1..1 + +Link: https://lore.kernel.org/20260628101118.35861-1-zenghui.yu@linux.dev +Fixes: 46fd75d4a3c9 ("selftests: mm: add pagemap ioctl tests") +Signed-off-by: Zenghui Yu +Cc: Muhammad Usama Anjum +Cc: David Hildenbrand +Cc: Liam R. Howlett +Cc: Lorenzo Stoakes +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: Zenghui Yu +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/mm/pagemap_ioctl.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/tools/testing/selftests/mm/pagemap_ioctl.c ++++ b/tools/testing/selftests/mm/pagemap_ioctl.c +@@ -1367,7 +1367,7 @@ void *thread_proc(void *mem) + ksft_exit_fail_msg("pthread_barrier_wait\n"); + + for (i = 0; i < access_per_thread; ++i) +- __atomic_add_fetch(m + i * (0x1000 / sizeof(*m)), 1, __ATOMIC_SEQ_CST); ++ __atomic_add_fetch(m + i * (page_size / sizeof(*m)), 1, __ATOMIC_SEQ_CST); + + ret = pthread_barrier_wait(&end_barrier); + if (ret && ret != PTHREAD_BARRIER_SERIAL_THREAD) +@@ -1402,15 +1402,15 @@ static void transact_test(int page_size) + if (pthread_barrier_init(&end_barrier, NULL, nthreads + 1)) + ksft_exit_fail_msg("pthread_barrier_init\n"); + +- mem = mmap(NULL, 0x1000 * nthreads * pages_per_thread, PROT_READ | PROT_WRITE, ++ mem = mmap(NULL, page_size * nthreads * pages_per_thread, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (mem == MAP_FAILED) + ksft_exit_fail_msg("Error mmap %s.\n", strerror(errno)); + +- wp_init(mem, 0x1000 * nthreads * pages_per_thread); +- wp_addr_range(mem, 0x1000 * nthreads * pages_per_thread); ++ wp_init(mem, page_size * nthreads * pages_per_thread); ++ wp_addr_range(mem, page_size * nthreads * pages_per_thread); + +- memset(mem, 0, 0x1000 * nthreads * pages_per_thread); ++ memset(mem, 0, page_size * nthreads * pages_per_thread); + + count = get_dirty_pages_reset(mem, nthreads * pages_per_thread, 1, page_size); + ksft_test_result(count > 0, "%s count %u\n", __func__, count); +@@ -1419,7 +1419,7 @@ static void transact_test(int page_size) + + finish = 0; + for (i = 0; i < nthreads; ++i) +- pthread_create(&th, NULL, thread_proc, mem + 0x1000 * i * pages_per_thread); ++ pthread_create(&th, NULL, thread_proc, mem + page_size * i * pages_per_thread); + + extra_pages = 0; + for (i = 0; i < iter_count; ++i) { diff --git a/queue-6.18/series b/queue-6.18/series index da49ef64ea..8a2f6d8db4 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -387,4 +387,19 @@ edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch watchdog-apple-add-apple-t8103-wdt-compatible.patch regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.patch i2c-core-fix-hang-on-adapter-registration-failure.patch +perf-aux-fix-page-uaf-in-map_range.patch +tracing-prevent-out-of-bounds-read-in-glob-matching.patch +audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch +nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch +rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.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 +riscv-mm-define-direct_map_physmem_end.patch +riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch +mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch +selftests-mm-fix-and-speedup-droppable-test.patch +mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch +mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch +selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch crypto-loongson-remove-broken-and-unused-loongson-rng.patch diff --git a/queue-6.18/tracing-prevent-out-of-bounds-read-in-glob-matching.patch b/queue-6.18/tracing-prevent-out-of-bounds-read-in-glob-matching.patch new file mode 100644 index 0000000000..62e2d1d752 --- /dev/null +++ b/queue-6.18/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') +@@ -122,4 +150,3 @@ backtrack: + } + } + } +-EXPORT_SYMBOL(glob_match);