Commit c2712b85 authored by Steven Rostedt (VMware)'s avatar Steven Rostedt (VMware) Committed by Ingo Molnar

kprobes, x86/ptrace.h: Make regs_get_kernel_stack_nth() not fault on bad stack

Andy had some concerns about using regs_get_kernel_stack_nth() in a new
function regs_get_kernel_argument() as if there's any error in the stack
code, it could cause a bad memory access. To be on the safe side, call
probe_kernel_read() on the stack address to be extra careful in accessing
the memory. A helper function, regs_get_kernel_stack_nth_addr(), was added
to just return the stack address (or NULL if not on the stack), that will be
used to find the address (and could be used by other functions) and read the
address with kernel_probe_read().
Requested-by: default avatarAndy Lutomirski <luto@amacapital.net>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
Reviewed-by: default avatarJoel Fernandes (Google) <joel@joelfernandes.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20181017165951.09119177@gandalf.local.homeSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent d4ae5529
...@@ -236,23 +236,51 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs, ...@@ -236,23 +236,51 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs,
(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
} }
/**
* regs_get_kernel_stack_nth_addr() - get the address of the Nth entry on stack
* @regs: pt_regs which contains kernel stack pointer.
* @n: stack entry number.
*
* regs_get_kernel_stack_nth() returns the address of the @n th entry of the
* kernel stack which is specified by @regs. If the @n th entry is NOT in
* the kernel stack, this returns NULL.
*/
static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n)
{
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
addr += n;
if (regs_within_kernel_stack(regs, (unsigned long)addr))
return addr;
else
return NULL;
}
/* To avoid include hell, we can't include uaccess.h */
extern long probe_kernel_read(void *dst, const void *src, size_t size);
/** /**
* regs_get_kernel_stack_nth() - get Nth entry of the stack * regs_get_kernel_stack_nth() - get Nth entry of the stack
* @regs: pt_regs which contains kernel stack pointer. * @regs: pt_regs which contains kernel stack pointer.
* @n: stack entry number. * @n: stack entry number.
* *
* regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
* is specified by @regs. If the @n th entry is NOT in the kernel stack, * is specified by @regs. If the @n th entry is NOT in the kernel stack
* this returns 0. * this returns 0.
*/ */
static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
unsigned int n) unsigned int n)
{ {
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); unsigned long *addr;
addr += n; unsigned long val;
if (regs_within_kernel_stack(regs, (unsigned long)addr)) long ret;
return *addr;
else addr = regs_get_kernel_stack_nth_addr(regs, n);
if (addr) {
ret = probe_kernel_read(&val, addr, sizeof(val));
if (!ret)
return val;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment