diff options
author | Keshavamurthy Anil S <anil.s.keshavamurthy@intel.com> | 2005-06-23 03:09:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-23 12:45:24 -0400 |
commit | 89cb14c0dd0e4a7d0315d19f449389c4d49237ee (patch) | |
tree | 795e52fd30c5236c365be7a3eaedb316e5c8cad5 /arch/ia64/kernel/kprobes.c | |
parent | 708de8f11c2901cc49fd7725baf4a0fbd7264e73 (diff) |
[PATCH] Kprobes/IA64: check jprobe break before handling
Once the jprobe instrumented function returns, it executes a jprobe_break
which is a break instruction with __IA64_JPROBE_BREAK value. The current
patch checks for this break value, before assuming that jprobe instrumented
function just completed.
The previous code was not checking for this value and that was a bug.
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 027d656664d2..41e80b42d3f3 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -419,10 +419,11 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs) | |||
419 | ia64_psr(regs)->ss = 1; | 419 | ia64_psr(regs)->ss = 1; |
420 | } | 420 | } |
421 | 421 | ||
422 | static int pre_kprobes_handler(struct pt_regs *regs) | 422 | static int pre_kprobes_handler(struct die_args *args) |
423 | { | 423 | { |
424 | struct kprobe *p; | 424 | struct kprobe *p; |
425 | int ret = 0; | 425 | int ret = 0; |
426 | struct pt_regs *regs = args->regs; | ||
426 | kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); | 427 | kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); |
427 | 428 | ||
428 | preempt_disable(); | 429 | preempt_disable(); |
@@ -437,7 +438,7 @@ static int pre_kprobes_handler(struct pt_regs *regs) | |||
437 | } | 438 | } |
438 | arch_disarm_kprobe(p); | 439 | arch_disarm_kprobe(p); |
439 | ret = 1; | 440 | ret = 1; |
440 | } else { | 441 | } else if (args->err == __IA64_BREAK_JPROBE) { |
441 | /* | 442 | /* |
442 | * jprobe instrumented function just completed | 443 | * jprobe instrumented function just completed |
443 | */ | 444 | */ |
@@ -445,6 +446,9 @@ static int pre_kprobes_handler(struct pt_regs *regs) | |||
445 | if (p->break_handler && p->break_handler(p, regs)) { | 446 | if (p->break_handler && p->break_handler(p, regs)) { |
446 | goto ss_probe; | 447 | goto ss_probe; |
447 | } | 448 | } |
449 | } else { | ||
450 | /* Not our break */ | ||
451 | goto no_kprobe; | ||
448 | } | 452 | } |
449 | } | 453 | } |
450 | 454 | ||
@@ -515,7 +519,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
515 | struct die_args *args = (struct die_args *)data; | 519 | struct die_args *args = (struct die_args *)data; |
516 | switch(val) { | 520 | switch(val) { |
517 | case DIE_BREAK: | 521 | case DIE_BREAK: |
518 | if (pre_kprobes_handler(args->regs)) | 522 | if (pre_kprobes_handler(args)) |
519 | return NOTIFY_STOP; | 523 | return NOTIFY_STOP; |
520 | break; | 524 | break; |
521 | case DIE_SS: | 525 | case DIE_SS: |