a0f7ab8a6a
cherry-pick from upstream 4.14
184 lines
5.7 KiB
Diff
184 lines
5.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Andy Lutomirski <luto@kernel.org>
|
|
Date: Mon, 4 Dec 2017 15:07:13 +0100
|
|
Subject: [PATCH] x86/dumpstack: Add get_stack_info() support for the SYSENTER
|
|
stack
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
CVE-2017-5754
|
|
|
|
get_stack_info() doesn't currently know about the SYSENTER stack, so
|
|
unwinding will fail if we entered the kernel on the SYSENTER stack
|
|
and haven't fully switched off. Teach get_stack_info() about the
|
|
SYSENTER stack.
|
|
|
|
With future patches applied that run part of the entry code on the
|
|
SYSENTER stack and introduce an intentional BUG(), I would get:
|
|
|
|
PANIC: double fault, error_code: 0x0
|
|
...
|
|
RIP: 0010:do_error_trap+0x33/0x1c0
|
|
...
|
|
Call Trace:
|
|
Code: ...
|
|
|
|
With this patch, I get:
|
|
|
|
PANIC: double fault, error_code: 0x0
|
|
...
|
|
Call Trace:
|
|
<SYSENTER>
|
|
? async_page_fault+0x36/0x60
|
|
? invalid_op+0x22/0x40
|
|
? async_page_fault+0x36/0x60
|
|
? sync_regs+0x3c/0x40
|
|
? sync_regs+0x2e/0x40
|
|
? error_entry+0x6c/0xd0
|
|
? async_page_fault+0x36/0x60
|
|
</SYSENTER>
|
|
Code: ...
|
|
|
|
which is a lot more informative.
|
|
|
|
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Reviewed-by: Borislav Petkov <bp@suse.de>
|
|
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
|
|
Cc: Borislav Petkov <bp@alien8.de>
|
|
Cc: Borislav Petkov <bpetkov@suse.de>
|
|
Cc: Brian Gerst <brgerst@gmail.com>
|
|
Cc: Dave Hansen <dave.hansen@intel.com>
|
|
Cc: Dave Hansen <dave.hansen@linux.intel.com>
|
|
Cc: David Laight <David.Laight@aculab.com>
|
|
Cc: Denys Vlasenko <dvlasenk@redhat.com>
|
|
Cc: Eduardo Valentin <eduval@amazon.com>
|
|
Cc: Greg KH <gregkh@linuxfoundation.org>
|
|
Cc: H. Peter Anvin <hpa@zytor.com>
|
|
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
|
|
Cc: Juergen Gross <jgross@suse.com>
|
|
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Cc: Peter Zijlstra <peterz@infradead.org>
|
|
Cc: Rik van Riel <riel@redhat.com>
|
|
Cc: Will Deacon <will.deacon@arm.com>
|
|
Cc: aliguori@amazon.com
|
|
Cc: daniel.gruss@iaik.tugraz.at
|
|
Cc: hughd@google.com
|
|
Cc: keescook@google.com
|
|
Link: https://lkml.kernel.org/r/20171204150605.392711508@linutronix.de
|
|
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
|
(cherry picked from commit 33a2f1a6c4d7c0a02d1c006fb0379cc5ca3b96bb)
|
|
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
|
|
(cherry picked from commit 72e90cc5463cf882c5f9508817029d85b317f2b5)
|
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
|
---
|
|
arch/x86/include/asm/stacktrace.h | 3 +++
|
|
arch/x86/kernel/dumpstack.c | 19 +++++++++++++++++++
|
|
arch/x86/kernel/dumpstack_32.c | 6 ++++++
|
|
arch/x86/kernel/dumpstack_64.c | 6 ++++++
|
|
4 files changed, 34 insertions(+)
|
|
|
|
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
|
|
index 2e41c50ddf47..95f999576131 100644
|
|
--- a/arch/x86/include/asm/stacktrace.h
|
|
+++ b/arch/x86/include/asm/stacktrace.h
|
|
@@ -15,6 +15,7 @@ enum stack_type {
|
|
STACK_TYPE_TASK,
|
|
STACK_TYPE_IRQ,
|
|
STACK_TYPE_SOFTIRQ,
|
|
+ STACK_TYPE_SYSENTER,
|
|
STACK_TYPE_EXCEPTION,
|
|
STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
|
|
};
|
|
@@ -27,6 +28,8 @@ struct stack_info {
|
|
bool in_task_stack(unsigned long *stack, struct task_struct *task,
|
|
struct stack_info *info);
|
|
|
|
+bool in_sysenter_stack(unsigned long *stack, struct stack_info *info);
|
|
+
|
|
int get_stack_info(unsigned long *stack, struct task_struct *task,
|
|
struct stack_info *info, unsigned long *visit_mask);
|
|
|
|
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
|
|
index 695cdce5dfc8..c211cbdff709 100644
|
|
--- a/arch/x86/kernel/dumpstack.c
|
|
+++ b/arch/x86/kernel/dumpstack.c
|
|
@@ -43,6 +43,25 @@ bool in_task_stack(unsigned long *stack, struct task_struct *task,
|
|
return true;
|
|
}
|
|
|
|
+bool in_sysenter_stack(unsigned long *stack, struct stack_info *info)
|
|
+{
|
|
+ struct tss_struct *tss = this_cpu_ptr(&cpu_tss);
|
|
+
|
|
+ /* Treat the canary as part of the stack for unwinding purposes. */
|
|
+ void *begin = &tss->SYSENTER_stack_canary;
|
|
+ void *end = (void *)&tss->SYSENTER_stack + sizeof(tss->SYSENTER_stack);
|
|
+
|
|
+ if ((void *)stack < begin || (void *)stack >= end)
|
|
+ return false;
|
|
+
|
|
+ info->type = STACK_TYPE_SYSENTER;
|
|
+ info->begin = begin;
|
|
+ info->end = end;
|
|
+ info->next_sp = NULL;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
static void printk_stack_address(unsigned long address, int reliable,
|
|
char *log_lvl)
|
|
{
|
|
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
|
|
index e5f0b40e66d2..3160bf2d100e 100644
|
|
--- a/arch/x86/kernel/dumpstack_32.c
|
|
+++ b/arch/x86/kernel/dumpstack_32.c
|
|
@@ -25,6 +25,9 @@ const char *stack_type_name(enum stack_type type)
|
|
if (type == STACK_TYPE_SOFTIRQ)
|
|
return "SOFTIRQ";
|
|
|
|
+ if (type == STACK_TYPE_SYSENTER)
|
|
+ return "SYSENTER";
|
|
+
|
|
return NULL;
|
|
}
|
|
|
|
@@ -92,6 +95,9 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
|
|
if (task != current)
|
|
goto unknown;
|
|
|
|
+ if (in_sysenter_stack(stack, info))
|
|
+ goto recursion_check;
|
|
+
|
|
if (in_hardirq_stack(stack, info))
|
|
goto recursion_check;
|
|
|
|
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
|
|
index 3e1471d57487..f5107b659f86 100644
|
|
--- a/arch/x86/kernel/dumpstack_64.c
|
|
+++ b/arch/x86/kernel/dumpstack_64.c
|
|
@@ -36,6 +36,9 @@ const char *stack_type_name(enum stack_type type)
|
|
if (type == STACK_TYPE_IRQ)
|
|
return "IRQ";
|
|
|
|
+ if (type == STACK_TYPE_SYSENTER)
|
|
+ return "SYSENTER";
|
|
+
|
|
if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
|
|
return exception_stack_names[type - STACK_TYPE_EXCEPTION];
|
|
|
|
@@ -114,6 +117,9 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
|
|
if (in_irq_stack(stack, info))
|
|
goto recursion_check;
|
|
|
|
+ if (in_sysenter_stack(stack, info))
|
|
+ goto recursion_check;
|
|
+
|
|
goto unknown;
|
|
|
|
recursion_check:
|
|
--
|
|
2.14.2
|
|
|