]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Jun 2019 12:53:48 +0000 (14:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Jun 2019 12:53:48 +0000 (14:53 +0200)
added patches:
powerpc-64s-fix-thp-pmd-collapse-serialisation.patch
powerpc-fix-kexec-failure-on-book3s-32.patch

queue-5.1/powerpc-64s-fix-thp-pmd-collapse-serialisation.patch [new file with mode: 0644]
queue-5.1/powerpc-fix-kexec-failure-on-book3s-32.patch [new file with mode: 0644]
queue-5.1/series

diff --git a/queue-5.1/powerpc-64s-fix-thp-pmd-collapse-serialisation.patch b/queue-5.1/powerpc-64s-fix-thp-pmd-collapse-serialisation.patch
new file mode 100644 (file)
index 0000000..f165c26
--- /dev/null
@@ -0,0 +1,102 @@
+From 33258a1db165cf43a9e6382587ad06e9b7f8187c Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Fri, 7 Jun 2019 13:56:35 +1000
+Subject: powerpc/64s: Fix THP PMD collapse serialisation
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+commit 33258a1db165cf43a9e6382587ad06e9b7f8187c upstream.
+
+Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian
+conversion in pte helpers") changed the actual bitwise tests in
+pte_access_permitted by using pte_write() and pte_present() helpers
+rather than raw bitwise testing _PAGE_WRITE and _PAGE_PRESENT bits.
+
+The pte_present() change now returns true for PTEs which are
+!_PAGE_PRESENT and _PAGE_INVALID, which is the combination used by
+pmdp_invalidate() to synchronize access from lock-free lookups.
+pte_access_permitted() is used by pmd_access_permitted(), so allowing
+GUP lock free access to proceed with such PTEs breaks this
+synchronisation.
+
+This bug has been observed on a host using the hash page table MMU,
+with random crashes and corruption in guests, usually together with
+bad PMD messages in the host.
+
+Fix this by adding an explicit check in pmd_access_permitted(), and
+documenting the condition explicitly.
+
+The pte_write() change should be okay, and would prevent GUP from
+falling back to the slow path when encountering savedwrite PTEs, which
+matches what x86 (that does not implement savedwrite) does.
+
+Fixes: 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion in pte helpers")
+Cc: stable@vger.kernel.org # v4.20+
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/book3s/64/pgtable.h |   30 +++++++++++++++++++++++++++
+ arch/powerpc/mm/pgtable-book3s64.c           |    3 ++
+ 2 files changed, 33 insertions(+)
+
+--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
++++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
+@@ -875,6 +875,23 @@ static inline int pmd_present(pmd_t pmd)
+       return false;
+ }
++static inline int pmd_is_serializing(pmd_t pmd)
++{
++      /*
++       * If the pmd is undergoing a split, the _PAGE_PRESENT bit is clear
++       * and _PAGE_INVALID is set (see pmd_present, pmdp_invalidate).
++       *
++       * This condition may also occur when flushing a pmd while flushing
++       * it (see ptep_modify_prot_start), so callers must ensure this
++       * case is fine as well.
++       */
++      if ((pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) ==
++                                              cpu_to_be64(_PAGE_INVALID))
++              return true;
++
++      return false;
++}
++
+ static inline int pmd_bad(pmd_t pmd)
+ {
+       if (radix_enabled())
+@@ -1090,6 +1107,19 @@ static inline int pmd_protnone(pmd_t pmd
+ #define pmd_access_permitted pmd_access_permitted
+ static inline bool pmd_access_permitted(pmd_t pmd, bool write)
+ {
++      /*
++       * pmdp_invalidate sets this combination (which is not caught by
++       * !pte_present() check in pte_access_permitted), to prevent
++       * lock-free lookups, as part of the serialize_against_pte_lookup()
++       * synchronisation.
++       *
++       * This also catches the case where the PTE's hardware PRESENT bit is
++       * cleared while TLB is flushed, which is suboptimal but should not
++       * be frequent.
++       */
++      if (pmd_is_serializing(pmd))
++              return false;
++
+       return pte_access_permitted(pmd_pte(pmd), write);
+ }
+--- a/arch/powerpc/mm/pgtable-book3s64.c
++++ b/arch/powerpc/mm/pgtable-book3s64.c
+@@ -116,6 +116,9 @@ pmd_t pmdp_invalidate(struct vm_area_str
+       /*
+        * This ensures that generic code that rely on IRQ disabling
+        * to prevent a parallel THP split work as expected.
++       *
++       * Marking the entry with _PAGE_INVALID && ~_PAGE_PRESENT requires
++       * a special case check in pmd_access_permitted.
+        */
+       serialize_against_pte_lookup(vma->vm_mm);
+       return __pmd(old_pmd);
diff --git a/queue-5.1/powerpc-fix-kexec-failure-on-book3s-32.patch b/queue-5.1/powerpc-fix-kexec-failure-on-book3s-32.patch
new file mode 100644 (file)
index 0000000..3a9ac5d
--- /dev/null
@@ -0,0 +1,79 @@
+From 6c284228eb356a1ec62a704b4d2329711831eaed Mon Sep 17 00:00:00 2001
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+Date: Mon, 3 Jun 2019 08:20:28 +0000
+Subject: powerpc: Fix kexec failure on book3s/32
+
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+
+commit 6c284228eb356a1ec62a704b4d2329711831eaed upstream.
+
+In the old days, _PAGE_EXEC didn't exist on 6xx aka book3s/32.
+Therefore, allthough __mapin_ram_chunk() was already mapping kernel
+text with PAGE_KERNEL_TEXT and the rest with PAGE_KERNEL, the entire
+memory was executable. Part of the memory (first 512kbytes) was
+mapped with BATs instead of page table, but it was also entirely
+mapped as executable.
+
+In commit 385e89d5b20f ("powerpc/mm: add exec protection on
+powerpc 603"), we started adding exec protection to some 6xx, namely
+the 603, for pages mapped via pagetables.
+
+Then, in commit 63b2bc619565 ("powerpc/mm/32s: Use BATs for
+STRICT_KERNEL_RWX"), the exec protection was extended to BAT mapped
+memory, so that really only the kernel text could be executed.
+
+The problem here is that kexec is based on copying some code into
+upper part of memory then executing it from there in order to install
+a fresh new kernel at its definitive location.
+
+However, the code is position independant and first part of it is
+just there to deactivate the MMU and jump to the second part. So it
+is possible to run this first part inplace instead of running the
+copy. Once the MMU is off, there is no protection anymore and the
+second part of the code will just run as before.
+
+Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
+Fixes: 63b2bc619565 ("powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX")
+Cc: stable@vger.kernel.org # v5.1+
+Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
+Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/kexec.h       |    3 +++
+ arch/powerpc/kernel/machine_kexec_32.c |    4 +++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/arch/powerpc/include/asm/kexec.h
++++ b/arch/powerpc/include/asm/kexec.h
+@@ -94,6 +94,9 @@ static inline bool kdump_in_progress(voi
+       return crashing_cpu >= 0;
+ }
++void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_code_buffer,
++                       unsigned long start_address) __noreturn;
++
+ #ifdef CONFIG_KEXEC_FILE
+ extern const struct kexec_file_ops kexec_elf64_ops;
+--- a/arch/powerpc/kernel/machine_kexec_32.c
++++ b/arch/powerpc/kernel/machine_kexec_32.c
+@@ -30,7 +30,6 @@ typedef void (*relocate_new_kernel_t)(
+  */
+ void default_machine_kexec(struct kimage *image)
+ {
+-      extern const unsigned char relocate_new_kernel[];
+       extern const unsigned int relocate_new_kernel_size;
+       unsigned long page_list;
+       unsigned long reboot_code_buffer, reboot_code_buffer_phys;
+@@ -58,6 +57,9 @@ void default_machine_kexec(struct kimage
+                               reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
+       printk(KERN_INFO "Bye!\n");
++      if (!IS_ENABLED(CONFIG_FSL_BOOKE) && !IS_ENABLED(CONFIG_44x))
++              relocate_new_kernel(page_list, reboot_code_buffer_phys, image->start);
++
+       /* now call it */
+       rnk = (relocate_new_kernel_t) reboot_code_buffer;
+       (*rnk)(page_list, reboot_code_buffer_phys, image->start);
index bc599bb2c1bb3aac223ad871a117a68bd62442a0..8a5b22507b41ce7fccc5dc9e2a87c68de72ad5da 100644 (file)
@@ -111,3 +111,5 @@ x86-mm-kaslr-compute-the-size-of-the-vmemmap-section-properly.patch
 x86-resctrl-prevent-null-pointer-dereference-when-local-mbm-is-disabled.patch
 drm-edid-abstract-override-firmware-edid-retrieval.patch
 drm-add-fallback-override-firmware-edid-modes-workaround.patch
+powerpc-fix-kexec-failure-on-book3s-32.patch
+powerpc-64s-fix-thp-pmd-collapse-serialisation.patch