Skip to content

Commit 29b810f

Browse files
jbeulichKAGA-KOKO
authored andcommitted
x86/xen/32: Make xen_iret_crit_fixup() independent of frame layout
Now that SS:ESP always get saved by SAVE_ALL, this also needs to be accounted for in xen_iret_crit_fixup(). Otherwise the old_ax value gets interpreted as EFLAGS, and hence VM86 mode appears to be active all the time, leading to random "vm86_32: no user_vm86: BAD" log messages alongside processes randomly crashing. Since following the previous model (sitting after SAVE_ALL) would further complicate the code _and_ retain the dependency of xen_iret_crit_fixup() on frame manipulations done by entry_32.S, switch things around and do the adjustment ahead of SAVE_ALL. Fixes: 3c88c69 ("x86/stackframe/32: Provide consistent pt_regs") Signed-off-by: Jan Beulich <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Juergen Gross <[email protected]> Cc: Stable Team <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 81ff2c3 commit 29b810f

File tree

2 files changed

+33
-55
lines changed

2 files changed

+33
-55
lines changed

arch/x86/entry/entry_32.S

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,28 +1341,24 @@ END(spurious_interrupt_bug)
13411341

13421342
#ifdef CONFIG_XEN_PV
13431343
ENTRY(xen_hypervisor_callback)
1344-
pushl $-1 /* orig_ax = -1 => not a system call */
1345-
SAVE_ALL
1346-
ENCODE_FRAME_POINTER
1347-
TRACE_IRQS_OFF
1348-
13491344
/*
13501345
* Check to see if we got the event in the critical
13511346
* region in xen_iret_direct, after we've reenabled
13521347
* events and checked for pending events. This simulates
13531348
* iret instruction's behaviour where it delivers a
13541349
* pending interrupt when enabling interrupts:
13551350
*/
1356-
movl PT_EIP(%esp), %eax
1357-
cmpl $xen_iret_start_crit, %eax
1351+
cmpl $xen_iret_start_crit, (%esp)
13581352
jb 1f
1359-
cmpl $xen_iret_end_crit, %eax
1353+
cmpl $xen_iret_end_crit, (%esp)
13601354
jae 1f
1361-
1362-
jmp xen_iret_crit_fixup
1363-
1364-
ENTRY(xen_do_upcall)
1365-
1: mov %esp, %eax
1355+
call xen_iret_crit_fixup
1356+
1:
1357+
pushl $-1 /* orig_ax = -1 => not a system call */
1358+
SAVE_ALL
1359+
ENCODE_FRAME_POINTER
1360+
TRACE_IRQS_OFF
1361+
mov %esp, %eax
13661362
call xen_evtchn_do_upcall
13671363
#ifndef CONFIG_PREEMPTION
13681364
call xen_maybe_preempt_hcall

arch/x86/xen/xen-asm_32.S

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,9 @@ hyper_iret:
126126
.globl xen_iret_start_crit, xen_iret_end_crit
127127

128128
/*
129-
* This is called by xen_hypervisor_callback in entry.S when it sees
129+
* This is called by xen_hypervisor_callback in entry_32.S when it sees
130130
* that the EIP at the time of interrupt was between
131-
* xen_iret_start_crit and xen_iret_end_crit. We're passed the EIP in
132-
* %eax so we can do a more refined determination of what to do.
131+
* xen_iret_start_crit and xen_iret_end_crit.
133132
*
134133
* The stack format at this point is:
135134
* ----------------
@@ -138,34 +137,23 @@ hyper_iret:
138137
* eflags } outer exception info
139138
* cs }
140139
* eip }
141-
* ---------------- <- edi (copy dest)
142-
* eax : outer eax if it hasn't been restored
143140
* ----------------
144-
* eflags } nested exception info
145-
* cs } (no ss/esp because we're nested
146-
* eip } from the same ring)
147-
* orig_eax }<- esi (copy src)
148-
* - - - - - - - -
149-
* fs }
150-
* es }
151-
* ds } SAVE_ALL state
152-
* eax }
153-
* : :
154-
* ebx }<- esp
141+
* eax : outer eax if it hasn't been restored
155142
* ----------------
143+
* eflags }
144+
* cs } nested exception info
145+
* eip }
146+
* return address : (into xen_hypervisor_callback)
156147
*
157-
* In order to deliver the nested exception properly, we need to shift
158-
* everything from the return addr up to the error code so it sits
159-
* just under the outer exception info. This means that when we
160-
* handle the exception, we do it in the context of the outer
161-
* exception rather than starting a new one.
148+
* In order to deliver the nested exception properly, we need to discard the
149+
* nested exception frame such that when we handle the exception, we do it
150+
* in the context of the outer exception rather than starting a new one.
162151
*
163-
* The only caveat is that if the outer eax hasn't been restored yet
164-
* (ie, it's still on stack), we need to insert its value into the
165-
* SAVE_ALL state before going on, since it's usermode state which we
166-
* eventually need to restore.
152+
* The only caveat is that if the outer eax hasn't been restored yet (i.e.
153+
* it's still on stack), we need to restore its value here.
167154
*/
168155
ENTRY(xen_iret_crit_fixup)
156+
pushl %ecx
169157
/*
170158
* Paranoia: Make sure we're really coming from kernel space.
171159
* One could imagine a case where userspace jumps into the
@@ -176,32 +164,26 @@ ENTRY(xen_iret_crit_fixup)
176164
* jump instruction itself, not the destination, but some
177165
* virtual environments get this wrong.
178166
*/
179-
movl PT_CS(%esp), %ecx
167+
movl 3*4(%esp), %ecx /* nested CS */
180168
andl $SEGMENT_RPL_MASK, %ecx
181169
cmpl $USER_RPL, %ecx
170+
popl %ecx
182171
je 2f
183172

184-
lea PT_ORIG_EAX(%esp), %esi
185-
lea PT_EFLAGS(%esp), %edi
186-
187173
/*
188174
* If eip is before iret_restore_end then stack
189175
* hasn't been restored yet.
190176
*/
191-
cmp $iret_restore_end, %eax
177+
cmpl $iret_restore_end, 1*4(%esp)
192178
jae 1f
193179

194-
movl 0+4(%edi), %eax /* copy EAX (just above top of frame) */
195-
movl %eax, PT_EAX(%esp)
180+
movl 4*4(%esp), %eax /* load outer EAX */
181+
ret $4*4 /* discard nested EIP, CS, and EFLAGS as
182+
* well as the just restored EAX */
196183

197-
lea ESP_OFFSET(%edi), %edi /* move dest up over saved regs */
198-
199-
/* set up the copy */
200-
1: std
201-
mov $PT_EIP / 4, %ecx /* saved regs up to orig_eax */
202-
rep movsl
203-
cld
204-
205-
lea 4(%edi), %esp /* point esp to new frame */
206-
2: jmp xen_do_upcall
184+
1:
185+
ret $3*4 /* discard nested EIP, CS, and EFLAGS */
207186

187+
2:
188+
ret
189+
END(xen_iret_crit_fixup)

0 commit comments

Comments
 (0)