CVE-2020-2732

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

CVE-2020-2732

Thadeu Lima de Souza Cascardo-3
These are backports of the fixes to CVE-2020-2732. They affect X86 hosts. A
nested guest (L2) may execute disallowed code, leading to access to L1
resources.

I used the backport from 4.4.y, which includes "emulate RDPID" as a pre-req, so
we divert the least as possible from stable upstream.

I did the same for Bionic 4.15, using the backports from 4.14.y.

D/E/F have been built-tested, Ben Romer did some nested guest smoke testing
with the Bionic patches, although with a version without the pre-req.

Xenial is build testing right now. More tests are in development.



--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial 1/4] KVM: x86: emulate RDPID

Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

commit fb6d4d340e0532032c808a9933eaaa7b8de435ab upstream.

This is encoded as F3 0F C7 /7 with a register argument.  The register
argument is the second array in the group9 GroupDual, while F3 is the
fourth element of a Prefix.

Reviewed-by: Wanpeng Li <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/cpuid.c   |  7 ++++++-
 arch/x86/kvm/emulate.c | 22 +++++++++++++++++++++-
 arch/x86/kvm/vmx.c     | 15 +++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 9c8096c09c4b..7adda28689e9 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -269,13 +269,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
 {
  switch (func) {
  case 0:
- entry->eax = 1; /* only one leaf currently */
+ entry->eax = 7;
  ++*nent;
  break;
  case 1:
  entry->ecx = F(MOVBE);
  ++*nent;
  break;
+ case 7:
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ if (index == 0)
+ entry->ecx = F(RDPID);
+ ++*nent;
  default:
  break;
  }
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index dba9d62eeaa4..666812e00ab3 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3518,6 +3518,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
  return X86EMUL_CONTINUE;
 }
 
