Skip to content

Commit d181d2d

Browse files
committed
x86/dumpstack: Dump user space code correctly again
H.J. reported that post 5.7 a segfault of a user space task does not longer dump the Code bytes when /proc/sys/debug/exception-trace is enabled. It prints 'Code: Bad RIP value.' instead. This was broken by a recent change which made probe_kernel_read() reject non-kernel addresses. Update show_opcodes() so it retrieves user space opcodes via copy_from_user_nmi(). Fixes: 98a2360 ("maccess: always use strict semantics for probe_kernel_read") Reported-by: H.J. Lu <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 039a7a3 commit d181d2d

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

arch/x86/kernel/dumpstack.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ static void printk_stack_address(unsigned long address, int reliable,
7171
printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
7272
}
7373

74+
static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
75+
unsigned int nbytes)
76+
{
77+
if (!user_mode(regs))
78+
return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
79+
80+
/*
81+
* Make sure userspace isn't trying to trick us into dumping kernel
82+
* memory by pointing the userspace instruction pointer at it.
83+
*/
84+
if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
85+
return -EINVAL;
86+
87+
return copy_from_user_nmi(buf, (void __user *)src, nbytes);
88+
}
89+
7490
/*
7591
* There are a couple of reasons for the 2/3rd prologue, courtesy of Linus:
7692
*
@@ -97,17 +113,8 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
97113
#define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE)
98114
u8 opcodes[OPCODE_BUFSIZE];
99115
unsigned long prologue = regs->ip - PROLOGUE_SIZE;
100-
bool bad_ip;
101-
102-
/*
103-
* Make sure userspace isn't trying to trick us into dumping kernel
104-
* memory by pointing the userspace instruction pointer at it.
105-
*/
106-
bad_ip = user_mode(regs) &&
107-
__chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
108116

109-
if (bad_ip || copy_from_kernel_nofault(opcodes, (u8 *)prologue,
110-
OPCODE_BUFSIZE)) {
117+
if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
111118
printk("%sCode: Bad RIP value.\n", loglvl);
112119
} else {
113120
printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"

0 commit comments

Comments
 (0)