Change the way SVS is disabled. Now you have to pass "boot -3" from the

bootloader. The machdep.svs.enabled sysctl becomes read-only, and just
indicates whether SVS is enabled.

Sent on port-amd64@.
This commit is contained in:
maxv 2019-05-15 17:31:41 +00:00
parent 58c984f9c2
commit e795d0888c
3 changed files with 12 additions and 178 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.S,v 1.181 2019/05/14 16:59:25 maxv Exp $ */
/* $NetBSD: locore.S,v 1.182 2019/05/15 17:31:41 maxv Exp $ */
/*
* Copyright-o-rama!
@ -1621,10 +1621,6 @@ END(intrfastexit)
.globl svs_enter_altstack, svs_enter_altstack_end
.globl svs_leave, svs_leave_end
.globl svs_leave_altstack, svs_leave_altstack_end
.globl nosvs_enter, nosvs_enter_end
.globl nosvs_enter_altstack, nosvs_enter_altstack_end
.globl nosvs_leave, nosvs_leave_end
.globl nosvs_leave_altstack, nosvs_leave_altstack_end
LABEL(svs_enter)
movabs SVS_UTLS+UTLS_KPDIRPA,%rax
@ -1668,30 +1664,6 @@ LABEL(svs_leave_nmi)
movq (FRAMESIZE+1*8)(%rsp),%rax /* nmistore->scratch */
movq %rax,%cr3
LABEL(svs_leave_nmi_end)
LABEL(nosvs_enter)
NOSVS_ENTER
LABEL(nosvs_enter_end)
LABEL(nosvs_enter_altstack)
NOSVS_ENTER_ALTSTACK
LABEL(nosvs_enter_altstack_end)
LABEL(nosvs_enter_nmi)
NOSVS_ENTER_NMI
LABEL(nosvs_enter_nmi_end)
LABEL(nosvs_leave)
NOSVS_LEAVE
LABEL(nosvs_leave_end)
LABEL(nosvs_leave_altstack)
NOSVS_LEAVE_ALTSTACK
LABEL(nosvs_leave_altstack_end)
LABEL(nosvs_leave_nmi)
NOSVS_LEAVE_NMI
LABEL(nosvs_leave_nmi_end)
#endif
.globl ibrs_enter, ibrs_enter_end

View File