+static int em_rdpid(struct x86_emulate_ctxt *ctxt)
+{
+ u64 tsc_aux = 0;
+
+ if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
+ return emulate_gp(ctxt, 0);
+ ctxt->dst.val = tsc_aux;
+ return X86EMUL_CONTINUE;
+}
+
 static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
 {
  u64 tsc = 0;
@@ -4378,10 +4388,20 @@ static const struct opcode group8[] = {
  F(DstMem | SrcImmByte | Lock | PageTable, em_btc),
 };
 
+/*
+ * The "memory" destination is actually always a register, since we come
+ * from the register case of group9.
+ */
+static const struct gprefix pfx_0f_c7_7 = {
+ N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
+};
+
+
 static const struct group_dual group9 = { {
  N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
 }, {
- N, N, N, N, N, N, N, N,
+ N, N, N, N, N, N, N,
+ GP(0, &pfx_0f_c7_7),
 } };
 
 static const struct opcode group11[] = {
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1f84143f4130..94e4177ef698 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -11034,6 +11034,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
 {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+
+ /*
+ * RDPID causes #UD if disabled through secondary execution controls.
+ * Because it is marked as EmulateOnUD, we need to intercept it here.
+ */
+ if (info->intercept == x86_intercept_rdtscp &&
+    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ /* TODO: check more intercepts... */
  return X86EMUL_CONTINUE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial 2/4] KVM: nVMX: Don't emulate instructions in guest mode

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

[ Upstream commit 07721feee46b4b248402133228235318199b05ec ]

vmx_check_intercept is not yet fully implemented. To avoid emulating
instructions disallowed by the L1 hypervisor, refuse to emulate
instructions by default.

Cc: [hidden email]
[Made commit, added commit msg - Oliver]
Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Sasha Levin <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 94e4177ef698..b62abefdb82b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -11049,7 +11049,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  }
 
  /* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
 }
 
 static void vmx_sched_in(struct kvm_vcpu *vcpu, int cpu)
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial 3/4] KVM: nVMX: Refactor IO bitmap checks into helper function

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit e71237d3ff1abf9f3388337cfebf53b96df2020d upstream.

Checks against the IO bitmap are useful for both instruction emulation
and VM-exit reflection. Refactor the IO bitmap checks into a helper
function.

Signed-off-by: Oliver Upton <[hidden email]>
Reviewed-by: Vitaly Kuznetsov <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b62abefdb82b..fb748973ad56 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4450,6 +4450,26 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
  (ss.selector & SEGMENT_RPL_MASK));
 }
 
+static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
+ unsigned int port, int size);
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+       struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification;
+ unsigned int port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+
+ return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
  * Check if guest state is valid. Returns true if valid, false if
  * not.
@@ -7802,23 +7822,17 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
 static const int kvm_vmx_max_exit_handlers =
  ARRAY_SIZE(kvm_vmx_exit_handlers);
 
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-       struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size)
 {
- unsigned long exit_qualification;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  gpa_t bitmap, last_bitmap;
- unsigned int port;
- int size;
  u8 b;
 
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
-
  last_bitmap = (gpa_t)-1;
  b = -1;
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial 4/4] KVM: nVMX: Check IO instruction VM-exit conditions

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit 35a571346a94fb93b5b3b6a599675ef3384bc75c upstream.

Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution
controls when checking instruction interception. If the 'use IO bitmaps'
VM-execution control is 1, check the instruction access against the IO
bitmaps to determine if the instruction causes a VM-exit.

Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 59 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index fb748973ad56..7e6868f4578b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4456,7 +4456,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12)
 {
  unsigned long exit_qualification;
- unsigned int port;
+ unsigned short port;
  int size;
 
  if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
@@ -11044,6 +11044,39 @@ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
  to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+  struct x86_instruction_info *info)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned short port;
+ bool intercept;
+ int size;
+
+ if (info->intercept == x86_intercept_in ||
+    info->intercept == x86_intercept_ins) {
+ port = info->src_val;
+ size = info->dst_bytes;
+ } else {
+ port = info->dst_val;
+ size = info->src_bytes;
+ }
+
+ /*
+ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+ * VM-exits depend on the 'unconditional IO exiting' VM-execution
+ * control.
+ *
+ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+ */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ intercept = nested_cpu_has(vmcs12,
+   CPU_BASED_UNCOND_IO_EXITING);
+ else
+ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
@@ -11051,18 +11084,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+ switch (info->intercept) {
  /*
  * RDPID causes #UD if disabled through secondary execution controls.
  * Because it is marked as EmulateOnUD, we need to intercept it here.
  */
- if (info->intercept == x86_intercept_rdtscp &&
-    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
- ctxt->exception.vector = UD_VECTOR;
- ctxt->exception.error_code_valid = false;
- return X86EMUL_PROPAGATE_FAULT;
- }
+ case x86_intercept_rdtscp:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+ break;
+
+ case x86_intercept_in:
+ case x86_intercept_ins:
+ case x86_intercept_out:
+ case x86_intercept_outs:
+ return vmx_check_intercept_io(vcpu, info);
 
  /* TODO: check more intercepts... */
+ default:
+ break;
+ }
+
  return X86EMUL_UNHANDLEABLE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Bionic 1/4] KVM: x86: emulate RDPID

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

commit fb6d4d340e0532032c808a9933eaaa7b8de435ab upstream.

This is encoded as F3 0F C7 /7 with a register argument.  The register
argument is the second array in the group9 GroupDual, while F3 is the
fourth element of a Prefix.

Reviewed-by: Wanpeng Li <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/cpuid.c   |  7 ++++++-
 arch/x86/kvm/emulate.c | 22 +++++++++++++++++++++-
 arch/x86/kvm/vmx.c     | 15 +++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index dd22f8f60798..d5fcb3aef85e 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -291,13 +291,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
 {
  switch (func) {
  case 0:
- entry->eax = 1; /* only one leaf currently */
+ entry->eax = 7;
  ++*nent;
  break;
  case 1:
  entry->ecx = F(MOVBE);
  ++*nent;
  break;
+ case 7:
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ if (index == 0)
+ entry->ecx = F(RDPID);
+ ++*nent;
  default:
  break;
  }
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 419192d53f75..65285b0dabaa 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3544,6 +3544,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
  return X86EMUL_CONTINUE;
 }
 
+static int em_rdpid(struct x86_emulate_ctxt *ctxt)
+{
+ u64 tsc_aux = 0;
+
+ if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
+ return emulate_gp(ctxt, 0);
+ ctxt->dst.val = tsc_aux;
+ return X86EMUL_CONTINUE;
+}
+
 static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
 {
  u64 tsc = 0;
@@ -4436,10 +4446,20 @@ static const struct opcode group8[] = {
  F(DstMem | SrcImmByte | Lock | PageTable, em_btc),
 };
 
+/*
+ * The "memory" destination is actually always a register, since we come
+ * from the register case of group9.
+ */
+static const struct gprefix pfx_0f_c7_7 = {
+ N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
+};
+
+
 static const struct group_dual group9 = { {
  N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
 }, {
- N, N, N, N, N, N, N, N,
+ N, N, N, N, N, N, N,
+ GP(0, &pfx_0f_c7_7),
 } };
 
 static const struct opcode group11[] = {
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b2f26d21556d..370464c73b41 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -12332,6 +12332,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
 {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+
+ /*
+ * RDPID causes #UD if disabled through secondary execution controls.
+ * Because it is marked as EmulateOnUD, we need to intercept it here.
+ */
+ if (info->intercept == x86_intercept_rdtscp &&
+    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ /* TODO: check more intercepts... */
  return X86EMUL_CONTINUE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Bionic 2/4] KVM: nVMX: Don't emulate instructions in guest mode

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

[ Upstream commit 07721feee46b4b248402133228235318199b05ec ]

vmx_check_intercept is not yet fully implemented. To avoid emulating
instructions disallowed by the L1 hypervisor, refuse to emulate
instructions by default.

Cc: [hidden email]
[Made commit, added commit msg - Oliver]
Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Sasha Levin <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 370464c73b41..987c28f4fbe5 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -12347,7 +12347,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  }
 
  /* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Bionic 3/4] KVM: nVMX: Refactor IO bitmap checks into helper function

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit e71237d3ff1abf9f3388337cfebf53b96df2020d upstream.

Checks against the IO bitmap are useful for both instruction emulation
and VM-exit reflection. Refactor the IO bitmap checks into a helper
function.

Signed-off-by: Oliver Upton <[hidden email]>
Reviewed-by: Vitaly Kuznetsov <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 987c28f4fbe5..6a2da0068ae2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4998,6 +4998,26 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
  (ss.selector & SEGMENT_RPL_MASK));
 }
 
+static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
+ unsigned int port, int size);
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+       struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification;
+ unsigned int port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+
+ return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
  * Check if guest state is valid. Returns true if valid, false if
  * not.
@@ -8523,23 +8543,17 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
 static const int kvm_vmx_max_exit_handlers =
  ARRAY_SIZE(kvm_vmx_exit_handlers);
 
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-       struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size)
 {
- unsigned long exit_qualification;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  gpa_t bitmap, last_bitmap;
- unsigned int port;
- int size;
  u8 b;
 
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
-
  last_bitmap = (gpa_t)-1;
  b = -1;
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Bionic 4/4] KVM: nVMX: Check IO instruction VM-exit conditions

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit 35a571346a94fb93b5b3b6a599675ef3384bc75c upstream.

Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution
controls when checking instruction interception. If the 'use IO bitmaps'
VM-execution control is 1, check the instruction access against the IO
bitmaps to determine if the instruction causes a VM-exit.

Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 59 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6a2da0068ae2..3728ecea95e4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5004,7 +5004,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12)
 {
  unsigned long exit_qualification;
- unsigned int port;
+ unsigned short port;
  int size;
 
  if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
@@ -12342,6 +12342,39 @@ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
  to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+  struct x86_instruction_info *info)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned short port;
+ bool intercept;
+ int size;
+
+ if (info->intercept == x86_intercept_in ||
+    info->intercept == x86_intercept_ins) {
+ port = info->src_val;
+ size = info->dst_bytes;
+ } else {
+ port = info->dst_val;
+ size = info->src_bytes;
+ }
+
+ /*
+ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+ * VM-exits depend on the 'unconditional IO exiting' VM-execution
+ * control.
+ *
+ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+ */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ intercept = nested_cpu_has(vmcs12,
+   CPU_BASED_UNCOND_IO_EXITING);
+ else
+ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
@@ -12349,18 +12382,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+ switch (info->intercept) {
  /*
  * RDPID causes #UD if disabled through secondary execution controls.
  * Because it is marked as EmulateOnUD, we need to intercept it here.
  */
- if (info->intercept == x86_intercept_rdtscp &&
-    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
- ctxt->exception.vector = UD_VECTOR;
- ctxt->exception.error_code_valid = false;
- return X86EMUL_PROPAGATE_FAULT;
- }
+ case x86_intercept_rdtscp:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+ break;
+
+ case x86_intercept_in:
+ case x86_intercept_ins:
+ case x86_intercept_out:
+ case x86_intercept_outs:
+ return vmx_check_intercept_io(vcpu, info);
 
  /* TODO: check more intercepts... */
+ default:
+ break;
+ }
+
  return X86EMUL_UNHANDLEABLE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[D/E/F 1/3] KVM: nVMX: Don't emulate instructions in guest mode

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

vmx_check_intercept is not yet fully implemented. To avoid emulating
instructions disallowed by the L1 hypervisor, refuse to emulate
instructions by default.

Cc: [hidden email]
[Made commit, added commit msg - Oliver]
Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
(cherry picked from commit 07721feee46b4b248402133228235318199b05ec)
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx/vmx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index f09a213fd5cb..bc6013e54463 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7146,7 +7146,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  }
 
  /* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[D/E/F 2/3] KVM: nVMX: Refactor IO bitmap checks into helper function

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

Checks against the IO bitmap are useful for both instruction emulation
and VM-exit reflection. Refactor the IO bitmap checks into a helper
function.

Signed-off-by: Oliver Upton <[hidden email]>
Reviewed-by: Vitaly Kuznetsov <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
(backported from commit e71237d3ff1abf9f3388337cfebf53b96df2020d)
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx/nested.c | 39 +++++++++++++++++++++++++--------------
 arch/x86/kvm/vmx/nested.h |  2 ++
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index d0523741fb03..0eb1ef92e94f 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -5130,24 +5130,17 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu)
  return 1;
 }
 
-
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-       struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size)
 {
- unsigned long exit_qualification;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  gpa_t bitmap, last_bitmap;
- unsigned int port;
- int size;
  u8 b;
 
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
-
  last_bitmap = (gpa_t)-1;
  b = -1;
 
@@ -5174,6 +5167,24 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
  return false;
 }
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+       struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification;
+ unsigned int port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+
+ return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
  * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
  * rather than handle it ourselves in L0. I.e., check whether L1 expressed
diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h
index 6280f33e5fa6..fc09c1585dc2 100644
--- a/arch/x86/kvm/vmx/nested.h
+++ b/arch/x86/kvm/vmx/nested.h
@@ -33,6 +33,8 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
 int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
  u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size);
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 {
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[D/E/F 3/3] KVM: nVMX: Check IO instruction VM-exit conditions

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution
controls when checking instruction interception. If the 'use IO bitmaps'
VM-execution control is 1, check the instruction access against the IO
bitmaps to determine if the instruction causes a VM-exit.

Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
(cherry picked from commit 35a571346a94fb93b5b3b6a599675ef3384bc75c)
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx/nested.c |  2 +-
 arch/x86/kvm/vmx/vmx.c    | 57 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 0eb1ef92e94f..1b3d36218b4e 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -5171,7 +5171,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12)
 {
  unsigned long exit_qualification;
- unsigned int port;
+ unsigned short port;
  int size;
 
  if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index bc6013e54463..41476b352dbb 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7127,6 +7127,39 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
  to_vmx(vcpu)->req_immediate_exit = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+  struct x86_instruction_info *info)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned short port;
+ bool intercept;
+ int size;
+
+ if (info->intercept == x86_intercept_in ||
+    info->intercept == x86_intercept_ins) {
+ port = info->src_val;
+ size = info->dst_bytes;
+ } else {
+ port = info->dst_val;
+ size = info->src_bytes;
+ }
+
+ /*
+ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+ * VM-exits depend on the 'unconditional IO exiting' VM-execution
+ * control.
+ *
+ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+ */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ intercept = nested_cpu_has(vmcs12,
+   CPU_BASED_UNCOND_IO_EXITING);
+ else
+ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
@@ -7134,18 +7167,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+ switch (info->intercept) {
  /*
  * RDPID causes #UD if disabled through secondary execution controls.
  * Because it is marked as EmulateOnUD, we need to intercept it here.
  */
- if (info->intercept == x86_intercept_rdtscp &&
-    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
- ctxt->exception.vector = UD_VECTOR;
- ctxt->exception.error_code_valid = false;
- return X86EMUL_PROPAGATE_FAULT;
- }
+ case x86_intercept_rdtscp:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+ break;
+
+ case x86_intercept_in:
+ case x86_intercept_ins:
+ case x86_intercept_out:
+ case x86_intercept_outs:
+ return vmx_check_intercept_io(vcpu, info);
 
  /* TODO: check more intercepts... */
+ default:
+ break;
+ }
+
  return X86EMUL_UNHANDLEABLE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK Re: CVE-2020-2732

benjamin.romer
In reply to this post by Thadeu Lima de Souza Cascardo-3
These patches look correct to me. We will likely need to drop the
prereq patch in livepatches, but I do not believe that will adversely
effect fixing the CVE.

Signed-off-by: Benjamin M Romer <[hidden email]>

On Thu, 2020-02-27 at 15:51 -0300, Thadeu Lima de Souza Cascardo wrote:

> These are backports of the fixes to CVE-2020-2732. They affect X86
> hosts. A
> nested guest (L2) may execute disallowed code, leading to access to
> L1
> resources.
>
> I used the backport from 4.4.y, which includes "emulate RDPID" as a
> pre-req, so
> we divert the least as possible from stable upstream.
>
> I did the same for Bionic 4.15, using the backports from 4.14.y.
>
> D/E/F have been built-tested, Ben Romer did some nested guest smoke
> testing
> with the Bionic patches, although with a version without the pre-req.
>
> Xenial is build testing right now. More tests are in development.
>
>
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial] NACK: CVE-2020-2732

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
Xenial has failed to build, will send a new version for xenial.

Cascardo.

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial v2 1/5] x86/vdso: Use RDPID in preference to LSL when available

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Andy Lutomirski <[hidden email]>

