]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Oct 2018 09:42:02 +0000 (11:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Oct 2018 09:42:02 +0000 (11:42 +0200)
added patches:
powerpc-avoid-code-patching-freed-init-sections.patch
powerpc-lib-code-patching-refactor-patch_instruction.patch
powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch

queue-4.14/powerpc-avoid-code-patching-freed-init-sections.patch [new file with mode: 0644]
queue-4.14/powerpc-lib-code-patching-refactor-patch_instruction.patch [new file with mode: 0644]
queue-4.14/powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/powerpc-avoid-code-patching-freed-init-sections.patch b/queue-4.14/powerpc-avoid-code-patching-freed-init-sections.patch
new file mode 100644 (file)
index 0000000..809bc8c
--- /dev/null
@@ -0,0 +1,87 @@
+From 51c3c62b58b357e8d35e4cc32f7b4ec907426fe3 Mon Sep 17 00:00:00 2001
+From: Michael Neuling <mikey@neuling.org>
+Date: Fri, 14 Sep 2018 11:14:11 +1000
+Subject: powerpc: Avoid code patching freed init sections
+
+From: Michael Neuling <mikey@neuling.org>
+
+commit 51c3c62b58b357e8d35e4cc32f7b4ec907426fe3 upstream.
+
+This stops us from doing code patching in init sections after they've
+been freed.
+
+In this chain:
+  kvm_guest_init() ->
+    kvm_use_magic_page() ->
+      fault_in_pages_readable() ->
+        __get_user() ->
+          __get_user_nocheck() ->
+            barrier_nospec();
+
+We have a code patching location at barrier_nospec() and
+kvm_guest_init() is an init function. This whole chain gets inlined,
+so when we free the init section (hence kvm_guest_init()), this code
+goes away and hence should no longer be patched.
+
+We seen this as userspace memory corruption when using a memory
+checker while doing partition migration testing on powervm (this
+starts the code patching post migration via
+/sys/kernel/mobility/migration). In theory, it could also happen when
+using /sys/kernel/debug/powerpc/barrier_nospec.
+
+Cc: stable@vger.kernel.org # 4.13+
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
+Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/setup.h |    1 +
+ arch/powerpc/lib/code-patching.c |    6 ++++++
+ arch/powerpc/mm/mem.c            |    2 ++
+ 3 files changed, 9 insertions(+)
+
+--- a/arch/powerpc/include/asm/setup.h
++++ b/arch/powerpc/include/asm/setup.h
+@@ -9,6 +9,7 @@ extern void ppc_printk_progress(char *s,
+ extern unsigned int rtas_data;
+ extern unsigned long long memory_limit;
++extern bool init_mem_is_free;
+ extern unsigned long klimit;
+ extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+--- a/arch/powerpc/lib/code-patching.c
++++ b/arch/powerpc/lib/code-patching.c
+@@ -28,6 +28,12 @@ static int __patch_instruction(unsigned
+ {
+       int err;
++      /* Make sure we aren't patching a freed init section */
++      if (init_mem_is_free && init_section_contains(exec_addr, 4)) {
++              pr_debug("Skipping init section patching addr: 0x%px\n", exec_addr);
++              return 0;
++      }
++
+       __put_user_size(instr, patch_addr, 4, err);
+       if (err)
+               return err;
+--- a/arch/powerpc/mm/mem.c
++++ b/arch/powerpc/mm/mem.c
+@@ -63,6 +63,7 @@
+ #endif
+ unsigned long long memory_limit;
++bool init_mem_is_free;
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+@@ -405,6 +406,7 @@ void free_initmem(void)
+ {
+       ppc_md.progress = ppc_printk_progress;
+       mark_initmem_nx();
++      init_mem_is_free = true;
+       free_initmem_default(POISON_FREE_INITMEM);
+ }
diff --git a/queue-4.14/powerpc-lib-code-patching-refactor-patch_instruction.patch b/queue-4.14/powerpc-lib-code-patching-refactor-patch_instruction.patch
new file mode 100644 (file)
index 0000000..95a7698
--- /dev/null
@@ -0,0 +1,103 @@
+From 8cf4c05712f04a405f0dacebcca8f042b391694a Mon Sep 17 00:00:00 2001
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+Date: Fri, 24 Nov 2017 08:31:07 +0100
+Subject: powerpc/lib/code-patching: refactor patch_instruction()
+
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+
+commit 8cf4c05712f04a405f0dacebcca8f042b391694a upstream.
+
+patch_instruction() uses almost the same sequence as
+__patch_instruction()
+
+This patch refactor it so that patch_instruction() uses
+__patch_instruction() instead of duplicating code.
+
+Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
+Acked-by: Balbir Singh <bsingharora@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/lib/code-patching.c |   30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/arch/powerpc/lib/code-patching.c
++++ b/arch/powerpc/lib/code-patching.c
+@@ -23,19 +23,26 @@
+ #include <asm/code-patching.h>
+ #include <asm/setup.h>
+-static int __patch_instruction(unsigned int *addr, unsigned int instr)
++static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
++                             unsigned int *patch_addr)
+ {
+       int err;
+-      __put_user_size(instr, addr, 4, err);
++      __put_user_size(instr, patch_addr, 4, err);
+       if (err)
+               return err;
+-      asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" :: "r" (addr));
++      asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
++                                                          "r" (exec_addr));
+       return 0;
+ }
++static int raw_patch_instruction(unsigned int *addr, unsigned int instr)
++{
++      return __patch_instruction(addr, instr, addr);
++}
++
+ #ifdef CONFIG_STRICT_KERNEL_RWX
+ static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
+@@ -138,7 +145,7 @@ static inline int unmap_patch_area(unsig
+ int patch_instruction(unsigned int *addr, unsigned int instr)
+ {
+       int err;
+-      unsigned int *dest = NULL;
++      unsigned int *patch_addr = NULL;
+       unsigned long flags;
+       unsigned long text_poke_addr;
+       unsigned long kaddr = (unsigned long)addr;
+@@ -149,7 +156,7 @@ int patch_instruction(unsigned int *addr
+        * to allow patching. We just do the plain old patching
+        */
+       if (!this_cpu_read(*PTRRELOC(&text_poke_area)))
+-              return __patch_instruction(addr, instr);
++              return raw_patch_instruction(addr, instr);
+       local_irq_save(flags);
+@@ -159,17 +166,10 @@ int patch_instruction(unsigned int *addr
+               goto out;
+       }
+-      dest = (unsigned int *)(text_poke_addr) +
++      patch_addr = (unsigned int *)(text_poke_addr) +
+                       ((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
+-      /*
+-       * We use __put_user_size so that we can handle faults while
+-       * writing to dest and return err to handle faults gracefully
+-       */
+-      __put_user_size(instr, dest, 4, err);
+-      if (!err)
+-              asm ("dcbst 0, %0; sync; icbi 0,%0; icbi 0,%1; sync; isync"
+-                      ::"r" (dest), "r"(addr));
++      __patch_instruction(addr, instr, patch_addr);
+       err = unmap_patch_area(text_poke_addr);
+       if (err)
+@@ -184,7 +184,7 @@ out:
+ int patch_instruction(unsigned int *addr, unsigned int instr)
+ {
+-      return __patch_instruction(addr, instr);
++      return raw_patch_instruction(addr, instr);
+ }
+ #endif /* CONFIG_STRICT_KERNEL_RWX */
diff --git a/queue-4.14/powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch b/queue-4.14/powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch
new file mode 100644 (file)
index 0000000..3c0d818
--- /dev/null
@@ -0,0 +1,79 @@
+From b45ba4a51cde29b2939365ef0c07ad34c8321789 Mon Sep 17 00:00:00 2001
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+Date: Mon, 1 Oct 2018 12:21:10 +0000
+Subject: powerpc/lib: fix book3s/32 boot failure due to code patching
+
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+
+commit b45ba4a51cde29b2939365ef0c07ad34c8321789 upstream.
+
+Commit 51c3c62b58b3 ("powerpc: Avoid code patching freed init
+sections") accesses 'init_mem_is_free' flag too early, before the
+kernel is relocated. This provokes early boot failure (before the
+console is active).
+
+As it is not necessary to do this verification that early, this
+patch moves the test into patch_instruction() instead of
+__patch_instruction().
+
+This modification also has the advantage of avoiding unnecessary
+remappings.
+
+Fixes: 51c3c62b58b3 ("powerpc: Avoid code patching freed init sections")
+Cc: stable@vger.kernel.org # 4.13+
+Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/lib/code-patching.c |   20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+--- a/arch/powerpc/lib/code-patching.c
++++ b/arch/powerpc/lib/code-patching.c
+@@ -28,12 +28,6 @@ static int __patch_instruction(unsigned
+ {
+       int err;
+-      /* Make sure we aren't patching a freed init section */
+-      if (init_mem_is_free && init_section_contains(exec_addr, 4)) {
+-              pr_debug("Skipping init section patching addr: 0x%px\n", exec_addr);
+-              return 0;
+-      }
+-
+       __put_user_size(instr, patch_addr, 4, err);
+       if (err)
+               return err;
+@@ -148,7 +142,7 @@ static inline int unmap_patch_area(unsig
+       return 0;
+ }
+-int patch_instruction(unsigned int *addr, unsigned int instr)
++static int do_patch_instruction(unsigned int *addr, unsigned int instr)
+ {
+       int err;
+       unsigned int *patch_addr = NULL;
+@@ -188,12 +182,22 @@ out:
+ }
+ #else /* !CONFIG_STRICT_KERNEL_RWX */
+-int patch_instruction(unsigned int *addr, unsigned int instr)
++static int do_patch_instruction(unsigned int *addr, unsigned int instr)
+ {
+       return raw_patch_instruction(addr, instr);
+ }
+ #endif /* CONFIG_STRICT_KERNEL_RWX */
++
++int patch_instruction(unsigned int *addr, unsigned int instr)
++{
++      /* Make sure we aren't patching a freed init section */
++      if (init_mem_is_free && init_section_contains(addr, 4)) {
++              pr_debug("Skipping init section patching addr: 0x%px\n", addr);
++              return 0;
++      }
++      return do_patch_instruction(addr, instr);
++}
+ NOKPROBE_SYMBOL(patch_instruction);
+ int patch_branch(unsigned int *addr, unsigned long target, int flags)
index 24accf0bd3904d31b5eeaaa5132a132c9462403f..43cf7b5ea971ff0dd5f5460558308ec9fa43215c 100644 (file)
@@ -30,3 +30,6 @@ cgroup-cpuset-remove-circular-dependency-deadlock.patch
 ath10k-fix-use-after-free-in-ath10k_wmi_cmd_send_nowait.patch
 ath10k-fix-kernel-panic-issue-during-pci-probe.patch
 nvme_fc-fix-ctrl-create-failures-racing-with-workq-items.patch
+powerpc-lib-code-patching-refactor-patch_instruction.patch
+powerpc-avoid-code-patching-freed-init-sections.patch
+powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch