Skip to content

Commit

Permalink
powerpc, hw_breakpoint: Fix off-by-one in checking access address
Browse files Browse the repository at this point in the history
The code would accept an access to an address one byte past the end
of the requested range as legitimate, due to having a "<=" rather than
a "<".  This fixes that and cleans up the code a bit.

Signed-off-by: Paul Mackerras <[email protected]>
  • Loading branch information
paulusmack committed Jun 23, 2010
1 parent e3e9408 commit 574cb24
Showing 1 changed file with 7 additions and 16 deletions.
23 changes: 7 additions & 16 deletions arch/powerpc/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
*/
int __kprobes hw_breakpoint_handler(struct die_args *args)
{
bool is_ptrace_bp = false;
int rc = NOTIFY_STOP;
struct perf_event *bp;
struct pt_regs *regs = args->regs;
Expand All @@ -208,6 +207,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)

/* Disable breakpoints during exception handling */
set_dabr(0);

/*
* The counter may be concurrently released but that can only
* occur from a call_rcu() path. We can then safely fetch
Expand All @@ -220,36 +220,27 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
if (!bp)
goto out;
info = counter_arch_bp(bp);
is_ptrace_bp = (bp->overflow_handler == ptrace_triggered) ?
true : false;

/*
* Return early after invoking user-callback function without restoring
* DABR if the breakpoint is from ptrace which always operates in
* one-shot mode. The ptrace-ed process will receive the SIGTRAP signal
* generated in do_dabr().
*/
if (is_ptrace_bp) {
if (bp->overflow_handler == ptrace_triggered) {
perf_bp_event(bp, regs);
rc = NOTIFY_DONE;
goto out;
}

/*
* Verify if dar lies within the address range occupied by the symbol
* being watched to filter extraneous exceptions.
* being watched to filter extraneous exceptions. If it doesn't,
* we still need to single-step the instruction, but we don't
* generate an event.
*/
if (!((bp->attr.bp_addr <= dar) &&
(dar <= (bp->attr.bp_addr + bp->attr.bp_len)))) {
/*
* This exception is triggered not because of a memory access
* on the monitored variable but in the double-word address
* range in which it is contained. We will consume this
* exception, considering it as 'noise'.
*/
info->extraneous_interrupt = true;
} else
info->extraneous_interrupt = false;
info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) &&
(dar - bp->attr.bp_addr < bp->attr.bp_len));

/* Do not emulate user-space instructions, instead single-step them */
if (user_mode(regs)) {
Expand Down

0 comments on commit 574cb24

Please sign in to comment.