diff options
Diffstat (limited to 'arch/x86/include/asm/ptrace.h')
| -rw-r--r-- | arch/x86/include/asm/ptrace.h | 46 | 
1 files changed, 38 insertions, 8 deletions
| diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6de1fd3d0097..f236bcd5485d 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -37,8 +37,10 @@ struct pt_regs {  	unsigned short __esh;  	unsigned short fs;  	unsigned short __fsh; +	/* On interrupt, gs and __gsh store the vector number. */  	unsigned short gs;  	unsigned short __gsh; +	/* On interrupt, this is the error code. */  	unsigned long orig_ax;  	unsigned long ip;  	unsigned short cs; @@ -144,7 +146,7 @@ static inline int v8086_mode(struct pt_regs *regs)  static inline bool user_64bit_mode(struct pt_regs *regs)  {  #ifdef CONFIG_X86_64 -#ifndef CONFIG_PARAVIRT +#ifndef CONFIG_PARAVIRT_XXL  	/*  	 * On non-paravirt systems, this is the only long mode CPL 3  	 * selector.  We do not allow long mode selectors in the LDT. @@ -237,23 +239,51 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs,  }  /** + * 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:	pt_regs which contains kernel stack pointer.   * @n:		stack entry number.   *   * 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.   */  static inline unsigned long regs_get_kernel_stack_nth(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 0; +	unsigned long *addr; +	unsigned long val; +	long ret; + +	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;  }  #define arch_has_single_step()	(1) |