Module Name:    src
Committed By:   maxv
Date:           Sat May  2 11:37:17 UTC 2020

Modified Files:
        src/external/cddl/osnet/dev/fbt/x86: fbt_isa.c
        src/sys/arch/amd64/amd64: cpufunc.S
        src/sys/arch/i386/i386: cpufunc.S
        src/sys/arch/x86/include: cpufunc.h
        src/sys/arch/x86/x86: patch.c spectre.c svs.c

Log Message:
Modify the hotpatch mechanism, in order to make it much less ROP-friendly.

Currently x86_patch_window_open is a big problem, because it is a perfect
function to inject/modify executable code with ROP.

 - Remove x86_patch_window_open(), along with its x86_patch_window_close()
   counterpart.
 - Introduce a read-only link-set of hotpatch descriptor structures,
   which reference a maximum of two read-only hotpatch sources.
 - Modify x86_hotpatch() to open a window and call the new
   x86_hotpatch_apply() function in a hard-coded manner.
 - Modify x86_hotpatch() to take a name and a selector, and have
   x86_hotpatch_apply() resolve the descriptor from the name and the
   source from the selector, before hotpatching.
 - Move the error handling in a separate x86_hotpatch_cleanup() function,
   that gets called after we closed the window.

The resulting implementation is a bit complex and non-obvious. But it
gains the following properties: the code executed in the hotpatch window
is strictly hard-coded (no callback and no possibility to execute your own
code in the window) and the pointers this code accesses are strictly
read-only (no possibility to forge pointers to hotpatch an area that was
not designated as hotpatchable at compile-time, and no possibility to
choose what bytes to write other than the maximum of two read-only
templates that were designated as valid for the given destination at
compile-time).

With current CPUs this slightly improves a situation that is already
pretty bad by definition on x86. Assuming CET however, this change closes
a big hole and is kinda great.

The only ~problem there is, is that dtrace-fbt tries to hotpatch random
places with random bytes, and there is just no way to make it safe.
However dtrace is only in a module, that is rarely used and never compiled
into the kernel, so it's not a big problem; add a shitty & vulnerable
independent hotpatch window in it, and leave big XXXs. It looks like fbt
is going to collapse soon anyway.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c
cvs rdiff -u -r1.49 -r1.50 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.38 -r1.39 src/sys/arch/i386/i386/cpufunc.S
cvs rdiff -u -r1.38 -r1.39 src/sys/arch/x86/include/cpufunc.h
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/x86/x86/patch.c
cvs rdiff -u -r1.34 -r1.35 src/sys/arch/x86/x86/spectre.c \
    src/sys/arch/x86/x86/svs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c
diff -u src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c:1.2 src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c:1.3
--- src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c:1.2	Wed Nov 13 10:13:41 2019
+++ src/external/cddl/osnet/dev/fbt/x86/fbt_isa.c	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: fbt_isa.c,v 1.2 2019/11/13 10:13:41 maxv Exp $	*/
+/*	$NetBSD: fbt_isa.c,v 1.3 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*
  * CDDL HEADER START
@@ -172,18 +172,40 @@ fbt_patch_tracepoint(fbt_probe_t *fbt, f
 #endif
 
 #ifdef __NetBSD__
+/*
+ * XXX XXX XXX This is absolutely unsafe, the mere existence of this code is a
+ * problem, because this function is too easily ROP-able. But this gets
+ * compiled as a module and never in the kernel, so we are fine "by default".
+ * XXX Add a #warning if it gets compiled in the kernel?
+ */
 void
 fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
 {
 	u_long psl, cr0;
 
-	x86_patch_window_open(&psl, &cr0);
+	/* Disable interrupts. */
+	psl = x86_read_psl();
+	x86_disable_intr();
+
+	/* Disable write protection in supervisor mode. */
+	cr0 = rcr0();
+	lcr0(cr0 & ~CR0_WP);
 
+	/* XXX XXX XXX Shouldn't rely on caller-provided dst! */
+	/* XXX XXX XXX Shouldn't rely on caller-provided val! */
 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
 		*fbt->fbtp_patchpoint = val;
 	}
 
-	x86_patch_window_close(psl, cr0);
+	/* Write back and invalidate cache, flush pipelines. */
+	wbinvd();
+	x86_flush();
+
+	/* Re-enable write protection. */
+	lcr0(cr0);
+
+	/* Restore the PSL, potentially re-enabling interrupts. */
+	x86_write_psl(psl);
 }
 #endif
 

Index: src/sys/arch/amd64/amd64/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.49 src/sys/arch/amd64/amd64/cpufunc.S:1.50
--- src/sys/arch/amd64/amd64/cpufunc.S:1.49	Thu Nov 21 19:23:58 2019
+++ src/sys/arch/amd64/amd64/cpufunc.S	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.49 2019/11/21 19:23:58 ad Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.50 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -380,3 +380,41 @@ ENTRY(outl)
 	outl	%eax, %dx
 	ret
 END(outl)
