FAILED: patch "[PATCH] mm: fix oops when filemap_map_pmd() without prealloc_pte" failed to apply to 5.15-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 9aa1345d66b8132745ffb99b348b1492088da9e2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023120945-citizen-library-9f46@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
9aa1345d66b8 ("mm: fix oops when filemap_map_pmd() without prealloc_pte") 03c4f20454e0 ("mm: introduce pmd_install() helper")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9aa1345d66b8132745ffb99b348b1492088da9e2 Mon Sep 17 00:00:00 2001
From: Hugh Dickins <[email protected]>
Date: Fri, 17 Nov 2023 00:49:18 -0800
Subject: [PATCH] mm: fix oops when filemap_map_pmd() without prealloc_pte
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
syzbot reports oops in lockdep's __lock_acquire(), called from __pte_offset_map_lock() called from filemap_map_pages(); or when I run the repro, the oops comes in pmd_install(), called from filemap_map_pmd() called from filemap_map_pages(), just before the __pte_offset_map_lock().
The problem is that filemap_map_pmd() has been assuming that when it finds pmd_none(), a page table has already been prepared in prealloc_pte; and indeed do_fault_around() has been careful to preallocate one there, when it finds pmd_none(): but what if *pmd became none in between?
My 6.6 mods in mm/khugepaged.c, avoiding mmap_lock for write, have made it easy for *pmd to be cleared while servicing a page fault; but even before those, a huge *pmd might be zapped while a fault is serviced.
The difference in symptomatic stack traces comes from the "memory model" in use: pmd_install() uses pmd_populate() uses page_to_pfn(): in some models that is strict, and will oops on the NULL prealloc_pte; in other models, it will construct a bogus value to be populated into *pmd, then __pte_offset_map_lock() oops when trying to access split ptlock pointer (or some other symptom in normal case of ptlock embedded not pointer).
mm/filemap.c +1 -1
@@ -3371,7 +3371,7 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct folio *folio, } } -if (pmd_none (*vmf->pmd)) +if (pmd_none (*vmf->pmd) && vmf->prealloc_pte)pmd_install (mm, vmf->pmd, &vmf->prealloc_pte);return false;
Matthew Wilcox
maintainerQuoted 4 lines · On Sat, Dec 09, 2023 at 01:35:45PM +0100, [email protected] wrote:
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
This should do the job. It's not clear to me whether this bug remains latent on 5.15, so it may not be appropriate to apply. I defer to Hugh.
mm/filemap.c +1 -1
@@ -3209,7 +3209,7 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct page *page) } } -if (pmd_none (*vmf->pmd)) { +if (pmd_none (*vmf->pmd) && vmf->prealloc_pte) { vmf->ptl =pmd_lock (mm, vmf->pmd);if (likely (pmd_none (*vmf->pmd))) {mm_inc_nr_ptes (mm);
Quoted 77 lines
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkoutFETCH_HEAD
git cherry-pick -x9aa1345d66b8132745ffb99b348b1492088da9e2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023120945-citizen-library-9f46@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..Possible dependencies:
9aa1345d66b8("mm: fix oops whenfilemap_map_pmd()withoutprealloc_pte")03c4f20454e0("mm: introducepmd_install()helper")thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
9aa1345d66b8132745ffb99b348b1492088da9e2Mon Sep 17 00:00:00 2001From: Hugh Dickins <[email protected]>
Date: Fri, 17 Nov 2023 00:49:18 -0800
Subject: [PATCH] mm: fix oops whenfilemap_map_pmd()withoutprealloc_pte
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bitsyzbot reports oops in lockdep's
__lock_acquire(), called from__pte_offset_map_lock()called fromfilemap_map_pages(); or when I run the repro, the oops comes inpmd_install(), called fromfilemap_map_pmd()called fromfilemap_map_pages(), just before the__pte_offset_map_lock().The problem is that
filemap_map_pmd()has been assuming that when it findspmd_none(), a page table has already been prepared inprealloc_pte; and indeeddo_fault_around()has been careful to preallocate one there, when it findspmd_none(): but what if *pmd became none in between?My 6.6 mods in
mm/khugepaged.c, avoidingmmap_lockfor write, have made it easy for *pmd to be cleared while servicing a page fault; but even before those, a huge *pmd might be zapped while a fault is serviced.The difference in symptomatic stack traces comes from the "memory model" in use:
pmd_install()usespmd_populate()usespage_to_pfn(): in some models that is strict, and will oops on the NULLprealloc_pte; in other models, it will construct a bogus value to be populated into *pmd, then__pte_offset_map_lock()oops when trying to access split ptlock pointer (or some other symptom in normal case of ptlock embedded not pointer).Fixes f9ce0be71d1f ("mm: Cleanup faultaround and finish_fault() codepaths")Signed-off-by Hugh Dickins <[email protected]>Reported-and-tested-by [email protected]Reviewed-by David Hildenbrand <[email protected]>Cc Jann Horn <[email protected]>,Cc José Pekkarinen <[email protected]>Cc Kirill A. Shutemov <[email protected]>Cc Matthew Wilcox (Oracle) <[email protected]>Cc <[email protected]> [5.12+]Signed-off-by Andrew Morton <[email protected]>mm/filemap.c +1
-1@@ -3371,7 +3371,7 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct folio *folio, } } -if (pmd_none (*vmf->pmd)) +if (pmd_none (*vmf->pmd) && vmf->prealloc_pte)pmd_install (mm, vmf->pmd, &vmf->prealloc_pte);return false;
Quoted 8 lines · Matthew Wilcox
Quoted 4 lines · On Sat, Dec 09, 2023 at 01:35:45PM +0100, [email protected] wrote:
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.This should do the job. It's not clear to me whether this bug remains latent on 5.15, so it may not be appropriate to apply. I defer to Hugh.
Yes, that's exactly it, thanks Matthew. I knew I was going to need to look at this one, and even the 6.1 version, when they came out: because my mods did change what a safe procedure is; but this and the 6.1 version are both good, because of the old pmd_devmap_trans_unstable() check which follows in both of those trees.
As to whether it's needed in 5.15 and 6.1: I believe so. There's no doubt that my changes made it very much easier to hit, but I think it was a possibility before them. When I first wrote the commit message, I was describing how: I think you need huge tmpfs, and MADV_DONTNEED zapping the huge pmd under mmap_lock for read, racing with this fault which, to come this way, would have needed to have been on a previous page table which khugepaged has collapsed just before MADV_DONTNEED and fault got mmap_lock for read.
Far fetched, and of course I could be wrong. But reading my original commit message, I thought it was needlessly encouraging to bad actors, so cut it out. What I'm most afraid of is the "(or some other symptom in normal case of ptlock embedded not pointer)" - data corruption or data leak perhaps.
I see Greg provides some new and helpfully explicit instructions below, on how to manage sending replacement patches: I'll send a replacement following those instructions (but might hit an issue at git send-email stage - will send manually if so).
Hugh
Quoted 92 lines
mm/filemap.c +1
-1@@ -3209,7 +3209,7 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct page *page) } } -if (pmd_none (*vmf->pmd)) { +if (pmd_none (*vmf->pmd) && vmf->prealloc_pte) { vmf->ptl =pmd_lock (mm, vmf->pmd);if (likely (pmd_none (*vmf->pmd))) {mm_inc_nr_ptes (mm);Quoted 78 lines
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkoutFETCH_HEAD
git cherry-pick -x9aa1345d66b8132745ffb99b348b1492088da9e2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023120945-citizen-library-9f46@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..Possible dependencies:
9aa1345d66b8("mm: fix oops whenfilemap_map_pmd()withoutprealloc_pte")03c4f20454e0("mm: introducepmd_install()helper")thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
9aa1345d66b8132745ffb99b348b1492088da9e2Mon Sep 17 00:00:00 2001From: Hugh Dickins <[email protected]>
Date: Fri, 17 Nov 2023 00:49:18 -0800
Subject: [PATCH] mm: fix oops whenfilemap_map_pmd()withoutprealloc_pte
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bitsyzbot reports oops in lockdep's
__lock_acquire(), called from__pte_offset_map_lock()called fromfilemap_map_pages(); or when I run the repro, the oops comes inpmd_install(), called fromfilemap_map_pmd()called fromfilemap_map_pages(), just before the__pte_offset_map_lock().The problem is that
filemap_map_pmd()has been assuming that when it findspmd_none(), a page table has already been prepared inprealloc_pte; and indeeddo_fault_around()has been careful to preallocate one there, when it findspmd_none(): but what if *pmd became none in between?My 6.6 mods in
mm/khugepaged.c, avoidingmmap_lockfor write, have made it easy for *pmd to be cleared while servicing a page fault; but even before those, a huge *pmd might be zapped while a fault is serviced.The difference in symptomatic stack traces comes from the "memory model" in use:
pmd_install()usespmd_populate()usespage_to_pfn(): in some models that is strict, and will oops on the NULLprealloc_pte; in other models, it will construct a bogus value to be populated into *pmd, then__pte_offset_map_lock()oops when trying to access split ptlock pointer (or some other symptom in normal case of ptlock embedded not pointer).Fixes f9ce0be71d1f ("mm: Cleanup faultaround and finish_fault() codepaths")Signed-off-by Hugh Dickins <[email protected]>Reported-and-tested-by [email protected]Reviewed-by David Hildenbrand <[email protected]>Cc Jann Horn <[email protected]>,Cc José Pekkarinen <[email protected]>Cc Kirill A. Shutemov <[email protected]>Cc Matthew Wilcox (Oracle) <[email protected]>Cc <[email protected]> [5.12+]Signed-off-by Andrew Morton <[email protected]>mm/filemap.c +1
-1@@ -3371,7 +3371,7 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct folio *folio, } } -if (pmd_none (*vmf->pmd)) +if (pmd_none (*vmf->pmd) && vmf->prealloc_pte)pmd_install (mm, vmf->pmd, &vmf->prealloc_pte);return false;