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

[xen master] x86emul/fuzz: sanitize CR4 values



commit 829d67e244e211216226bc0b9d1912a413ffe4c2
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Wed Aug 26 14:14:03 2026 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Aug 26 14:14:03 2026 +0200

    x86emul/fuzz: sanitize CR4 values
    
    While the CPU policy is obtained from hardware, the CRn values to start
    with are taken from fuzzed input. Since most CR4 bits can only be set when
    the respective feature is indicated as available by CPUID, the emulator
    often only checks the CR4 bit. Without sanitization, assertions like the
    one in emul_test_read_xcr() (checking XSAVE support) could therefore
    trigger.
    
    Omit most paging-only bits from sanitization, as the core emulator doesn't
    itself walk page tables. LA57 wants checking for the bit being used by
    CANONICALIZE_MAYBE().
    
    Reported-by: Andrew Mbugua <andrewprecious388@xxxxxxxxx>
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 111 +++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 2 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index a797d17fe5..dec4790aa6 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -824,6 +824,58 @@ static void sanitize_input(struct x86_emulate_ctxt *ctxt)
     regs->error_code = 0;
     regs->entry_vector = 0;
 
+    /*
+     * Most CR4 bits can only be set when corresponding CPUID bits are set.
+     * (In such cases the emulator may only check the CR4 bit.)
+     */
+    if ( !cpu_policy.basic.vme )
+        c->cr[4] &= ~(X86_CR4_VME | X86_CR4_PVI);
+
+    if ( !cpu_policy.basic.tsc )
+        c->cr[4] &= ~X86_CR4_TSD;
+
+    if ( !cpu_policy.basic.de )
+        c->cr[4] &= ~X86_CR4_DE;
+
+    if ( !cpu_policy.basic.fxsr )
+        c->cr[4] &= ~X86_CR4_OSFXSR;
+
+    if ( !cpu_policy.basic.sse )
+        c->cr[4] &= ~X86_CR4_OSXMMEXCPT;
+
+    if ( !cpu_policy.feat.umip )
+        c->cr[4] &= ~X86_CR4_UMIP;
+
+    if ( !cpu_policy.feat.la57 )
+        c->cr[4] &= ~X86_CR4_LA57;
+
+    if ( !cpu_policy.basic.vmx )
+        c->cr[4] &= ~X86_CR4_VMXE;
+
+    if ( !cpu_policy.basic.smx )
+        c->cr[4] &= ~X86_CR4_SMXE;
+
+    if ( !cpu_policy.feat.fsgsbase )
+        c->cr[4] &= ~X86_CR4_FSGSBASE;
+
+    if ( !cpu_policy.basic.pcid )
+        c->cr[4] &= ~X86_CR4_PCIDE;
+
+    if ( !cpu_policy.basic.xsave || !cpu_has_xsave )
+        c->cr[4] &= ~X86_CR4_OSXSAVE;
+
+    if ( !cpu_policy.feat.pku )
+        c->cr[4] &= ~X86_CR4_PKE;
+
+    if ( !cpu_policy.feat.cet_ss && !cpu_policy.feat.cet_ibt )
+        c->cr[4] &= ~X86_CR4_CET;
+
+    if ( !cpu_policy.feat.pks )
+        c->cr[4] &= ~X86_CR4_PKS;
+
+    if ( !cpu_policy.feat.fred )
+        c->cr[4] &= ~X86_CR4_FRED;
+
     /*
      * For both RIP and RSP make sure we test with canonical values in at
      * least a fair number of cases. As all other registers aren't tied to
@@ -839,10 +891,14 @@ static void sanitize_input(struct x86_emulate_ctxt *ctxt)
     if ( c->cr[0] & X86_CR0_PG )
         c->cr[0] |= X86_CR0_PE;
 
-    /* EFLAGS.VM not available in long mode */
+    /* EFLAGS.VM not available in long mode, but CR4.PAE is required. */
     if ( long_mode_active(ctxt) )
+    {
         regs->rflags &= ~X86_EFLAGS_VM;
 
+        c->cr[4] |= X86_CR4_PAE;
+    }
+
     /* EFLAGS.VM implies 16-bit mode */
     if ( regs->rflags & X86_EFLAGS_VM )
     {
@@ -862,12 +918,63 @@ static bool check_state(struct x86_emulate_ctxt *ctxt)
     const struct fuzz_corpus *c = s->corpus;
     const struct cpu_user_regs *regs = &c->regs;
 
-    if ( long_mode_active(ctxt) && !(c->cr[0] & X86_CR0_PG) )
+    if ( long_mode_active(ctxt) &&
+         (!(c->cr[0] & X86_CR0_PG) || !(c->cr[4] & X86_CR4_PAE)) )
         return false;
 
     if ( (c->cr[0] & X86_CR0_PG) && !(c->cr[0] & X86_CR0_PE) )
         return false;
 
+    if ( (c->cr[4] & (X86_CR4_VME | X86_CR4_PVI)) && !cpu_policy.basic.vme )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_TSD) && !cpu_policy.basic.tsc )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_DE) && !cpu_policy.basic.de )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_OSFXSR) && !cpu_policy.basic.fxsr )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_OSXMMEXCPT) && !cpu_policy.basic.sse )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_UMIP) && !cpu_policy.feat.umip )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_LA57) && !cpu_policy.feat.la57 )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_VMXE) && !cpu_policy.basic.vmx )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_SMXE) && !cpu_policy.basic.smx )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_FSGSBASE) && !cpu_policy.feat.fsgsbase )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_PCIDE) && !cpu_policy.basic.pcid )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_OSXSAVE) &&
+         (!cpu_policy.basic.xsave || !cpu_has_xsave) )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_PKE) && !cpu_policy.feat.pku )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_CET) &&
+         !cpu_policy.feat.cet_ss && !cpu_policy.feat.cet_ibt )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_PKS) && !cpu_policy.feat.pks )
+        return false;
+
+    if ( (c->cr[4] & X86_CR4_FRED) && !cpu_policy.feat.fred )
+        return false;
+
     if ( (regs->rflags & X86_EFLAGS_VM) &&
          (c->segments[x86_seg_cs].db || c->segments[x86_seg_ss].db) )
         return false;
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

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