From: Greg Kroah-Hartman Date: Wed, 15 Jul 2026 15:06:32 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b70edf870a0c03305cae2a36ba06de063cda935b;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-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 exfat-preserve-benign-secondary-entries-during-rename-and-move.patch lib-test_hmm-use-kvfree-to-free-kvcalloc-allocations.patch liveupdate-reject-liveupdate_ioctl_create_session-with-invalid-name-length.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 nouveau-vmm-fix-another-spt-lpt-race.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-liveupdate-add-test-cases-for-liveupdate_ioctl_create_session-calls-with-invalid-length.patch selftests-mm-fix-and-speedup-droppable-test.patch selftests-mm-fix-ksft_process_madv.sh-test-category.patch selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch tracing-prevent-out-of-bounds-read-in-glob-matching.patch vt-fix-spurious-modifier-in-csi-cursor-key-sequences.patch --- diff --git a/queue-7.1/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch b/queue-7.1/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch new file mode 100644 index 0000000000..7e90bbcc8b --- /dev/null +++ b/queue-7.1/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 +@@ -62,6 +62,7 @@ + #include + #include + #include ++#include + + #include "audit.h" + +@@ -2080,7 +2081,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; + +@@ -2090,7 +2092,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-7.1/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch b/queue-7.1/exfat-bound-uniname-advance-in-exfat_find_dir_entry.patch new file mode 100644 index 0000000000..263be1fb35 --- /dev/null +++ b/queue-7.1/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 +@@ -1067,6 +1067,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) { +@@ -1075,13 +1076,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-7.1/exfat-preserve-benign-secondary-entries-during-rename-and-move.patch b/queue-7.1/exfat-preserve-benign-secondary-entries-during-rename-and-move.patch new file mode 100644 index 0000000000..b87f608323 --- /dev/null +++ b/queue-7.1/exfat-preserve-benign-secondary-entries-during-rename-and-move.patch @@ -0,0 +1,338 @@ +From 942296784b2a9439651750c42f540bf2579b330f Mon Sep 17 00:00:00 2001 +From: Rochan Avlur +Date: Thu, 28 May 2026 07:21:37 -0700 +Subject: exfat: preserve benign secondary entries during rename and move + +From: Rochan Avlur + +commit 942296784b2a9439651750c42f540bf2579b330f upstream. + +Commit 8258ef28001a ("exfat: handle unreconized benign secondary +entries") added cluster freeing for benign secondary entries inside +exfat_remove_entries(). However, exfat_remove_entries() is also called +from the rename and move paths (exfat_rename_file and exfat_move_file), +where the old entry set is being relocated rather than deleted. This +causes benign secondary entries such as vendor extension entries to be +silently destroyed on rename or cross-directory move, violating the +exFAT spec requirement (section 8.2) that implementations preserve +unrecognized benign secondary entries. + +Fix this by adding a free_benign parameter to exfat_remove_entries() +so callers can suppress cluster freeing during relocation, and +extending exfat_init_ext_entry() to copy trailing benign secondary +entries from the old entry set into the new one internally. Also +clean up the error paths to delete newly allocated entries on failure. + +Fixes: 8258ef28001a ("exfat: handle unreconized benign secondary entries") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/linux-fsdevel/CAG7tbBV--waov7XVu2FHQEc6paR92dufS=em9DW5Kzsrpu3iQg@mail.gmail.com/ +Signed-off-by: Rochan Avlur +Reviewed-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/dir.c | 50 +++++++++++++++++++++++++---- + fs/exfat/exfat_fs.h | 5 +- + fs/exfat/namei.c | 89 ++++++++++++++++++++++++++++++++++++++++------------ + 3 files changed, 116 insertions(+), 28 deletions(-) + +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -470,32 +470,70 @@ static void exfat_free_benign_secondary_ + exfat_free_cluster(inode, &dir); + } + ++/* ++ * exfat_init_ext_entry - initialize extension entries in a directory entry set ++ * @es: target entry set ++ * @num_entries: number of entries excluding benign secondary entries ++ * @p_uniname: filename to store ++ * @old_es: optional source entry set with benign secondary entries, or NULL ++ * @num_extra: number of benign secondary entries to copy from @old_es ++ * ++ * Set up the file, stream extension, and filename entries in @es, optionally ++ * preserving @num_extra benign secondary entries from @old_es. @es and @old_es ++ * may refer to the same entry set; excess entries are marked as deleted. ++ */ + void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries, +- struct exfat_uni_name *p_uniname) ++ struct exfat_uni_name *p_uniname, ++ struct exfat_entry_set_cache *old_es, int num_extra) + { +- int i; ++ int i, src_start = 0, old_num; + unsigned short *uniname = p_uniname->name; + struct exfat_dentry *ep; + +- es->num_entries = num_entries; ++ if (WARN_ON(num_extra < 0 || (num_extra && (!old_es || ++ old_es->num_entries < ES_IDX_FIRST_FILENAME + num_extra)))) ++ num_extra = 0; ++ ++ /* ++ * Save old entry count and source position before modifying ++ * es->num_entries, since old_es and es may point to the same ++ * entry set. ++ */ ++ old_num = es->num_entries; ++ if (old_es && num_extra > 0) ++ src_start = old_es->num_entries - num_extra; ++ ++ es->num_entries = num_entries + num_extra; + ep = exfat_get_dentry_cached(es, ES_IDX_FILE); +- ep->dentry.file.num_ext = (unsigned char)(num_entries - 1); ++ ep->dentry.file.num_ext = (unsigned char)(num_entries - 1 + num_extra); + + ep = exfat_get_dentry_cached(es, ES_IDX_STREAM); + ep->dentry.stream.name_len = p_uniname->name_len; + ep->dentry.stream.name_hash = cpu_to_le16(p_uniname->name_hash); + ++ if (old_es && num_extra > 0) { ++ for (i = 0; i < num_extra; i++) ++ *exfat_get_dentry_cached(es, num_entries + i) = ++ *exfat_get_dentry_cached(old_es, src_start + i); ++ } ++ + for (i = ES_IDX_FIRST_FILENAME; i < num_entries; i++) { + ep = exfat_get_dentry_cached(es, i); + exfat_init_name_entry(ep, uniname); + uniname += EXFAT_FILE_NAME_LEN; + } + ++ /* Mark excess old entries as deleted (in-place shrink) */ ++ for (i = num_entries + num_extra; i < old_num; i++) { ++ ep = exfat_get_dentry_cached(es, i); ++ exfat_set_entry_type(ep, TYPE_DELETED); ++ } ++ + exfat_update_dir_chksum(es); + } + + void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es, +- int order) ++ int order, bool free_benign) + { + int i; + struct exfat_dentry *ep; +@@ -503,7 +541,7 @@ void exfat_remove_entries(struct inode * + for (i = order; i < es->num_entries; i++) { + ep = exfat_get_dentry_cached(es, i); + +- if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC) ++ if (free_benign && (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC)) + exfat_free_benign_secondary_clusters(inode, ep); + + exfat_set_entry_type(ep, TYPE_DELETED); +--- a/fs/exfat/exfat_fs.h ++++ b/fs/exfat/exfat_fs.h +@@ -524,9 +524,10 @@ void exfat_init_dir_entry(struct exfat_e + unsigned int type, unsigned int start_clu, + unsigned long long size, struct timespec64 *ts); + void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries, +- struct exfat_uni_name *p_uniname); ++ struct exfat_uni_name *p_uniname, ++ struct exfat_entry_set_cache *old_es, int num_extra); + void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es, +- int order); ++ int order, bool free_benign); + void exfat_update_dir_chksum(struct exfat_entry_set_cache *es); + int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); + int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, +--- a/fs/exfat/namei.c ++++ b/fs/exfat/namei.c +@@ -503,7 +503,7 @@ static int exfat_add_entry(struct inode + * the first cluster is not determined yet. (0) + */ + exfat_init_dir_entry(&es, type, start_clu, clu_size, &ts); +- exfat_init_ext_entry(&es, num_entries, &uniname); ++ exfat_init_ext_entry(&es, num_entries, &uniname, NULL, 0); + + ret = exfat_put_dentry_set(&es, IS_DIRSYNC(inode)); + if (ret) +@@ -814,7 +814,7 @@ static int exfat_unlink(struct inode *di + exfat_set_volume_dirty(sb); + + /* update the directory entry */ +- exfat_remove_entries(inode, &es, ES_IDX_FILE); ++ exfat_remove_entries(inode, &es, ES_IDX_FILE, true); + + err = exfat_put_dentry_set(&es, IS_DIRSYNC(inode)); + if (err) +@@ -969,7 +969,7 @@ static int exfat_rmdir(struct inode *dir + + exfat_set_volume_dirty(sb); + +- exfat_remove_entries(inode, &es, ES_IDX_FILE); ++ exfat_remove_entries(inode, &es, ES_IDX_FILE, true); + + err = exfat_put_dentry_set(&es, IS_DIRSYNC(dir)); + if (err) +@@ -996,6 +996,23 @@ unlock: + return err; + } + ++/* ++ * Count benign secondary entries beyond the filename entries. ++ * Returns the count, or -EIO if the entry set is inconsistent. ++ */ ++static int exfat_count_extra_entries(struct exfat_entry_set_cache *es) ++{ ++ struct exfat_dentry *stream; ++ unsigned int name_entries; ++ int extra; ++ ++ stream = exfat_get_dentry_cached(es, ES_IDX_STREAM); ++ name_entries = EXFAT_FILENAME_ENTRY_NUM(stream->dentry.stream.name_len); ++ extra = es->num_entries - (ES_IDX_FIRST_FILENAME + name_entries); ++ ++ return extra >= 0 ? extra : -EIO; ++} ++ + static int exfat_rename_file(struct inode *parent_inode, + struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei) + { +@@ -1004,6 +1021,7 @@ static int exfat_rename_file(struct inod + struct super_block *sb = parent_inode->i_sb; + struct exfat_entry_set_cache old_es, new_es; + int sync = IS_DIRSYNC(parent_inode); ++ unsigned int num_extra_entries, num_total_entries; + + if (unlikely(exfat_forced_shutdown(sb))) + return -EIO; +@@ -1013,19 +1031,23 @@ static int exfat_rename_file(struct inod + return num_new_entries; + + ret = exfat_get_dentry_set_by_ei(&old_es, sb, ei); +- if (ret) { +- ret = -EIO; +- return ret; +- } ++ if (ret) ++ return -EIO; + + epold = exfat_get_dentry_cached(&old_es, ES_IDX_FILE); + +- if (old_es.num_entries < num_new_entries) { ++ ret = exfat_count_extra_entries(&old_es); ++ if (ret < 0) ++ goto put_old_es; ++ num_extra_entries = ret; ++ num_total_entries = num_new_entries + num_extra_entries; ++ ++ if (old_es.num_entries < num_total_entries) { + int newentry; + struct exfat_chain dir; + + newentry = exfat_find_empty_entry(parent_inode, &dir, +- num_new_entries, &new_es); ++ num_total_entries, &new_es); + if (newentry < 0) { + ret = newentry; /* -EIO or -ENOSPC */ + goto put_old_es; +@@ -1042,13 +1064,23 @@ static int exfat_rename_file(struct inod + epnew = exfat_get_dentry_cached(&new_es, ES_IDX_STREAM); + *epnew = *epold; + +- exfat_init_ext_entry(&new_es, num_new_entries, p_uniname); ++ exfat_init_ext_entry(&new_es, num_new_entries, p_uniname, ++ &old_es, num_extra_entries); + + ret = exfat_put_dentry_set(&new_es, sync); +- if (ret) ++ if (ret) { ++ /* Best-effort delete to avoid duplicate entries */ ++ if (!exfat_get_dentry_set(&new_es, sb, ++ &dir, newentry, ++ ES_ALL_ENTRIES)) { ++ exfat_remove_entries(parent_inode, &new_es, ++ ES_IDX_FILE, false); ++ exfat_put_dentry_set(&new_es, false); ++ } + goto put_old_es; ++ } + +- exfat_remove_entries(parent_inode, &old_es, ES_IDX_FILE); ++ exfat_remove_entries(parent_inode, &old_es, ES_IDX_FILE, false); + ei->dir = dir; + ei->entry = newentry; + } else { +@@ -1057,8 +1089,8 @@ static int exfat_rename_file(struct inod + ei->attr |= EXFAT_ATTR_ARCHIVE; + } + +- exfat_remove_entries(parent_inode, &old_es, ES_IDX_FIRST_FILENAME + 1); +- exfat_init_ext_entry(&old_es, num_new_entries, p_uniname); ++ exfat_init_ext_entry(&old_es, num_new_entries, p_uniname, ++ &old_es, num_extra_entries); + } + return exfat_put_dentry_set(&old_es, sync); + +@@ -1074,6 +1106,7 @@ static int exfat_move_file(struct inode + struct exfat_dentry *epmov, *epnew; + struct exfat_entry_set_cache mov_es, new_es; + struct exfat_chain newdir; ++ unsigned int num_extra_entries, num_total_entries; + + num_new_entries = exfat_calc_num_entries(p_uniname); + if (num_new_entries < 0) +@@ -1083,8 +1116,14 @@ static int exfat_move_file(struct inode + if (ret) + return -EIO; + ++ ret = exfat_count_extra_entries(&mov_es); ++ if (ret < 0) ++ goto put_mov_es; ++ num_extra_entries = ret; ++ num_total_entries = num_new_entries + num_extra_entries; ++ + newentry = exfat_find_empty_entry(parent_inode, &newdir, +- num_new_entries, &new_es); ++ num_total_entries, &new_es); + if (newentry < 0) { + ret = newentry; /* -EIO or -ENOSPC */ + goto put_mov_es; +@@ -1102,21 +1141,31 @@ static int exfat_move_file(struct inode + epnew = exfat_get_dentry_cached(&new_es, ES_IDX_STREAM); + *epnew = *epmov; + +- exfat_init_ext_entry(&new_es, num_new_entries, p_uniname); +- exfat_remove_entries(parent_inode, &mov_es, ES_IDX_FILE); ++ exfat_init_ext_entry(&new_es, num_new_entries, p_uniname, ++ &mov_es, num_extra_entries); ++ ++ exfat_remove_entries(parent_inode, &mov_es, ES_IDX_FILE, false); + + ei->dir = newdir; + ei->entry = newentry; + + ret = exfat_put_dentry_set(&new_es, IS_DIRSYNC(parent_inode)); +- if (ret) ++ if (ret) { ++ /* Best-effort delete to avoid duplicate entries */ ++ if (!exfat_get_dentry_set(&new_es, parent_inode->i_sb, ++ &newdir, newentry, ++ ES_ALL_ENTRIES)) { ++ exfat_remove_entries(parent_inode, &new_es, ++ ES_IDX_FILE, false); ++ exfat_put_dentry_set(&new_es, false); ++ } + goto put_mov_es; ++ } + + return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(parent_inode)); + + put_mov_es: + exfat_put_dentry_set(&mov_es, false); +- + return ret; + } + +@@ -1190,7 +1239,7 @@ static int __exfat_rename(struct inode * + goto del_out; + } + +- exfat_remove_entries(new_inode, &es, ES_IDX_FILE); ++ exfat_remove_entries(new_inode, &es, ES_IDX_FILE, true); + + ret = exfat_put_dentry_set(&es, IS_DIRSYNC(new_inode)); + if (ret) diff --git a/queue-7.1/lib-test_hmm-use-kvfree-to-free-kvcalloc-allocations.patch b/queue-7.1/lib-test_hmm-use-kvfree-to-free-kvcalloc-allocations.patch new file mode 100644 index 0000000000..ece832ffb5 --- /dev/null +++ b/queue-7.1/lib-test_hmm-use-kvfree-to-free-kvcalloc-allocations.patch @@ -0,0 +1,49 @@ +From 59f19bf6f119eecfa16355186b593abba8eb5198 Mon Sep 17 00:00:00 2001 +From: Hao Ge +Date: Wed, 13 May 2026 16:25:25 +0800 +Subject: lib/test_hmm: use kvfree() to free kvcalloc() allocations + +From: Hao Ge + +commit 59f19bf6f119eecfa16355186b593abba8eb5198 upstream. + +Coccinelle scripts/coccinelle/api/kfree_mismatch.cocci reports +the following warnings: + + lib/test_hmm.c:1256:15-16: WARNING kvmalloc is used to allocate this memory at line 1191 + lib/test_hmm.c:1257:15-16: WARNING kvmalloc is used to allocate this memory at line 1196 + +Fix this by replacing kfree() with kvfree() to correctly handle the +vmalloc() fallback path of kvcalloc(). + +Link: https://lore.kernel.org/20260513082525.154036-1-hao.ge@linux.dev +Fixes: 775465fd26a3 ("lib/test_hmm: add zone device private THP test infrastructure") +Signed-off-by: Hao Ge +Acked-by: Balbir Singh +Cc: Jason Gunthorpe +Cc: Leon Romanovsky +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + lib/test_hmm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/test_hmm.c b/lib/test_hmm.c +index 213504915737..38996c4baa40 100644 +--- a/lib/test_hmm.c ++++ b/lib/test_hmm.c +@@ -1253,8 +1253,8 @@ static int dmirror_migrate_to_device(struct dmirror *dmirror, + mmap_read_unlock(mm); + mmput(mm); + free_mem: +- kfree(src_pfns); +- kfree(dst_pfns); ++ kvfree(src_pfns); ++ kvfree(dst_pfns); + return ret; + } + +-- +2.55.0 + diff --git a/queue-7.1/liveupdate-reject-liveupdate_ioctl_create_session-with-invalid-name-length.patch b/queue-7.1/liveupdate-reject-liveupdate_ioctl_create_session-with-invalid-name-length.patch new file mode 100644 index 0000000000..7fd4786db3 --- /dev/null +++ b/queue-7.1/liveupdate-reject-liveupdate_ioctl_create_session-with-invalid-name-length.patch @@ -0,0 +1,43 @@ +From e947433cd0d2b95a277757451b9b9c2714136dc2 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Wed, 29 Apr 2026 22:21:14 +0100 +Subject: liveupdate: reject LIVEUPDATE_IOCTL_CREATE_SESSION with invalid name length + +From: Luca Boccassi + +commit e947433cd0d2b95a277757451b9b9c2714136dc2 upstream. + +A session name must not be an empty string, and must not exceed the +maximum size define in the uapi header, including null termination. + +Fixes: 0153094d03df ("liveupdate: luo_session: add sessions support") +Cc: stable@vger.kernel.org + +Signed-off-by: Luca Boccassi +Reviewed-by: Pasha Tatashin +Reviewed-by: Pratyush Yadav +Acked-by: Mike Rapoport (Microsoft) +Link: https://lore.kernel.org/r/20260429212221.814107-2-luca.boccassi@gmail.com +Signed-off-by: Pasha Tatashin +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/liveupdate/luo_session.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/kernel/liveupdate/luo_session.c ++++ b/kernel/liveupdate/luo_session.c +@@ -382,9 +382,13 @@ static int luo_session_getfile(struct lu + + int luo_session_create(const char *name, struct file **filep) + { ++ size_t len = strnlen(name, LIVEUPDATE_SESSION_NAME_LENGTH); + struct luo_session *session; + int err; + ++ if (len == 0 || len > LIVEUPDATE_SESSION_NAME_LENGTH - 1) ++ return -EINVAL; ++ + session = luo_session_alloc(name); + if (IS_ERR(session)) + return PTR_ERR(session); diff --git a/queue-7.1/mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch b/queue-7.1/mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch new file mode 100644 index 0000000000..70c63552b1 --- /dev/null +++ b/queue-7.1/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 +@@ -2438,6 +2438,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 +@@ -4671,7 +4671,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 +@@ -336,8 +336,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 +@@ -227,8 +227,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-7.1/mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch b/queue-7.1/mm-fix-mmap-errno-value-when-map_droppable-is-not-supported.patch new file mode 100644 index 0000000000..996366341d --- /dev/null +++ b/queue-7.1/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 +@@ -504,7 +504,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-7.1/mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch b/queue-7.1/mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access.patch new file mode 100644 index 0000000000..dd51b02f01 --- /dev/null +++ b/queue-7.1/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 +@@ -120,14 +120,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); +@@ -138,19 +142,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)) +@@ -183,9 +190,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-7.1/module-decompress-check-return-value-of-module_extend_max_pages.patch b/queue-7.1/module-decompress-check-return-value-of-module_extend_max_pages.patch new file mode 100644 index 0000000000..f2856619cb --- /dev/null +++ b/queue-7.1/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-7.1/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch b/queue-7.1/nfsv4-include-may_write-in-open-permission-mask-for-o_trunc.patch new file mode 100644 index 0000000000..1727339014 --- /dev/null +++ b/queue-7.1/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 +@@ -3344,6 +3344,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-7.1/nouveau-vmm-fix-another-spt-lpt-race.patch b/queue-7.1/nouveau-vmm-fix-another-spt-lpt-race.patch new file mode 100644 index 0000000000..1532ff902e --- /dev/null +++ b/queue-7.1/nouveau-vmm-fix-another-spt-lpt-race.patch @@ -0,0 +1,84 @@ +From 6763a0aea6d658d69b9215ab9151d7bd4c1c314b Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Mon, 15 Jun 2026 14:47:37 +1000 +Subject: nouveau/vmm: fix another SPT/LPT race + +From: Dave Airlie + +commit 6763a0aea6d658d69b9215ab9151d7bd4c1c314b upstream. + +We've had an unknown Turing issue for a while with page faults since +large pages and compression. + +I've got a patch series that syncs all our L2 handling with ogkm and it +made this fault happen more. + +After writing a bunch of debugging patches, I spotted an invalid LPT +entry where there should have been a valid one. + +A 64K MAP succeeds on a range, but a subsequent SPT put drops SPT refs +across multiple ranges, + +We shouldn't assume all ranges where SPTEs go away will have the same +sparse/invalid/valid state, just iterate over each instead and do the +right thing. + +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Fixes: d19512f5abb1 ("nouveau/vmm: start tracking if the LPT PTE is valid. (v6)") +Link: https://patch.msgid.link/20260615044737.3419585-1-airlied@gmail.com +[ Properly format commit message. - Danilo ] +Signed-off-by: Danilo Krummrich +(cherry picked from commit d008141ed4ce924167a03d46fbce9ad1fe4efa29) +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 31 +++++++++++--------------- + 1 file changed, 14 insertions(+), 17 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +@@ -230,29 +230,26 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_ite + * covered by a number of LPTEs, the LPTEs once again take + * control over their address range. + * +- * Determine how many LPTEs need to transition state. ++ * Transition each LPTE individually as each may have a ++ * different target state (sparse, invalid, or valid). + */ +- pgt->pte[ptei].s.spte_valid = false; +- for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { ++ for (ptei++; ptei < lpti; ptei++) { + if (pgt->pte[ptei].s.sptes) + break; +- pgt->pte[ptei].s.spte_valid = false; + } + +- if (pgt->pte[pteb].s.sparse) { +- TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes); +- pair->func->sparse(vmm, pgt->pt[0], pteb, ptes); +- } else if (!pgt->pte[pteb].s.lpte_valid) { +- if (pair->func->invalid) { +- /* If the MMU supports it, restore the LPTE to the +- * INVALID state to tell the MMU there is no point +- * trying to fetch the corresponding SPTEs. +- */ +- TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); +- pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); ++ while (pteb < ptei) { ++ pgt->pte[pteb].s.spte_valid = false; ++ if (pgt->pte[pteb].s.sparse) { ++ TRA(it, "LPTE %05x: U -> S", pteb); ++ pair->func->sparse(vmm, pgt->pt[0], pteb, 1); ++ } else if (!pgt->pte[pteb].s.lpte_valid) { ++ if (pair->func->invalid) { ++ TRA(it, "LPTE %05x: U -> I", pteb); ++ pair->func->invalid(vmm, pgt->pt[0], pteb, 1); ++ } + } +- } else { +- TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes); ++ pteb++; + } + } + } diff --git a/queue-7.1/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch b/queue-7.1/ntb-epf-fix-request_irq-unwind-in-ntb_epf_init_isr.patch new file mode 100644 index 0000000000..20fcae4c5d --- /dev/null +++ b/queue-7.1/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-7.1/perf-aux-fix-page-uaf-in-map_range.patch b/queue-7.1/perf-aux-fix-page-uaf-in-map_range.patch new file mode 100644 index 0000000000..1479a3c3e5 --- /dev/null +++ b/queue-7.1/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 +@@ -7150,6 +7150,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-7.1/riscv-mm-define-direct_map_physmem_end.patch b/queue-7.1/riscv-mm-define-direct_map_physmem_end.patch new file mode 100644 index 0000000000..43d200051a --- /dev/null +++ b/queue-7.1/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-7.1/riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch b/queue-7.1/riscv-mm-unconditionally-sfence.vma-for-spurious-fault.patch new file mode 100644 index 0000000000..54fa25ee1c --- /dev/null +++ b/queue-7.1/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-7.1/rqspinlock-fix-order-in-raw_res_spin_-un-lock_irq-to-allow-schedule.patch b/queue-7.1/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-7.1/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-7.1/selftests-liveupdate-add-test-cases-for-liveupdate_ioctl_create_session-calls-with-invalid-length.patch b/queue-7.1/selftests-liveupdate-add-test-cases-for-liveupdate_ioctl_create_session-calls-with-invalid-length.patch new file mode 100644 index 0000000000..cc12916f66 --- /dev/null +++ b/queue-7.1/selftests-liveupdate-add-test-cases-for-liveupdate_ioctl_create_session-calls-with-invalid-length.patch @@ -0,0 +1,74 @@ +From dab2b4c66aa0f44ccb6a0096906e5680c604fe39 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Wed, 29 Apr 2026 22:21:15 +0100 +Subject: selftests/liveupdate: add test cases for LIVEUPDATE_IOCTL_CREATE_SESSION calls with invalid length + +From: Luca Boccassi + +commit dab2b4c66aa0f44ccb6a0096906e5680c604fe39 upstream. + +Verify that LIVEUPDATE_IOCTL_CREATE_SESSION ioctl which provide a name +that is an empty string or too long are not allowed. + +Cc: stable@vger.kernel.org + +Signed-off-by: Luca Boccassi +Reviewed-by: Pasha Tatashin +Reviewed-by: Pratyush Yadav +Link: https://lore.kernel.org/r/20260429212221.814107-3-luca.boccassi@gmail.com +Signed-off-by: Pasha Tatashin +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/liveupdate/liveupdate.c | 42 ++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/tools/testing/selftests/liveupdate/liveupdate.c ++++ b/tools/testing/selftests/liveupdate/liveupdate.c +@@ -386,4 +386,46 @@ TEST_F(liveupdate_device, prevent_double + ASSERT_EQ(close(session_fd2), 0); + } + ++/* ++ * Test Case: Create Session with No Null Termination ++ * ++ * Verifies that filling the entire 64-byte name field with non-null characters ++ * (no '\0' terminator) is rejected by the kernel with EINVAL. ++ */ ++TEST_F(liveupdate_device, create_session_no_null_termination) ++{ ++ struct liveupdate_ioctl_create_session args = {}; ++ ++ self->fd1 = open(LIVEUPDATE_DEV, O_RDWR); ++ if (self->fd1 < 0 && errno == ENOENT) ++ SKIP(return, "%s does not exist", LIVEUPDATE_DEV); ++ ASSERT_GE(self->fd1, 0); ++ ++ /* Fill entire name field with 'X', no null terminator */ ++ args.size = sizeof(args); ++ memset(args.name, 'X', sizeof(args.name)); ++ ++ EXPECT_LT(ioctl(self->fd1, LIVEUPDATE_IOCTL_CREATE_SESSION, &args), 0); ++ EXPECT_EQ(errno, EINVAL); ++} ++ ++/* ++ * Test Case: Create Session with Empty Name ++ * ++ * Verifies that creating a session with an empty string name fails ++ * with EINVAL. ++ */ ++TEST_F(liveupdate_device, create_session_empty_name) ++{ ++ int session_fd; ++ ++ self->fd1 = open(LIVEUPDATE_DEV, O_RDWR); ++ if (self->fd1 < 0 && errno == ENOENT) ++ SKIP(return, "%s does not exist", LIVEUPDATE_DEV); ++ ASSERT_GE(self->fd1, 0); ++ ++ session_fd = create_session(self->fd1, ""); ++ EXPECT_EQ(session_fd, -EINVAL); ++} ++ + TEST_HARNESS_MAIN diff --git a/queue-7.1/selftests-mm-fix-and-speedup-droppable-test.patch b/queue-7.1/selftests-mm-fix-and-speedup-droppable-test.patch new file mode 100644 index 0000000000..451ae62eee --- /dev/null +++ b/queue-7.1/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-7.1/selftests-mm-fix-ksft_process_madv.sh-test-category.patch b/queue-7.1/selftests-mm-fix-ksft_process_madv.sh-test-category.patch new file mode 100644 index 0000000000..358b5d9812 --- /dev/null +++ b/queue-7.1/selftests-mm-fix-ksft_process_madv.sh-test-category.patch @@ -0,0 +1,50 @@ +From 4b0363cb1f3ec42b0b1346e5ab0b8a3dceeee9be Mon Sep 17 00:00:00 2001 +From: Sarthak Sharma +Date: Mon, 8 Jun 2026 16:02:24 +0530 +Subject: selftests/mm: fix ksft_process_madv.sh test category + +From: Sarthak Sharma + +commit 4b0363cb1f3ec42b0b1346e5ab0b8a3dceeee9be upstream. + +ksft_process_madv.sh currently runs run_vmtests.sh with the mmap category. +Update it to run the process_madv category, since ksft_mmap.sh already +runs the mmap category tests. + +This avoids running mmap tests twice and ensures that process_madv tests +are run through the kselftest harness. + +Link: https://lore.kernel.org/20260608103224.344101-1-sarthak.sharma@arm.com +Fixes: 6ce964c02f1c ("selftests/mm: have the harness run each test category separately") +Signed-off-by: Sarthak Sharma +Reviewed-by: Mark Brown +Reviewed-by: Dev Jain +Acked-by: David Hildenbrand (Arm) +Cc: Liam R. Howlett +Cc: Lorenzo Stoakes +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/ksft_process_madv.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/mm/ksft_process_madv.sh b/tools/testing/selftests/mm/ksft_process_madv.sh +index 2c3137ae8bc8..edad2d2d888f 100755 +--- a/tools/testing/selftests/mm/ksft_process_madv.sh ++++ b/tools/testing/selftests/mm/ksft_process_madv.sh +@@ -1,4 +1,4 @@ + #!/bin/sh -e + # SPDX-License-Identifier: GPL-2.0 + +-./run_vmtests.sh -t mmap ++./run_vmtests.sh -t process_madv +-- +2.55.0 + diff --git a/queue-7.1/selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch b/queue-7.1/selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch new file mode 100644 index 0000000000..8d6baeb445 --- /dev/null +++ b/queue-7.1/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 +@@ -1366,7 +1366,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) +@@ -1401,15 +1401,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); +@@ -1418,7 +1418,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-7.1/series b/queue-7.1/series index 469856406d..6a15df52fa 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -405,3 +405,25 @@ 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 +liveupdate-reject-liveupdate_ioctl_create_session-with-invalid-name-length.patch +selftests-liveupdate-add-test-cases-for-liveupdate_ioctl_create_session-calls-with-invalid-length.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 +vt-fix-spurious-modifier-in-csi-cursor-key-sequences.patch +exfat-preserve-benign-secondary-entries-during-rename-and-move.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 +lib-test_hmm-use-kvfree-to-free-kvcalloc-allocations.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 +selftests-mm-fix-ksft_process_madv.sh-test-category.patch +nouveau-vmm-fix-another-spt-lpt-race.patch diff --git a/queue-7.1/tracing-prevent-out-of-bounds-read-in-glob-matching.patch b/queue-7.1/tracing-prevent-out-of-bounds-read-in-glob-matching.patch new file mode 100644 index 0000000000..98c296015d --- /dev/null +++ b/queue-7.1/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 +@@ -11,6 +11,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]". +@@ -41,6 +44,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 +@@ -55,9 +81,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') +@@ -125,4 +153,3 @@ backtrack: + } + } + } +-EXPORT_SYMBOL(glob_match); diff --git a/queue-7.1/vt-fix-spurious-modifier-in-csi-cursor-key-sequences.patch b/queue-7.1/vt-fix-spurious-modifier-in-csi-cursor-key-sequences.patch new file mode 100644 index 0000000000..bd60d0b5c9 --- /dev/null +++ b/queue-7.1/vt-fix-spurious-modifier-in-csi-cursor-key-sequences.patch @@ -0,0 +1,82 @@ +From e9ad4d5ca309cb517d3f7a85251c3c5328f40f1f Mon Sep 17 00:00:00 2001 +From: Nicolas Pitre +Date: Thu, 25 Jun 2026 22:48:33 -0400 +Subject: vt: fix spurious modifier in CSI/cursor key sequences + +From: Nicolas Pitre + +commit e9ad4d5ca309cb517d3f7a85251c3c5328f40f1f upstream. + +csi_modifier_param() builds the xterm modifier parameter from +shift_state, counting KG_SHIFTL/KG_SHIFTR as Shift, KG_ALTGR as Alt +and KG_CTRLL/KG_CTRLR as Ctrl in addition to the canonical KG_SHIFT, +KG_ALT and KG_CTRL. + +That is wrong when those weights are not plain modifiers. Keymaps +derived from XKB layouts (by kbd's xkbsupport, and by the +console-setup used in Debian, Ubuntu and others) encode the active +layout group using KG_SHIFTL/KG_SHIFTR: + + group 1: - + group 2: shiftl + group 3: shiftr + group 4: shiftl | shiftr + +So while a non-default layout group is selected, KG_SHIFTL and/or +KG_SHIFTR are set in shift_state with no Shift key held. +csi_modifier_param() then adds a spurious Shift to every cursor and +CSI key: pressing Up while group 2 is active emits ESC[1;2A (Shift+Up) +instead of ESC[A. KG_ALTGR has the same problem since it is the +standard third-level selector. + +Normal keymaps bind the physical Shift/Ctrl/Alt keys to KG_SHIFT, +KG_CTRL and KG_ALT, leaving the left/right and AltGr weights free for +layout and level selection. Count only those canonical weights, so +genuine modifiers are still encoded while layout/level selectors are +not. + +Fixes: 4af70f151671 ("vt: add modifier support to cursor keys") +Reported-by: Alexey Gladkov +Closes: https://lore.kernel.org/kbd/aj2gR0Y7sM6i9s2G@example.org/ +Cc: stable +Signed-off-by: Nicolas Pitre +Link: https://patch.msgid.link/20260626024833.3419086-1-nico@fluxnic.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/keyboard.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c +index dfdea0842149..763a3f1b7be0 100644 +--- a/drivers/tty/vt/keyboard.c ++++ b/drivers/tty/vt/keyboard.c +@@ -765,16 +765,22 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) + /* + * Compute xterm-style modifier parameter for CSI sequences. + * Returns 1 + (shift ? 1 : 0) + (alt ? 2 : 0) + (ctrl ? 4 : 0) ++ * ++ * Only the canonical modifier weights are counted. The left/right variants ++ * (KG_SHIFTL, KG_SHIFTR, KG_CTRLL, KG_CTRLR) and KG_ALTGR are commonly ++ * repurposed as keymap layout-group or level selectors rather than as plain ++ * modifiers (for instance XKB-derived keymaps select the layout group with ++ * KG_SHIFTL/KG_SHIFTR), so counting them would encode a spurious modifier. + */ + static int csi_modifier_param(void) + { + int mod = 1; + +- if (shift_state & (BIT(KG_SHIFT) | BIT(KG_SHIFTL) | BIT(KG_SHIFTR))) ++ if (shift_state & BIT(KG_SHIFT)) + mod += 1; +- if (shift_state & (BIT(KG_ALT) | BIT(KG_ALTGR))) ++ if (shift_state & BIT(KG_ALT)) + mod += 2; +- if (shift_state & (BIT(KG_CTRL) | BIT(KG_CTRLL) | BIT(KG_CTRLR))) ++ if (shift_state & BIT(KG_CTRL)) + mod += 4; + return mod; + } +-- +2.55.0 +