From: Greg Kroah-Hartman Date: Thu, 11 Oct 2018 09:42:02 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v3.18.124~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6013bbe91a3ddf9a267742d9c76c81b29c693a0c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches 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 --- 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 index 00000000000..809bc8c82f6 --- /dev/null +++ b/queue-4.14/powerpc-avoid-code-patching-freed-init-sections.patch @@ -0,0 +1,87 @@ +From 51c3c62b58b357e8d35e4cc32f7b4ec907426fe3 Mon Sep 17 00:00:00 2001 +From: Michael Neuling +Date: Fri, 14 Sep 2018 11:14:11 +1000 +Subject: powerpc: Avoid code patching freed init sections + +From: Michael Neuling + +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 +Reviewed-by: Nicholas Piggin +Reviewed-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..95a7698c87b --- /dev/null +++ b/queue-4.14/powerpc-lib-code-patching-refactor-patch_instruction.patch @@ -0,0 +1,103 @@ +From 8cf4c05712f04a405f0dacebcca8f042b391694a Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Fri, 24 Nov 2017 08:31:07 +0100 +Subject: powerpc/lib/code-patching: refactor patch_instruction() + +From: Christophe Leroy + +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 +Acked-by: Balbir Singh +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + +-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 index 00000000000..3c0d8181f2d --- /dev/null +++ b/queue-4.14/powerpc-lib-fix-book3s-32-boot-failure-due-to-code-patching.patch @@ -0,0 +1,79 @@ +From b45ba4a51cde29b2939365ef0c07ad34c8321789 Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Mon, 1 Oct 2018 12:21:10 +0000 +Subject: powerpc/lib: fix book3s/32 boot failure due to code patching + +From: Christophe Leroy + +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 +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-4.14/series b/queue-4.14/series index 24accf0bd39..43cf7b5ea97 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -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