ia64/linux-2.6.18-xen.hg

changeset 870:9b9454800544

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@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 14 10:08:40 2009 +0100 (2009-05-14)
parents 271d9b9bee40
children 9cbcc9008446
files arch/i386/kernel/entry-xen.S
line diff
     1.1 --- a/arch/i386/kernel/entry-xen.S	Thu May 14 10:08:10 2009 +0100
     1.2 +++ b/arch/i386/kernel/entry-xen.S	Thu May 14 10:08:40 2009 +0100
     1.3 @@ -531,8 +531,8 @@ 1:	iret
     1.4  .previous
     1.5  14:	__DISABLE_INTERRUPTS
     1.6  	TRACE_IRQS_OFF
     1.7 -	jmp  11f
     1.8  ecrit:  /**** END OF CRITICAL REGION ****/
     1.9 +	jmp  .Ldo_upcall
    1.10  
    1.11  	CFI_RESTORE_STATE
    1.12  hypervisor_iret:
    1.13 @@ -790,17 +790,23 @@ ENTRY(hypervisor_callback)
    1.14  	pushl %eax
    1.15  	CFI_ADJUST_CFA_OFFSET 4
    1.16  	SAVE_ALL
    1.17 +	testb $2,CS(%esp)
    1.18  	movl EIP(%esp),%eax
    1.19 +	jnz  .Ldo_upcall
    1.20  	cmpl $scrit,%eax
    1.21 -	jb   11f
    1.22 +	jb   0f
    1.23  	cmpl $ecrit,%eax
    1.24  	jb   critical_region_fixup
    1.25 +0:
    1.26 +#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL
    1.27  	cmpl $sysexit_scrit,%eax
    1.28 -	jb   11f
    1.29 +	jb   .Ldo_upcall
    1.30  	cmpl $sysexit_ecrit,%eax
    1.31 -	ja   11f
    1.32 +	ja   .Ldo_upcall
    1.33  	addl $OLDESP,%esp		# Remove eflags...ebx from stack frame.
    1.34 -11:	push %esp
    1.35 +#endif
    1.36 +.Ldo_upcall:
    1.37 +	push %esp
    1.38  	CFI_ADJUST_CFA_OFFSET 4
    1.39  	call evtchn_do_upcall
    1.40  	add  $4,%esp
    1.41 @@ -816,39 +822,35 @@ 11:	push %esp
    1.42  # provides the number of bytes which have already been popped from the
    1.43  # interrupted stack frame.
    1.44  critical_region_fixup:
    1.45 -	movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes popped
    1.46 -	cmpb $0xff,%cl                  # 0xff => vcpu_info critical region
    1.47 -	jne  15f
    1.48 -	xorl %ecx,%ecx
    1.49 -15:	leal (%esp,%ecx),%esi		# %esi points at end of src region
    1.50 +	movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped
    1.51 +	testl %ecx,%ecx
    1.52 +	leal (%esp,%ecx,4),%esi		# %esi points at end of src region
    1.53  	leal OLDESP(%esp),%edi		# %edi points at end of dst region
    1.54 -	shrl $2,%ecx			# convert words to bytes
    1.55 -	je   17f			# skip loop if nothing to copy
    1.56 +	jle   17f			# skip loop if nothing to copy
    1.57  16:	subl $4,%esi			# pre-decrementing copy loop
    1.58  	subl $4,%edi
    1.59  	movl (%esi),%eax
    1.60  	movl %eax,(%edi)
    1.61  	loop 16b
    1.62  17:	movl %edi,%esp			# final %edi is top of merged stack
    1.63 -	jmp  11b
    1.64 +	jmp  .Ldo_upcall
    1.65  
    1.66  .section .rodata,"a"
    1.67  critical_fixup_table:
    1.68 -	.byte 0xff,0xff,0xff		# testb $0xff,(%esi) = __TEST_PENDING
    1.69 -	.byte 0xff,0xff			# jnz  14f
    1.70 -	.byte 0x00			# pop  %ebx
    1.71 -	.byte 0x04			# pop  %ecx
    1.72 -	.byte 0x08			# pop  %edx
    1.73 -	.byte 0x0c			# pop  %esi
    1.74 -	.byte 0x10			# pop  %edi
    1.75 -	.byte 0x14			# pop  %ebp
    1.76 -	.byte 0x18			# pop  %eax
    1.77 -	.byte 0x1c			# pop  %ds
    1.78 -	.byte 0x20			# pop  %es
    1.79 -	.byte 0x24,0x24,0x24		# add  $4,%esp
    1.80 -	.byte 0x28			# iret
    1.81 -	.byte 0xff,0xff,0xff,0xff	# movb $1,1(%esi)
    1.82 -	.byte 0x00,0x00			# jmp  11b
    1.83 +	.byte -1,-1,-1			# testb $0xff,(%esi) = __TEST_PENDING
    1.84 +	.byte -1,-1			# jnz  14f
    1.85 +	.byte 0				# pop  %ebx
    1.86 +	.byte 1				# pop  %ecx
    1.87 +	.byte 2				# pop  %edx
    1.88 +	.byte 3				# pop  %esi
    1.89 +	.byte 4				# pop  %edi
    1.90 +	.byte 5				# pop  %ebp
    1.91 +	.byte 6				# pop  %eax
    1.92 +	.byte 7				# pop  %ds
    1.93 +	.byte 8				# pop  %es
    1.94 +	.byte 9,9,9			# add  $4,%esp
    1.95 +	.byte 10			# iret
    1.96 +	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
    1.97  .previous
    1.98  
    1.99  # Hypervisor uses this for application faults while it executes.