aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/probes/kprobes/core.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index 269f66e66ff5..ad1f4e6a9e33 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -441,6 +441,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
441 struct hlist_node *tmp; 441 struct hlist_node *tmp;
442 unsigned long flags, orig_ret_address = 0; 442 unsigned long flags, orig_ret_address = 0;
443 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; 443 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
444 kprobe_opcode_t *correct_ret_addr = NULL;
444 445
445 INIT_HLIST_HEAD(&empty_rp); 446 INIT_HLIST_HEAD(&empty_rp);
446 kretprobe_hash_lock(current, &head, &flags); 447 kretprobe_hash_lock(current, &head, &flags);
@@ -463,14 +464,34 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
463 /* another task is sharing our hash bucket */ 464 /* another task is sharing our hash bucket */
464 continue; 465 continue;
465 466
467 orig_ret_address = (unsigned long)ri->ret_addr;
468
469 if (orig_ret_address != trampoline_address)
470 /*
471 * This is the real return address. Any other
472 * instances associated with this task are for
473 * other calls deeper on the call stack
474 */
475 break;
476 }
477
478 kretprobe_assert(ri, orig_ret_address, trampoline_address);
479
480 correct_ret_addr = ri->ret_addr;
481 hlist_for_each_entry_safe(ri, tmp, head, hlist) {
482 if (ri->task != current)
483 /* another task is sharing our hash bucket */
484 continue;
485
486 orig_ret_address = (unsigned long)ri->ret_addr;
466 if (ri->rp && ri->rp->handler) { 487 if (ri->rp && ri->rp->handler) {
467 __this_cpu_write(current_kprobe, &ri->rp->kp); 488 __this_cpu_write(current_kprobe, &ri->rp->kp);
468 get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; 489 get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
490 ri->ret_addr = correct_ret_addr;
469 ri->rp->handler(ri, regs); 491 ri->rp->handler(ri, regs);
470 __this_cpu_write(current_kprobe, NULL); 492 __this_cpu_write(current_kprobe, NULL);
471 } 493 }
472 494
473 orig_ret_address = (unsigned long)ri->ret_addr;
474 recycle_rp_inst(ri, &empty_rp); 495 recycle_rp_inst(ri, &empty_rp);
475 496
476 if (orig_ret_address != trampoline_address) 497 if (orig_ret_address != trampoline_address)
@@ -482,7 +503,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
482 break; 503 break;
483 } 504 }
484 505
485 kretprobe_assert(ri, orig_ret_address, trampoline_address);
486 kretprobe_hash_unlock(current, &flags); 506 kretprobe_hash_unlock(current, &flags);
487 507
488 hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { 508 hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {