Date: Tue, 15 Sep 2020 20:22:50 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r365766 - head/sys/amd64/vmm/amd Message-ID: <202009152022.08FKMoV2096689@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Sep 15 20:22:50 2020 New Revision: 365766 URL: https://svnweb.freebsd.org/changeset/base/365766 Log: bhyve: intercept AMD SVM instructions. Intercept and report #UD to VM on SVM/AMD in case VM tried to execute an SVM instruction. Otherwise, SVM allows execution of them, and instructions operate on host physical addresses despite being executed in guest mode. Reported by: Maxime Villard <max@m00nbsd.net> admbug: 972 CVE: CVE-2020-7467 Reviewed by: grehan, markj Differential revision: https://reviews.freebsd.org/D26313 Modified: head/sys/amd64/vmm/amd/svm.c head/sys/amd64/vmm/amd/vmcb.h Modified: head/sys/amd64/vmm/amd/svm.c ============================================================================== --- head/sys/amd64/vmm/amd/svm.c Tue Sep 15 19:23:42 2020 (r365765) +++ head/sys/amd64/vmm/amd/svm.c Tue Sep 15 20:22:50 2020 (r365766) @@ -488,11 +488,24 @@ vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iop svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_SHUTDOWN); svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_FERR_FREEZE); + svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_INVD); + svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_INVLPGA); svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_MONITOR); svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_MWAIT); /* + * Intercept SVM instructions since AMD enables them in guests otherwise. + * Non-intercepted VMMCALL causes #UD, skip it. + */ + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_VMLOAD); + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_VMSAVE); + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_STGI); + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_CLGI); + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_SKINIT); + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_ICEBP); + + /* * From section "Canonicalization and Consistency Checks" in APMv2 * the VMRUN intercept bit must be set to pass the consistency check. */ @@ -1236,43 +1249,45 @@ emulate_rdmsr(struct svm_softc *sc, int vcpu, u_int nu static const char * exit_reason_to_str(uint64_t reason) { + int i; static char reasonbuf[32]; + static const struct { + int reason; + const char *str; + } reasons[] = { + { .reason = VMCB_EXIT_INVALID, .str = "invalvmcb" }, + { .reason = VMCB_EXIT_SHUTDOWN, .str = "shutdown" }, + { .reason = VMCB_EXIT_NPF, .str = "nptfault" }, + { .reason = VMCB_EXIT_PAUSE, .str = "pause" }, + { .reason = VMCB_EXIT_HLT, .str = "hlt" }, + { .reason = VMCB_EXIT_CPUID, .str = "cpuid" }, + { .reason = VMCB_EXIT_IO, .str = "inout" }, + { .reason = VMCB_EXIT_MC, .str = "mchk" }, + { .reason = VMCB_EXIT_INTR, .str = "extintr" }, + { .reason = VMCB_EXIT_NMI, .str = "nmi" }, + { .reason = VMCB_EXIT_VINTR, .str = "vintr" }, + { .reason = VMCB_EXIT_MSR, .str = "msr" }, + { .reason = VMCB_EXIT_IRET, .str = "iret" }, + { .reason = VMCB_EXIT_MONITOR, .str = "monitor" }, + { .reason = VMCB_EXIT_MWAIT, .str = "mwait" }, + { .reason = VMCB_EXIT_VMRUN, .str = "vmrun" }, + { .reason = VMCB_EXIT_VMMCALL, .str = "vmmcall" }, + { .reason = VMCB_EXIT_VMLOAD, .str = "vmload" }, + { .reason = VMCB_EXIT_VMSAVE, .str = "vmsave" }, + { .reason = VMCB_EXIT_STGI, .str = "stgi" }, + { .reason = VMCB_EXIT_CLGI, .str = "clgi" }, + { .reason = VMCB_EXIT_SKINIT, .str = "skinit" }, + { .reason = VMCB_EXIT_ICEBP, .str = "icebp" }, + { .reason = VMCB_EXIT_INVD, .str = "invd" }, + { .reason = VMCB_EXIT_INVLPGA, .str = "invlpga" }, + }; - switch (reason) { - case VMCB_EXIT_INVALID: - return ("invalvmcb"); - case VMCB_EXIT_SHUTDOWN: - return ("shutdown"); - case VMCB_EXIT_NPF: - return ("nptfault"); - case VMCB_EXIT_PAUSE: - return ("pause"); - case VMCB_EXIT_HLT: - return ("hlt"); - case VMCB_EXIT_CPUID: - return ("cpuid"); - case VMCB_EXIT_IO: - return ("inout"); - case VMCB_EXIT_MC: - return ("mchk"); - case VMCB_EXIT_INTR: - return ("extintr"); - case VMCB_EXIT_NMI: - return ("nmi"); - case VMCB_EXIT_VINTR: - return ("vintr"); - case VMCB_EXIT_MSR: - return ("msr"); - case VMCB_EXIT_IRET: - return ("iret"); - case VMCB_EXIT_MONITOR: - return ("monitor"); - case VMCB_EXIT_MWAIT: - return ("mwait"); - default: - snprintf(reasonbuf, sizeof(reasonbuf), "%#lx", reason); - return (reasonbuf); + for (i = 0; i < nitems(reasons); i++) { + if (reasons[i].reason == reason) + return (reasons[i].str); } + snprintf(reasonbuf, sizeof(reasonbuf), "%#lx", reason); + return (reasonbuf); } #endif /* KTR */ @@ -1523,6 +1538,20 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct break; case VMCB_EXIT_MWAIT: vmexit->exitcode = VM_EXITCODE_MWAIT; + break; + case VMCB_EXIT_SHUTDOWN: + case VMCB_EXIT_VMRUN: + case VMCB_EXIT_VMMCALL: + case VMCB_EXIT_VMLOAD: + case VMCB_EXIT_VMSAVE: + case VMCB_EXIT_STGI: + case VMCB_EXIT_CLGI: + case VMCB_EXIT_SKINIT: + case VMCB_EXIT_ICEBP: + case VMCB_EXIT_INVD: + case VMCB_EXIT_INVLPGA: + vm_inject_ud(svm_sc->vm, vcpu); + handled = 1; break; default: vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_UNKNOWN, 1); Modified: head/sys/amd64/vmm/amd/vmcb.h ============================================================================== --- head/sys/amd64/vmm/amd/vmcb.h Tue Sep 15 19:23:42 2020 (r365765) +++ head/sys/amd64/vmm/amd/vmcb.h Tue Sep 15 20:22:50 2020 (r365766) @@ -71,8 +71,8 @@ #define VMCB_INTCPT_INVD BIT(22) #define VMCB_INTCPT_PAUSE BIT(23) #define VMCB_INTCPT_HLT BIT(24) -#define VMCB_INTCPT_INVPG BIT(25) -#define VMCB_INTCPT_INVPGA BIT(26) +#define VMCB_INTCPT_INVLPG BIT(25) +#define VMCB_INTCPT_INVLPGA BIT(26) #define VMCB_INTCPT_IO BIT(27) #define VMCB_INTCPT_MSR BIT(28) #define VMCB_INTCPT_TASK_SWITCH BIT(29) @@ -134,12 +134,21 @@ #define VMCB_EXIT_POPF 0x71 #define VMCB_EXIT_CPUID 0x72 #define VMCB_EXIT_IRET 0x74 +#define VMCB_EXIT_INVD 0x76 #define VMCB_EXIT_PAUSE 0x77 #define VMCB_EXIT_HLT 0x78 +#define VMCB_EXIT_INVLPGA 0x7A #define VMCB_EXIT_IO 0x7B #define VMCB_EXIT_MSR 0x7C #define VMCB_EXIT_SHUTDOWN 0x7F +#define VMCB_EXIT_VMRUN 0x80 +#define VMCB_EXIT_VMMCALL 0x81 +#define VMCB_EXIT_VMLOAD 0x82 #define VMCB_EXIT_VMSAVE 0x83 +#define VMCB_EXIT_STGI 0x84 +#define VMCB_EXIT_CLGI 0x85 +#define VMCB_EXIT_SKINIT 0x86 +#define VMCB_EXIT_ICEBP 0x88 #define VMCB_EXIT_MONITOR 0x8A #define VMCB_EXIT_MWAIT 0x8B #define VMCB_EXIT_NPF 0x400
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202009152022.08FKMoV2096689>