ia64/xen-unstable

changeset 9867:4d667a139318

This patch addresses CVE-2006-1056 (information leak from
fxsave/fxrstor on AMD CPUs) and also adjusts 64-bit handling so that
full 64-bit RIP/RDP values get saved/restored. More fine-grained
handling may be needed if 32-bit processes are expected to properly
see their selectors (native Linux doesn't currently do that either,
but there is a patch to adjust it there).

Original patch: Jan Beulich (based on Linux original by Andi Kleen)

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Apr 26 20:01:37 2006 +0100 (2006-04-26)
parents 1d69cff40b8c
children 3d884434ec97
files xen/arch/x86/i387.c
line diff
     1.1 --- a/xen/arch/x86/i387.c	Wed Apr 26 17:41:19 2006 +0100
     1.2 +++ b/xen/arch/x86/i387.c	Wed Apr 26 20:01:37 2006 +0100
     1.3 @@ -26,19 +26,54 @@ void init_fpu(void)
     1.4  void save_init_fpu(struct vcpu *v)
     1.5  {
     1.6      unsigned long cr0 = read_cr0();
     1.7 +    char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
     1.8  
     1.9      /* This can happen, if a paravirtualised guest OS has set its CR0.TS. */
    1.10      if ( cr0 & X86_CR0_TS )
    1.11          clts();
    1.12  
    1.13      if ( cpu_has_fxsr )
    1.14 +    {
    1.15 +#ifdef __i386__
    1.16          __asm__ __volatile__ (
    1.17 -            "fxsave %0 ; fnclex"
    1.18 -            : "=m" (v->arch.guest_context.fpu_ctxt) );
    1.19 +            "fxsave %0"
    1.20 +            : "=m" (*fpu_ctxt) );
    1.21 +#else /* __x86_64__ */
    1.22 +        /*
    1.23 +         * The only way to force fxsaveq on a wide range of gas versions. On 
    1.24 +         * older versions the rex64 prefix works only if we force an addressing 
    1.25 +         * mode that doesn't require extended registers.
    1.26 +         */
    1.27 +        __asm__ __volatile__ (
    1.28 +            "rex64/fxsave (%1)"
    1.29 +            : "=m" (*fpu_ctxt) : "cdaSDb" (fpu_ctxt) );
    1.30 +#endif
    1.31 +
    1.32 +        /* Clear exception flags if FSW.ES is set. */
    1.33 +        if ( unlikely(fpu_ctxt[2] & 0x80) )
    1.34 +            __asm__ __volatile__ ("fnclex");
    1.35 +
    1.36 +        /*
    1.37 +         * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
    1.38 +         * is pending. Clear the x87 state here by setting it to fixed
    1.39 +         * values. The hypervisor data segment can be sometimes 0 and
    1.40 +         * sometimes new user value. Both should be ok. Use the FPU saved
    1.41 +         * data block as a safe address because it should be in L1.
    1.42 +         */
    1.43 +        if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
    1.44 +        {
    1.45 +            __asm__ __volatile__ (
    1.46 +                "emms\n\t"  /* clear stack tags */
    1.47 +                "fildl %0"  /* load to clear state */
    1.48 +                : : "m" (*fpu_ctxt) );
    1.49 +        }
    1.50 +    }
    1.51      else
    1.52 +    {
    1.53          __asm__ __volatile__ (
    1.54              "fnsave %0 ; fwait"
    1.55 -            : "=m" (v->arch.guest_context.fpu_ctxt) );
    1.56 +            : "=m" (*fpu_ctxt) );
    1.57 +    }
    1.58  
    1.59      clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags);
    1.60      write_cr0(cr0|X86_CR0_TS);
    1.61 @@ -46,14 +81,22 @@ void save_init_fpu(struct vcpu *v)
    1.62  
    1.63  void restore_fpu(struct vcpu *v)
    1.64  {
    1.65 +    char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
    1.66 +
    1.67      /*
    1.68       * FXRSTOR can fault if passed a corrupted data block. We handle this
    1.69       * possibility, which may occur if the block was passed to us by control
    1.70       * tools, by silently clearing the block.
    1.71       */
    1.72      if ( cpu_has_fxsr )
    1.73 +    {
    1.74          __asm__ __volatile__ (
    1.75 +#ifdef __i386__
    1.76              "1: fxrstor %0            \n"
    1.77 +#else /* __x86_64__ */
    1.78 +            /* See above for why the operands/constraints are this way. */
    1.79 +            "1: rex64/fxrstor (%2)    \n"
    1.80 +#endif
    1.81              ".section .fixup,\"ax\"   \n"
    1.82              "2: push %%"__OP"ax       \n"
    1.83              "   push %%"__OP"cx       \n"
    1.84 @@ -72,12 +115,19 @@ void restore_fpu(struct vcpu *v)
    1.85              "   "__FIXUP_WORD" 1b,2b  \n"
    1.86              ".previous                \n"
    1.87              : 
    1.88 -            : "m" (v->arch.guest_context.fpu_ctxt),
    1.89 -              "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4) );
    1.90 +            : "m" (*fpu_ctxt),
    1.91 +              "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4)
    1.92 +#ifdef __x86_64__
    1.93 +             ,"cdaSDb" (fpu_ctxt)
    1.94 +#endif
    1.95 +            );
    1.96 +    }
    1.97      else
    1.98 +    {
    1.99          __asm__ __volatile__ (
   1.100              "frstor %0"
   1.101              : : "m" (v->arch.guest_context.fpu_ctxt) );
   1.102 +    }
   1.103  }
   1.104  
   1.105  /*