All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/unwind: ensure stack pointer is aligned
@ 2017-04-17 13:44 Josh Poimboeuf
  2017-04-18 12:51 ` [tip:x86/asm] x86/unwind: Ensure " tip-bot for Josh Poimboeuf
  0 siblings, 1 reply; 2+ messages in thread
From: Josh Poimboeuf @ 2017-04-17 13:44 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel

With frame pointers disabled, on some older versions of GCC (like
4.8.3), it's possible for the stack pointer to get aligned at a
half-word boundary:

  00000000000004d0 <fib_table_lookup>:
       4d0:       41 57                   push   %r15
       4d2:       41 56                   push   %r14
       4d4:       41 55                   push   %r13
       4d6:       41 54                   push   %r12
       4d8:       55                      push   %rbp
       4d9:       53                      push   %rbx
       4da:       48 83 ec 24             sub    $0x24,%rsp

In such a case, the unwinder ends up reading the entire stack at the
wrong alignment.  Then the last read goes past the end of the stack,
hitting the stack guard page:

  BUG: stack guard page was hit at ffffc900217c4000 (stack is ffffc900217c0000..ffffc900217c3fff)
  kernel stack overflow (page fault): 0000 [#1] SMP
  CPU: 48 PID: 3700 Comm: mosh-server Not tainted 4.9.0-9.el7.nodebug2.x86_64 #1
  Hardware name: Dell Inc. PowerEdge R820/0RN9TC, BIOS 2.3.4 01/22/2016
  task: ffff88081f4de040 task.stack: ffffc900217c0000
  RIP: 0010:[<ffffffff810203b2>] [<ffffffff810203b2>] show_trace_log_lvl+0xe2/0x200
  RSP: 0018:ffff88081fb057b0  EFLAGS: 00010012
  RAX: 0000000000000000 RBX: ffffc900217c3ffc RCX: 0000000000000001
  RDX: 0000000000000000 RSI: ffff88081fb057b8 RDI: 0000002b00007ffc
  RBP: ffff88081fb05850 R08: 0000000000000a91 R09: ffff88081fb0ecf3
  R10: 0000000000000003 R11: 000000000000000f R12: 0000002b00007ffc
  R13: ffff88081f4de040 R14: ffffffff81950d37 R15: 0000000000000000
  FS:  00007fd0ffe61840(0000) GS:ffff88081fb00000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: ffffc900217c4000 CR3: 000000081c44a000 CR4: 00000000001406e0
  Call Trace:
   <NMI>
    ? show_stack_log_lvl+0x15e/0x1f0
    ? vmalloc_fault+0x31d/0x330
    ? vmalloc_fault+0x31d/0x330
    ? dump_stack+0x5c/0x7c
    ? __warn+0xba/0xe0
    ? vmalloc_fault+0x31d/0x330
    ? __do_page_fault+0x330/0x4b0
    ? do_page_fault+0x2b/0x70
    ? page_fault+0x28/0x30
    ? unwind_next_frame+0x35/0x70
    ? vsnprintf+0x3c5/0x590
    ? sprintf+0x56/0x80
    ? kallsyms_lookup+0x7b/0xb0
    ? __sprint_symbol+0xd0/0x100
    ? symbol_string+0x56/0xa0
    ? kallsyms_lookup+0x7b/0xb0
    ? __sprint_symbol+0xd0/0x100
    ? symbol_string+0x56/0xa0
    ? pointer+0x23d/0x410
    ? vsnprintf+0x25c/0x590
    ? irq_work_queue+0x9/0x70
    ? vprintk_nmi+0x99/0xa0
    ? vprintk_nmi+0x99/0xa0
    ? printk+0x58/0x6f
    ? __module_text_address+0x9/0x60
    ? is_module_text_address+0x5/0x10
    ? show_trace_log_lvl+0xed/0x200
    ? no_context+0x233/0x400
    ? no_context+0x233/0x400
    ? show_stack_log_lvl+0x15e/0x1f0
    ? show_regs+0xa7/0x1c0
    ? __die+0x9e/0xe0
    ? die+0x2e/0x60
    ? handle_stack_overflow+0x3a/0x50
    ? no_context+0x233/0x400
   <EOE>

Fix it by ensuring the stack pointer is properly aligned before
unwinding.

Reported-by: Jirka Hladky <jhladky@redhat.com>
Fixes: 7c7900f89770 ("x86/unwind: Add new unwind interface and implementations")
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/dumpstack.c    | 2 +-
 arch/x86/kernel/unwind_guess.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 924f45e..dbce3cc 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -77,7 +77,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
 	 * - softirq stack
 	 * - hardirq stack
 	 */
-	for (regs = NULL; stack; stack = stack_info.next_sp) {
+	for (regs = NULL; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
 		const char *stack_name;
 
 		/*
diff --git a/arch/x86/kernel/unwind_guess.c b/arch/x86/kernel/unwind_guess.c
index 22881dd..039f367 100644
--- a/arch/x86/kernel/unwind_guess.c
+++ b/arch/x86/kernel/unwind_guess.c
@@ -34,7 +34,7 @@ bool unwind_next_frame(struct unwind_state *state)
 				return true;
 		}
 
-		state->sp = info->next_sp;
+		state->sp = PTR_ALIGN(info->next_sp, sizeof(long));
 
 	} while (!get_stack_info(state->sp, state->task, info,
 				 &state->stack_mask));
@@ -49,7 +49,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 	memset(state, 0, sizeof(*state));
 
 	state->task = task;
-	state->sp   = first_frame;
+	state->sp   = PTR_ALIGN(first_frame, sizeof(long));
 
 	get_stack_info(first_frame, state->task, &state->stack_info,
 		       &state->stack_mask);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [tip:x86/asm] x86/unwind: Ensure stack pointer is aligned
  2017-04-17 13:44 [PATCH] x86/unwind: ensure stack pointer is aligned Josh Poimboeuf
@ 2017-04-18 12:51 ` tip-bot for Josh Poimboeuf
  0 siblings, 0 replies; 2+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2017-04-18 12:51 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, jpoimboe, mingo, torvalds, linux-kernel, dvlasenk, peterz,
	tglx, brgerst, bp, jhladky, luto

