untrusted comment: verify with openbsd-65-base.pub
RWSZaRmt1LEQT4o7CopjJE9AAIat2+ocE6NxihmnUPZ9K7Iuo4hWWaRptGIRQH9a54LXVpvRl+7U9WdTAE7D2g0Ee8pKKaRGwQA=

OpenBSD 6.5 errata 008, Aug 9, 2019:

Intel CPUs have another cross privilege side-channel attack (SWAPGS).

Apply by doing:
   signify -Vep /etc/signify/openbsd-65-base.pub -x 008_swapgs.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install a new kernel:
   KK=`sysctl -n kern.osversion | cut -d# -f1`
   cd /usr/src/sys/arch/`machine`/compile/$KK
   make obj
   make config
   make
   make install

Index: sys/arch/amd64/amd64/codepatch.c
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/amd64/codepatch.c,v
retrieving revision 1.7
diff -u -p -r1.7 codepatch.c
--- sys/arch/amd64/amd64/codepatch.c    13 Jul 2018 08:30:34 -0000      1.7
+++ sys/arch/amd64/amd64/codepatch.c    7 Aug 2019 20:43:49 -0000
@@ -39,6 +39,9 @@ extern struct codepatch codepatch_end;
extern char __cptext_start[];
extern char __cptext_end[];

