Commit 26b31c1908e02a316edfba08080373342e662c14
Committed by
Linus Torvalds
1 parent
4a296e07c3
Exists in
master
and in
4 other branches
kprobes: add (un)register_jprobes for batch registration
Introduce unregister_/register_jprobes() for jprobe batch registration. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com> Cc: Shaohua Li <shaohua.li@intel.com> Cc: David Miller <davem@davemloft.net> Cc: "Frank Ch. Eigler" <fche@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 65 additions and 9 deletions Side-by-side Diff
include/linux/kprobes.h
... | ... | @@ -240,6 +240,8 @@ |
240 | 240 | int longjmp_break_handler(struct kprobe *, struct pt_regs *); |
241 | 241 | int register_jprobe(struct jprobe *p); |
242 | 242 | void unregister_jprobe(struct jprobe *p); |
243 | +int register_jprobes(struct jprobe **jps, int num); | |
244 | +void unregister_jprobes(struct jprobe **jps, int num); | |
243 | 245 | void jprobe_return(void); |
244 | 246 | unsigned long arch_deref_entry_point(void *); |
245 | 247 | |
246 | 248 | |
... | ... | @@ -279,7 +281,14 @@ |
279 | 281 | { |
280 | 282 | return -ENOSYS; |
281 | 283 | } |
284 | +static inline int register_jprobes(struct jprobe **jps, int num) | |
285 | +{ | |
286 | + return -ENOSYS; | |
287 | +} | |
282 | 288 | static inline void unregister_jprobe(struct jprobe *p) |
289 | +{ | |
290 | +} | |
291 | +static inline void unregister_jprobes(struct jprobe **jps, int num) | |
283 | 292 | { |
284 | 293 | } |
285 | 294 | static inline void jprobe_return(void) |
kernel/kprobes.c
... | ... | @@ -755,26 +755,71 @@ |
755 | 755 | return (unsigned long)entry; |
756 | 756 | } |
757 | 757 | |
758 | -int __kprobes register_jprobe(struct jprobe *jp) | |
758 | +static int __register_jprobes(struct jprobe **jps, int num, | |
759 | + unsigned long called_from) | |
759 | 760 | { |
760 | - unsigned long addr = arch_deref_entry_point(jp->entry); | |
761 | + struct jprobe *jp; | |
762 | + int ret = 0, i; | |
761 | 763 | |
762 | - if (!kernel_text_address(addr)) | |
764 | + if (num <= 0) | |
763 | 765 | return -EINVAL; |
766 | + for (i = 0; i < num; i++) { | |
767 | + unsigned long addr; | |
768 | + jp = jps[i]; | |
769 | + addr = arch_deref_entry_point(jp->entry); | |
764 | 770 | |
765 | - /* Todo: Verify probepoint is a function entry point */ | |
766 | - jp->kp.pre_handler = setjmp_pre_handler; | |
767 | - jp->kp.break_handler = longjmp_break_handler; | |
771 | + if (!kernel_text_address(addr)) | |
772 | + ret = -EINVAL; | |
773 | + else { | |
774 | + /* Todo: Verify probepoint is a function entry point */ | |
775 | + jp->kp.pre_handler = setjmp_pre_handler; | |
776 | + jp->kp.break_handler = longjmp_break_handler; | |
777 | + ret = __register_kprobe(&jp->kp, called_from); | |
778 | + } | |
779 | + if (ret < 0 && i > 0) { | |
780 | + unregister_jprobes(jps, i); | |
781 | + break; | |
782 | + } | |
783 | + } | |
784 | + return ret; | |
785 | +} | |
768 | 786 | |
769 | - return __register_kprobe(&jp->kp, | |
787 | +int __kprobes register_jprobe(struct jprobe *jp) | |
788 | +{ | |
789 | + return __register_jprobes(&jp, 1, | |
770 | 790 | (unsigned long)__builtin_return_address(0)); |
771 | 791 | } |
772 | 792 | |
773 | 793 | void __kprobes unregister_jprobe(struct jprobe *jp) |
774 | 794 | { |
775 | - unregister_kprobe(&jp->kp); | |
795 | + unregister_jprobes(&jp, 1); | |
776 | 796 | } |
777 | 797 | |
798 | +int __kprobes register_jprobes(struct jprobe **jps, int num) | |
799 | +{ | |
800 | + return __register_jprobes(jps, num, | |
801 | + (unsigned long)__builtin_return_address(0)); | |
802 | +} | |
803 | + | |
804 | +void __kprobes unregister_jprobes(struct jprobe **jps, int num) | |
805 | +{ | |
806 | + int i; | |
807 | + | |
808 | + if (num <= 0) | |
809 | + return; | |
810 | + mutex_lock(&kprobe_mutex); | |
811 | + for (i = 0; i < num; i++) | |
812 | + if (__unregister_kprobe_top(&jps[i]->kp) < 0) | |
813 | + jps[i]->kp.addr = NULL; | |
814 | + mutex_unlock(&kprobe_mutex); | |
815 | + | |
816 | + synchronize_sched(); | |
817 | + for (i = 0; i < num; i++) { | |
818 | + if (jps[i]->kp.addr) | |
819 | + __unregister_kprobe_bottom(&jps[i]->kp); | |
820 | + } | |
821 | +} | |
822 | + | |
778 | 823 | #ifdef CONFIG_KRETPROBES |
779 | 824 | /* |
780 | 825 | * This kprobe pre_handler is registered with every kretprobe. When probe |
... | ... | @@ -1236,6 +1281,8 @@ |
1236 | 1281 | EXPORT_SYMBOL_GPL(unregister_kprobes); |
1237 | 1282 | EXPORT_SYMBOL_GPL(register_jprobe); |
1238 | 1283 | EXPORT_SYMBOL_GPL(unregister_jprobe); |
1284 | +EXPORT_SYMBOL_GPL(register_jprobes); | |
1285 | +EXPORT_SYMBOL_GPL(unregister_jprobes); | |
1239 | 1286 | #ifdef CONFIG_KPROBES |
1240 | 1287 | EXPORT_SYMBOL_GPL(jprobe_return); |
1241 | 1288 | #endif |