svn commit: r365767 - stable/12/sys/amd64/vmm/amd
Konstantin Belousov
kib at FreeBSD.org
Tue Sep 15 20:25:31 UTC 2020
Author: kib
Date: Tue Sep 15 20:25:30 2020
New Revision: 365767
URL: https://svnweb.freebsd.org/changeset/base/365767
Log:
MFC r365766:
bhyve: intercept AMD SVM instructions.
CVE: CVE-2020-7467
Modified:
stable/12/sys/amd64/vmm/amd/svm.c
stable/12/sys/amd64/vmm/amd/vmcb.h
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/amd64/vmm/amd/svm.c
==============================================================================
--- stable/12/sys/amd64/vmm/amd/svm.c Tue Sep 15 20:22:50 2020 (r365766)
+++ stable/12/sys/amd64/vmm/amd/svm.c Tue Sep 15 20:25:30 2020 (r365767)
@@ -466,11 +466,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.
*/
@@ -1214,43 +1227,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 */
@@ -1501,6 +1516,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: stable/12/sys/amd64/vmm/amd/vmcb.h
==============================================================================
--- stable/12/sys/amd64/vmm/amd/vmcb.h Tue Sep 15 20:22:50 2020 (r365766)
+++ stable/12/sys/amd64/vmm/amd/vmcb.h Tue Sep 15 20:25:30 2020 (r365767)
@@ -73,8 +73,8 @@ struct svm_softc;
#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)
@@ -136,12 +136,21 @@ struct svm_softc;
#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
More information about the svn-src-all
mailing list