+void   codepatch_control_flow(uint16_t _tag, void *_func, int _opcode,
+           const char *_op);
+
void
codepatch_fill_nop(void *caddr, uint16_t len)
{
@@ -149,28 +152,42 @@ codepatch_replace(uint16_t tag, void *co
       DBGPRINT("patched %d places", i);
}

-/* Patch with calls to func */
void
codepatch_call(uint16_t tag, void *func)
{
+       /* 0xe8 == call near */
+       codepatch_control_flow(tag, func, 0xe8, "call");
+}
+
+void
+codepatch_jmp(uint16_t tag, void *func)
+{
+       /* 0xe9 == jmp near */
+       codepatch_control_flow(tag, func, 0xe9, "jmp");
+}
+
+/* Patch with call or jump to func */
+void
+codepatch_control_flow(uint16_t tag, void *func, int opcode, const char *op)
+{
       struct codepatch *patch;
       unsigned char *rwaddr;
       int32_t offset;
       int i = 0;
       vaddr_t rwmap = 0;

-       DBGPRINT("patching tag %u with call %p", tag, func);
+       DBGPRINT("patching tag %u with %s %p", tag, op, func);

       for (patch = &codepatch_begin; patch < &codepatch_end; patch++) {
               if (patch->tag != tag)
                       continue;
               if (patch->len < 5)
-                       panic("%s: can't replace len %u with call at %#lx",
-                           __func__, patch->len, patch->addr);
+                       panic("%s: can't replace len %u with %s at %#lx",
+                           __func__, patch->len, op, patch->addr);

               offset = (vaddr_t)func - (patch->addr + 5);
               rwaddr = codepatch_maprw(&rwmap, patch->addr);
-               rwaddr[0] = 0xe8; /* call near */
+               rwaddr[0] = opcode;
               memcpy(rwaddr + 1, &offset, sizeof(offset));
               codepatch_fill_nop(rwaddr + 5, patch->len - 5);
               i++;
Index: sys/arch/amd64/amd64/cpu.c
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/amd64/cpu.c,v
retrieving revision 1.134.2.1
diff -u -p -r1.134.2.1 cpu.c
--- sys/arch/amd64/amd64/cpu.c  28 May 2019 14:23:21 -0000      1.134.2.1
+++ sys/arch/amd64/amd64/cpu.c  7 Aug 2019 20:43:49 -0000
@@ -173,20 +173,66 @@ void
replacemeltdown(void)
{
       static int replacedone = 0;
-       int s;
+       struct cpu_info *ci = &cpu_info_primary;
+       int swapgs_vuln = 0, s;

       if (replacedone)
               return;
       replacedone = 1;

+       if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
+               int family = ci->ci_family;
+               int model = ci->ci_model;
+
+               swapgs_vuln = 1;
+               if (family == 0x6 &&
+                   (model == 0x37 || model == 0x4a || model == 0x4c ||
+                    model == 0x4d || model == 0x5a || model == 0x5d ||
+                    model == 0x6e || model == 0x65 || model == 0x75)) {
+                       /* Silvermont, Airmont */
+                       swapgs_vuln = 0;
+               } else if (family == 0x6 && (model == 0x85 || model == 0x57)) {
+                       /* KnightsLanding */
+                       swapgs_vuln = 0;
+               }
+       }
+
       s = splhigh();
       if (!cpu_meltdown)
               codepatch_nop(CPTAG_MELTDOWN_NOP);
-       else if (pmap_use_pcid) {
-               extern long _pcid_set_reuse;
-               DPRINTF("%s: codepatching PCID use", __func__);
-               codepatch_replace(CPTAG_PCID_SET_REUSE, &_pcid_set_reuse,
-                   PCID_SET_REUSE_SIZE);
+       else {
+               extern long alltraps_kern_meltdown;
+
+               /* eliminate conditional branch in alltraps */
+               codepatch_jmp(CPTAG_MELTDOWN_ALLTRAPS, &alltraps_kern_meltdown);
+
+               /* enable reuse of PCID for U-K page tables */
+               if (pmap_use_pcid) {
+                       extern long _pcid_set_reuse;
+                       DPRINTF("%s: codepatching PCID use", __func__);
+                       codepatch_replace(CPTAG_PCID_SET_REUSE,
+                           &_pcid_set_reuse, PCID_SET_REUSE_SIZE);
+               }
+       }
+
+       /*
+        * CVE-2019-1125: if the CPU has SMAP and it's not vulnerable to
+        * Meltdown, then it's protected both from speculatively mis-skipping
+        * the swapgs during interrupts of userspace and from speculatively
+        * mis-taking a swapgs during interrupts while already in the kernel
+        * as the speculative path will fault from SMAP.  Warning: enabling
+        * WRGSBASE would break this 'protection'.
+        *
+        * Otherwise, if the CPU's swapgs can't be speculated over and it
+        * _is_ vulnerable to Meltdown then the %cr3 change will serialize
+        * user->kern transitions, but we still need to mitigate the
+        * already-in-kernel cases.
+        */
+       if (!cpu_meltdown && (ci->ci_feature_sefflags_ebx & SEFF0EBX_SMAP)) {
+               codepatch_nop(CPTAG_FENCE_SWAPGS_MIS_TAKEN);
+               codepatch_nop(CPTAG_FENCE_NO_SAFE_SMAP);
+       } else if (!swapgs_vuln && cpu_meltdown) {
+               codepatch_nop(CPTAG_FENCE_SWAPGS_MIS_TAKEN);
       }
       splx(s);
}
Index: sys/arch/amd64/amd64/locore.S
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/amd64/locore.S,v
retrieving revision 1.116.2.1
diff -u -p -r1.116.2.1 locore.S
--- sys/arch/amd64/amd64/locore.S       28 May 2019 14:23:21 -0000      1.116.2.1
+++ sys/arch/amd64/amd64/locore.S       7 Aug 2019 20:43:49 -0000
@@ -563,7 +563,7 @@ XUsyscall_meltdown:
        * (thank you, Intel), at which point we'll continue at the
        * "movq CPUVAR(KERN_RSP),%rax" after Xsyscall below.
        * In case the CPU speculates past the mov to cr3, we put a
-        * retpoline-style pause-jmp-to-pause loop.
+        * retpoline-style pause-lfence-jmp-to-pause loop.
        */
       swapgs
       movq    %rax,CPUVAR(SCRATCH)
Index: sys/arch/amd64/amd64/vector.S
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/amd64/vector.S,v
retrieving revision 1.79
diff -u -p -r1.79 vector.S
--- sys/arch/amd64/amd64/vector.S       20 Jan 2019 00:53:08 -0000      1.79
+++ sys/arch/amd64/amd64/vector.S       7 Aug 2019 20:43:49 -0000
@@ -141,6 +141,7 @@ calltrap_specstk:                   # special stack path
       .text
       .globl  INTRENTRY_LABEL(calltrap_specstk)
INTRENTRY_LABEL(calltrap_specstk):
+       lfence                          # block speculation through jz above
       cld
       SMAP_CLAC
       movq    %rsp,%rdi
@@ -183,6 +184,7 @@ IDTVEC(trap03)
       .text
       .global INTRENTRY_LABEL(trap03)
INTRENTRY_LABEL(trap03):
+       FENCE_NO_SAFE_SMAP
       INTR_ENTRY_KERN
       INTR_SAVE_MOST_GPRS_NO_ADJ
       sti
@@ -313,7 +315,8 @@ IDTVEC(trap0d)
.Lhandle_doreti:
       /* iretq faulted; resume in a stub that acts like we got a #GP */
       leaq    .Lhandle_doreti_resume(%rip),%rcx
-1:     movq    %rcx,24(%rsp)           /* over %r[cd]x and err to %rip */
+1:     lfence          /* block speculation through conditionals above */
+       movq    %rcx,24(%rsp)           /* over %r[cd]x and err to %rip */
       popq    %rcx
       popq    %rdx
       addq    $8,%rsp                 /* pop the err code */
@@ -388,12 +391,13 @@ KUTEXT_PAGE_START
        * the kernel page tables (thank you, Intel) will make us
        * continue at the "movq CPUVAR(KERN_RSP),%rax" after alltraps
        * below.  In case the CPU speculates past the mov to cr3,
-        * we put a retpoline-style pause-jmp-to-pause loop.
+        * we put a retpoline-style pause-lfence-jmp-to-pause loop.
        */
Xalltraps:
       swapgs
       movq    %rax,CPUVAR(SCRATCH)
       movq    CPUVAR(KERN_CR3),%rax
+       .byte   0x66, 0x90      /* space for FENCE_SWAPGS_MIS_TAKEN below */
       movq    %rax,%cr3
0:     pause
       lfence
@@ -403,9 +407,12 @@ KUTEXT_PAGE_END
KTEXT_PAGE_START
       .align  NBPG, 0xcc
GENTRY(alltraps)
+       CODEPATCH_START
       testb   $SEL_RPL,24(%rsp)
       je      alltraps_kern
       swapgs
+       CODEPATCH_END(CPTAG_MELTDOWN_ALLTRAPS)
+       FENCE_SWAPGS_MIS_TAKEN
       movq    %rax,CPUVAR(SCRATCH)
       .space  (0b - Xalltraps) - (. - alltraps), 0x90

@@ -428,9 +435,15 @@ END(alltraps)

/*
 * Traps from supervisor mode (kernel)
+ * If we're not mitigating Meltdown, then there's a conditional branch
+ * above and we may need a fence to mitigate CVE-2019-1225.  If we're
+ * doing Meltdown mitigation there's just an unconditional branch and
+ * can skip the fence.
 */
       _ALIGN_TRAPS
GENTRY(alltraps_kern)
+       FENCE_NO_SAFE_SMAP
+GENTRY(alltraps_kern_meltdown)
       INTR_ENTRY_KERN
       INTR_SAVE_MOST_GPRS_NO_ADJ
       sti
@@ -467,6 +480,7 @@ spl_lowered:
       .popsection
#endif /* DIAGNOSTIC */
END(alltraps_kern)
+END(alltraps_kern_meltdown)
KTEXT_PAGE_END


Index: sys/arch/amd64/include/codepatch.h
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/include/codepatch.h,v
retrieving revision 1.8.4.1
diff -u -p -r1.8.4.1 codepatch.h
--- sys/arch/amd64/include/codepatch.h  28 May 2019 14:23:21 -0000      1.8.4.1
+++ sys/arch/amd64/include/codepatch.h  7 Aug 2019 20:43:49 -0000
@@ -30,7 +30,8 @@ __cptext void codepatch_unmaprw(vaddr_t
__cptext void codepatch_fill_nop(void *caddr, uint16_t len);
__cptext void codepatch_nop(uint16_t tag);
__cptext void codepatch_replace(uint16_t tag, void *code, size_t len);
-__cptext void codepatch_call(uint16_t tag, void *func);
+__cptext void codepatch_call(uint16_t _tag, void *_func);
+__cptext void codepatch_jmp(uint16_t _tag, void *_func);
void codepatch_disable(void);

#endif /* !_LOCORE */
@@ -58,9 +59,12 @@ void codepatch_disable(void);
#define CPTAG_XRSTOR           4
#define CPTAG_XSAVE            5
#define CPTAG_MELTDOWN_NOP     6
-#define CPTAG_PCID_SET_REUSE   7
-#define CPTAG_MDS              8
-#define CPTAG_MDS_VMM          9
+#define CPTAG_MELTDOWN_ALLTRAPS        7
+#define CPTAG_PCID_SET_REUSE   8
+#define CPTAG_MDS              9
+#define CPTAG_MDS_VMM          10
+#define CPTAG_FENCE_SWAPGS_MIS_TAKEN   11
+#define CPTAG_FENCE_NO_SAFE_SMAP       12

/*
 * As stac/clac SMAP instructions are 3 bytes, we want the fastest
@@ -78,6 +82,17 @@ void codepatch_disable(void);
#define SMAP_CLAC      CODEPATCH_START                 ;\
                       SMAP_NOP                        ;\
                       CODEPATCH_END(CPTAG_CLAC)
+
+/* CVE-2019-1125: block speculation after swapgs */
+#define        FENCE_SWAPGS_MIS_TAKEN \
+       CODEPATCH_START                         ; \
+       lfence                                  ; \
+       CODEPATCH_END(CPTAG_FENCE_SWAPGS_MIS_TAKEN)
+/* block speculation when a correct SMAP impl would have been enough */
+#define        FENCE_NO_SAFE_SMAP \
+       CODEPATCH_START                         ; \
+       lfence                                  ; \
+       CODEPATCH_END(CPTAG_FENCE_NO_SAFE_SMAP)

#define        PCID_SET_REUSE_SIZE     12
#define        PCID_SET_REUSE_NOP                                      \
Index: sys/arch/amd64/include/frameasm.h
===================================================================
RCS file: /var/cvs/src/sys/arch/amd64/include/frameasm.h,v
retrieving revision 1.20
diff -u -p -r1.20 frameasm.h
--- sys/arch/amd64/include/frameasm.h   23 Jul 2018 17:54:04 -0000      1.20
+++ sys/arch/amd64/include/frameasm.h   7 Aug 2019 20:43:49 -0000
@@ -63,6 +63,7 @@
       testb   $SEL_RPL,24(%rsp)       ; \
       je      INTRENTRY_LABEL(label)  ; \
       swapgs                          ; \
+       FENCE_SWAPGS_MIS_TAKEN          ; \
       movq    %rax,CPUVAR(SCRATCH)    ; \
       CODEPATCH_START                 ; \
       movq    CPUVAR(KERN_CR3),%rax   ; \
@@ -73,6 +74,7 @@
       _ALIGN_TRAPS                    ; \
       .global INTRENTRY_LABEL(label)  ; \
INTRENTRY_LABEL(label):        /* from kernel */ \
+       FENCE_NO_SAFE_SMAP              ; \
       INTR_ENTRY_KERN                 ; \
       jmp     99f                     ; \
       _ALIGN_TRAPS                    ; \