@ -1,7 +1,7 @@
/* $NetBSD: svs.c,v 1.25 2019/04/21 06:37:21 maxv Exp $ */
/* $NetBSD: svs.c,v 1.26 2019/05/15 17:31:41 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.25 2019/04/21 06:37:21 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.26 2019/05/15 17:31:41 maxv Exp $");
#include "opt_svs.h"
@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.25 2019/04/21 06:37:21 maxv Exp $");
#include <sys/kauth.h>
#include <sys/sysctl.h>
#include <sys/xcall.h>
#include <sys/reboot.h>
#include <x86/cputypes.h>
#include <machine/cpuvar.h>
@ -611,147 +612,6 @@ svs_enable(void)
x86_patch_window_close(psl, cr0);
}
static void
svs_disable_hotpatch(void)
{
extern uint8_t nosvs_enter, nosvs_enter_end;
extern uint8_t nosvs_enter_altstack, nosvs_enter_altstack_end;
extern uint8_t nosvs_enter_nmi, nosvs_enter_nmi_end;
extern uint8_t nosvs_leave, nosvs_leave_end;
extern uint8_t nosvs_leave_altstack, nosvs_leave_altstack_end;
extern uint8_t nosvs_leave_nmi, nosvs_leave_nmi_end;
u_long psl, cr0;
uint8_t *bytes;
size_t size;
x86_patch_window_open(&psl, &cr0);
bytes = &nosvs_enter;
size = (size_t)&nosvs_enter_end - (size_t)&nosvs_enter;
x86_hotpatch(HP_NAME_SVS_ENTER, bytes, size);
bytes = &nosvs_enter_altstack;
size = (size_t)&nosvs_enter_altstack_end -
(size_t)&nosvs_enter_altstack;
x86_hotpatch(HP_NAME_SVS_ENTER_ALT, bytes, size);
bytes = &nosvs_enter_nmi;
size = (size_t)&nosvs_enter_nmi_end -
(size_t)&nosvs_enter_nmi;
x86_hotpatch(HP_NAME_SVS_ENTER_NMI, bytes, size);
bytes = &nosvs_leave;
size = (size_t)&nosvs_leave_end - (size_t)&nosvs_leave;
x86_hotpatch(HP_NAME_SVS_LEAVE, bytes, size);
bytes = &nosvs_leave_altstack;
size = (size_t)&nosvs_leave_altstack_end -
(size_t)&nosvs_leave_altstack;
x86_hotpatch(HP_NAME_SVS_LEAVE_ALT, bytes, size);
bytes = &nosvs_leave_nmi;
size = (size_t)&nosvs_leave_nmi_end -
(size_t)&nosvs_leave_nmi;
x86_hotpatch(HP_NAME_SVS_LEAVE_NMI, bytes, size);
x86_patch_window_close(psl, cr0);
}
static volatile unsigned long svs_cpu_barrier1 __cacheline_aligned;
static volatile unsigned long svs_cpu_barrier2 __cacheline_aligned;
typedef void (vector)(void);
static void
svs_disable_cpu(void *arg1, void *arg2)
{
struct cpu_info *ci = curcpu();
extern vector Xsyscall;
u_long psl;
psl = x86_read_psl();
x86_disable_intr();
atomic_dec_ulong(&svs_cpu_barrier1);
while (atomic_cas_ulong(&svs_cpu_barrier1, 0, 0) != 0) {
x86_pause();
}
/* cpu0 is the one that does the hotpatch job */
if (ci == &cpu_info_primary) {
svs_enabled = false;
svs_disable_hotpatch();
}
/* put back the non-SVS syscall entry point */
wrmsr(MSR_LSTAR, (uint64_t)Xsyscall);
/* enable global pages */
if (cpu_feature[0] & CPUID_PGE)
lcr4(rcr4() | CR4_PGE);
atomic_dec_ulong(&svs_cpu_barrier2);
while (atomic_cas_ulong(&svs_cpu_barrier2, 0, 0) != 0) {
x86_pause();
}
/* Write back and invalidate cache, flush pipelines. */
wbinvd();
x86_flush();
x86_write_psl(psl);
}
static int
svs_disable(void)
{
uint64_t xc;
svs_cpu_barrier1 = ncpu;
svs_cpu_barrier2 = ncpu;
printf("[+] Disabling SVS...");
xc = xc_broadcast(0, svs_disable_cpu, NULL, NULL);
xc_wait(xc);
printf(" done!\n");
return 0;
}
int sysctl_machdep_svs_enabled(SYSCTLFN_ARGS);
int
sysctl_machdep_svs_enabled(SYSCTLFN_ARGS)
{
struct sysctlnode node;
int error;
bool val;
val = *(bool *)rnode->sysctl_data;
node = *rnode;
node.sysctl_data = &val;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error != 0 || newp == NULL)
return error;
if (val == 1) {
if (svs_enabled)
error = 0;
else
error = EOPNOTSUPP;
} else if (svs_enabled) {
error = kauth_authorize_machdep(kauth_cred_get(),
KAUTH_MACHDEP_SVS_DISABLE, NULL, NULL, NULL, NULL);
if (!error)
error = svs_disable();
} else {
error = 0;
}
return error;
}
void
svs_init(void)
{
@ -760,6 +620,9 @@ svs_init(void)
if (cpu_vendor != CPUVENDOR_INTEL) {
return;
}
if (boothowto & RB_MD3) {
return;
}
if (cpu_info_primary.ci_feat_val[7] & CPUID_SEF_ARCH_CAP) {
msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
if (msr & IA32_ARCH_RDCL_NO) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: x86_machdep.c,v 1.124 2019/02/15 08:54:01 nonaka Exp $ */
/* $NetBSD: x86_machdep.c,v 1.125 2019/05/15 17:31:41 maxv Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.124 2019/02/15 08:54:01 nonaka Exp $");
__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.125 2019/05/15 17:31:41 maxv Exp $");
#include "opt_modular.h"
#include "opt_physmem.h"
@ -1287,7 +1287,6 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
sysctl_machdep_hypervisor, 0, NULL, 0,
CTL_MACHDEP, CTL_CREATE, CTL_EOL);
#ifdef SVS
int sysctl_machdep_svs_enabled(SYSCTLFN_ARGS);
const struct sysctlnode *svs_rnode = NULL;
sysctl_createv(clog, 0, NULL, &svs_rnode,
CTLFLAG_PERMANENT,
@ -1295,10 +1294,10 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
NULL, 0, NULL, 0,
CTL_MACHDEP, CTL_CREATE);
sysctl_createv(clog, 0, &svs_rnode, &svs_rnode,
CTLFLAG_READWRITE,
CTLFLAG_PERMANENT,
CTLTYPE_BOOL, "enabled",
SYSCTL_DESCR("Whether the kernel uses SVS"),
sysctl_machdep_svs_enabled, 0, &svs_enabled, 0,
NULL, 0, &svs_enabled, 0,
CTL_CREATE, CTL_EOL);
#endif