Convert vmf->page to a folio as soon as we're going to use it. This fixes a bug if the fault handler returns a tail page with hardware poison; tail pages have an invalid page->index, so we would fail to unmap the page from the page tables. We actually have to unmap the entire folio (or mapping_evict_folio() will fail), so use unmap_mapping_folio() instead.
This also saves various calls to compound_head() hidden in lock_page(), put_page(), etc.
Signed-off-by: Matthew Wilcox (Oracle) willy@infradead.org Fixes: 793917d997df ("mm/readahead: Add large folio readahead") Cc: stable@vger.kernel.org --- mm/memory.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c index 1f18ed4a5497..c2ee303ba6b3 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4239,6 +4239,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf) static vm_fault_t __do_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; + struct folio *folio; vm_fault_t ret;
/* @@ -4267,27 +4268,26 @@ static vm_fault_t __do_fault(struct vm_fault *vmf) VM_FAULT_DONE_COW))) return ret;
+ folio = page_folio(vmf->page); if (unlikely(PageHWPoison(vmf->page))) { - struct page *page = vmf->page; vm_fault_t poisonret = VM_FAULT_HWPOISON; if (ret & VM_FAULT_LOCKED) { - if (page_mapped(page)) - unmap_mapping_pages(page_mapping(page), - page->index, 1, false); - /* Retry if a clean page was removed from the cache. */ - if (invalidate_inode_page(page)) + if (page_mapped(vmf->page)) + unmap_mapping_folio(folio); + /* Retry if a clean folio was removed from the cache. */ + if (mapping_evict_folio(folio->mapping, folio)) poisonret = VM_FAULT_NOPAGE; - unlock_page(page); + folio_unlock(folio); } - put_page(page); + folio_put(folio); vmf->page = NULL; return poisonret; }
if (unlikely(!(ret & VM_FAULT_LOCKED))) - lock_page(vmf->page); + folio_lock(folio); else - VM_BUG_ON_PAGE(!PageLocked(vmf->page), vmf->page); + VM_BUG_ON_PAGE(!folio_test_locked(folio), vmf->page);
return ret; }
On Wed, 8 Nov 2023 18:28:05 +0000 "Matthew Wilcox (Oracle)" willy@infradead.org wrote:
Convert vmf->page to a folio as soon as we're going to use it. This fixes a bug if the fault handler returns a tail page with hardware poison; tail pages have an invalid page->index, so we would fail to unmap the page from the page tables. We actually have to unmap the entire folio (or mapping_evict_folio() will
Would we merely fail to unmap or is there a possibility of unmapping some random innocent other page?
How might this bug manifest in userspace, worst case?
fail), so use unmap_mapping_folio() instead.
This also saves various calls to compound_head() hidden in lock_page(), put_page(), etc.
Signed-off-by: Matthew Wilcox (Oracle) willy@infradead.org Fixes: 793917d997df ("mm/readahead: Add large folio readahead") Cc: stable@vger.kernel.org
As it's cc:stable I'll pluck this patch out of the rest of the series and shall stage it for 6.7-rcX, via mm-hotfixes-unstable -> mm-hotfixes-stable -> Linus. Unless this bug is a very minor thing?
On Wed, Nov 08, 2023 at 01:07:51PM -0800, Andrew Morton wrote:
On Wed, 8 Nov 2023 18:28:05 +0000 "Matthew Wilcox (Oracle)" willy@infradead.org wrote:
Convert vmf->page to a folio as soon as we're going to use it. This fixes a bug if the fault handler returns a tail page with hardware poison; tail pages have an invalid page->index, so we would fail to unmap the page from the page tables. We actually have to unmap the entire folio (or mapping_evict_folio() will
Would we merely fail to unmap or is there a possibility of unmapping some random innocent other page?
How might this bug manifest in userspace, worst case?
I think we might unmap a random other page in this file. But then the next fault on that page will bring it back in, so it's only going to be a tiny performance blip. And we've just found a hwpoisoned page which is going to cause all kinds of other excitement, so I doubt it'll be noticed in the grand scheme of things.
As it's cc:stable I'll pluck this patch out of the rest of the series and shall stage it for 6.7-rcX, via mm-hotfixes-unstable -> mm-hotfixes-stable -> Linus. Unless this bug is a very minor thing?
I think it's minor enough that it can wait for 6.8. Unless anyone disagrees?
linux-stable-mirror@lists.linaro.org