CVE-2020-2732

commit a582c540ac1b10f0a7d37415e04c4af42409fd08 upstream.

RDPID is a new instruction that reads MSR_TSC_AUX quickly.  This
should be considerably faster than reading the GDT.  Add a
cpufeature for it and use it from __vdso_getcpu() when available.

Tested-by: Megha Dey <[hidden email]>
Signed-off-by: Andy Lutomirski <[hidden email]>
Cc: Borislav Petkov <[hidden email]>
Cc: Brian Gerst <[hidden email]>
Cc: Denys Vlasenko <[hidden email]>
Cc: H. Peter Anvin <[hidden email]>
Cc: Josh Poimboeuf <[hidden email]>
Cc: Linus Torvalds <[hidden email]>
Cc: Peter Zijlstra <[hidden email]>
Cc: Thomas Gleixner <[hidden email]>
Link: http://lkml.kernel.org/r/4f6c3a22012d10f1c65b9ca15800e01b42c7d39d.1479320367.git.luto@...
Signed-off-by: Ingo Molnar <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/include/asm/cpufeatures.h | 1 +
 arch/x86/include/asm/vgtod.h       | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index b298bf1a3eab..bea9f0c46513 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -307,6 +307,7 @@
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
 #define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
+#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index f556c4843aa1..51e7533bbf79 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -83,8 +83,13 @@ static inline unsigned int __getcpu(void)
  * works on all CPUs.  This is volatile so that it orders
  * correctly wrt barrier() and to keep gcc from cleverly
  * hoisting it out of the calling function.
