From: kaf24@firebug.cl.cam.ac.uk Date: Wed, 11 Jan 2006 19:14:27 +0000 (+0100) Subject: More do_iret() fixes. We need to take care in restoring X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16541^2~61^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=8a790edb70aa0745d5cb25eceba8ab077a36efe4;p=xen.git 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 --- diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 6f7fb83640..e9c98d8aa8 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -160,7 +160,7 @@ asmlinkage void do_double_fault(void) static inline void pop_from_guest_stack( void *dst, struct cpu_user_regs *regs, unsigned int bytes) { - if ( unlikely(copy_from_user(dst, (void __user *)regs->esp, bytes)) ) + if ( unlikely(__copy_from_user(dst, (void __user *)regs->esp, bytes)) ) domain_crash_synchronous(); regs->esp += bytes; } @@ -168,19 +168,31 @@ static inline void pop_from_guest_stack( asmlinkage unsigned long do_iret(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); + u32 eflags; + + /* Check worst-case stack frame for overlap with Xen protected area. */ + if ( unlikely(!access_ok(regs->esp, 40)) ) + domain_crash_synchronous(); /* Pop and restore EAX (clobbered by hypercall). */ pop_from_guest_stack(®s->eax, regs, 4); - /* Pop and restore EFLAGS, CS and EIP. */ - pop_from_guest_stack(®s->eip, regs, 12); + /* Pop and restore CS and EIP. */ + pop_from_guest_stack(®s->eip, regs, 8); + + /* + * Pop, fix up and restore EFLAGS. We fix up in a local staging area + * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt. + */ + pop_from_guest_stack(&eflags, regs, 4); + regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF; if ( VM86_MODE(regs) ) { /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ pop_from_guest_stack(®s->esp, regs, 24); } - else if ( RING_0(regs) ) + else if ( unlikely(RING_0(regs)) ) { domain_crash_synchronous(); } @@ -190,10 +202,6 @@ asmlinkage unsigned long do_iret(void) pop_from_guest_stack(®s->esp, regs, 8); } - /* Fixup EFLAGS. */ - regs->eflags &= ~X86_EFLAGS_IOPL; - regs->eflags |= X86_EFLAGS_IF; - /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags);