Skip to content

Commit

Permalink
hw-breakpoints: Keep track of user disabled breakpoints
Browse files Browse the repository at this point in the history
When we disable a breakpoint through dr7, we unregister it right
away, making us lose track of its corresponding address
register value.

It means that the following sequence would be unsupported:

 - set address in dr0
 - enable it through dr7
 - disable it through dr7
 - enable it through dr7

because we lost the address register value when we disabled the
breakpoint.

Don't unregister the disabled breakpoints but rather disable
them.

Reported-by: "K.Prasad" <prasad@linux.vnet.ibm.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <1259735536-9236-1-git-send-regression-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed Dec 2, 2009
1 parent 6b62fe0 commit 1cedae7
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions arch/x86/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ static unsigned long ptrace_get_dr7(struct perf_event *bp[])

static struct perf_event *
ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
struct task_struct *tsk)
struct task_struct *tsk, int disabled)
{
int err;
int gen_len, gen_type;
Expand All @@ -616,7 +616,7 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
attr = bp->attr;
attr.bp_len = gen_len;
attr.bp_type = gen_type;
attr.disabled = 0;
attr.disabled = disabled;

return modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk);
}
Expand Down Expand Up @@ -655,13 +655,21 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
*/
if (!second_pass)
continue;

thread->ptrace_bps[i] = NULL;
unregister_hw_breakpoint(bp);
bp = ptrace_modify_breakpoint(bp, len, type,
tsk, 1);
if (IS_ERR(bp)) {
rc = PTR_ERR(bp);
thread->ptrace_bps[i] = NULL;
break;
}
thread->ptrace_bps[i] = bp;
}
continue;
}

bp = ptrace_modify_breakpoint(bp, len, type, tsk);
bp = ptrace_modify_breakpoint(bp, len, type, tsk, 0);

/* Incorrect bp, or we have a bug in bp API */
if (IS_ERR(bp)) {
Expand Down

0 comments on commit 1cedae7

Please sign in to comment.