[PATCH v4 16/57] x86/entry/32: fix the end of the stack for newly forked tasks
From: Josh Poimboeuf
Date: Thu Aug 18 2016 - 09:28:43 EST
The unwinder expects the last frame on the stack to always be at the
same offset from the end of the page, which allows it to validate the
stack. Calling schedule_tail() directly breaks that convention because
its an asmlinkage function so its argument has to be pushed on the
stack. Add a wrapper which creates a proper "end of stack" frame header
before the call.
Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
---
arch/x86/entry/entry_32.S | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 0b56666..52b77ac 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -44,6 +44,7 @@
#include <asm/alternative-asm.h>
#include <asm/asm.h>
#include <asm/smap.h>
+#include <asm/frame.h>
.section .entry.text, "ax"
@@ -204,11 +205,27 @@
POP_GS_EX
.endm
-ENTRY(ret_from_fork)
+/*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack. This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+ FRAME_BEGIN
+
pushl %eax
call schedule_tail
popl %eax
+ FRAME_END
+ ret
+ENDPROC(schedule_tail_wrapper)
+
+ENTRY(ret_from_fork)
+ call schedule_tail_wrapper
+
/* When we fork, we trace the syscall return in the child, too. */
movl %esp, %eax
call syscall_return_slowpath
@@ -216,9 +233,8 @@ ENTRY(ret_from_fork)
END(ret_from_fork)
ENTRY(ret_from_kernel_thread)
- pushl %eax
- call schedule_tail
- popl %eax
+ call schedule_tail_wrapper
+
movl PT_EBP(%esp), %eax
call *PT_EBX(%esp)
movl $0, PT_EAX(%esp)
--
2.7.4