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

Re: [PATCH v1] nSVM: Check injected event consistency


  • To: Abdelkareem Abdelsaamad <abdelkareem.abdelsaamad@xxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Teddy Astie <teddy.astie@xxxxxxxxxx>
  • Date: Wed, 15 Jul 2026 16:13:05 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=vates.tech header.i="@vates.tech" header.h="From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:In-Reply-To:References:Feedback-ID"
  • Autocrypt: addr=teddy.astie@xxxxxxxxxx; keydata= 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 x9fhaZEsniw8/bYgC3igkk5YJiOa
  • Cc: jbeulich@xxxxxxxx, andrew.cooper3@xxxxxxxxxx, roger.pau@xxxxxxxxxx, jason.andryuk@xxxxxxx
  • Delivery-date: Wed, 15 Jul 2026 14:13:20 +0000
  • Feedback-id: default:8631fc262581453bbf619ec5b2062170:Sweego
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Le 15/07/2026 à 15:39, Abdelkareem Abdelsaamad a écrit :
On the AMD platforms, allowing a VMRUN instruction with a malformed VMCB has
debugging complications, security and performance implications. The APM volume
2 15.20 [1] states two possibilities that result in a VMRUN exit with
VMEXIT_INVALID due to injected events. These are either
• Reserved values of TYPE have been specified.
• TYPE = 3 (exception) has been specified with a vector that does not
   correspond to an exception (this includes vector 2, which is an NMI, not
   an exception).
Extend the VMCB checks to check for such inconsistency.

The collection of the invalid exception vectors are picked from the upstream KVM
commit ("7e79f71bca5c" KVM: nSVM: Add missing consistency check for EVENTINJ).

[1] https://docs.amd.com/v/u/en-US/24593_3.44_APM_Vol2

Signed-off-by: Abdelkareem Abdelsaamad <abdelkareem.abdelsaamad@xxxxxxxxxx>
---
Testing:
  - Using a locally developed XTF nested virt setup, I manually tested VMRUN
    instruction handling with a malformed VMCB:
    1) Inject event with the type (7).
       The hypervisor logs show the message
       (XEN) [  645.155609] d2v0[nsvm_vmcb_prepare4vmrun]: eventinj: Invalid 
Injected
             Event Type: (0x7)
    2) Inject event with the exception value (3) and the vector value (2) for 
NMI.
       The hypervisor logs show the message
       (XEN) [  645.157277] d2v0[nsvm_vmcb_prepare4vmrun]: eventinj: Invalid 
Injected Event.
              Exception type: (0x3), with a vector: (0x2) does not belong to an 
exception

  - CI tests:
https://gitlab.com/xen-project/people/aabdelsa/xen/-/pipelines/2678629270
---
  xen/arch/x86/hvm/svm/vmcb.c | 36 ++++++++++++++++++++++++++++++++++++
  xen/arch/x86/hvm/svm/vmcb.h |  3 +++
  2 files changed, 39 insertions(+)

diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 975a1eaef8..1ca8474958 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -320,6 +320,31 @@ void svm_vmcb_dump(const char *from, const struct 
vmcb_struct *vmcb)
      svm_dump_sel("  TR", &vmcb->tr);
  }
+static bool is_valid_svm_vmcb_injected_exception_vector(
+    const struct vmcb_struct *vmcb, uint8_t vmcb_injected_vector)
+{
+    return ( (vmcb_injected_vector == X86_EXC_DE) ||
+             (vmcb_injected_vector == X86_EXC_DB) ||
+             (vmcb_injected_vector == X86_EXC_BP) ||
+             (vmcb_injected_vector == X86_EXC_OF) ||
+             (vmcb_injected_vector == X86_EXC_BR) ||
+             (vmcb_injected_vector == X86_EXC_UD) ||
+             (vmcb_injected_vector == X86_EXC_NM) ||
+             (vmcb_injected_vector == X86_EXC_DF) ||
+             (vmcb_injected_vector == X86_EXC_TS) ||
+             (vmcb_injected_vector == X86_EXC_NP) ||
+             (vmcb_injected_vector == X86_EXC_SS) ||
+             (vmcb_injected_vector == X86_EXC_GP) ||
+             (vmcb_injected_vector == X86_EXC_PF) ||
+             (vmcb_injected_vector == X86_EXC_MF) ||
+             (vmcb_injected_vector == X86_EXC_AC) ||
+             (vmcb_injected_vector == X86_EXC_MC) ||
+             (vmcb_injected_vector == X86_EXC_XM) ||
+             (vmcb_injected_vector == X86_EXC_HV) ||
+             (vmcb_injected_vector == X86_EXC_SX) ||
+             (vmcb_get_sev_es(vmcb) && vmcb_injected_vector == X86_EXC_VC) );

I'm not sure that #VC is gated behind SEV-ES guest.

Regardless, injecting manually #VC is weird (especially for SEV-ES guests where it's strongly discouraged), but it could be somewhat abused to emulate some of the SEV-ES semantics. So I would suggest to threat it like the others.

+}
+
  bool svm_vmcb_isvalid(
      const char *from, const struct vmcb_struct *vmcb, const struct vcpu *v,
      bool verbose)
@@ -330,6 +355,8 @@ bool svm_vmcb_isvalid(
      unsigned long cr4 = vmcb_get_cr4(vmcb);
      unsigned long valid;
      uint64_t efer = vmcb_get_efer(vmcb);
+    uint8_t vmcb_injected_type = vmcb->event_inj.type & 
SVM_EVENT_INJ_TYPE_MASK;
+    uint8_t vmcb_injected_vector = vmcb->event_inj.vector & 
SVM_EVENT_INJ_VEC_MASK;

What are these masks for ?

The definition of vmcb->event_inj suggest that they are not required
> uint8_t  vector;
> uint8_t  type:3;

#define PRINTF(fmt, args...) do { \
      if ( !verbose ) return true; \
@@ -392,6 +419,15 @@ bool svm_vmcb_isvalid(
          PRINTF("eventinj: MBZ bits are set (%#"PRIx64")\n",
                 vmcb->event_inj.raw);
+ if ( vmcb_injected_type > X86_ET_SW_INT )
+        PRINTF("eventinj: Invalid Injected Event Type: (%#"PRIx8")\n",
+               vmcb_injected_type);

What about vmcb_injected_type == 1 case ?

+
+    if ( (vmcb_injected_type == X86_ET_HW_EXC) &&
+         !is_valid_svm_vmcb_injected_exception_vector(vmcb, 
vmcb_injected_vector) )
+        PRINTF("eventinj: Invalid Injected Event. Exception type: (%#"PRIx8"),"
+               " with a vector: (%#"PRIx8") does not belong to an exception\n",
+               vmcb_injected_type, vmcb_injected_vector);
  #undef PRINTF
      return ret;
  }
diff --git a/xen/arch/x86/hvm/svm/vmcb.h b/xen/arch/x86/hvm/svm/vmcb.h
index 13ccfd3ff9..3c22095db1 100644
--- a/xen/arch/x86/hvm/svm/vmcb.h
+++ b/xen/arch/x86/hvm/svm/vmcb.h
@@ -306,6 +306,9 @@ enum
      TLB_CTRL_FLUSH_ASID_NONGLOBAL = 7,
  };
+#define SVM_EVENT_INJ_VEC_MASK 0xff
+#define SVM_EVENT_INJ_TYPE_MASK    0x7
+
  typedef union
  {
      struct

Teddy

Attachment: OpenPGP_0x660FA9D102CBCFD0.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature


 


Rackspace

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