+ *
+ * If RDPID is available, use it.
  */
- asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+ alternative_io ("lsl %[p],%[seg]",
+ ".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */
+ X86_FEATURE_RDPID,
+ [p] "=a" (p), [seg] "r" (__PER_CPU_SEG));
 
  return p;
 }
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial v2 2/5] KVM: x86: emulate RDPID

Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

commit fb6d4d340e0532032c808a9933eaaa7b8de435ab upstream.

This is encoded as F3 0F C7 /7 with a register argument.  The register
argument is the second array in the group9 GroupDual, while F3 is the
fourth element of a Prefix.

Reviewed-by: Wanpeng Li <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/cpuid.c   |  7 ++++++-
 arch/x86/kvm/emulate.c | 22 +++++++++++++++++++++-
 arch/x86/kvm/vmx.c     | 15 +++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 9c8096c09c4b..7adda28689e9 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -269,13 +269,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
 {
  switch (func) {
  case 0:
- entry->eax = 1; /* only one leaf currently */
+ entry->eax = 7;
  ++*nent;
  break;
  case 1:
  entry->ecx = F(MOVBE);
  ++*nent;
  break;
+ case 7:
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ if (index == 0)
+ entry->ecx = F(RDPID);
+ ++*nent;
  default:
  break;
  }
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index dba9d62eeaa4..666812e00ab3 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3518,6 +3518,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
  return X86EMUL_CONTINUE;
 }
 
