diff options
author | 2018-06-14 19:57:29 +0000 | |
---|---|---|
committer | 2018-06-14 19:57:29 +0000 | |
commit | f0f07b0b67d7c76ec94d2e5d5c83b1f57878cf69 (patch) | |
tree | 0b2090d9ea0c46dea6470ed1ae040af50d7fb7a7 | |
parent | Return from magic_test does not need to be copied because the caller (diff) | |
download | wireguard-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@
-rw-r--r-- | sys/arch/amd64/amd64/locore.S | 3 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/vector.S | 4 | ||||
-rw-r--r-- | sys/arch/amd64/include/frameasm.h | 29 |
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 ; \ |