From: Greg Kroah-Hartman Date: Fri, 22 Nov 2019 09:58:07 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v5.3.13~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=55b2ce9301c8f7295cc3d128a478d89127ad1dde;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: arm64-uaccess-ensure-pan-is-re-enabled-after-unhandled-uaccess-fault.patch --- diff --git a/queue-4.9/arm64-uaccess-ensure-pan-is-re-enabled-after-unhandled-uaccess-fault.patch b/queue-4.9/arm64-uaccess-ensure-pan-is-re-enabled-after-unhandled-uaccess-fault.patch new file mode 100644 index 00000000000..55cd52dea79 --- /dev/null +++ b/queue-4.9/arm64-uaccess-ensure-pan-is-re-enabled-after-unhandled-uaccess-fault.patch @@ -0,0 +1,121 @@ +From 94bb804e1e6f0a9a77acf20d7c70ea141c6c821e Mon Sep 17 00:00:00 2001 +From: Pavel Tatashin +Date: Tue, 19 Nov 2019 17:10:06 -0500 +Subject: arm64: uaccess: Ensure PAN is re-enabled after unhandled uaccess fault + +From: Pavel Tatashin + +commit 94bb804e1e6f0a9a77acf20d7c70ea141c6c821e upstream. + +A number of our uaccess routines ('__arch_clear_user()' and +'__arch_copy_{in,from,to}_user()') fail to re-enable PAN if they +encounter an unhandled fault whilst accessing userspace. + +For CPUs implementing both hardware PAN and UAO, this bug has no effect +when both extensions are in use by the kernel. + +For CPUs implementing hardware PAN but not UAO, this means that a kernel +using hardware PAN may execute portions of code with PAN inadvertently +disabled, opening us up to potential security vulnerabilities that rely +on userspace access from within the kernel which would usually be +prevented by this mechanism. In other words, parts of the kernel run the +same way as they would on a CPU without PAN implemented/emulated at all. + +For CPUs not implementing hardware PAN and instead relying on software +emulation via 'CONFIG_ARM64_SW_TTBR0_PAN=y', the impact is unfortunately +much worse. Calling 'schedule()' with software PAN disabled means that +the next task will execute in the kernel using the page-table and ASID +of the previous process even after 'switch_mm()', since the actual +hardware switch is deferred until return to userspace. At this point, or +if there is a intermediate call to 'uaccess_enable()', the page-table +and ASID of the new process are installed. Sadly, due to the changes +introduced by KPTI, this is not an atomic operation and there is a very +small window (two instructions) where the CPU is configured with the +page-table of the old task and the ASID of the new task; a speculative +access in this state is disastrous because it would corrupt the TLB +entries for the new task with mappings from the previous address space. + +As Pavel explains: + + | I was able to reproduce memory corruption problem on Broadcom's SoC + | ARMv8-A like this: + | + | Enable software perf-events with PERF_SAMPLE_CALLCHAIN so userland's + | stack is accessed and copied. + | + | The test program performed the following on every CPU and forking + | many processes: + | + | unsigned long *map = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, + | MAP_SHARED | MAP_ANONYMOUS, -1, 0); + | map[0] = getpid(); + | sched_yield(); + | if (map[0] != getpid()) { + | fprintf(stderr, "Corruption detected!"); + | } + | munmap(map, PAGE_SIZE); + | + | From time to time I was getting map[0] to contain pid for a + | different process. + +Ensure that PAN is re-enabled when returning after an unhandled user +fault from our uaccess routines. + +Cc: Catalin Marinas +Reviewed-by: Mark Rutland +Tested-by: Mark Rutland +Cc: +Fixes: 338d4f49d6f7 ("arm64: kernel: Add support for Privileged Access Never") +Signed-off-by: Pavel Tatashin +[will: rewrote commit message] +[will: backport for 4.9.y stable kernels] +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm64/lib/clear_user.S | 2 ++ + arch/arm64/lib/copy_from_user.S | 2 ++ + arch/arm64/lib/copy_in_user.S | 2 ++ + arch/arm64/lib/copy_to_user.S | 2 ++ + 4 files changed, 8 insertions(+) + +--- a/arch/arm64/lib/clear_user.S ++++ b/arch/arm64/lib/clear_user.S +@@ -62,5 +62,7 @@ ENDPROC(__arch_clear_user) + .section .fixup,"ax" + .align 2 + 9: mov x0, x2 // return the original size ++ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ ++ CONFIG_ARM64_PAN) + ret + .previous +--- a/arch/arm64/lib/copy_from_user.S ++++ b/arch/arm64/lib/copy_from_user.S +@@ -80,5 +80,7 @@ ENDPROC(__arch_copy_from_user) + .section .fixup,"ax" + .align 2 + 9998: sub x0, end, dst // bytes not copied ++ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ ++ CONFIG_ARM64_PAN) + ret + .previous +--- a/arch/arm64/lib/copy_in_user.S ++++ b/arch/arm64/lib/copy_in_user.S +@@ -81,5 +81,7 @@ ENDPROC(__arch_copy_in_user) + .section .fixup,"ax" + .align 2 + 9998: sub x0, end, dst // bytes not copied ++ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ ++ CONFIG_ARM64_PAN) + ret + .previous +--- a/arch/arm64/lib/copy_to_user.S ++++ b/arch/arm64/lib/copy_to_user.S +@@ -79,5 +79,7 @@ ENDPROC(__arch_copy_to_user) + .section .fixup,"ax" + .align 2 + 9998: sub x0, end, dst // bytes not copied ++ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ ++ CONFIG_ARM64_PAN) + ret + .previous diff --git a/queue-4.9/series b/queue-4.9/series index 6c3dad9c61c..ab6a08e1982 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -219,3 +219,4 @@ misc-cxl-fix-possible-null-pointer-dereference.patch mac80211-minstrel-fix-cck-rate-group-streams-value.patch spi-rockchip-initialize-dma_slave_config-properly.patch arm-dts-omap5-fix-dual-role-mode-on-super-speed-port.patch +arm64-uaccess-ensure-pan-is-re-enabled-after-unhandled-uaccess-fault.patch