From: Sasha Levin Date: Fri, 1 May 2026 00:51:40 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v6.12.86~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39a4c5a2947a377ede17f538ae1819efa46581f1;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch b/queue-6.1/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch new file mode 100644 index 0000000000..91dc8abdaf --- /dev/null +++ b/queue-6.1/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch @@ -0,0 +1,77 @@ +From acf106a4b8d5a034e3e52b100c1346ebaf6b3ef1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2026 13:55:37 +0800 +Subject: f2fs: fix to detect potential corrupted nid in free_nid_list + +From: Chao Yu + +[ Upstream commit 8fc6056dcf79937c46c97fa4996cda65956437a9 ] + +As reported, on-disk footer.ino and footer.nid is the same and +out-of-range, let's add sanity check on f2fs_alloc_nid() to detect +any potential corruption in free_nid_list. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Robert Garcia +Signed-off-by: Sasha Levin +--- + fs/f2fs/node.c | 17 ++++++++++++++++- + include/linux/f2fs_fs.h | 1 + + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index 2555787c79bbe..06c94680ae4e7 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -27,12 +27,17 @@ static struct kmem_cache *free_nid_slab; + static struct kmem_cache *nat_entry_set_slab; + static struct kmem_cache *fsync_node_entry_slab; + ++static inline bool is_invalid_nid(struct f2fs_sb_info *sbi, nid_t nid) ++{ ++ return nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid; ++} ++ + /* + * Check whether the given nid is within node id range. + */ + int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) + { +- if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) { ++ if (unlikely(is_invalid_nid(sbi, nid))) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", + __func__, nid); +@@ -2593,6 +2598,16 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) + f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); + i = list_first_entry(&nm_i->free_nid_list, + struct free_nid, list); ++ ++ if (unlikely(is_invalid_nid(sbi, i->nid))) { ++ spin_unlock(&nm_i->nid_list_lock); ++ f2fs_err(sbi, "Corrupted nid %u in free_nid_list", ++ i->nid); ++ f2fs_stop_checkpoint(sbi, false, ++ STOP_CP_REASON_CORRUPTED_NID); ++ return false; ++ } ++ + *nid = i->nid; + + __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); +diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h +index c61d8fc1deb3e..26c7daca99598 100644 +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -81,6 +81,7 @@ enum stop_cp_reason { + STOP_CP_REASON_CORRUPTED_SUMMARY, + STOP_CP_REASON_UPDATE_INODE, + STOP_CP_REASON_FLUSH_FAIL, ++ STOP_CP_REASON_CORRUPTED_NID, + STOP_CP_REASON_MAX, + }; + +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 07ae1dc2f5..3c9c959317 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -179,3 +179,4 @@ ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch driver-core-don-t-let-a-device-probe-until-it-s-read.patch wifi-rtw88-check-for-pci-upstream-bridge-existence.patch um-drivers-call-kernel_strrchr-explicitly-in-cow_user.c.patch +f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch diff --git a/queue-6.12/mm-memory_hotplug-fix-hwpoisoned-large-folio-handlin.patch b/queue-6.12/mm-memory_hotplug-fix-hwpoisoned-large-folio-handlin.patch new file mode 100644 index 0000000000..73887f4b15 --- /dev/null +++ b/queue-6.12/mm-memory_hotplug-fix-hwpoisoned-large-folio-handlin.patch @@ -0,0 +1,86 @@ +From ebd37391cfef1c18d2a2616219189cf1b31e5a02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2026 14:37:31 +0300 +Subject: mm/memory_hotplug: fix hwpoisoned large folio handling in + do_migrate_range() + +From: Jinjiang Tu + +commit 397f6d14f9c370e4910e6885294c340f39dedbf5 upstream. + +In do_migrate_range(), the hwpoisoned folio may be large folio, which +can't be handled by unmap_poisoned_folio(). + +I can reproduce this issue in qemu after adding delay in memory_failure() + +BUG: kernel NULL pointer dereference, address: 0000000000000000 +Workqueue: kacpi_hotplug acpi_hotplug_work_fn +RIP: 0010:try_to_unmap_one+0x16a/0xfc0 + + rmap_walk_anon+0xda/0x1f0 + try_to_unmap+0x78/0x80 + ? __pfx_try_to_unmap_one+0x10/0x10 + ? __pfx_folio_not_mapped+0x10/0x10 + ? __pfx_folio_lock_anon_vma_read+0x10/0x10 + unmap_poisoned_folio+0x60/0x140 + do_migrate_range+0x4d1/0x600 + ? slab_memory_callback+0x6a/0x190 + ? notifier_call_chain+0x56/0xb0 + offline_pages+0x3e6/0x460 + memory_subsys_offline+0x130/0x1f0 + device_offline+0xba/0x110 + acpi_bus_offline+0xb7/0x130 + acpi_scan_hot_remove+0x77/0x290 + acpi_device_hotplug+0x1e0/0x240 + acpi_hotplug_work_fn+0x1a/0x30 + process_one_work+0x186/0x340 + +Besides, do_migrate_range() may be called between memory_failure set +hwpoison flag and isolate the folio from lru, so remove WARN_ON(). In other +places, unmap_poisoned_folio() is called when the folio is isolated, obey +it in do_migrate_range() too. + +[david@redhat.com: don't abort offlining, fixed typo, add comment] +Link: https://lkml.kernel.org/r/3c214dff-9649-4015-840f-10de0e03ebe4@redhat.com +Fixes: b15c87263a69 ("hwpoison, memory_hotplug: allow hwpoisoned pages to be offlined") +Signed-off-by: Jinjiang Tu +Signed-off-by: David Hildenbrand +Acked-by: Zi Yan +Reviewed-by: Miaohe Lin +Cc: Kefeng Wang +Cc: Luis Chamberalin +Cc: Matthew Wilcox (Oracle) +Cc: Michal Hocko +Cc: Oscar Salvador +Cc: Pankaj Raghav +Signed-off-by: Andrew Morton +Signed-off-by: Alexandra Diupina +Signed-off-by: Sasha Levin +--- + mm/memory_hotplug.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index 0a42e9a8caba2..16d788547b9b6 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1802,8 +1802,14 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) + goto put_folio; + + if (folio_contain_hwpoisoned_page(folio)) { +- if (WARN_ON(folio_test_lru(folio))) +- folio_isolate_lru(folio); ++ /* ++ * unmap_poisoned_folio() cannot handle large folios ++ * in all cases yet. ++ */ ++ if (folio_test_large(folio) && !folio_test_hugetlb(folio)) ++ goto put_folio; ++ if (folio_test_lru(folio) && !folio_isolate_lru(folio)) ++ goto put_folio; + if (folio_mapped(folio)) { + folio_lock(folio); + unmap_poisoned_folio(folio, pfn, false); +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index c23f863dfb..142e730889 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -32,3 +32,4 @@ vfio-cdx-fix-null-pointer-dereference-in-interrupt-trigger-path.patch um-drivers-call-kernel_strrchr-explicitly-in-cow_user.c.patch spi-imx-fix-use-after-free-on-unbind.patch spi-ch341-fix-memory-leaks-on-probe-failures.patch +mm-memory_hotplug-fix-hwpoisoned-large-folio-handlin.patch diff --git a/queue-6.18/mm-call-free_folio-directly-in-folio_unmap_invalidat.patch b/queue-6.18/mm-call-free_folio-directly-in-folio_unmap_invalidat.patch new file mode 100644 index 0000000000..36de3828e7 --- /dev/null +++ b/queue-6.18/mm-call-free_folio-directly-in-folio_unmap_invalidat.patch @@ -0,0 +1,89 @@ +From 5dd31b7e3d2e26e15c2bb1184a483828c00ad2ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Apr 2026 18:22:22 +0100 +Subject: mm: call ->free_folio() directly in folio_unmap_invalidate() + +From: Matthew Wilcox (Oracle) + +commit 615d9bb2ccad42f9e21d837431e401db2e471195 upstream. + +We can only call filemap_free_folio() if we have a reference to (or hold a +lock on) the mapping. Otherwise, we've already removed the folio from the +mapping so it no longer pins the mapping and the mapping can be removed, +causing a use-after-free when accessing mapping->a_ops. + +Follow the same pattern as __remove_mapping() and load the free_folio +function pointer before dropping the lock on the mapping. That lets us +make filemap_free_folio() static as this was the only caller outside +filemap.c. + +Link: https://lore.kernel.org/20260413184314.3419945-1-willy@infradead.org +Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes") +Signed-off-by: Matthew Wilcox (Oracle) +Reported-by: Google Big Sleep +Cc: Jens Axboe +Cc: Jan Kara +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + mm/filemap.c | 3 ++- + mm/internal.h | 1 - + mm/truncate.c | 6 +++++- + 3 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/mm/filemap.c b/mm/filemap.c +index 91dcfe14a67b7..e3339cf37a1f0 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -227,7 +227,8 @@ void __filemap_remove_folio(struct folio *folio, void *shadow) + page_cache_delete(mapping, folio, shadow); + } + +-void filemap_free_folio(struct address_space *mapping, struct folio *folio) ++static void filemap_free_folio(const struct address_space *mapping, ++ struct folio *folio) + { + void (*free_folio)(struct folio *); + +diff --git a/mm/internal.h b/mm/internal.h +index c80c6f566c2d9..4cf6a12ff491d 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -471,7 +471,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t *start, + pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices); + unsigned find_get_entries(struct address_space *mapping, pgoff_t *start, + pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices); +-void filemap_free_folio(struct address_space *mapping, struct folio *folio); + int truncate_inode_folio(struct address_space *mapping, struct folio *folio); + bool truncate_inode_partial_folio(struct folio *folio, loff_t start, + loff_t end); +diff --git a/mm/truncate.c b/mm/truncate.c +index 3c5a50ae32741..4bf64fd610c94 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -622,6 +622,7 @@ static int folio_launder(struct address_space *mapping, struct folio *folio) + int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio, + gfp_t gfp) + { ++ void (*free_folio)(struct folio *); + int ret; + + VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); +@@ -648,9 +649,12 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio, + xa_unlock_irq(&mapping->i_pages); + if (mapping_shrinkable(mapping)) + inode_add_lru(mapping->host); ++ free_folio = mapping->a_ops->free_folio; + spin_unlock(&mapping->host->i_lock); + +- filemap_free_folio(mapping, folio); ++ if (free_folio) ++ free_folio(folio); ++ folio_put_refs(folio, folio_nr_pages(folio)); + return 1; + failed: + xa_unlock_irq(&mapping->i_pages); +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 2239dd44bb..d8a5c01c15 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -35,3 +35,4 @@ um-drivers-call-kernel_strrchr-explicitly-in-cow_user.c.patch thermal-core-fix-thermal-zone-governor-cleanup-issues.patch spi-imx-fix-use-after-free-on-unbind.patch spi-ch341-fix-memory-leaks-on-probe-failures.patch +mm-call-free_folio-directly-in-folio_unmap_invalidat.patch diff --git a/queue-6.6/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch b/queue-6.6/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch new file mode 100644 index 0000000000..ad24fad75e --- /dev/null +++ b/queue-6.6/f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch @@ -0,0 +1,77 @@ +From 7e6c290bd29fb2739746b9b6e30ffd6cfeffeff1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2026 13:45:10 +0800 +Subject: f2fs: fix to detect potential corrupted nid in free_nid_list + +From: Chao Yu + +[ Upstream commit 8fc6056dcf79937c46c97fa4996cda65956437a9 ] + +As reported, on-disk footer.ino and footer.nid is the same and +out-of-range, let's add sanity check on f2fs_alloc_nid() to detect +any potential corruption in free_nid_list. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Robert Garcia +Signed-off-by: Sasha Levin +--- + fs/f2fs/node.c | 17 ++++++++++++++++- + include/linux/f2fs_fs.h | 1 + + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index 133141f10d94d..586a90643ddd2 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -27,12 +27,17 @@ static struct kmem_cache *free_nid_slab; + static struct kmem_cache *nat_entry_set_slab; + static struct kmem_cache *fsync_node_entry_slab; + ++static inline bool is_invalid_nid(struct f2fs_sb_info *sbi, nid_t nid) ++{ ++ return nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid; ++} ++ + /* + * Check whether the given nid is within node id range. + */ + int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) + { +- if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) { ++ if (unlikely(is_invalid_nid(sbi, nid))) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", + __func__, nid); +@@ -2603,6 +2608,16 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) + f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); + i = list_first_entry(&nm_i->free_nid_list, + struct free_nid, list); ++ ++ if (unlikely(is_invalid_nid(sbi, i->nid))) { ++ spin_unlock(&nm_i->nid_list_lock); ++ f2fs_err(sbi, "Corrupted nid %u in free_nid_list", ++ i->nid); ++ f2fs_stop_checkpoint(sbi, false, ++ STOP_CP_REASON_CORRUPTED_NID); ++ return false; ++ } ++ + *nid = i->nid; + + __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); +diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h +index b9affa64b7fa2..fed8bec024db7 100644 +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -77,6 +77,7 @@ enum stop_cp_reason { + STOP_CP_REASON_UPDATE_INODE, + STOP_CP_REASON_FLUSH_FAIL, + STOP_CP_REASON_NO_SEGMENT, ++ STOP_CP_REASON_CORRUPTED_NID, + STOP_CP_REASON_MAX, + }; + +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index e9fc592020..302cfb86e3 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -25,3 +25,4 @@ zram-do-not-forget-to-endio-for-partial-discard-requests.patch wifi-rtw88-check-for-pci-upstream-bridge-existence.patch um-drivers-call-kernel_strrchr-explicitly-in-cow_user.c.patch spi-imx-fix-use-after-free-on-unbind.patch +f2fs-fix-to-detect-potential-corrupted-nid-in-free_n.patch