All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Denys Vlasenko <dvlasenk@redhat.com>,
	Jim Keniston <jkenisto@us.ibm.com>,
	Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org,
	Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	David Long <dave.long@linaro.org>
Subject: Re: [PATCH 1/1] uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap
Date: Tue, 13 May 2014 15:23:32 +0900	[thread overview]
Message-ID: <5371BA64.8070203@hitachi.com> (raw)
In-Reply-To: <20140512170850.GB28335@redhat.com>

(2014/05/13 2:08), Oleg Nesterov wrote:
> If the probed insn triggers a trap, ->si_addr = regs->ip is technically
> correct, but this is not what the signal handler wants; we need to pass
> the address of the probed insn, not the address of xol slot.
> 
> Add the new arch-agnostic helper, uprobe_get_trap_addr(), and change
> fill_trap_info() and math_error() to use it. !CONFIG_UPROBES case in
> uprobes.h uses a macro to avoid include hell and ensure that it can be
> compiled even if an architecture doesn't define instruction_pointer().
> 
> Test-case:
> 
> 	#include <signal.h>
> 	#include <stdio.h>
> 	#include <unistd.h>
> 
> 	extern void probe_div(void);
> 
> 	void sigh(int sig, siginfo_t *info, void *c)
> 	{
> 		int passed = (info->si_addr == probe_div);
> 		printf(passed ? "PASS\n" : "FAIL\n");
> 		_exit(!passed);
> 	}
> 
> 	int main(void)
> 	{
> 		struct sigaction sa = {
> 			.sa_sigaction	= sigh,
> 			.sa_flags	= SA_SIGINFO,
> 		};
> 
> 		sigaction(SIGFPE, &sa, NULL);
> 
> 		asm (
> 			"xor %ecx,%ecx\n"
> 			".globl probe_div; probe_div:\n"
> 			"idiv %ecx\n"
> 		);
> 
> 		return 0;
> 	}
> 
> it fails if probe_div() is probed.
> 
> Note: show_unhandled_signals users should probably use this helper too,
> but we need to cleanup them first.
> 
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Looks good to me :)

Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Thanks,

> ---
>  arch/x86/kernel/traps.c |    7 ++++---
>  include/linux/uprobes.h |    4 ++++
>  kernel/events/uprobes.c |   10 ++++++++++
>  3 files changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 73b3ea3..3fdb205 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -23,6 +23,7 @@
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/ptrace.h>
> +#include <linux/uprobes.h>
>  #include <linux/string.h>
>  #include <linux/delay.h>
>  #include <linux/errno.h>
> @@ -148,11 +149,11 @@ static siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr,
>  
>  	case X86_TRAP_DE:
>  		sicode = FPE_INTDIV;
> -		siaddr = regs->ip;
> +		siaddr = uprobe_get_trap_addr(regs);
>  		break;
>  	case X86_TRAP_UD:
>  		sicode = ILL_ILLOPN;
> -		siaddr = regs->ip;
> +		siaddr = uprobe_get_trap_addr(regs);
>  		break;
>  	case X86_TRAP_AC:
>  		sicode = BUS_ADRALN;
> @@ -531,7 +532,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
>  	task->thread.error_code = error_code;
>  	info.si_signo = SIGFPE;
>  	info.si_errno = 0;
> -	info.si_addr = (void __user *)regs->ip;
> +	info.si_addr = (void __user *)uprobe_get_trap_addr(regs);
>  	if (trapnr == X86_TRAP_MF) {
>  		unsigned short cwd, swd;
>  		/*
> diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
> index edff2b9..88c3b7e 100644
> --- a/include/linux/uprobes.h
> +++ b/include/linux/uprobes.h
> @@ -102,6 +102,7 @@ extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, u
>  extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
>  extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
>  extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
> +extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
>  extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
>  extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
>  extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
> @@ -130,6 +131,9 @@ extern bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *r
>  #else /* !CONFIG_UPROBES */
>  struct uprobes_state {
>  };
> +
> +#define uprobe_get_trap_addr(regs)	instruction_pointer(regs)
> +
>  static inline int
>  uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
>  {
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index a13251e..3b02c72 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1351,6 +1351,16 @@ unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs)
>  	return instruction_pointer(regs) - UPROBE_SWBP_INSN_SIZE;
>  }
>  
> +unsigned long uprobe_get_trap_addr(struct pt_regs *regs)
> +{
> +	struct uprobe_task *utask = current->utask;
> +
> +	if (unlikely(utask && utask->active_uprobe))
> +		return utask->vaddr;
> +
> +	return instruction_pointer(regs);
> +}
> +
>  /*
>   * Called with no locks held.
>   * Called in context of a exiting or a exec-ing thread.
> 


-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com



  reply	other threads:[~2014-05-13  6:23 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-08 19:11 [PATCH 0/6] x86/traps: cleanup DO_ERROR*() to prepare for uprobes fixes Oleg Nesterov
2014-05-08 19:11 ` [PATCH 1/6] x86/traps: Make math_error() static Oleg Nesterov
2014-05-08 19:11 ` [PATCH 2/6] x86/traps: Use SEND_SIG_PRIV instead of force_sig() Oleg Nesterov
2014-05-08 19:11 ` [PATCH 3/6] x86/traps: Introduce do_error_trap() Oleg Nesterov
2014-05-08 19:12 ` [PATCH 4/6] x86/traps: Introduce fill_trap_info(), simplify DO_ERROR_INFO() Oleg Nesterov
2014-05-08 19:12 ` [PATCH 5/6] x86/traps: Shift fill_trap_info() from DO_ERROR_INFO() to do_error_trap() Oleg Nesterov
2014-05-08 19:12 ` [PATCH 6/6] x86/traps: Kill DO_ERROR_INFO() Oleg Nesterov
2014-05-09 14:07 ` can't we kill DIE_GPF ? (Was: x86/traps: cleanup DO_ERROR*() to prepare for uprobes fixes) Oleg Nesterov
2014-05-13  6:07   ` Masami Hiramatsu
2014-05-13 17:11     ` Oleg Nesterov
2014-05-12 17:08 ` [PATCH 0/1] (Was: " Oleg Nesterov
2014-05-12 17:08   ` [PATCH 1/1] uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap Oleg Nesterov
2014-05-13  6:23     ` Masami Hiramatsu [this message]
2014-05-12 19:39   ` [PATCH 0/1] (Was: cleanup DO_ERROR*() to prepare for uprobes fixes) David Long
2014-05-13  5:10   ` Ananth N Mavinakayanahalli

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=5371BA64.8070203@hitachi.com \
    --to=masami.hiramatsu.pt@hitachi.com \
    --cc=ananth@in.ibm.com \
    --cc=dave.long@linaro.org \
    --cc=dvlasenk@redhat.com \
    --cc=hpa@zytor.com \
    --cc=jkenisto@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=srikar@linux.vnet.ibm.com \
    --cc=tglx@linutronix.de \
    --cc=x86@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.