+static int em_rdpid(struct x86_emulate_ctxt *ctxt)
+{
+ u64 tsc_aux = 0;
+
+ if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
+ return emulate_gp(ctxt, 0);
+ ctxt->dst.val = tsc_aux;
+ return X86EMUL_CONTINUE;
+}
+
 static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
 {
  u64 tsc = 0;
@@ -4378,10 +4388,20 @@ static const struct opcode group8[] = {
  F(DstMem | SrcImmByte | Lock | PageTable, em_btc),
 };
 
+/*
+ * The "memory" destination is actually always a register, since we come
+ * from the register case of group9.
+ */
+static const struct gprefix pfx_0f_c7_7 = {
+ N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
+};
+
+
 static const struct group_dual group9 = { {
  N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
 }, {
- N, N, N, N, N, N, N, N,
+ N, N, N, N, N, N, N,
+ GP(0, &pfx_0f_c7_7),
 } };
 
 static const struct opcode group11[] = {
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1f84143f4130..94e4177ef698 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -11034,6 +11034,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
 {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+
+ /*
+ * RDPID causes #UD if disabled through secondary execution controls.
+ * Because it is marked as EmulateOnUD, we need to intercept it here.
+ */
+ if (info->intercept == x86_intercept_rdtscp &&
+    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ /* TODO: check more intercepts... */
  return X86EMUL_CONTINUE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial v2 3/5] KVM: nVMX: Don't emulate instructions in guest mode

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Paolo Bonzini <[hidden email]>

CVE-2020-2732

[ Upstream commit 07721feee46b4b248402133228235318199b05ec ]

vmx_check_intercept is not yet fully implemented. To avoid emulating
instructions disallowed by the L1 hypervisor, refuse to emulate
instructions by default.

Cc: [hidden email]
[Made commit, added commit msg - Oliver]
Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Sasha Levin <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 94e4177ef698..b62abefdb82b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -11049,7 +11049,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  }
 
  /* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
 }
 
 static void vmx_sched_in(struct kvm_vcpu *vcpu, int cpu)
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial v2 4/5] KVM: nVMX: Refactor IO bitmap checks into helper function

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit e71237d3ff1abf9f3388337cfebf53b96df2020d upstream.

Checks against the IO bitmap are useful for both instruction emulation
and VM-exit reflection. Refactor the IO bitmap checks into a helper
function.

Signed-off-by: Oliver Upton <[hidden email]>
Reviewed-by: Vitaly Kuznetsov <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b62abefdb82b..fb748973ad56 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4450,6 +4450,26 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
  (ss.selector & SEGMENT_RPL_MASK));
 }
 
+static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
+ unsigned int port, int size);
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+       struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification;
+ unsigned int port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+
+ return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
  * Check if guest state is valid. Returns true if valid, false if
  * not.
@@ -7802,23 +7822,17 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
 static const int kvm_vmx_max_exit_handlers =
  ARRAY_SIZE(kvm_vmx_exit_handlers);
 
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-       struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size)
 {
- unsigned long exit_qualification;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  gpa_t bitmap, last_bitmap;
- unsigned int port;
- int size;
  u8 b;
 
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
-
  last_bitmap = (gpa_t)-1;
  b = -1;
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[Xenial v2 5/5] KVM: nVMX: Check IO instruction VM-exit conditions

Thadeu Lima de Souza Cascardo-3
In reply to this post by Thadeu Lima de Souza Cascardo-3
From: Oliver Upton <[hidden email]>

CVE-2020-2732

commit 35a571346a94fb93b5b3b6a599675ef3384bc75c upstream.

Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution
controls when checking instruction interception. If the 'use IO bitmaps'
VM-execution control is 1, check the instruction access against the IO
bitmaps to determine if the instruction causes a VM-exit.

Signed-off-by: Oliver Upton <[hidden email]>
Signed-off-by: Paolo Bonzini <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
Signed-off-by: Thadeu Lima de Souza Cascardo <[hidden email]>
---
 arch/x86/kvm/vmx.c | 59 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index fb748973ad56..7e6868f4578b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4456,7 +4456,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12)
 {
  unsigned long exit_qualification;
- unsigned int port;
+ unsigned short port;
  int size;
 
  if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
@@ -11044,6 +11044,39 @@ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
  to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+  struct x86_instruction_info *info)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned short port;
+ bool intercept;
+ int size;
+
+ if (info->intercept == x86_intercept_in ||
+    info->intercept == x86_intercept_ins) {
+ port = info->src_val;
+ size = info->dst_bytes;
+ } else {
+ port = info->dst_val;
+ size = info->src_bytes;
+ }
+
+ /*
+ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+ * VM-exits depend on the 'unconditional IO exiting' VM-execution
+ * control.
+ *
+ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+ */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ intercept = nested_cpu_has(vmcs12,
+   CPU_BASED_UNCOND_IO_EXITING);
+ else
+ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct x86_instruction_info *info,
        enum x86_intercept_stage stage)
@@ -11051,18 +11084,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
  struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
  struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+ switch (info->intercept) {
  /*
  * RDPID causes #UD if disabled through secondary execution controls.
  * Because it is marked as EmulateOnUD, we need to intercept it here.
  */
- if (info->intercept == x86_intercept_rdtscp &&
-    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
- ctxt->exception.vector = UD_VECTOR;
- ctxt->exception.error_code_valid = false;
- return X86EMUL_PROPAGATE_FAULT;
- }
+ case x86_intercept_rdtscp:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+ break;
+
+ case x86_intercept_in:
+ case x86_intercept_ins:
+ case x86_intercept_out:
+ case x86_intercept_outs:
+ return vmx_check_intercept_io(vcpu, info);
 
  /* TODO: check more intercepts... */
+ default:
+ break;
+ }
+
  return X86EMUL_UNHANDLEABLE;
 }
 
--
2.25.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: CVE-2020-2732

Khaled Elmously
In reply to this post by Thadeu Lima de Souza Cascardo-3
On 2020-02-27 15:51:14 , Thadeu Lima de Souza Cascardo wrote:

> These are backports of the fixes to CVE-2020-2732. They affect X86 hosts. A
> nested guest (L2) may execute disallowed code, leading to access to L1
> resources.
>
> I used the backport from 4.4.y, which includes "emulate RDPID" as a pre-req, so
> we divert the least as possible from stable upstream.
>
> I did the same for Bionic 4.15, using the backports from 4.14.y.
>
> D/E/F have been built-tested, Ben Romer did some nested guest smoke testing
> with the Bionic patches, although with a version without the pre-req.
>
> Xenial is build testing right now. More tests are in development.
>
>
>

Acked-by: Khalid Elmously <[hidden email]>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
12