ia64/xen-unstable

changeset 8573:1e1107e3d894

More do_iret() fixes. We need to take care in restoring
EFLAGS that we do not pull in non-zero IOPL, then crash
the domain, and then bug out when dom0 gets vcpu context.
This could otherwise be triggered by a malicious guest.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jan 11 20:14:27 2006 +0100 (2006-01-11)
parents 1c186b28289b
children 08d2a74dce81
files xen/arch/x86/x86_32/traps.c
line diff
     1.1 --- a/xen/arch/x86/x86_32/traps.c	Wed Jan 11 20:03:53 2006 +0100
     1.2 +++ b/xen/arch/x86/x86_32/traps.c	Wed Jan 11 20:14:27 2006 +0100
     1.3 @@ -160,7 +160,7 @@ asmlinkage void do_double_fault(void)
     1.4  static inline void pop_from_guest_stack(
     1.5      void *dst, struct cpu_user_regs *regs, unsigned int bytes)
     1.6  {
     1.7 -    if ( unlikely(copy_from_user(dst, (void __user *)regs->esp, bytes)) )
     1.8 +    if ( unlikely(__copy_from_user(dst, (void __user *)regs->esp, bytes)) )
     1.9          domain_crash_synchronous();
    1.10      regs->esp += bytes;
    1.11  }
    1.12 @@ -168,19 +168,31 @@ static inline void pop_from_guest_stack(
    1.13  asmlinkage unsigned long do_iret(void)
    1.14  {
    1.15      struct cpu_user_regs *regs = guest_cpu_user_regs();
    1.16 +    u32 eflags;
    1.17 +
    1.18 +    /* Check worst-case stack frame for overlap with Xen protected area. */
    1.19 +    if ( unlikely(!access_ok(regs->esp, 40)) )
    1.20 +        domain_crash_synchronous();
    1.21  
    1.22      /* Pop and restore EAX (clobbered by hypercall). */
    1.23      pop_from_guest_stack(&regs->eax, regs, 4);
    1.24  
    1.25 -    /* Pop and restore EFLAGS, CS and EIP. */
    1.26 -    pop_from_guest_stack(&regs->eip, regs, 12);
    1.27 +    /* Pop and restore CS and EIP. */
    1.28 +    pop_from_guest_stack(&regs->eip, regs, 8);
    1.29 +
    1.30 +    /*
    1.31 +     * Pop, fix up and restore EFLAGS. We fix up in a local staging area
    1.32 +     * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
    1.33 +     */
    1.34 +    pop_from_guest_stack(&eflags, regs, 4);
    1.35 +    regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF;
    1.36  
    1.37      if ( VM86_MODE(regs) )
    1.38      {
    1.39          /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */
    1.40          pop_from_guest_stack(&regs->esp, regs, 24);
    1.41      }
    1.42 -    else if ( RING_0(regs) )
    1.43 +    else if ( unlikely(RING_0(regs)) )
    1.44      {
    1.45          domain_crash_synchronous();
    1.46      }
    1.47 @@ -190,10 +202,6 @@ asmlinkage unsigned long do_iret(void)
    1.48          pop_from_guest_stack(&regs->esp, regs, 8);
    1.49      }
    1.50  
    1.51 -    /* Fixup EFLAGS. */
    1.52 -    regs->eflags &= ~X86_EFLAGS_IOPL;
    1.53 -    regs->eflags |= X86_EFLAGS_IF;
    1.54 -
    1.55      /* No longer in NMI context. */
    1.56      clear_bit(_VCPUF_nmi_masked, &current->vcpu_flags);
    1.57