linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: linux-kernel@vger.kernel.org, ananth@in.ibm.com,
	a.p.zijlstra@chello.nl, mingo@redhat.com,
	srikar@linux.vnet.ibm.com, roland@hack.frob.com
Subject: Re: [PATCH 2/2] x86/uprobes: implement x86 specific arch_uprobe_*_step
Date: Tue, 31 Jul 2012 19:51:08 +0200	[thread overview]
Message-ID: <20120731175108.GC14576@redhat.com> (raw)
In-Reply-To: <1343735548-18101-2-git-send-email-bigeasy@linutronix.de>

Oh, Sebastian, I'll try to read this patch tomorrow, but I am not
expert anyway.

However, honestly I do not like it. I think we should change this
step-by-step, that is why I suggested to use TIF_SINGLESTEP and
user_enable_single_step() like your initial patch did. With this
patch at least the debugger doesn't lose the control over the tracee
if it steps over the probed insn, and this is the main (and known ;)
problem to me.

Every change needs the discussion. For example, _enable should
clear DEBUGCTLMSR_BTF, this is obvious. But it is not clear to
me if _disable should restore it. What if the probed insn was
"jmp"? We need the additional complications to handle this case
really correctly, and for what? OK, gdb can get the extra SIGTRAP
from the tracee, but this is fine. And uprobes can confuse gdb
in many ways.

Even the "send_sig(SIGTRAP)" from _disable should be weighted.
Yes, yes, it was me who pointed we miss the trap. But is it really
that important? I dunno, and the problem is that send_sig(SIGTRAP)
is not the right interface (yes, handle_swbp() does this too).


But I am not maintainer.

Srikar, what do you think?


On 07/31, Sebastian Andrzej Siewior wrote:
> The arch specific implementation enables single stepping directly by
> setting the trap flag. "Single-Step on branches" is always disabled
> since only one opcode has to be executed.
> 
> The disable call removes the trap flag unless it was there before. It
> does not touch the flags register if the executed instruction was
> "popf". It does not take into account various prefixes like "lock popf"
> or "repz popf".
> SIGTRAP is sent to the process in case it was traced so the debugger
> knows once we advanced by one opcode. This isn't done in case we have to
> restore the BTF flag. In case the BTF flag is set, we should look at the
> opcode and send SIGTRAP depending on the jump/flag status. For now we
> wait for the next exception/jump to be taken.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  arch/x86/include/asm/uprobes.h |    3 ++
>  arch/x86/kernel/uprobes.c      |   60 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
> index f3971bb..47f4cf1 100644
> --- a/arch/x86/include/asm/uprobes.h
> +++ b/arch/x86/include/asm/uprobes.h
> @@ -46,6 +46,9 @@ struct arch_uprobe_task {
>  #ifdef CONFIG_X86_64
>  	unsigned long			saved_scratch_register;
>  #endif
> +#define UPROBE_CLEAR_TF			(1 << 0)
> +#define UPROBE_SET_BTF			(1 << 1)
> +	unsigned int			restore_flags;
>  };
>  
>  extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
> diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
> index 36fd420..6eec3e4 100644
> --- a/arch/x86/kernel/uprobes.c
> +++ b/arch/x86/kernel/uprobes.c
> @@ -673,3 +673,63 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
>  	}
>  	return false;
>  }
> +
> +static int insn_is_popf(const u8 *insn)
> +{
> +	/* popf */
> +	if (insn[0] == 0x9d)
> +		return 1;
> +	return 0;
> +}
> +
> +void arch_uprobe_enable_step(struct task_struct *child,
> +		struct arch_uprobe *auprobe)
> +{
> +	struct uprobe_task	*utask		= child->utask;
> +	struct arch_uprobe_task	*autask		= &utask->autask;
> +	struct pt_regs		*regs		= task_pt_regs(child);
> +	unsigned long		debugctl;
> +
> +	autask->restore_flags = 0;
> +	if (!(regs->flags & X86_EFLAGS_TF) &&
> +			!insn_is_popf(auprobe->insn)) {
> +		autask->restore_flags |= UPROBE_CLEAR_TF;
> +
> +		debugctl = get_debugctlmsr();
> +		if (debugctl & DEBUGCTLMSR_BTF) {
> +			autask->restore_flags |= UPROBE_SET_BTF;
> +			debugctl &= ~DEBUGCTLMSR_BTF;
> +			update_debugctlmsr(debugctl);
> +		}
> +	}
> +	regs->flags |= X86_EFLAGS_TF;
> +}
> +
> +void arch_uprobe_disable_step(struct task_struct *child,
> +		struct arch_uprobe *auprobe)
> +{
> +	struct uprobe_task *utask	= child->utask;
> +	struct arch_uprobe_task	*autask		= &utask->autask;
> +	struct pt_regs *regs		= task_pt_regs(child);
> +
> +	/*
> +	 * Disable the single step flag if it was set by us. Notify the debugger
> +	 * via SIGTRAP in case it was already there so it learns that we
> +	 * advanced by an opcode unless the debugger is waiting for the next
> +	 * jump to be taken. This logic gets it wrong if the uprobe was set
> +	 * on jump instruction that would raise an exception.
> +	 */
> +	if (autask->restore_flags & UPROBE_CLEAR_TF) {
> +		regs->flags &= ~X86_EFLAGS_TF;
> +	} else {
> +		if (autask->restore_flags & UPROBE_SET_BTF) {
> +			unsigned long	debugctl;
> +
> +			debugctl = get_debugctlmsr();
> +			debugctl |= DEBUGCTLMSR_BTF;
> +			update_debugctlmsr(debugctl);
> +		} else {
> +			send_sig(SIGTRAP, current, 0);
> +		}
> +	}
> +}
> -- 
> 1.7.10.4
> 


  reply	other threads:[~2012-07-31 18:23 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-26 15:20 [PATCH] uprobes: don't enable/disable signle step if the user did it Sebastian Andrzej Siewior
2012-07-26 17:31 ` Oleg Nesterov
2012-07-27 17:39   ` Sebastian Andrzej Siewior
2012-07-27 18:04     ` Oleg Nesterov
2012-07-26 17:38 ` Sebastian Andrzej Siewior
2012-07-30 11:06 ` Ananth N Mavinakayanahalli
2012-07-30 14:16   ` Oleg Nesterov
2012-07-30 15:15     ` Sebastian Andrzej Siewior
2012-07-31  4:01     ` Ananth N Mavinakayanahalli
2012-07-31  5:22     ` Srikar Dronamraju
2012-07-31 17:38       ` Oleg Nesterov
2012-07-31 11:52     ` [PATCH 1/2] uprobes: Use a helper instead of ptrace's single step enable Sebastian Andrzej Siewior
2012-07-31 11:52       ` [PATCH 2/2] x86/uprobes: implement x86 specific arch_uprobe_*_step Sebastian Andrzej Siewior
2012-07-31 17:51         ` Oleg Nesterov [this message]
2012-07-31 19:30           ` Sebastian Andrzej Siewior
2012-08-01 12:26             ` Oleg Nesterov
2012-08-01 13:01               ` Q: user_enable_single_step() && update_debugctlmsr() Oleg Nesterov
2012-08-01 13:32                 ` Sebastian Andrzej Siewior
2012-08-01 13:46                   ` Oleg Nesterov
2012-08-01 13:54                     ` Sebastian Andrzej Siewior
2012-08-01 14:01                       ` Oleg Nesterov
2012-08-01 14:21                         ` Sebastian Andrzej Siewior
2012-08-01 14:31                           ` Oleg Nesterov
2012-08-01 14:47                             ` Oleg Nesterov
2012-08-01 14:51                             ` Sebastian Andrzej Siewior
2012-08-01 15:01                               ` Oleg Nesterov
2012-08-01 15:12                                 ` Sebastian Andrzej Siewior
2012-08-01 15:14                                   ` Oleg Nesterov
2012-08-01 18:46                                     ` Sebastian Andrzej Siewior
2012-08-02 13:05                                       ` Oleg Nesterov
2012-08-02 13:20                                         ` Sebastian Andrzej Siewior
2012-08-02 13:24                                           ` Oleg Nesterov
2012-08-01 13:43         ` [PATCH 2/2] x86/uprobes: implement x86 specific arch_uprobe_*_step Oleg Nesterov
2012-08-02  4:58           ` Ananth N Mavinakayanahalli
2012-07-31 17:40       ` [PATCH 1/2] uprobes: Use a helper instead of ptrace's single step enable Oleg Nesterov

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=20120731175108.GC14576@redhat.com \
    --to=oleg@redhat.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=ananth@in.ibm.com \
    --cc=bigeasy@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=roland@hack.frob.com \
    --cc=srikar@linux.vnet.ibm.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).