+
+/*
+ * %rdi = name
+ * %rsi = sel
+ */
+ENTRY(x86_hotpatch)
+	/* save RFLAGS, and disable intrs */
+	pushfq
+	cli
+
+	/* save CR0, and disable WP */
+	movq	%cr0,%rcx
+	pushq	%rcx
+	andq	$~CR0_WP,%rcx
+	movq	%rcx,%cr0
+
+	callq	_C_LABEL(x86_hotpatch_apply)
+
+	/* write back and invalidate cache */
+	wbinvd
+
+	/* restore CR0 */
+	popq	%rcx
+	movq	%rcx,%cr0
+
+	/* flush instruction pipeline */
+	pushq	%rax
+	callq	x86_flush
+	popq	%rax
+
+	/* clean up */
+	movq	%rax,%rdi
+	callq	_C_LABEL(x86_hotpatch_cleanup)
+
+	/* restore RFLAGS */
+	popfq
+	ret
+END(x86_hotpatch)

Index: src/sys/arch/i386/i386/cpufunc.S
diff -u src/sys/arch/i386/i386/cpufunc.S:1.38 src/sys/arch/i386/i386/cpufunc.S:1.39
--- src/sys/arch/i386/i386/cpufunc.S:1.38	Thu Nov 21 19:24:00 2019
+++ src/sys/arch/i386/i386/cpufunc.S	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.38 2019/11/21 19:24:00 ad Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.39 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 #include <sys/errno.h>
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.38 2019/11/21 19:24:00 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.39 2020/05/02 11:37:17 maxv Exp $");
 
 #include "opt_xen.h"
 
@@ -274,3 +274,41 @@ ENTRY(outl)
 	outl	%eax, %dx
 	ret
 END(outl)
+
+ENTRY(x86_hotpatch)
+	/* save EFLAGS, and disable intrs */
+	pushfl
+	cli
+
+	/* save CR0, and disable WP */
+	movl	%cr0,%ecx
+	pushl	%ecx
+	andl	$~CR0_WP,%ecx
+	movl	%ecx,%cr0
+
+	pushl	4*4(%esp) /* arg2 */
+	pushl	4*4(%esp) /* arg1 */
+	call	_C_LABEL(x86_hotpatch_apply)
+	addl	$2*4,%esp
+
+	/* write back and invalidate cache */
+	wbinvd
+
+	/* restore CR0 */
+	popl	%ecx
+	movl	%ecx,%cr0
+
+	/* flush instruction pipeline */
+	pushl	%eax
+	call	x86_flush
+	popl	%eax
+
+	/* clean up */
+	pushl	%eax
+	call	_C_LABEL(x86_hotpatch_cleanup)
+	addl	$4,%esp
+
+	/* restore RFLAGS */
+	popfl
+	ret
+END(x86_hotpatch)

