Skip to content

Commit a1a338e

Browse files
amlutoPeter Zijlstra
authored andcommitted
x86/entry/32: Unwind the ESPFIX stack earlier on exception entry
Right now, we do some fancy parts of the exception entry path while SS might have a nonzero base: we fill in regs->ss and regs->sp, and we consider switching to the kernel stack. This results in regs->ss and regs->sp referring to a non-flat stack and it may result in overflowing the entry stack. The former issue means that we can try to call iret_exc on a non-flat stack, which doesn't work. Tested with selftests/x86/sigreturn_32. Fixes: 45d7b25 ("x86/entry/32: Enter the kernel via trampoline stack") Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected]
1 parent 82cb8a0 commit a1a338e

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

arch/x86/entry/entry_32.S

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,6 @@
210210
/*
211211
* The high bits of the CS dword (__csh) are used for CS_FROM_*.
212212
* Clear them in case hardware didn't do this for us.
213-
*
214-
* Be careful: we may have nonzero SS base due to ESPFIX.
215213
*/
216214
andl $0x0000ffff, 4*4(%esp)
217215

@@ -307,12 +305,21 @@
307305
.Lfinished_frame_\@:
308306
.endm
309307

310-
.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0
308+
.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0 unwind_espfix=0
311309
cld
312310
.if \skip_gs == 0
313311
PUSH_GS
314312
.endif
315313
pushl %fs
314+
315+
pushl %eax
316+
movl $(__KERNEL_PERCPU), %eax
317+
movl %eax, %fs
318+
.if \unwind_espfix > 0
319+
UNWIND_ESPFIX_STACK
320+
.endif
321+
popl %eax
322+
316323
FIXUP_FRAME
317324
pushl %es
318325
pushl %ds
@@ -326,8 +333,6 @@
326333
movl $(__USER_DS), %edx
327334
movl %edx, %ds
328335
movl %edx, %es
329-
movl $(__KERNEL_PERCPU), %edx
330-
movl %edx, %fs
331336
.if \skip_gs == 0
332337
SET_KERNEL_GS %edx
333338
.endif
@@ -1153,18 +1158,17 @@ ENDPROC(entry_INT80_32)
11531158
lss (%esp), %esp /* switch to the normal stack segment */
11541159
#endif
11551160
.endm
1161+
11561162
.macro UNWIND_ESPFIX_STACK
1163+
/* It's safe to clobber %eax, all other regs need to be preserved */
11571164
#ifdef CONFIG_X86_ESPFIX32
11581165
movl %ss, %eax
11591166
/* see if on espfix stack */
11601167
cmpw $__ESPFIX_SS, %ax
1161-
jne 27f
1162-
movl $__KERNEL_DS, %eax
1163-
movl %eax, %ds
1164-
movl %eax, %es
1168+
jne .Lno_fixup_\@
11651169
/* switch to normal stack */
11661170
FIXUP_ESPFIX_STACK
1167-
27:
1171+
.Lno_fixup_\@:
11681172
#endif
11691173
.endm
11701174

@@ -1458,10 +1462,9 @@ END(page_fault)
14581462

14591463
common_exception_read_cr2:
14601464
/* the function address is in %gs's slot on the stack */
1461-
SAVE_ALL switch_stacks=1 skip_gs=1
1465+
SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
14621466

14631467
ENCODE_FRAME_POINTER
1464-
UNWIND_ESPFIX_STACK
14651468

14661469
/* fixup %gs */
14671470
GS_TO_REG %ecx
@@ -1483,9 +1486,8 @@ END(common_exception_read_cr2)
14831486

14841487
common_exception:
14851488
/* the function address is in %gs's slot on the stack */
1486-
SAVE_ALL switch_stacks=1 skip_gs=1
1489+
SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
14871490
ENCODE_FRAME_POINTER
1488-
UNWIND_ESPFIX_STACK
14891491

14901492
/* fixup %gs */
14911493
GS_TO_REG %ecx

0 commit comments

Comments
 (0)