Skip to content

Commit

Permalink
Revert "x86/entry: Fix the end of the stack for newly forked tasks"
Browse files Browse the repository at this point in the history
Petr Mladek reported the following warning when loading the livepatch
sample module:

  WARNING: CPU: 1 PID: 3699 at arch/x86/kernel/stacktrace.c:132 save_stack_trace_tsk_reliable+0x133/0x1a0
  ...
  Call Trace:
   __schedule+0x273/0x820
   schedule+0x36/0x80
   kthreadd+0x305/0x310
   ? kthread_create_on_cpu+0x80/0x80
   ? icmp_echo.part.32+0x50/0x50
   ret_from_fork+0x2c/0x40

That warning means the end of the stack is no longer recognized as such
for newly forked tasks.  The problem was introduced with the following
commit:

  ff3f7e2 ("x86/entry: Fix the end of the stack for newly forked tasks")

... which was completely misguided.  It only partially fixed the
reported issue, and it introduced another bug in the process.  None of
the other entry code saves the frame pointer before calling into C code,
so it doesn't make sense for ret_from_fork to do so either.

Contrary to what I originally thought, the original issue wasn't related
to newly forked tasks.  It was actually related to ftrace.  When entry
code calls into a function which then calls into an ftrace handler, the
stack frame looks different than normal.

The original issue will be fixed in the unwinder, in a subsequent patch.

Reported-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Dave Jones <davej@codemonkey.org.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: live-patching@vger.kernel.org
Fixes: ff3f7e2 ("x86/entry: Fix the end of the stack for newly forked tasks")
Link: http://lkml.kernel.org/r/f350760f7e82f0750c8d1dd093456eb212751caa.1495553739.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Josh Poimboeuf authored and Ingo Molnar committed May 24, 2017
1 parent 3780578 commit ebd5749
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 18 deletions.
30 changes: 19 additions & 11 deletions arch/x86/entry/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,23 @@ ENTRY(__switch_to_asm)
jmp __switch_to
END(__switch_to_asm)

/*
* 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)
/*
* A newly forked process directly context switches into this address.
*
Expand All @@ -259,24 +276,15 @@ END(__switch_to_asm)
* edi: kernel thread arg
*/
ENTRY(ret_from_fork)
FRAME_BEGIN /* help unwinder find end of stack */

/*
* schedule_tail() is asmlinkage so we have to put its 'prev' argument
* on the stack.
*/
pushl %eax
call schedule_tail
popl %eax
call schedule_tail_wrapper

testl %ebx, %ebx
jnz 1f /* kernel threads are uncommon */

2:
/* When we fork, we trace the syscall return in the child, too. */
leal FRAME_OFFSET(%esp), %eax
movl %esp, %eax
call syscall_return_slowpath
FRAME_END
jmp restore_all

/* kernel thread */
Expand Down
11 changes: 4 additions & 7 deletions arch/x86/entry/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include <asm/smap.h>
#include <asm/pgtable_types.h>
#include <asm/export.h>
#include <asm/frame.h>
#include <linux/err.h>

.code64
Expand Down Expand Up @@ -406,19 +405,17 @@ END(__switch_to_asm)
* r12: kernel thread arg
*/
ENTRY(ret_from_fork)
FRAME_BEGIN /* help unwinder find end of stack */
movq %rax, %rdi
call schedule_tail /* rdi: 'prev' task parameter */
call schedule_tail /* rdi: 'prev' task parameter */

testq %rbx, %rbx /* from kernel_thread? */
jnz 1f /* kernel threads are uncommon */
testq %rbx, %rbx /* from kernel_thread? */
jnz 1f /* kernel threads are uncommon */

2:
leaq FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
movq %rsp, %rdi
call syscall_return_slowpath /* returns with IRQs disabled */
TRACE_IRQS_ON /* user mode is traced as IRQS on */
SWAPGS
FRAME_END
jmp restore_regs_and_iret

1:
Expand Down

0 comments on commit ebd5749

Please sign in to comment.