Bug #13170
closedfix SVM instruction intercepts in bhyve
100%
Description
It was reported that bhyve was not establishing the proper interception for SVM-related instructions. This meant that a guest could issue instructions like vmsave
, which take a physical memory address as their argument, and result in writes to that physical host address. Given that the SVM capability not reported as available for guests (via CPUID), it would be appropriate for all of these instructions to result in #UD
. This was reported to FreeBSD by Maxime Villard.
Updated by Electric Monk about 3 years ago
- Status changed from New to Closed
- % Done changed from 0 to 100
git commit 8c2fd2ffa72935b73b4236eeb5745a22f782f780
commit 8c2fd2ffa72935b73b4236eeb5745a22f782f780 Author: Patrick Mooney <pmooney@pfmooney.com> Date: 2020-09-15T21:32:31.000Z 13170 fix SVM instruction intercepts in bhyve Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Joshua M. Clulow <josh@sysmgr.org> Approved by: Dan McDonald <danmcd@joyent.com>
Updated by Patrick Mooney about 3 years ago
To test this fix, I drew up a small kernel module so I could issue the instructions from ring 0 in an OmniOSCE guest. I verified that all of the newly-intercepted privileged instructions resulted in a #UD
being raised on that CPU. Without the fix, I confirmed that all the instructions in question did complete successfully, and in the case of vmsave
, I could see the changes written to host-physical memory.
Updated by Patrick Mooney about 3 years ago
Source of that test module I used to exercise those instructions:
amdvuln.c
/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. * * Copyright 2020 Oxide Computer Company */ #include <sys/types.h> #include <sys/errno.h> #include <sys/modctl.h> void amdvuln_vmsave(uintptr_t pa); void amdvuln_vmload(uintptr_t pa); void amdvuln_clgi(void); void amdvuln_stgi(void); void amdvuln_invd(void); void amdvuln_invlpga(uintptr_t pa, uint_t asid); void amdvuln_skinit(uint_t base); #define TEST_PA 0x2000 #define TEST_ASID 1 #define TEST_BASE 0xffff0000 int _init(void) { /* Choose your own adventure */ //amdvuln_vmsave(TEST_PA); //amdvuln_vmload(TEST_PA); //amdvuln_clgi(); //amdvuln_stgi(); //amdvuln_invd(); //amdvuln_invlpga(TEST_PA, TEST_ASID); //amdvuln_skinit(TEST_BASE); return (EINVAL); } int _fini(void) { return (0); } int _info(struct modinfo *modinfop) { return (EINVAL); }
amdvuln_ml.s
/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. * * Copyright 2020 Oxide Computer Company */ #include <sys/asm_linkage.h> ENTRY_NP(amdvuln_vmsave) movq %rdi, %rax vmsave ret SET_SIZE(amdvuln_vmsave) ENTRY_NP(amdvuln_vmload) movq %rdi, %rax vmload ret SET_SIZE(amdvuln_vmload) ENTRY_NP(amdvuln_clgi) clgi ret SET_SIZE(amdvuln_clgi) ENTRY_NP(amdvuln_stgi) stgi ret SET_SIZE(amdvuln_stgi) ENTRY_NP(amdvuln_invd) invd ret SET_SIZE(amdvuln_invd) ENTRY_NP(amdvuln_invlpga) movq %rdi, %rax movl %esi, %ecx invlpga ret SET_SIZE(amdvuln_invlpga) ENTRY_NP(amdvuln_skinit) movl %edi, %eax skinit ret SET_SIZE(amdvuln_skinit)
Makefile
# # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # Copyright 2020 Oxide Computer Company # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../.. # # Define the module and object file sets. # MODULE = amdvuln AMDVULN_OBJS = amdvuln.o amdvuln_ml.o OBJECTS = $(AMDVULN_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(USR_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/i86pc/io/amdvuln # # Include common rules. # include $(UTSBASE)/i86pc/Makefile.i86pc # # Define targets # ALL_TARGET = $(BINARY) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) # # Overrides and additions # ALL_BUILDS = $(ALL_BUILDSONLY64) DEF_BUILDS = $(DEF_BUILDSONLY64) LDFLAGS += -dy # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/Makefile.targ