From: Sasha Levin Date: Thu, 27 Nov 2025 14:22:38 +0000 (-0500) Subject: Fixes for all trees X-Git-Tag: v6.6.118~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ac66eec7f17bd091a9fb1c2efcdce0d0a288e33;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/filemap-cap-pte-range-to-be-created-to-allowed-zero-.patch b/queue-6.1/filemap-cap-pte-range-to-be-created-to-allowed-zero-.patch new file mode 100644 index 0000000000..9a0563f420 --- /dev/null +++ b/queue-6.1/filemap-cap-pte-range-to-be-created-to-allowed-zero-.patch @@ -0,0 +1,77 @@ +From 9fa2ee29c40e2b592a95ba7bf431ee2b31e2e603 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 13:50:56 +0000 +Subject: filemap: cap PTE range to be created to allowed zero fill in + folio_map_range() + +From: Pankaj Raghav + +[ Upstream commit 743a2753a02e805347969f6f89f38b736850d808 ] + +Usually the page cache does not extend beyond the size of the inode, +therefore, no PTEs are created for folios that extend beyond the size. + +But with LBS support, we might extend page cache beyond the size of the +inode as we need to guarantee folios of minimum order. While doing a +read, do_fault_around() can create PTEs for pages that lie beyond the +EOF leading to incorrect error return when accessing a page beyond the +mapped file. + +Cap the PTE range to be created for the page cache up to the end of +file(EOF) in filemap_map_pages() so that return error codes are consistent +with POSIX[1] for LBS configurations. + +generic/749 has been created to trigger this edge case. This also fixes +generic/749 for tmpfs with huge=always on systems with 4k base page size. + +[1](from mmap(2)) SIGBUS + Attempted access to a page of the buffer that lies beyond the end + of the mapped file. For an explanation of the treatment of the + bytes in the page that corresponds to the end of a mapped file + that is not a multiple of the page size, see NOTES. + +Signed-off-by: Luis Chamberlain +Signed-off-by: Pankaj Raghav +Link: https://lore.kernel.org/r/20240822135018.1931258-6-kernel@pankajraghav.com +Tested-by: David Howells +Acked-by: Darrick J. Wong +Reviewed-by: Hannes Reinecke +Reviewed-by: Matthew Wilcox (Oracle) +Reviewed-by: Darrick J. Wong +Reviewed-by: Daniel Gomez +Reviewed-by: Dave Chinner +Signed-off-by: Christian Brauner +Signed-off-by: Kiryl Shutsemau +Signed-off-by: Sasha Levin +--- + mm/filemap.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/mm/filemap.c b/mm/filemap.c +index b77f534dfad35..40c186c7210bf 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3460,7 +3460,7 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, + struct vm_area_struct *vma = vmf->vma; + struct file *file = vma->vm_file; + struct address_space *mapping = file->f_mapping; +- pgoff_t last_pgoff = start_pgoff; ++ pgoff_t file_end, last_pgoff = start_pgoff; + unsigned long addr; + XA_STATE(xas, &mapping->i_pages, start_pgoff); + struct folio *folio; +@@ -3480,6 +3480,11 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, + + addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT); + vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl); ++ ++ file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1; ++ if (end_pgoff > file_end) ++ end_pgoff = file_end; ++ + do { + again: + page = folio_file_page(folio, xas.xa_index); +-- +2.51.0 + diff --git a/queue-6.1/mm-memory-do-not-populate-page-table-entries-beyond-.patch b/queue-6.1/mm-memory-do-not-populate-page-table-entries-beyond-.patch new file mode 100644 index 0000000000..89bbbfbf78 --- /dev/null +++ b/queue-6.1/mm-memory-do-not-populate-page-table-entries-beyond-.patch @@ -0,0 +1,206 @@ +From 88bcba15d6acd2a7c362d3b593d098a2d3be9dcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 13:50:57 +0000 +Subject: mm/memory: do not populate page table entries beyond i_size + +From: Kiryl Shutsemau + +[ Upstream commit 74207de2ba10c2973334906822dc94d2e859ffc5 ] + +Patch series "Fix SIGBUS semantics with large folios", v3. + +Accessing memory within a VMA, but beyond i_size rounded up to the next +page size, is supposed to generate SIGBUS. + +Darrick reported[1] an xfstests regression in v6.18-rc1. generic/749 +failed due to missing SIGBUS. This was caused by my recent changes that +try to fault in the whole folio where possible: + + 19773df031bc ("mm/fault: try to map the entire file folio in finish_fault()") + 357b92761d94 ("mm/filemap: map entire large folio faultaround") + +These changes did not consider i_size when setting up PTEs, leading to +xfstest breakage. + +However, the problem has been present in the kernel for a long time - +since huge tmpfs was introduced in 2016. The kernel happily maps +PMD-sized folios as PMD without checking i_size. And huge=always tmpfs +allocates PMD-size folios on any writes. + +I considered this corner case when I implemented a large tmpfs, and my +conclusion was that no one in their right mind should rely on receiving a +SIGBUS signal when accessing beyond i_size. I cannot imagine how it could +be useful for the workload. + +But apparently filesystem folks care a lot about preserving strict SIGBUS +semantics. + +Generic/749 was introduced last year with reference to POSIX, but no real +workloads were mentioned. It also acknowledged the tmpfs deviation from +the test case. + +POSIX indeed says[3]: + + References within the address range starting at pa and + continuing for len bytes to whole pages following the end of an + object shall result in delivery of a SIGBUS signal. + +The patchset fixes the regression introduced by recent changes as well as +more subtle SIGBUS breakage due to split failure on truncation. + +This patch (of 2): + +Accesses within VMA, but beyond i_size rounded up to PAGE_SIZE are +supposed to generate SIGBUS. + +Recent changes attempted to fault in full folio where possible. They did +not respect i_size, which led to populating PTEs beyond i_size and +breaking SIGBUS semantics. + +Darrick reported generic/749 breakage because of this. + +However, the problem existed before the recent changes. With huge=always +tmpfs, any write to a file leads to PMD-size allocation. Following the +fault-in of the folio will install PMD mapping regardless of i_size. + +Fix filemap_map_pages() and finish_fault() to not install: + - PTEs beyond i_size; + - PMD mappings across i_size; + +Make an exception for shmem/tmpfs that for long time intentionally +mapped with PMDs across i_size. + +Link: https://lkml.kernel.org/r/20251027115636.82382-1-kirill@shutemov.name +Link: https://lkml.kernel.org/r/20251027115636.82382-2-kirill@shutemov.name +Signed-off-by: Kiryl Shutsemau +Fixes: 6795801366da ("xfs: Support large folios") +Reported-by: "Darrick J. Wong" +Cc: Al Viro +Cc: Baolin Wang +Cc: Christian Brauner +Cc: Dave Chinner +Cc: David Hildenbrand +Cc: Hugh Dickins +Cc: Johannes Weiner +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Matthew Wilcox (Oracle) +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Rik van Riel +Cc: Shakeel Butt +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Kiryl Shutsemau +Signed-off-by: Sasha Levin +--- + mm/filemap.c | 20 +++++++++++++++----- + mm/memory.c | 24 +++++++++++++++++++++++- + 2 files changed, 38 insertions(+), 6 deletions(-) + +diff --git a/mm/filemap.c b/mm/filemap.c +index 40c186c7210bf..4088d1a5360fa 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3467,13 +3467,27 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, + struct page *page; + unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss); + vm_fault_t ret = 0; ++ bool can_map_large; + + rcu_read_lock(); + folio = first_map_page(mapping, &xas, end_pgoff); + if (!folio) + goto out; + +- if (filemap_map_pmd(vmf, &folio->page)) { ++ file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1; ++ end_pgoff = min(end_pgoff, file_end); ++ ++ /* ++ * Do not allow to map with PTEs beyond i_size and with PMD ++ * across i_size to preserve SIGBUS semantics. ++ * ++ * Make an exception for shmem/tmpfs that for long time ++ * intentionally mapped with PMDs across i_size. ++ */ ++ can_map_large = shmem_mapping(mapping) || ++ file_end >= folio_next_index(folio); ++ ++ if (can_map_large && filemap_map_pmd(vmf, &folio->page)) { + ret = VM_FAULT_NOPAGE; + goto out; + } +@@ -3481,10 +3495,6 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, + addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT); + vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl); + +- file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1; +- if (end_pgoff > file_end) +- end_pgoff = file_end; +- + do { + again: + page = folio_file_page(folio, xas.xa_index); +diff --git a/mm/memory.c b/mm/memory.c +index 454d918449b3a..f0b506acfcc5d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -4452,6 +4453,8 @@ static bool vmf_pte_changed(struct vm_fault *vmf) + vm_fault_t finish_fault(struct vm_fault *vmf) + { + struct vm_area_struct *vma = vmf->vma; ++ bool needs_fallback = false; ++ struct folio *folio; + struct page *page; + vm_fault_t ret; + +@@ -4461,6 +4464,8 @@ vm_fault_t finish_fault(struct vm_fault *vmf) + else + page = vmf->page; + ++ folio = page_folio(page); ++ + /* + * check even for read faults because we might have lost our CoWed + * page +@@ -4471,8 +4476,25 @@ vm_fault_t finish_fault(struct vm_fault *vmf) + return ret; + } + ++ if (!needs_fallback && vma->vm_file) { ++ struct address_space *mapping = vma->vm_file->f_mapping; ++ pgoff_t file_end; ++ ++ file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); ++ ++ /* ++ * Do not allow to map with PTEs beyond i_size and with PMD ++ * across i_size to preserve SIGBUS semantics. ++ * ++ * Make an exception for shmem/tmpfs that for long time ++ * intentionally mapped with PMDs across i_size. ++ */ ++ needs_fallback = !shmem_mapping(mapping) && ++ file_end < folio_next_index(folio); ++ } ++ + if (pmd_none(*vmf->pmd)) { +- if (PageTransCompound(page)) { ++ if (!needs_fallback && PageTransCompound(page)) { + ret = do_set_pmd(vmf, page); + if (ret != VM_FAULT_FALLBACK) + return ret; +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 1a4a1c212d..4a4f329f59 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -492,3 +492,5 @@ selftests-mptcp-connect-fix-fallback-note-due-to-ooo.patch pmdomain-samsung-plug-potential-memleak-during-probe.patch pmdomain-arm-scmi-fix-genpd-leak-on-provider-registration-failure.patch pmdomain-imx-fix-reference-count-leak-in-imx_gpc_remove.patch +filemap-cap-pte-range-to-be-created-to-allowed-zero-.patch +mm-memory-do-not-populate-page-table-entries-beyond-.patch