# 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
|