Commit-ID:  e335bb51cc15e80ac180701a0d335ef1c050828e
Gitweb:     http://git.kernel.org/tip/e335bb51cc15e80ac180701a0d335ef1c050828e
Author:     Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Mon, 17 Apr 2017 08:44:00 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 18 Apr 2017 10:30:23 +0200

x86/unwind: Ensure stack pointer is aligned

With frame pointers disabled, on some older versions of GCC (like
4.8.3), it's possible for the stack pointer to get aligned at a
half-word boundary:

  00000000000004d0 <fib_table_lookup>:
       4d0:       41 57                   push   %r15
       4d2:       41 56                   push   %r14
       4d4:       41 55                   push   %r13
       4d6:       41 54                   push   %r12
       4d8:       55                      push   %rbp
       4d9:       53                      push   %rbx
       4da:       48 83 ec 24             sub    $0x24,%rsp

In such a case, the unwinder ends up reading the entire stack at the
wrong alignment.  Then the last read goes past the end of the stack,
hitting the stack guard page:

  BUG: stack guard page was hit at ffffc900217c4000 (stack is ffffc900217c0000..ffffc900217c3fff)
  kernel stack overflow (page fault): 0000 [#1] SMP
  ...

Fix it by ensuring the stack pointer is properly aligned before
unwinding.

Reported-by: Jirka Hladky <jhladky@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Fixes: 7c7900f89770 ("x86/unwind: Add new unwind interface and implementations")
Link: http://lkml.kernel.org/r/cff33847cc9b02fa548625aa23268ac574460d8d.1492436590.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/dumpstack.c    | 2 +-
 arch/x86/kernel/unwind_guess.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 924f45e..dbce3cc 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -77,7 +77,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
 	 * - softirq stack
 	 * - hardirq stack
 	 */
-	for (regs = NULL; stack; stack = stack_info.next_sp) {
+	for (regs = NULL; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
 		const char *stack_name;
 
 		/*
diff --git a/arch/x86/kernel/unwind_guess.c b/arch/x86/kernel/unwind_guess.c
index 22881dd..039f367 100644
--- a/arch/x86/kernel/unwind_guess.c
+++ b/arch/x86/kernel/unwind_guess.c
@@ -34,7 +34,7 @@ bool unwind_next_frame(struct unwind_state *state)
 				return true;
 		}
 
-		state->sp = info->next_sp;
+		state->sp = PTR_ALIGN(info->next_sp, sizeof(long));
 
 	} while (!get_stack_info(state->sp, state->task, info,
 				 &state->stack_mask));
@@ -49,7 +49,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 	memset(state, 0, sizeof(*state));
 
 	state->task = task;
-	state->sp   = first_frame;
+	state->sp   = PTR_ALIGN(first_frame, sizeof(long));
 
 	get_stack_info(first_frame, state->task, &state->stack_info,
 		       &state->stack_mask);

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-04-18 12:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-17 13:44 [PATCH] x86/unwind: ensure stack pointer is aligned Josh Poimboeuf
2017-04-18 12:51 ` [tip:x86/asm] x86/unwind: Ensure " tip-bot for Josh Poimboeuf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.