[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86/hvm: Intercept RDPMC when vPMU is disabled



vPMU isn't security supported, and in general guests can't access any of the
performance counter MSRs.  However, the RDPMC instruction isn't intercepted,
meaning that guest software can read the instantaneous counter values.

When vPMU isn't configured, intercept RDPMC and unconditionally fail it as if
software has requested a bad counter index (#GP fault).  It is model specific
as to which counters are available to begin with, and in levelled scenarios,
this information may not be accurate in the first place.

This change isn't expected to have any impact on VMs.  Userspace is not
usually given access to RDPMC (Windows appear to completely prohibit it; Linux
is restricted to root), and kernels won't be executing RDPMC instructions if
their PMU drivers have failed to start.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Jun Nakajima <jun.nakajima@xxxxxxxxx>
CC: Kevin Tian <kevin.tian@xxxxxxxxx>
CC: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
CC: Brian Woods <brian.woods@xxxxxxx>
CC: Juergen Gross <jgross@xxxxxxxx>

This should be taken into Xen 4.12 and backported to the stable releases.
While it isn't an XSA itself, it is an information leak (Xen's NMI watchdog in
particular) which could be advantagous to an attacker trying to exploit a race
condition.

The only other option is to emulate the reported family and offer back all 0's
for the accessable counters.  Obviously this is a non-starter.

This patch has had some basic testing in XenServer with no issues identified
with any guests.
---
 xen/arch/x86/hvm/svm/svm.c  | 8 ++++++++
 xen/arch/x86/hvm/svm/vmcb.c | 3 +++
 xen/arch/x86/hvm/vmx/vmcs.c | 2 ++
 xen/arch/x86/hvm/vmx/vmx.c  | 9 +++++++++
 4 files changed, 22 insertions(+)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 2584b90..de20bb2 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2984,6 +2984,14 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
         svm_vmexit_do_rdtsc(regs, exit_reason == VMEXIT_RDTSCP);
         break;
 
+    case VMEXIT_RDPMC:
+        /*
+         * Interception is only active when VPMU is disabled, and the guest
+         * mustn't be able to read the counters.  Emulate "bad counter index".
+         */
+        hvm_inject_hw_exception(TRAP_gp_fault, 0);
+        break;
+
     case VMEXIT_MONITOR:
     case VMEXIT_MWAIT:
         hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC);
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 9d1c5bf..092c049 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -67,6 +67,9 @@ static int construct_vmcb(struct vcpu *v)
         GENERAL1_INTERCEPT_INVLPGA     | GENERAL1_INTERCEPT_IOIO_PROT   |
         GENERAL1_INTERCEPT_MSR_PROT    | GENERAL1_INTERCEPT_SHUTDOWN_EVT|
         GENERAL1_INTERCEPT_TASK_SWITCH;
+    if ( !vpmu_available(v) )
+        vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_RDPMC;
+
     vmcb->_general2_intercepts = 
         GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
         GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 74f2a08..e860db9 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -994,6 +994,8 @@ static int construct_vmcs(struct vcpu *v)
     __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
 
     v->arch.hvm.vmx.exec_control = vmx_cpu_based_exec_control;
+    if ( !vpmu_available(v) )
+        v->arch.hvm.vmx.exec_control |= CPU_BASED_RDPMC_EXITING;
     if ( d->arch.vtsc && !cpu_has_vmx_tsc_scaling )
         v->arch.hvm.vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
 
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 24def93..c5e5804 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -3956,6 +3956,15 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
         vmx_invlpg_intercept(exit_qualification);
         break;
+
+    case EXIT_REASON_RDPMC:
+        /*
+         * Interception is only active when VPMU is disabled, and the guest
+         * mustn't be able to read the counters.  Emulate "bad counter index".
+         */
+        hvm_inject_hw_exception(TRAP_gp_fault, 0);
+        break;
+
     case EXIT_REASON_RDTSCP:
         if ( !currd->arch.cpuid->extd.rdtscp )
         {
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.