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

[Xen-changelog] [linux-2.6.18-xen] xen/i386: hypervisor_callback adjustments



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1242292120 -3600
# Node ID 9b945480054430882b60bb5e5f660822a1c07b70
# Parent  271d9b9bee40657b1714b2bb62531e989c7b5813
xen/i386: hypervisor_callback adjustments

The missing check of the interrupted code's code selector in
hypervisor_callback() allowed a user mode application to oops (and
perhaps crash) the kernel.

Further adjustments:
- the 'main' critical region does not include the jmp following the
  disabling of interrupts
- the sysexit_[se]crit range checks got broken at some point - the
  sysexit ciritcal region is always at higher addresses than the
  'main'
  one, yielding the check pointless (but consuming execution time);
  since the supervisor mode kernel isn't actively used afaict, I moved
  that code into an #ifdef using a hypothetical config option
- the use of a numeric label across more than 300 lines of code always
  seemed pretty fragile to me, so the patch replaces this with a local
  named label
- streamlined the critical_region_fixup code to eliminate a branch

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 arch/i386/kernel/entry-xen.S |   58 ++++++++++++++++++++++---------------------
 1 files changed, 30 insertions(+), 28 deletions(-)

diff -r 271d9b9bee40 -r 9b9454800544 arch/i386/kernel/entry-xen.S
--- a/arch/i386/kernel/entry-xen.S      Thu May 14 10:08:10 2009 +0100
+++ b/arch/i386/kernel/entry-xen.S      Thu May 14 10:08:40 2009 +0100
@@ -531,8 +531,8 @@ 1:  iret
 .previous
 14:    __DISABLE_INTERRUPTS
        TRACE_IRQS_OFF
-       jmp  11f
 ecrit:  /**** END OF CRITICAL REGION ****/
+       jmp  .Ldo_upcall
 
        CFI_RESTORE_STATE
 hypervisor_iret:
@@ -790,17 +790,23 @@ ENTRY(hypervisor_callback)
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
+       testb $2,CS(%esp)
        movl EIP(%esp),%eax
+       jnz  .Ldo_upcall
        cmpl $scrit,%eax
-       jb   11f
+       jb   0f
        cmpl $ecrit,%eax
        jb   critical_region_fixup
+0:
+#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL
        cmpl $sysexit_scrit,%eax
-       jb   11f
+       jb   .Ldo_upcall
        cmpl $sysexit_ecrit,%eax
-       ja   11f
+       ja   .Ldo_upcall
        addl $OLDESP,%esp               # Remove eflags...ebx from stack frame.
-11:    push %esp
+#endif
+.Ldo_upcall:
+       push %esp
        CFI_ADJUST_CFA_OFFSET 4
        call evtchn_do_upcall
        add  $4,%esp
@@ -816,39 +822,35 @@ 11:       push %esp
 # provides the number of bytes which have already been popped from the
 # interrupted stack frame.
 critical_region_fixup:
-       movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes 
popped
-       cmpb $0xff,%cl                  # 0xff => vcpu_info critical region
-       jne  15f
-       xorl %ecx,%ecx
-15:    leal (%esp,%ecx),%esi           # %esi points at end of src region
+       movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots 
popped
+       testl %ecx,%ecx
+       leal (%esp,%ecx,4),%esi         # %esi points at end of src region
        leal OLDESP(%esp),%edi          # %edi points at end of dst region
-       shrl $2,%ecx                    # convert words to bytes
-       je   17f                        # skip loop if nothing to copy
+       jle   17f                       # skip loop if nothing to copy
 16:    subl $4,%esi                    # pre-decrementing copy loop
        subl $4,%edi
        movl (%esi),%eax
        movl %eax,(%edi)
        loop 16b
 17:    movl %edi,%esp                  # final %edi is top of merged stack
-       jmp  11b
+       jmp  .Ldo_upcall
 
 .section .rodata,"a"
 critical_fixup_table:
-       .byte 0xff,0xff,0xff            # testb $0xff,(%esi) = __TEST_PENDING
-       .byte 0xff,0xff                 # jnz  14f
-       .byte 0x00                      # pop  %ebx
-       .byte 0x04                      # pop  %ecx
-       .byte 0x08                      # pop  %edx
-       .byte 0x0c                      # pop  %esi
-       .byte 0x10                      # pop  %edi
-       .byte 0x14                      # pop  %ebp
-       .byte 0x18                      # pop  %eax
-       .byte 0x1c                      # pop  %ds
-       .byte 0x20                      # pop  %es
-       .byte 0x24,0x24,0x24            # add  $4,%esp
-       .byte 0x28                      # iret
-       .byte 0xff,0xff,0xff,0xff       # movb $1,1(%esi)
-       .byte 0x00,0x00                 # jmp  11b
+       .byte -1,-1,-1                  # testb $0xff,(%esi) = __TEST_PENDING
+       .byte -1,-1                     # jnz  14f
+       .byte 0                         # pop  %ebx
+       .byte 1                         # pop  %ecx
+       .byte 2                         # pop  %edx
+       .byte 3                         # pop  %esi
+       .byte 4                         # pop  %edi
+       .byte 5                         # pop  %ebp
+       .byte 6                         # pop  %eax
+       .byte 7                         # pop  %ds
+       .byte 8                         # pop  %es
+       .byte 9,9,9                     # add  $4,%esp
+       .byte 10                        # iret
+       .byte -1,-1,-1,-1               # movb $1,1(%esi) = __DISABLE_INTERRUPTS
 .previous
 
 # Hypervisor uses this for application faults while it executes.

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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