From: Jann Horn <jannh@google.com>
To: stable@vger.kernel.org, jannh@google.com
Subject: [PATCH for 4.18.y] x86/dumpstack: Don't dump kernel memory based on usermode RIP
Date: Mon, 3 Sep 2018 16:32:48 +0200 [thread overview]
Message-ID: <20180903143248.98687-1-jannh@google.com> (raw)
commit 342db04ae71273322f0011384a9ed414df8bdae4 upstream.
show_opcodes() is used both for dumping kernel instructions and for dumping
user instructions. If userspace causes #PF by jumping to a kernel address,
show_opcodes() can be reached with regs->ip controlled by the user,
pointing to kernel code. Make sure that userspace can't trick us into
dumping kernel memory into dmesg.
Manually backported: show_opcodes() has changed a bit in the meantime.
I have manually tested the backport.
Fixes: 7cccf0725cf7 ("x86/dumpstack: Add a show_ip() function")
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20180828154901.112726-1-jannh@google.com
Signed-off-by: Jann Horn <jannh@google.com>
---
Since I manually backported this, I have removed all other
sign-off/reviewed-by lines. I hope that's correct?
arch/x86/include/asm/stacktrace.h | 2 +-
arch/x86/kernel/dumpstack.c | 21 +++++++++++++++------
arch/x86/mm/fault.c | 2 +-
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index b6dc698f992a..f335aad404a4 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -111,6 +111,6 @@ static inline unsigned long caller_frame_pointer(void)
return (unsigned long)frame;
}
-void show_opcodes(u8 *rip, const char *loglvl);
+void show_opcodes(struct pt_regs *regs, const char *loglvl);
void show_ip(struct pt_regs *regs, const char *loglvl);
#endif /* _ASM_X86_STACKTRACE_H */
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 666a284116ac..1c65c648cacc 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -91,23 +91,32 @@ static void printk_stack_address(unsigned long address, int reliable,
* Thus, the 2/3rds prologue and 64 byte OPCODE_BUFSIZE is just a random
* guesstimate in attempt to achieve all of the above.
*/
-void show_opcodes(u8 *rip, const char *loglvl)
+void show_opcodes(struct pt_regs *regs, const char *loglvl)
{
unsigned int code_prologue = OPCODE_BUFSIZE * 2 / 3;
u8 opcodes[OPCODE_BUFSIZE];
- u8 *ip;
+ unsigned long ip;
int i;
+ bool bad_ip;
printk("%sCode: ", loglvl);
- ip = (u8 *)rip - code_prologue;
- if (probe_kernel_read(opcodes, ip, OPCODE_BUFSIZE)) {
+ ip = regs->ip - code_prologue;
+
+ /*
+ * Make sure userspace isn't trying to trick us into dumping kernel
+ * memory by pointing the userspace instruction pointer at it.
+ */
+ bad_ip = user_mode(regs) &&
+ __chk_range_not_ok(ip, OPCODE_BUFSIZE, TASK_SIZE_MAX);
+
+ if (bad_ip || probe_kernel_read(opcodes, (u8 *)ip, OPCODE_BUFSIZE)) {
pr_cont("Bad RIP value.\n");
return;
}
for (i = 0; i < OPCODE_BUFSIZE; i++, ip++) {
- if (ip == rip)
+ if (ip == regs->ip)
pr_cont("<%02x> ", opcodes[i]);
else
pr_cont("%02x ", opcodes[i]);
@@ -122,7 +131,7 @@ void show_ip(struct pt_regs *regs, const char *loglvl)
#else
printk("%sRIP: %04x:%pS\n", loglvl, (int)regs->cs, (void *)regs->ip);
#endif
- show_opcodes((u8 *)regs->ip, loglvl);
+ show_opcodes(regs, loglvl);
}
void show_iret_regs(struct pt_regs *regs)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2aafa6ab6103..d1f1612672c7 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -838,7 +838,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
printk(KERN_CONT "\n");
- show_opcodes((u8 *)regs->ip, loglvl);
+ show_opcodes(regs, loglvl);
}
static void
--
2.19.0.rc1.350.ge57e33dbd1-goog
next reply other threads:[~2018-09-03 18:53 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-03 14:32 Jann Horn [this message]
2018-09-03 16:16 ` [PATCH for 4.18.y] x86/dumpstack: Don't dump kernel memory based on usermode RIP Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180903143248.98687-1-jannh@google.com \
--to=jannh@google.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.