* [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.