From: Greg Kroah-Hartman Date: Mon, 16 Dec 2019 18:44:32 +0000 (+0100) Subject: drop mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch, again :( X-Git-Tag: v5.4.4~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5a1759898a629149b5d6d9b3ae90dae485b44990;p=thirdparty%2Fkernel%2Fstable-queue.git drop mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch, again :( --- diff --git a/queue-4.14/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch b/queue-4.14/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch deleted file mode 100644 index 795c732ee8c..00000000000 --- a/queue-4.14/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 08a630ce27a21360fd5b0b801fdde49c6ddce0da Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sat, 30 Nov 2019 17:51:32 -0800 -Subject: mm/memory.c: fix a huge pud insertion race during faulting - -From: Thomas Hellstrom - -[ Upstream commit 3e0a2ff638b34f322eb170b1ae4515f61cfe3b14 ] - -[ Upstream commit 625110b5e9dae9074d8a7e67dd07f821a053eed7 ] - -A huge pud page can theoretically be faulted in racing with pmd_alloc() -in __handle_mm_fault(). That will lead to pmd_alloc() returning an -invalid pmd pointer. - -Fix this by adding a pud_trans_unstable() function similar to -pmd_trans_unstable() and check whether the pud is really stable before -using the pmd pointer. - -Race: - Thread 1: Thread 2: Comment - create_huge_pud() Fallback - not taken. - create_huge_pud() Taken. - pmd_alloc() Returns an invalid pointer. - -This will result in user-visible huge page data corruption. - -Note that this was caught during a code audit rather than a real -experienced problem. It looks to me like the only implementation that -currently creates huge pud pagetable entries is dev_dax_huge_fault() -which doesn't appear to care much about private (COW) mappings or -write-tracking which is, I believe, a prerequisite for create_huge_pud() -falling back on thread 1, but not in thread 2. - -Link: http://lkml.kernel.org/r/20191115115808.21181-2-thomas_os@shipmail.org -Fixes: a00cc7d9dd93 ("mm, x86: add support for PUD-sized transparent hugepages") -Signed-off-by: Thomas Hellstrom -Acked-by: Kirill A. Shutemov -Cc: Arnd Bergmann -Cc: Matthew Wilcox -Cc: -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/asm-generic/pgtable.h | 25 +++++++++++++++++++++++++ - mm/memory.c | 6 ++++++ - 2 files changed, 31 insertions(+) - -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 0c21014a38f23..876826240dead 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -846,6 +846,31 @@ static inline int pud_trans_huge(pud_t pud) - } - #endif - -+/* See pmd_none_or_trans_huge_or_clear_bad for discussion. */ -+static inline int pud_none_or_trans_huge_or_dev_or_clear_bad(pud_t *pud) -+{ -+ pud_t pudval = READ_ONCE(*pud); -+ -+ if (pud_none(pudval) || pud_trans_huge(pudval) || pud_devmap(pudval)) -+ return 1; -+ if (unlikely(pud_bad(pudval))) { -+ pud_clear_bad(pud); -+ return 1; -+ } -+ return 0; -+} -+ -+/* See pmd_trans_unstable for discussion. */ -+static inline int pud_trans_unstable(pud_t *pud) -+{ -+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ -+ defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) -+ return pud_none_or_trans_huge_or_dev_or_clear_bad(pud); -+#else -+ return 0; -+#endif -+} -+ - #ifndef pmd_read_atomic - static inline pmd_t pmd_read_atomic(pmd_t *pmdp) - { -diff --git a/mm/memory.c b/mm/memory.c -index 24963eee4fb03..174252bd87df8 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -4054,6 +4054,7 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, - vmf.pud = pud_alloc(mm, p4d, address); - if (!vmf.pud) - return VM_FAULT_OOM; -+retry_pud: - if (pud_none(*vmf.pud) && __transparent_hugepage_enabled(vma)) { - ret = create_huge_pud(&vmf); - if (!(ret & VM_FAULT_FALLBACK)) -@@ -4080,6 +4081,11 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, - vmf.pmd = pmd_alloc(mm, vmf.pud, address); - if (!vmf.pmd) - return VM_FAULT_OOM; -+ -+ /* Huge pud page fault raced with pmd_alloc? */ -+ if (pud_trans_unstable(vmf.pud)) -+ goto retry_pud; -+ - if (pmd_none(*vmf.pmd) && __transparent_hugepage_enabled(vma)) { - ret = create_huge_pmd(&vmf); - if (!(ret & VM_FAULT_FALLBACK)) --- -2.20.1 - diff --git a/queue-4.14/series b/queue-4.14/series index 27a4b6202f8..a84824c7a11 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -264,4 +264,3 @@ mm-shmem.c-cast-the-type-of-unmap_start-to-u64.patch ext4-fix-a-bug-in-ext4_wait_for_tail_page_commit.patch mfd-rk808-fix-rk818-id-template.patch mm-thp-proc-report-thp-eligibility-for-each-vma.patch -mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch diff --git a/queue-4.19/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch b/queue-4.19/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch deleted file mode 100644 index bb1f5482fc9..00000000000 --- a/queue-4.19/mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 3e0a2ff638b34f322eb170b1ae4515f61cfe3b14 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sat, 30 Nov 2019 17:51:32 -0800 -Subject: mm/memory.c: fix a huge pud insertion race during faulting - -From: Thomas Hellstrom - -[ Upstream commit 625110b5e9dae9074d8a7e67dd07f821a053eed7 ] - -A huge pud page can theoretically be faulted in racing with pmd_alloc() -in __handle_mm_fault(). That will lead to pmd_alloc() returning an -invalid pmd pointer. - -Fix this by adding a pud_trans_unstable() function similar to -pmd_trans_unstable() and check whether the pud is really stable before -using the pmd pointer. - -Race: - Thread 1: Thread 2: Comment - create_huge_pud() Fallback - not taken. - create_huge_pud() Taken. - pmd_alloc() Returns an invalid pointer. - -This will result in user-visible huge page data corruption. - -Note that this was caught during a code audit rather than a real -experienced problem. It looks to me like the only implementation that -currently creates huge pud pagetable entries is dev_dax_huge_fault() -which doesn't appear to care much about private (COW) mappings or -write-tracking which is, I believe, a prerequisite for create_huge_pud() -falling back on thread 1, but not in thread 2. - -Link: http://lkml.kernel.org/r/20191115115808.21181-2-thomas_os@shipmail.org -Fixes: a00cc7d9dd93 ("mm, x86: add support for PUD-sized transparent hugepages") -Signed-off-by: Thomas Hellstrom -Acked-by: Kirill A. Shutemov -Cc: Arnd Bergmann -Cc: Matthew Wilcox -Cc: -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Sasha Levin ---- - include/asm-generic/pgtable.h | 25 +++++++++++++++++++++++++ - mm/memory.c | 6 ++++++ - 2 files changed, 31 insertions(+) - -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 15fd0277ffa69..f94c39070dcca 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -874,6 +874,31 @@ static inline int pud_trans_huge(pud_t pud) - } - #endif - -+/* See pmd_none_or_trans_huge_or_clear_bad for discussion. */ -+static inline int pud_none_or_trans_huge_or_dev_or_clear_bad(pud_t *pud) -+{ -+ pud_t pudval = READ_ONCE(*pud); -+ -+ if (pud_none(pudval) || pud_trans_huge(pudval) || pud_devmap(pudval)) -+ return 1; -+ if (unlikely(pud_bad(pudval))) { -+ pud_clear_bad(pud); -+ return 1; -+ } -+ return 0; -+} -+ -+/* See pmd_trans_unstable for discussion. */ -+static inline int pud_trans_unstable(pud_t *pud) -+{ -+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ -+ defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) -+ return pud_none_or_trans_huge_or_dev_or_clear_bad(pud); -+#else -+ return 0; -+#endif -+} -+ - #ifndef pmd_read_atomic - static inline pmd_t pmd_read_atomic(pmd_t *pmdp) - { -diff --git a/mm/memory.c b/mm/memory.c -index bbf0cc4066c84..f910da42a1f01 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -4106,6 +4106,7 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma, - vmf.pud = pud_alloc(mm, p4d, address); - if (!vmf.pud) - return VM_FAULT_OOM; -+retry_pud: - if (pud_none(*vmf.pud) && __transparent_hugepage_enabled(vma)) { - ret = create_huge_pud(&vmf); - if (!(ret & VM_FAULT_FALLBACK)) -@@ -4132,6 +4133,11 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma, - vmf.pmd = pmd_alloc(mm, vmf.pud, address); - if (!vmf.pmd) - return VM_FAULT_OOM; -+ -+ /* Huge pud page fault raced with pmd_alloc? */ -+ if (pud_trans_unstable(vmf.pud)) -+ goto retry_pud; -+ - if (pmd_none(*vmf.pmd) && __transparent_hugepage_enabled(vma)) { - ret = create_huge_pmd(&vmf); - if (!(ret & VM_FAULT_FALLBACK)) --- -2.20.1 - diff --git a/queue-4.19/series b/queue-4.19/series index 414b1ca23b7..85576247dce 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -136,5 +136,4 @@ splice-only-read-in-as-much-information-as-there-is-pipe-buffer-space.patch ext4-fix-a-bug-in-ext4_wait_for_tail_page_commit.patch mfd-rk808-fix-rk818-id-template.patch mm-thp-proc-report-thp-eligibility-for-each-vma.patch -mm-memory.c-fix-a-huge-pud-insertion-race-during-fau.patch s390-smp-vdso-fix-asce-handling.patch