summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2018-06-14 19:57:29 +0000
committerguenther <guenther@openbsd.org>2018-06-14 19:57:29 +0000
commitf0f07b0b67d7c76ec94d2e5d5c83b1f57878cf69 (patch)
tree0b2090d9ea0c46dea6470ed1ae040af50d7fb7a7 /sys
parentReturn from magic_test does not need to be copied because the caller (diff)
downloadwireguard-openbsd-f0f07b0b67d7c76ec94d2e5d5c83b1f57878cf69.tar.xz
wireguard-openbsd-f0f07b0b67d7c76ec94d2e5d5c83b1f57878cf69.zip
Clear the GPRs when entering the kernel from userspace so that
user-controlled values can't take part in speculative execution in the kernel down paths that end up "not taken" but that may cause user-visible effects (cache, etc). prodded by dragonflybsd commit 9474cbef7fcb61cd268019694d94db6a75af7dbe ok deraadt@ kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/locore.S3
-rw-r--r--sys/arch/amd64/amd64/vector.S4
-rw-r--r--sys/arch/amd64/include/frameasm.h29
3 files changed, 32 insertions, 4 deletions
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index f8a1b94b3fc..66b3321adbb 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.100 2018/06/09 16:51:23 guenther Exp $ */
+/* $OpenBSD: locore.S,v 1.101 2018/06/14 19:57:29 guenther Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -583,6 +583,7 @@ NENTRY(Xsyscall_untramp)
movq $(GSEL(GUCODE_SEL, SEL_UPL)), TF_CS(%rsp)
movq %rcx,TF_RIP(%rsp)
movq %rax,TF_ERR(%rsp) /* stash syscall # for SPL check */
+ INTR_CLEAR_GPRS
movq CPUVAR(CURPROC),%r14
movq %rsp,P_MD_REGS(%r14) # save pointer to frame
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
index 2a9ed1496ba..0573123e6b4 100644
--- a/sys/arch/amd64/amd64/vector.S
+++ b/sys/arch/amd64/amd64/vector.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: vector.S,v 1.65 2018/06/13 23:39:00 guenther Exp $ */
+/* $OpenBSD: vector.S,v 1.66 2018/06/14 19:57:29 guenther Exp $ */
/* $NetBSD: vector.S,v 1.5 2004/06/28 09:13:11 fvdl Exp $ */
/*
@@ -141,6 +141,7 @@ calltrap_specstk: # special stack path
.text
.globl INTRENTRY_LABEL(calltrap_specstk)
INTRENTRY_LABEL(calltrap_specstk):
+ INTR_CLEAR_GPRS
cld
SMAP_CLAC
movq %rsp,%rdi
@@ -418,6 +419,7 @@ END(alltraps_kern)
NENTRY(alltraps_user)
INTR_ENTRY_USER
INTR_SAVE_MOST_GPRS_NO_ADJ
+ INTR_CLEAR_GPRS
sti
cld
SMAP_CLAC
diff --git a/sys/arch/amd64/include/frameasm.h b/sys/arch/amd64/include/frameasm.h
index d0fdd6d30e1..8fffbfdce2b 100644
--- a/sys/arch/amd64/include/frameasm.h
+++ b/sys/arch/amd64/include/frameasm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frameasm.h,v 1.15 2018/06/10 15:02:50 guenther Exp $ */
+/* $OpenBSD: frameasm.h,v 1.16 2018/06/14 19:57:29 guenther Exp $ */
/* $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
#ifndef _AMD64_MACHINE_FRAMEASM_H
@@ -33,6 +33,30 @@
movq %rdx,TF_RDX(%rsp) ; \
movq %rax,TF_RAX(%rsp)
+/*
+ * We clear registers when coming from userspace to prevent
+ * user-controlled values from being availible for use in speculative
+ * execution in the kernel. %rsp and %rbp are the kernel values when
+ * this is used, so there are only 14 to clear. 32bit operations clear
+ * the register upper-halves automatically.
+ */
+#define INTR_CLEAR_GPRS \
+ xorl %eax,%eax ; \
+ movl %eax,%ebx ; \
+ movl %eax,%ecx ; \
+ movl %eax,%edx ; \
+ movl %eax,%esi ; \
+ movl %eax,%edi ; \
+ movl %eax,%r8d ; \
+ movl %eax,%r9d ; \
+ movl %eax,%r10d ; \
+ movl %eax,%r11d ; \
+ movl %eax,%r12d ; \
+ movl %eax,%r13d ; \
+ movl %eax,%r14d ; \
+ movl %eax,%r15d
+
+
/* For real interrupt code paths, where we can come from userspace */
#define INTRENTRY_LABEL(label) X##label##_untramp
#define INTRENTRY(label) \
@@ -52,7 +76,8 @@ INTRENTRY_LABEL(label): /* from kernel */ \
jmp 99f ; \
98: /* from userspace */ \
INTR_ENTRY_USER ; \
-99: INTR_SAVE_MOST_GPRS_NO_ADJ
+99: INTR_SAVE_MOST_GPRS_NO_ADJ ; \
+ INTR_CLEAR_GPRS
#define INTR_ENTRY_KERN \
subq $152,%rsp ; \