]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/9b9454800544 |
2 | # HG changeset 870 patch | |
3 | # User Keir Fraser <keir.fraser@citrix.com> | |
4 | # Date 1242292120 -3600 | |
5 | # Node ID 9b945480054430882b60bb5e5f660822a1c07b70 | |
6 | # Parent 271d9b9bee40657b1714b2bb62531e989c7b5813 | |
7 | Subject: i386: hypervisor_callback adjustments | |
8 | References: bnc#503457 CVE-2009-1758 | |
9 | Patch-mainline: obsolete | |
10 | ||
11 | The missing check of the interrupted code's code selector in | |
12 | hypervisor_callback() allowed a user mode application to oops (and | |
13 | perhaps crash) the kernel. | |
14 | ||
15 | Further adjustments: | |
16 | - the 'main' critical region does not include the jmp following the | |
17 | disabling of interrupts | |
18 | - the sysexit_[se]crit range checks got broken at some point - the | |
19 | sysexit ciritcal region is always at higher addresses than the | |
20 | 'main' | |
21 | one, yielding the check pointless (but consuming execution time); | |
22 | since the supervisor mode kernel isn't actively used afaict, I moved | |
23 | that code into an #ifdef using a hypothetical config option | |
24 | - the use of a numeric label across more than 300 lines of code always | |
25 | seemed pretty fragile to me, so the patch replaces this with a local | |
26 | named label | |
27 | - streamlined the critical_region_fixup code to eliminate a branch | |
28 | ||
29 | Signed-off-by: Jan Beulich <jbeulich@novell.com> | |
30 | ||
31 | --- sle11-2009-05-14.orig/arch/x86/kernel/entry_32-xen.S 2009-05-15 08:44:13.000000000 +0200 | |
32 | +++ sle11-2009-05-14/arch/x86/kernel/entry_32-xen.S 2009-05-15 08:45:36.000000000 +0200 | |
33 | @@ -529,8 +529,8 @@ scrit: /**** START OF CRITICAL REGION ** | |
34 | .previous | |
35 | 14: __DISABLE_INTERRUPTS | |
36 | TRACE_IRQS_OFF | |
37 | - jmp 11f | |
38 | ecrit: /**** END OF CRITICAL REGION ****/ | |
39 | + jmp .Ldo_upcall | |
40 | ||
41 | CFI_RESTORE_STATE | |
42 | hypervisor_iret: | |
43 | @@ -788,17 +788,23 @@ ENTRY(hypervisor_callback) | |
44 | pushl %eax | |
45 | CFI_ADJUST_CFA_OFFSET 4 | |
46 | SAVE_ALL | |
47 | + testb $2,CS(%esp) | |
48 | movl EIP(%esp),%eax | |
49 | + jnz .Ldo_upcall | |
50 | cmpl $scrit,%eax | |
51 | - jb 11f | |
52 | + jb 0f | |
53 | cmpl $ecrit,%eax | |
54 | jb critical_region_fixup | |
55 | +0: | |
56 | +#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL | |
57 | cmpl $sysexit_scrit,%eax | |
58 | - jb 11f | |
59 | + jb .Ldo_upcall | |
60 | cmpl $sysexit_ecrit,%eax | |
61 | - ja 11f | |
62 | + ja .Ldo_upcall | |
63 | addl $OLDESP,%esp # Remove eflags...ebx from stack frame. | |
64 | -11: push %esp | |
65 | +#endif | |
66 | +.Ldo_upcall: | |
67 | + push %esp | |
68 | CFI_ADJUST_CFA_OFFSET 4 | |
69 | call evtchn_do_upcall | |
70 | add $4,%esp | |
71 | @@ -814,39 +820,35 @@ ENTRY(hypervisor_callback) | |
72 | # provides the number of bytes which have already been popped from the | |
73 | # interrupted stack frame. | |
74 | critical_region_fixup: | |
75 | - movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes popped | |
76 | - cmpb $0xff,%cl # 0xff => vcpu_info critical region | |
77 | - jne 15f | |
78 | - xorl %ecx,%ecx | |
79 | -15: leal (%esp,%ecx),%esi # %esi points at end of src region | |
80 | + movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped | |
81 | + testl %ecx,%ecx | |
82 | + leal (%esp,%ecx,4),%esi # %esi points at end of src region | |
83 | leal OLDESP(%esp),%edi # %edi points at end of dst region | |
84 | - shrl $2,%ecx # convert words to bytes | |
85 | - je 17f # skip loop if nothing to copy | |
86 | + jle 17f # skip loop if nothing to copy | |
87 | 16: subl $4,%esi # pre-decrementing copy loop | |
88 | subl $4,%edi | |
89 | movl (%esi),%eax | |
90 | movl %eax,(%edi) | |
91 | loop 16b | |
92 | 17: movl %edi,%esp # final %edi is top of merged stack | |
93 | - jmp 11b | |
94 | + jmp .Ldo_upcall | |
95 | ||
96 | .section .rodata,"a" | |
97 | critical_fixup_table: | |
98 | - .byte 0xff,0xff,0xff # testb $0xff,(%esi) = __TEST_PENDING | |
99 | - .byte 0xff,0xff # jnz 14f | |
100 | - .byte 0x00 # pop %ebx | |
101 | - .byte 0x04 # pop %ecx | |
102 | - .byte 0x08 # pop %edx | |
103 | - .byte 0x0c # pop %esi | |
104 | - .byte 0x10 # pop %edi | |
105 | - .byte 0x14 # pop %ebp | |
106 | - .byte 0x18 # pop %eax | |
107 | - .byte 0x1c # pop %ds | |
108 | - .byte 0x20 # pop %es | |
109 | - .byte 0x24,0x24,0x24 # add $4,%esp | |
110 | - .byte 0x28 # iret | |
111 | - .byte 0xff,0xff,0xff,0xff # movb $1,1(%esi) | |
112 | - .byte 0x00,0x00 # jmp 11b | |
113 | + .byte -1,-1,-1 # testb $0xff,(%esi) = __TEST_PENDING | |
114 | + .byte -1,-1 # jnz 14f | |
115 | + .byte 0 # pop %ebx | |
116 | + .byte 1 # pop %ecx | |
117 | + .byte 2 # pop %edx | |
118 | + .byte 3 # pop %esi | |
119 | + .byte 4 # pop %edi | |
120 | + .byte 5 # pop %ebp | |
121 | + .byte 6 # pop %eax | |
122 | + .byte 7 # pop %ds | |
123 | + .byte 8 # pop %es | |
124 | + .byte 9,9,9 # add $4,%esp | |
125 | + .byte 10 # iret | |
126 | + .byte -1,-1,-1,-1 # movb $1,1(%esi) = __DISABLE_INTERRUPTS | |
127 | .previous | |
128 | ||
129 | # Hypervisor uses this for application faults while it executes. |