FAILED: patch "[PATCH] x86/dumpstack: Don't dump kernel memory based on usermode RIP" failed to apply to 4.18-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 4.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
342db04ae71273322f0011384a9ed414df8bdae4Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Tue, 28 Aug 2018 17:49:01 +0200
Subject: [PATCH] x86/dumpstack: Don't dump kernel memory based on usermode RIP
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.
arch/x86/include/asm/stacktrace.h +1 -1
@@ -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 */
arch/x86/kernel/dumpstack.c +13 -3
@@ -90,14 +90,24 @@ 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) {#define PROLOGUE_SIZE 42#define EPILOGUE_SIZE 21#define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE)u8 opcodes[OPCODE_BUFSIZE ]; +unsigned long prologue = regs->ip -PROLOGUE_SIZE ; +bool bad_ip; -if (probe_kernel_read (opcodes, rip -PROLOGUE_SIZE ,OPCODE_BUFSIZE )) { +/* +* 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 (prologue,OPCODE_BUFSIZE ,TASK_SIZE_MAX ); + +if (bad_ip ||probe_kernel_read (opcodes, (u8 *)prologue, +OPCODE_BUFSIZE )) {printk ("%sCode: Bad RIP value.\n" , loglvl); }else { printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"
@@ -113,7 +123,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)
arch/x86/mm/fault.c +1 -1
@@ -837,7 +837,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