Index: src/sys/arch/x86/include/cpufunc.h
diff -u src/sys/arch/x86/include/cpufunc.h:1.38 src/sys/arch/x86/include/cpufunc.h:1.39
--- src/sys/arch/x86/include/cpufunc.h:1.38	Sat Apr 25 15:26:18 2020
+++ src/sys/arch/x86/include/cpufunc.h	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.h,v 1.38 2020/04/25 15:26:18 bouyer Exp $	*/
+/*	$NetBSD: cpufunc.h,v 1.39 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2007, 2019 The NetBSD Foundation, Inc.
@@ -104,9 +104,18 @@ rdtsc(void)
 }
 
 #ifndef XENPV
-void	x86_hotpatch(uint32_t, const uint8_t *, size_t);
-void	x86_patch_window_open(u_long *, u_long *);
-void	x86_patch_window_close(u_long, u_long);
+struct x86_hotpatch_source {
+	uint8_t *saddr;
+	uint8_t *eaddr;
+};
+
+struct x86_hotpatch_descriptor {
+	uint8_t name;
+	uint8_t nsrc;
+	const struct x86_hotpatch_source *srcs[];
+};
+
+void	x86_hotpatch(uint8_t, uint8_t);
 void	x86_patch(bool);
 #endif
 

Index: src/sys/arch/x86/x86/patch.c
diff -u src/sys/arch/x86/x86/patch.c:1.46 src/sys/arch/x86/x86/patch.c:1.47
--- src/sys/arch/x86/x86/patch.c:1.46	Fri May  1 09:40:47 2020
+++ src/sys/arch/x86/x86/patch.c	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: patch.c,v 1.46 2020/05/01 09:40:47 maxv Exp $	*/
+/*	$NetBSD: patch.c,v 1.47 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.46 2020/05/01 09:40:47 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.47 2020/05/02 11:37:17 maxv Exp $");
 
 #include "opt_lockdebug.h"
 #ifdef i386
@@ -52,12 +52,137 @@ __KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.
 #include <x86/cpuvar.h>
 #include <x86/cputypes.h>
 
-struct hotpatch {
+__link_set_decl(x86_hotpatch_descriptors, struct x86_hotpatch_descriptor);
+
+struct x86_hotpatch_destination {
 	uint8_t name;
 	uint8_t size;
 	void *addr;
 } __packed;
 
+/* -------------------------------------------------------------------------- */
+
+/* CLAC instruction, part of SMAP. */
+extern uint8_t hp_clac, hp_clac_end;
+static const struct x86_hotpatch_source hp_clac_source = {
+	.saddr = &hp_clac,
+	.eaddr = &hp_clac_end
+};
+static const struct x86_hotpatch_descriptor hp_clac_desc = {
+	.name = HP_NAME_CLAC,
+	.nsrc = 1,
+	.srcs = { &hp_clac_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_clac_desc);
+
+/* STAC instruction, part of SMAP. */
+extern uint8_t hp_stac, hp_stac_end;
+static const struct x86_hotpatch_source hp_stac_source = {
+	.saddr = &hp_stac,
+	.eaddr = &hp_stac_end
+};
+static const struct x86_hotpatch_descriptor hp_stac_desc = {
+	.name = HP_NAME_STAC,
+	.nsrc = 1,
+	.srcs = { &hp_stac_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_stac_desc);
+
+/* Errata on certain AMD CPUs. */
+extern uint8_t hp_retfence, hp_retfence_end;
+static const struct x86_hotpatch_source hp_retfence_source = {
+	.saddr = &hp_retfence,
+	.eaddr = &hp_retfence_end
+};
+static const struct x86_hotpatch_descriptor hp_retfence_desc = {
+	.name = HP_NAME_RETFENCE,
+	.nsrc = 1,
+	.srcs = { &hp_retfence_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_retfence_desc);
+
+/* No lock when on a single processor. */
+extern uint8_t hp_nolock, hp_nolock_end;
+static const struct x86_hotpatch_source hp_nolock_source = {
+	.saddr = &hp_nolock,
+	.eaddr = &hp_nolock_end
+};
+static const struct x86_hotpatch_descriptor hp_nolock_desc = {
+	.name = HP_NAME_NOLOCK,
+	.nsrc = 1,
+	.srcs = { &hp_nolock_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_nolock_desc);
+
+/* Use LFENCE if available, part of SSE2. */
+extern uint8_t sse2_lfence, sse2_lfence_end;
+static const struct x86_hotpatch_source hp_sse2_lfence_source = {
+	.saddr = &sse2_lfence,
+	.eaddr = &sse2_lfence_end
+};
+static const struct x86_hotpatch_descriptor hp_sse2_lfence_desc = {
+	.name = HP_NAME_SSE2_LFENCE,
+	.nsrc = 1,
+	.srcs = { &hp_sse2_lfence_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_sse2_lfence_desc);
+
+/* Use MFENCE if available, part of SSE2. */
+extern uint8_t sse2_mfence, sse2_mfence_end;
+static const struct x86_hotpatch_source hp_sse2_mfence_source = {
+	.saddr = &sse2_mfence,
+	.eaddr = &sse2_mfence_end
+};
+static const struct x86_hotpatch_descriptor hp_sse2_mfence_desc = {
+	.name = HP_NAME_SSE2_MFENCE,
+	.nsrc = 1,
+	.srcs = { &hp_sse2_mfence_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_sse2_mfence_desc);
+
+#ifdef i386
+/* CAS_64. */
+extern uint8_t _atomic_cas_cx8, _atomic_cas_cx8_end;
+static const struct x86_hotpatch_source hp_cas_cx8_source = {
+	.saddr = &_atomic_cas_cx8,
+	.eaddr = &_atomic_cas_cx8_end
+};
+static const struct x86_hotpatch_descriptor hp_cas_cx8_desc = {
+	.name = HP_NAME_CAS_64,
+	.nsrc = 1,
+	.srcs = { &hp_cas_cx8_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_cas_cx8_desc);
+
+/* SPLLOWER. */
+extern uint8_t cx8_spllower, cx8_spllower_end;
+static const struct x86_hotpatch_source hp_cx8_spllower_source = {
+	.saddr = &cx8_spllower,
+	.eaddr = &cx8_spllower_end
+};
+static const struct x86_hotpatch_descriptor hp_cx8_spllower_desc = {
+	.name = HP_NAME_SPLLOWER,
+	.nsrc = 1,
+	.srcs = { &hp_cx8_spllower_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_cx8_spllower_desc);
+
+/* MUTEX_EXIT. */
+extern uint8_t i686_mutex_spin_exit, i686_mutex_spin_exit_end;
+static const struct x86_hotpatch_source hp_i686_mutex_spin_exit_source = {
+	.saddr = &i686_mutex_spin_exit,
+	.eaddr = &i686_mutex_spin_exit_end
+};
+static const struct x86_hotpatch_descriptor hp_i686_mutex_spin_exit_desc = {
+	.name = HP_NAME_MUTEX_EXIT,
+	.nsrc = 1,
+	.srcs = { &hp_i686_mutex_spin_exit_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_i686_mutex_spin_exit_desc);
+#endif
+
+/* -------------------------------------------------------------------------- */
+
 static inline void __unused
 patchbytes(void *addr, const uint8_t *bytes, size_t size)
 {
@@ -69,63 +194,86 @@ patchbytes(void *addr, const uint8_t *by
 	}
 }
 
-/* The local variables have unknown alignment to UBSan */
-__noubsan
-void
-x86_hotpatch(uint32_t name, const uint8_t *bytes, size_t size)
+/*
+ * Rules: each pointer accessed in this function MUST be read-only.
+ *
+ * Called from ASM only, prototype not public.
+ */
+int x86_hotpatch_apply(uint8_t, uint8_t);
+int
+__noubsan /* the local variables have unknown alignment to UBSan */
+x86_hotpatch_apply(uint8_t name, uint8_t sel)
 {
+	struct x86_hotpatch_descriptor * const *iter;
+	const struct x86_hotpatch_descriptor *desc;
+	const struct x86_hotpatch_source *src;
+	const struct x86_hotpatch_destination *hps, *hpe, *hp;
 	extern char __rodata_hotpatch_start;
 	extern char __rodata_hotpatch_end;
-	struct hotpatch *hps, *hpe, *hp;
+	const uint8_t *bytes;
+	bool found = false;
+	size_t size;
+
+	/*
+	 * Find the descriptor, and perform some sanity checks.
+	 */
+	__link_set_foreach(iter, x86_hotpatch_descriptors) {
+		desc = *iter;
+		if (desc->name == name) {
+			found = true;
+			break;
+		}
+	}
+	if (!found)
+		return -1;
+	if (desc->nsrc > 2)
+		return -1;
+	if (sel >= desc->nsrc)
+		return -1;
 
-	hps = (struct hotpatch *)&__rodata_hotpatch_start;
-	hpe = (struct hotpatch *)&__rodata_hotpatch_end;
+	/*
+	 * Get the hotpatch source.
+	 */
+	src = desc->srcs[sel];
+	bytes = src->saddr;
+	size = (size_t)src->eaddr - (size_t)src->saddr;
 
+	/*
+	 * Apply the hotpatch on each registered destination.
+	 */
+	hps = (struct x86_hotpatch_destination *)&__rodata_hotpatch_start;
+	hpe = (struct x86_hotpatch_destination *)&__rodata_hotpatch_end;
 	for (hp = hps; hp < hpe; hp++) {
 		if (hp->name != name) {
 			continue;
 		}
 		if (hp->size != size) {
-			panic("x86_hotpatch: incorrect size");
+			return -1;
 		}
 		patchbytes(hp->addr, bytes, size);
 	}
-}
 
-void
-x86_patch_window_open(u_long *psl, u_long *cr0)
-{
-	/* Disable interrupts. */
-	*psl = x86_read_psl();
-	x86_disable_intr();
-
-	/* Disable write protection in supervisor mode. */
-	*cr0 = rcr0();
-	lcr0(*cr0 & ~CR0_WP);
+	return 0;
 }
 
+/*
+ * Interrupts disabled here. Called from ASM only, prototype not public.
+ */
+void x86_hotpatch_cleanup(int);
 void
-x86_patch_window_close(u_long psl, u_long cr0)
+x86_hotpatch_cleanup(int retval)
 {
-	/* Write back and invalidate cache, flush pipelines. */
-	wbinvd();
-	x86_flush();
-
-	/* Re-enable write protection. */
-	lcr0(cr0);
-
-	/* Restore the PSL, potentially re-enabling interrupts. */
-	x86_write_psl(psl);
+	if (retval != 0) {
+		panic("x86_hotpatch_apply failed");
+	}
 }
 
+/* -------------------------------------------------------------------------- */
+
 void
 x86_patch(bool early)
 {
 	static bool first, second;
-	uint8_t *bytes;
-	size_t size;
-	u_long psl;
-	u_long cr0;
 
 	if (early) {
 		if (first)
@@ -137,18 +285,12 @@ x86_patch(bool early)
 		second = true;
 	}
 
-	x86_patch_window_open(&psl, &cr0);
-
 	if (!early && ncpu == 1) {
 #ifndef LOCKDEBUG
 		/*
 		 * Uniprocessor: kill LOCK prefixes.
 		 */
-		extern uint8_t hp_nolock, hp_nolock_end;
-
-		bytes = &hp_nolock;
-		size = (size_t)&hp_nolock_end - (size_t)&hp_nolock;
-		x86_hotpatch(HP_NAME_NOLOCK, bytes, size);
+		x86_hotpatch(HP_NAME_NOLOCK, 0);
 #endif
 	}
 
@@ -159,16 +301,8 @@ x86_patch(bool early)
 		 * ordinary non-temporal stores are always issued in
 		 * program order to main memory and to other CPUs.
 		 */
-		extern uint8_t sse2_lfence, sse2_lfence_end;
-		extern uint8_t sse2_mfence, sse2_mfence_end;
-
-		bytes = &sse2_lfence;
-		size = (size_t)&sse2_lfence_end - (size_t)&sse2_lfence;
-		x86_hotpatch(HP_NAME_SSE2_LFENCE, bytes, size);
-
-		bytes = &sse2_mfence;
-		size = (size_t)&sse2_mfence_end - (size_t)&sse2_mfence;
-		x86_hotpatch(HP_NAME_SSE2_MFENCE, bytes, size);
+		x86_hotpatch(HP_NAME_SSE2_LFENCE, 0);
+		x86_hotpatch(HP_NAME_SSE2_MFENCE, 0);
 	}
 
 #ifdef i386
@@ -177,27 +311,15 @@ x86_patch(bool early)
 	 * may be gone.
 	 */
 	if ((cpu_feature[0] & CPUID_CX8) != 0) {
-		extern uint8_t _atomic_cas_cx8, _atomic_cas_cx8_end;
-
-		bytes = &_atomic_cas_cx8;
-		size = (size_t)&_atomic_cas_cx8_end - (size_t)&_atomic_cas_cx8;
-		x86_hotpatch(HP_NAME_CAS_64, bytes, size);
+		x86_hotpatch(HP_NAME_CAS_64, 0);
 	}
 
 #if !defined(SPLDEBUG)
 	if (!early && (cpu_feature[0] & CPUID_CX8) != 0) {
 		/* Faster splx(), mutex_spin_exit(). */
-		extern uint8_t cx8_spllower, cx8_spllower_end;
-		extern uint8_t i686_mutex_spin_exit, i686_mutex_spin_exit_end;
-
-		bytes = &cx8_spllower;
-		size = (size_t)&cx8_spllower_end - (size_t)&cx8_spllower;
-		x86_hotpatch(HP_NAME_SPLLOWER, bytes, size);
-
+		x86_hotpatch(HP_NAME_SPLLOWER, 0);
 #if !defined(LOCKDEBUG)
-		bytes = &i686_mutex_spin_exit;
-		size = (size_t)&i686_mutex_spin_exit_end - (size_t)&i686_mutex_spin_exit;
-		x86_hotpatch(HP_NAME_MUTEX_EXIT, bytes, size);
+		x86_hotpatch(HP_NAME_MUTEX_EXIT, 0);
 #endif
 	}
 #endif /* !SPLDEBUG */
@@ -212,11 +334,7 @@ x86_patch(bool early)
 	    (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xe ||
 	    (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xf &&
 	    CPUID_TO_EXTMODEL(cpu_info_primary.ci_signature) < 0x4))) {
-		extern uint8_t hp_retfence, hp_retfence_end;
-
-		bytes = &hp_retfence;
-		size = (size_t)&hp_retfence_end - (size_t)&hp_retfence;
-		x86_hotpatch(HP_NAME_RETFENCE, bytes, size);
+		x86_hotpatch(HP_NAME_RETFENCE, 0);
 	}
 
 	/*
@@ -224,19 +342,9 @@ x86_patch(bool early)
 	 * instructions.
 	 */
 	if (!early && cpu_feature[5] & CPUID_SEF_SMAP) {
-		extern uint8_t hp_clac, hp_clac_end;
-		extern uint8_t hp_stac, hp_stac_end;
-
 		KASSERT(rcr4() & CR4_SMAP);
 
-		bytes = &hp_clac;
-		size = (size_t)&hp_clac_end - (size_t)&hp_clac;
-		x86_hotpatch(HP_NAME_CLAC, bytes, size);
-
-		bytes = &hp_stac;
-		size = (size_t)&hp_stac_end - (size_t)&hp_stac;
-		x86_hotpatch(HP_NAME_STAC, bytes, size);
+		x86_hotpatch(HP_NAME_CLAC, 0);
+		x86_hotpatch(HP_NAME_STAC, 0);
 	}
-
-	x86_patch_window_close(psl, cr0);
 }

Index: src/sys/arch/x86/x86/spectre.c
diff -u src/sys/arch/x86/x86/spectre.c:1.34 src/sys/arch/x86/x86/spectre.c:1.35
--- src/sys/arch/x86/x86/spectre.c:1.34	Fri Feb 21 00:26:22 2020
+++ src/sys/arch/x86/x86/spectre.c	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: spectre.c,v 1.34 2020/02/21 00:26:22 joerg Exp $	*/
+/*	$NetBSD: spectre.c,v 1.35 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018-2019 NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.34 2020/02/21 00:26:22 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.35 2020/05/02 11:37:17 maxv Exp $");
 
 #include "opt_spectre.h"
 
@@ -169,48 +169,54 @@ static volatile unsigned long ibrs_cpu_b
 static volatile unsigned long ibrs_cpu_barrier2 __cacheline_aligned;
 
 #ifdef __x86_64__
+/* IBRS_ENTER. */
+extern uint8_t noibrs_enter, noibrs_enter_end;
+extern uint8_t ibrs_enter, ibrs_enter_end;
+static const struct x86_hotpatch_source hp_noibrs_enter_source = {
+	.saddr = &noibrs_enter,
+	.eaddr = &noibrs_enter_end
+};
+static const struct x86_hotpatch_source hp_ibrs_enter_source = {
+	.saddr = &ibrs_enter,
+	.eaddr = &ibrs_enter_end
+};
+static const struct x86_hotpatch_descriptor hp_ibrs_enter_desc = {
+	.name = HP_NAME_IBRS_ENTER,
+	.nsrc = 2,
+	.srcs = { &hp_noibrs_enter_source, &hp_ibrs_enter_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_ibrs_enter_desc);
+
+/* IBRS_LEAVE. */
+extern uint8_t noibrs_leave, noibrs_leave_end;
+extern uint8_t ibrs_leave, ibrs_leave_end;
+static const struct x86_hotpatch_source hp_noibrs_leave_source = {
+	.saddr = &noibrs_leave,
+	.eaddr = &noibrs_leave_end
+};
+static const struct x86_hotpatch_source hp_ibrs_leave_source = {
+	.saddr = &ibrs_leave,
+	.eaddr = &ibrs_leave_end
+};
+static const struct x86_hotpatch_descriptor hp_ibrs_leave_desc = {
+	.name = HP_NAME_IBRS_LEAVE,
+	.nsrc = 2,
+	.srcs = { &hp_noibrs_leave_source, &hp_ibrs_leave_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_ibrs_leave_desc);
+
 static void
 ibrs_disable_hotpatch(void)
 {
-	extern uint8_t noibrs_enter, noibrs_enter_end;
-	extern uint8_t noibrs_leave, noibrs_leave_end;
-	u_long psl, cr0;
-	uint8_t *bytes;
-	size_t size;
-
-	x86_patch_window_open(&psl, &cr0);
-
-	bytes = &noibrs_enter;
-	size = (size_t)&noibrs_enter_end - (size_t)&noibrs_enter;
-	x86_hotpatch(HP_NAME_IBRS_ENTER, bytes, size);
-
-	bytes = &noibrs_leave;
-	size = (size_t)&noibrs_leave_end - (size_t)&noibrs_leave;
-	x86_hotpatch(HP_NAME_IBRS_LEAVE, bytes, size);
-
-	x86_patch_window_close(psl, cr0);
+	x86_hotpatch(HP_NAME_IBRS_ENTER, /* noibrs */ 0);
+	x86_hotpatch(HP_NAME_IBRS_LEAVE, /* noibrs */ 0);
 }
 
 static void
 ibrs_enable_hotpatch(void)
 {
-	extern uint8_t ibrs_enter, ibrs_enter_end;
-	extern uint8_t ibrs_leave, ibrs_leave_end;
-	u_long psl, cr0;
-	uint8_t *bytes;
-	size_t size;
-
-	x86_patch_window_open(&psl, &cr0);
-
-	bytes = &ibrs_enter;
-	size = (size_t)&ibrs_enter_end - (size_t)&ibrs_enter;
-	x86_hotpatch(HP_NAME_IBRS_ENTER, bytes, size);
-
-	bytes = &ibrs_leave;
-	size = (size_t)&ibrs_leave_end - (size_t)&ibrs_leave;
-	x86_hotpatch(HP_NAME_IBRS_LEAVE, bytes, size);
-
-	x86_patch_window_close(psl, cr0);
+	x86_hotpatch(HP_NAME_IBRS_ENTER, /* ibrs */ 1);
+	x86_hotpatch(HP_NAME_IBRS_LEAVE, /* ibrs */ 1);
 }
 #else
 /* IBRS not supported on i386 */
@@ -564,38 +570,34 @@ static volatile unsigned long mds_cpu_ba
 static volatile unsigned long mds_cpu_barrier2 __cacheline_aligned;
 
 #ifdef __x86_64__
+/* MDS_LEAVE. */
+extern uint8_t nomds_leave, nomds_leave_end;
+extern uint8_t mds_leave, mds_leave_end;
+static const struct x86_hotpatch_source hp_nomds_leave_source = {
+	.saddr = &nomds_leave,
+	.eaddr = &nomds_leave_end
+};
+static const struct x86_hotpatch_source hp_mds_leave_source = {
+	.saddr = &mds_leave,
+	.eaddr = &mds_leave_end
+};
+static const struct x86_hotpatch_descriptor hp_mds_leave_desc = {
+	.name = HP_NAME_MDS_LEAVE,
+	.nsrc = 2,
+	.srcs = { &hp_nomds_leave_source, &hp_mds_leave_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_mds_leave_desc);
+
 static void
 mds_disable_hotpatch(void)
 {
-	extern uint8_t nomds_leave, nomds_leave_end;
-	u_long psl, cr0;
-	uint8_t *bytes;
-	size_t size;
-
-	x86_patch_window_open(&psl, &cr0);
-
-	bytes = &nomds_leave;
-	size = (size_t)&nomds_leave_end - (size_t)&nomds_leave;
-	x86_hotpatch(HP_NAME_MDS_LEAVE, bytes, size);
-
-	x86_patch_window_close(psl, cr0);
+	x86_hotpatch(HP_NAME_MDS_LEAVE, /* nomds */ 0);
 }
 
 static void
 mds_enable_hotpatch(void)
 {
-	extern uint8_t mds_leave, mds_leave_end;
-	u_long psl, cr0;
-	uint8_t *bytes;
-	size_t size;
-
-	x86_patch_window_open(&psl, &cr0);
-
-	bytes = &mds_leave;
-	size = (size_t)&mds_leave_end - (size_t)&mds_leave;
-	x86_hotpatch(HP_NAME_MDS_LEAVE, bytes, size);
-
-	x86_patch_window_close(psl, cr0);
+	x86_hotpatch(HP_NAME_MDS_LEAVE, /* mds */ 1);
 }
 #else
 /* MDS not supported on i386 */
Index: src/sys/arch/x86/x86/svs.c
diff -u src/sys/arch/x86/x86/svs.c:1.34 src/sys/arch/x86/x86/svs.c:1.35
--- src/sys/arch/x86/x86/svs.c:1.34	Sat Apr 25 15:26:18 2020
+++ src/sys/arch/x86/x86/svs.c	Sat May  2 11:37:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: svs.c,v 1.34 2020/04/25 15:26:18 bouyer Exp $	*/
+/*	$NetBSD: svs.c,v 1.35 2020/05/02 11:37:17 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.34 2020/04/25 15:26:18 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.35 2020/05/02 11:37:17 maxv Exp $");
 
 #include "opt_svs.h"
 #include "opt_user_ldt.h"
@@ -226,6 +226,88 @@ __KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.34
  *    makes sense on GENERIC_KASLR kernels.
  */
 
+/* -------------------------------------------------------------------------- */
+
+/* SVS_ENTER. */
+extern uint8_t svs_enter, svs_enter_end;
+static const struct x86_hotpatch_source hp_svs_enter_source = {
+	.saddr = &svs_enter,
+	.eaddr = &svs_enter_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_enter_desc = {
+	.name = HP_NAME_SVS_ENTER,
+	.nsrc = 1,
+	.srcs = { &hp_svs_enter_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_enter_desc);
+
+/* SVS_ENTER_ALT. */
+extern uint8_t svs_enter_altstack, svs_enter_altstack_end;
+static const struct x86_hotpatch_source hp_svs_enter_altstack_source = {
+	.saddr = &svs_enter_altstack,
+	.eaddr = &svs_enter_altstack_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_enter_altstack_desc = {
+	.name = HP_NAME_SVS_ENTER_ALT,
+	.nsrc = 1,
+	.srcs = { &hp_svs_enter_altstack_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_enter_altstack_desc);
+
+/* SVS_ENTER_NMI. */
+extern uint8_t svs_enter_nmi, svs_enter_nmi_end;
+static const struct x86_hotpatch_source hp_svs_enter_nmi_source = {
+	.saddr = &svs_enter_nmi,
+	.eaddr = &svs_enter_nmi_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_enter_nmi_desc = {
+	.name = HP_NAME_SVS_ENTER_NMI,
+	.nsrc = 1,
+	.srcs = { &hp_svs_enter_nmi_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_enter_nmi_desc);
+
+/* SVS_LEAVE. */
+extern uint8_t svs_leave, svs_leave_end;
+static const struct x86_hotpatch_source hp_svs_leave_source = {
+	.saddr = &svs_leave,
+	.eaddr = &svs_leave_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_leave_desc = {
+	.name = HP_NAME_SVS_LEAVE,
+	.nsrc = 1,
+	.srcs = { &hp_svs_leave_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_leave_desc);
+
+/* SVS_LEAVE_ALT. */
+extern uint8_t svs_leave_altstack, svs_leave_altstack_end;
+static const struct x86_hotpatch_source hp_svs_leave_altstack_source = {
+	.saddr = &svs_leave_altstack,
+	.eaddr = &svs_leave_altstack_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_leave_altstack_desc = {
+	.name = HP_NAME_SVS_LEAVE_ALT,
+	.nsrc = 1,
+	.srcs = { &hp_svs_leave_altstack_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_leave_altstack_desc);
+
+/* SVS_LEAVE_NMI. */
+extern uint8_t svs_leave_nmi, svs_leave_nmi_end;
+static const struct x86_hotpatch_source hp_svs_leave_nmi_source = {
+	.saddr = &svs_leave_nmi,
+	.eaddr = &svs_leave_nmi_end
+};
+static const struct x86_hotpatch_descriptor hp_svs_leave_nmi_desc = {
+	.name = HP_NAME_SVS_LEAVE_NMI,
+	.nsrc = 1,
+	.srcs = { &hp_svs_leave_nmi_source }
+};
+__link_set_add_rodata(x86_hotpatch_descriptors, hp_svs_leave_nmi_desc);
+
+/* -------------------------------------------------------------------------- */
+
 bool svs_enabled __read_mostly = false;
 bool svs_pcid __read_mostly = false;
 
@@ -636,49 +718,15 @@ svs_pdir_switch(struct pmap *pmap)
 static void
 svs_enable(void)
 {
-	extern uint8_t svs_enter, svs_enter_end;
-	extern uint8_t svs_enter_altstack, svs_enter_altstack_end;
-	extern uint8_t svs_enter_nmi, svs_enter_nmi_end;
-	extern uint8_t svs_leave, svs_leave_end;
-	extern uint8_t svs_leave_altstack, svs_leave_altstack_end;
-	extern uint8_t svs_leave_nmi, svs_leave_nmi_end;
-	u_long psl, cr0;
-	uint8_t *bytes;
-	size_t size;
-
 	svs_enabled = true;
 
-	x86_patch_window_open(&psl, &cr0);
-
-	bytes = &svs_enter;
-	size = (size_t)&svs_enter_end - (size_t)&svs_enter;
-	x86_hotpatch(HP_NAME_SVS_ENTER, bytes, size);
-
-	bytes = &svs_enter_altstack;
-	size = (size_t)&svs_enter_altstack_end -
-	    (size_t)&svs_enter_altstack;
-	x86_hotpatch(HP_NAME_SVS_ENTER_ALT, bytes, size);
-
-	bytes = &svs_enter_nmi;
-	size = (size_t)&svs_enter_nmi_end -
-	    (size_t)&svs_enter_nmi;
-	x86_hotpatch(HP_NAME_SVS_ENTER_NMI, bytes, size);
-
-	bytes = &svs_leave;
-	size = (size_t)&svs_leave_end - (size_t)&svs_leave;
-	x86_hotpatch(HP_NAME_SVS_LEAVE, bytes, size);
-
-	bytes = &svs_leave_altstack;
-	size = (size_t)&svs_leave_altstack_end -
-	    (size_t)&svs_leave_altstack;
-	x86_hotpatch(HP_NAME_SVS_LEAVE_ALT, bytes, size);
-
-	bytes = &svs_leave_nmi;
-	size = (size_t)&svs_leave_nmi_end -
-	    (size_t)&svs_leave_nmi;
-	x86_hotpatch(HP_NAME_SVS_LEAVE_NMI, bytes, size);
-
-	x86_patch_window_close(psl, cr0);
+	x86_hotpatch(HP_NAME_SVS_ENTER, 0);
+	x86_hotpatch(HP_NAME_SVS_ENTER_ALT, 0);
+	x86_hotpatch(HP_NAME_SVS_ENTER_NMI, 0);
+
+	x86_hotpatch(HP_NAME_SVS_LEAVE, 0);
+	x86_hotpatch(HP_NAME_SVS_LEAVE_ALT, 0);
+	x86_hotpatch(HP_NAME_SVS_LEAVE_NMI, 0);
 }
 
 void

Reply via email to