Commit ebd57499 authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Ingo Molnar
Browse files

Revert "x86/entry: Fix the end of the stack for newly forked tasks"



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:

  ff3f7e24 ("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: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Acked-by: default avatarThomas 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: ff3f7e24 ("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: default avatarIngo Molnar <mingo@kernel.org>
parent 37805787
Loading
Loading
Loading
Loading
+19 −11
Original line number Diff line number Diff line
@@ -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.
 *
@@ -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 */
+4 −7
Original line number Diff line number Diff line
@@ -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
@@ -406,7 +405,6 @@ 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 */

@@ -414,11 +412,10 @@ ENTRY(ret_from_fork)
	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: