Re: [PATCH 3/6] ptrace/x86: introduce ptrace_register_breakpoint()

From: Oleg Nesterov
Date: Thu Apr 18 2013 - 15:04:45 EST


On 04/18, Oleg Nesterov wrote:
>
> No functional changes, preparation.
>
> Extract the "register breakpoint" code from ptrace_get_debugreg()
> into the new/generic helper, ptrace_register_breakpoint(). It will
> have more users.
>
> The patch also adds another simple helper, ptrace_fill_bp_fields(),
> to factor out the arch_bp_generic_fields() logic in register/modify.

This patch is hardly readable. To simplify the review, I attached the
new/modified code below.

Oleg.

static int ptrace_fill_bp_fields(struct perf_event_attr *attr,
int len, int type, bool disabled)
{
int err, bp_len, bp_type;

err = arch_bp_generic_fields(len, type, &bp_len, &bp_type);
if (!err) {
attr->bp_len = bp_len;
attr->bp_type = bp_type;
attr->disabled = disabled;
}

return err;
}

static struct perf_event *
ptrace_register_breakpoint(struct task_struct *tsk, int len, int type,
unsigned long addr, bool disabled)
{
struct perf_event_attr attr;
int err;

ptrace_breakpoint_init(&attr);
attr.bp_addr = addr;

err = ptrace_fill_bp_fields(&attr, len, type, disabled);
if (err)
return ERR_PTR(err);

return register_user_hw_breakpoint(&attr, ptrace_triggered,
NULL, tsk);
}

static int ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
int disabled)
{
struct perf_event_attr attr = bp->attr;
int err;

err = ptrace_fill_bp_fields(&attr, len, type, disabled);
if (err)
return err;

return modify_user_hw_breakpoint(bp, &attr);
}

static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
unsigned long addr)
{
struct thread_struct *t = &tsk->thread;
struct perf_event *bp = t->ptrace_bps[nr];
int err = 0;

if (!bp) {
/*
* Put stub len and type to create an inactive but correct bp.
*
* CHECKME: the previous code returned -EIO if the addr wasn't
* a valid task virtual addr. The new one will return -EINVAL in
* this case.
* -EINVAL may be what we want for in-kernel breakpoints users,
* but -EIO looks better for ptrace, since we refuse a register
* writing for the user. And anyway this is the previous
* behaviour.
*/
bp = ptrace_register_breakpoint(tsk,
X86_BREAKPOINT_LEN_1, X86_BREAKPOINT_WRITE,
addr, true);
if (IS_ERR(bp))
err = PTR_ERR(bp);
else
t->ptrace_bps[nr] = bp;
} else {
struct perf_event_attr attr = bp->attr;

attr.bp_addr = addr;
err = modify_user_hw_breakpoint(bp, &attr);
}

return err;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/