Author: kib
Date: Tue Sep 15 20:26:31 2020
New Revision: 365769
URL: https://svnweb.freebsd.org/changeset/base/365769

Log:
  MFC r365766:
  bhyve: intercept AMD SVM instructions.
  
  CVE:  CVE-2020-7467

Modified:
  stable/11/sys/amd64/vmm/amd/svm.c
  stable/11/sys/amd64/vmm/amd/vmcb.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/amd64/vmm/amd/svm.c
==============================================================================
--- stable/11/sys/amd64/vmm/amd/svm.c   Tue Sep 15 20:25:38 2020        
(r365768)
+++ stable/11/sys/amd64/vmm/amd/svm.c   Tue Sep 15 20:26:31 2020        
(r365769)
@@ -469,11 +469,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.
         */
@@ -1217,43 +1230,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 */
 
@@ -1504,6 +1519,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/11/sys/amd64/vmm/amd/vmcb.h
==============================================================================
--- stable/11/sys/amd64/vmm/amd/vmcb.h  Tue Sep 15 20:25:38 2020        
(r365768)
+++ stable/11/sys/amd64/vmm/amd/vmcb.h  Tue Sep 15 20:26:31 2020        
(r365769)
@@ -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
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to