diff options
| -rw-r--r-- | arch/x86/kernel/kprobes/core.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 18fbe9be2d68..fed46ddb1eef 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
| @@ -749,11 +749,16 @@ asm( | |||
| 749 | NOKPROBE_SYMBOL(kretprobe_trampoline); | 749 | NOKPROBE_SYMBOL(kretprobe_trampoline); |
| 750 | STACK_FRAME_NON_STANDARD(kretprobe_trampoline); | 750 | STACK_FRAME_NON_STANDARD(kretprobe_trampoline); |
| 751 | 751 | ||
| 752 | static struct kprobe kretprobe_kprobe = { | ||
| 753 | .addr = (void *)kretprobe_trampoline, | ||
| 754 | }; | ||
| 755 | |||
| 752 | /* | 756 | /* |
| 753 | * Called from kretprobe_trampoline | 757 | * Called from kretprobe_trampoline |
| 754 | */ | 758 | */ |
| 755 | static __used void *trampoline_handler(struct pt_regs *regs) | 759 | static __used void *trampoline_handler(struct pt_regs *regs) |
| 756 | { | 760 | { |
| 761 | struct kprobe_ctlblk *kcb; | ||
| 757 | struct kretprobe_instance *ri = NULL; | 762 | struct kretprobe_instance *ri = NULL; |
| 758 | struct hlist_head *head, empty_rp; | 763 | struct hlist_head *head, empty_rp; |
| 759 | struct hlist_node *tmp; | 764 | struct hlist_node *tmp; |
| @@ -763,6 +768,17 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 763 | void *frame_pointer; | 768 | void *frame_pointer; |
| 764 | bool skipped = false; | 769 | bool skipped = false; |
| 765 | 770 | ||
| 771 | preempt_disable(); | ||
| 772 | |||
| 773 | /* | ||
| 774 | * Set a dummy kprobe for avoiding kretprobe recursion. | ||
| 775 | * Since kretprobe never run in kprobe handler, kprobe must not | ||
| 776 | * be running at this point. | ||
| 777 | */ | ||
| 778 | kcb = get_kprobe_ctlblk(); | ||
| 779 | __this_cpu_write(current_kprobe, &kretprobe_kprobe); | ||
| 780 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 781 | |||
| 766 | INIT_HLIST_HEAD(&empty_rp); | 782 | INIT_HLIST_HEAD(&empty_rp); |
| 767 | kretprobe_hash_lock(current, &head, &flags); | 783 | kretprobe_hash_lock(current, &head, &flags); |
| 768 | /* fixup registers */ | 784 | /* fixup registers */ |
| @@ -838,10 +854,9 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 838 | orig_ret_address = (unsigned long)ri->ret_addr; | 854 | orig_ret_address = (unsigned long)ri->ret_addr; |
| 839 | if (ri->rp && ri->rp->handler) { | 855 | if (ri->rp && ri->rp->handler) { |
| 840 | __this_cpu_write(current_kprobe, &ri->rp->kp); | 856 | __this_cpu_write(current_kprobe, &ri->rp->kp); |
| 841 | get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 842 | ri->ret_addr = correct_ret_addr; | 857 | ri->ret_addr = correct_ret_addr; |
| 843 | ri->rp->handler(ri, regs); | 858 | ri->rp->handler(ri, regs); |
| 844 | __this_cpu_write(current_kprobe, NULL); | 859 | __this_cpu_write(current_kprobe, &kretprobe_kprobe); |
| 845 | } | 860 | } |
| 846 | 861 | ||
| 847 | recycle_rp_inst(ri, &empty_rp); | 862 | recycle_rp_inst(ri, &empty_rp); |
| @@ -857,6 +872,9 @@ static __used void *trampoline_handler(struct pt_regs *regs) | |||
| 857 | 872 | ||
| 858 | kretprobe_hash_unlock(current, &flags); | 873 | kretprobe_hash_unlock(current, &flags); |
| 859 | 874 | ||
| 875 | __this_cpu_write(current_kprobe, NULL); | ||
| 876 | preempt_enable(); | ||
| 877 | |||
| 860 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { | 878 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { |
| 861 | hlist_del(&ri->hlist); | 879 | hlist_del(&ri->hlist); |
| 862 | kfree(ri); | 880 | kfree(ri); |
