diff options
| author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2014-04-17 04:17:54 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2014-04-24 04:03:01 -0400 |
| commit | 55479f64756fc508182a05e35e52f01395a50d4d (patch) | |
| tree | 7b54c148e68e74f38108edde74a2408c1d04fe2c /kernel | |
| parent | 7ec8a97a990da8e3ba87175a757731e17f74072e (diff) | |
kprobes: Allow probe on some kprobe functions
There is no need to prohibit probing on the functions
used for preparation, registeration, optimization,
controll etc. Those are safely probed because those are
not invoked from breakpoint/fault/debug handlers,
there is no chance to cause recursive exceptions.
Following functions are now removed from the kprobes blacklist:
add_new_kprobe
aggr_kprobe_disabled
alloc_aggr_kprobe
alloc_aggr_kprobe
arm_all_kprobes
__arm_kprobe
arm_kprobe
arm_kprobe_ftrace
check_kprobe_address_safe
collect_garbage_slots
collect_garbage_slots
collect_one_slot
debugfs_kprobe_init
__disable_kprobe
disable_kprobe
disarm_all_kprobes
__disarm_kprobe
disarm_kprobe
disarm_kprobe_ftrace
do_free_cleaned_kprobes
do_optimize_kprobes
do_unoptimize_kprobes
enable_kprobe
force_unoptimize_kprobe
free_aggr_kprobe
free_aggr_kprobe
__free_insn_slot
__get_insn_slot
get_optimized_kprobe
__get_valid_kprobe
init_aggr_kprobe
init_aggr_kprobe
in_nokprobe_functions
kick_kprobe_optimizer
kill_kprobe
kill_optimized_kprobe
kprobe_addr
kprobe_optimizer
kprobe_queued
kprobe_seq_next
kprobe_seq_start
kprobe_seq_stop
kprobes_module_callback
kprobes_open
optimize_all_kprobes
optimize_kprobe
prepare_kprobe
prepare_optimized_kprobe
register_aggr_kprobe
register_jprobe
register_jprobes
register_kprobe
register_kprobes
register_kretprobe
register_kretprobe
register_kretprobes
register_kretprobes
report_probe
show_kprobe_addr
try_to_optimize_kprobe
unoptimize_all_kprobes
unoptimize_kprobe
unregister_jprobe
unregister_jprobes
unregister_kprobe
__unregister_kprobe_bottom
unregister_kprobes
__unregister_kprobe_top
unregister_kretprobe
unregister_kretprobe
unregister_kretprobes
unregister_kretprobes
wait_for_kprobe_optimizer
I tested those functions by putting kprobes on all
instructions in the functions with the bash script
I sent to LKML. See:
https://lkml.org/lkml/2014/3/27/33
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Link: http://lkml.kernel.org/r/20140417081753.26341.57889.stgit@ltc230.yrl.intra.hitachi.co.jp
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: fche@redhat.com
Cc: systemtap@sourceware.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kprobes.c | 153 |
1 files changed, 76 insertions, 77 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 5ffc6875d2a7..4db2cc616f50 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -138,13 +138,13 @@ struct kprobe_insn_cache kprobe_insn_slots = { | |||
| 138 | .insn_size = MAX_INSN_SIZE, | 138 | .insn_size = MAX_INSN_SIZE, |
| 139 | .nr_garbage = 0, | 139 | .nr_garbage = 0, |
| 140 | }; | 140 | }; |
| 141 | static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c); | 141 | static int collect_garbage_slots(struct kprobe_insn_cache *c); |
| 142 | 142 | ||
| 143 | /** | 143 | /** |
| 144 | * __get_insn_slot() - Find a slot on an executable page for an instruction. | 144 | * __get_insn_slot() - Find a slot on an executable page for an instruction. |
| 145 | * We allocate an executable page if there's no room on existing ones. | 145 | * We allocate an executable page if there's no room on existing ones. |
| 146 | */ | 146 | */ |
| 147 | kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c) | 147 | kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c) |
| 148 | { | 148 | { |
| 149 | struct kprobe_insn_page *kip; | 149 | struct kprobe_insn_page *kip; |
| 150 | kprobe_opcode_t *slot = NULL; | 150 | kprobe_opcode_t *slot = NULL; |
| @@ -201,7 +201,7 @@ out: | |||
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | /* Return 1 if all garbages are collected, otherwise 0. */ | 203 | /* Return 1 if all garbages are collected, otherwise 0. */ |
| 204 | static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) | 204 | static int collect_one_slot(struct kprobe_insn_page *kip, int idx) |
| 205 | { | 205 | { |
| 206 | kip->slot_used[idx] = SLOT_CLEAN; | 206 | kip->slot_used[idx] = SLOT_CLEAN; |
| 207 | kip->nused--; | 207 | kip->nused--; |
| @@ -222,7 +222,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) | |||
| 222 | return 0; | 222 | return 0; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c) | 225 | static int collect_garbage_slots(struct kprobe_insn_cache *c) |
| 226 | { | 226 | { |
| 227 | struct kprobe_insn_page *kip, *next; | 227 | struct kprobe_insn_page *kip, *next; |
| 228 | 228 | ||
| @@ -244,8 +244,8 @@ static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c) | |||
| 244 | return 0; | 244 | return 0; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | void __kprobes __free_insn_slot(struct kprobe_insn_cache *c, | 247 | void __free_insn_slot(struct kprobe_insn_cache *c, |
| 248 | kprobe_opcode_t *slot, int dirty) | 248 | kprobe_opcode_t *slot, int dirty) |
| 249 | { | 249 | { |
| 250 | struct kprobe_insn_page *kip; | 250 | struct kprobe_insn_page *kip; |
| 251 | 251 | ||
| @@ -361,7 +361,7 @@ void __kprobes opt_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | /* Free optimized instructions and optimized_kprobe */ | 363 | /* Free optimized instructions and optimized_kprobe */ |
| 364 | static __kprobes void free_aggr_kprobe(struct kprobe *p) | 364 | static void free_aggr_kprobe(struct kprobe *p) |
| 365 | { | 365 | { |
| 366 | struct optimized_kprobe *op; | 366 | struct optimized_kprobe *op; |
| 367 | 367 | ||
| @@ -399,7 +399,7 @@ static inline int kprobe_disarmed(struct kprobe *p) | |||
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | /* Return true(!0) if the probe is queued on (un)optimizing lists */ | 401 | /* Return true(!0) if the probe is queued on (un)optimizing lists */ |
| 402 | static int __kprobes kprobe_queued(struct kprobe *p) | 402 | static int kprobe_queued(struct kprobe *p) |
| 403 | { | 403 | { |
| 404 | struct optimized_kprobe *op; | 404 | struct optimized_kprobe *op; |
| 405 | 405 | ||
| @@ -415,7 +415,7 @@ static int __kprobes kprobe_queued(struct kprobe *p) | |||
| 415 | * Return an optimized kprobe whose optimizing code replaces | 415 | * Return an optimized kprobe whose optimizing code replaces |
| 416 | * instructions including addr (exclude breakpoint). | 416 | * instructions including addr (exclude breakpoint). |
| 417 | */ | 417 | */ |
| 418 | static struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr) | 418 | static struct kprobe *get_optimized_kprobe(unsigned long addr) |
| 419 | { | 419 | { |
| 420 | int i; | 420 | int i; |
| 421 | struct kprobe *p = NULL; | 421 | struct kprobe *p = NULL; |
| @@ -447,7 +447,7 @@ static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer); | |||
| 447 | * Optimize (replace a breakpoint with a jump) kprobes listed on | 447 | * Optimize (replace a breakpoint with a jump) kprobes listed on |
| 448 | * optimizing_list. | 448 | * optimizing_list. |
| 449 | */ | 449 | */ |
| 450 | static __kprobes void do_optimize_kprobes(void) | 450 | static void do_optimize_kprobes(void) |
| 451 | { | 451 | { |
| 452 | /* Optimization never be done when disarmed */ | 452 | /* Optimization never be done when disarmed */ |
| 453 | if (kprobes_all_disarmed || !kprobes_allow_optimization || | 453 | if (kprobes_all_disarmed || !kprobes_allow_optimization || |
| @@ -475,7 +475,7 @@ static __kprobes void do_optimize_kprobes(void) | |||
| 475 | * Unoptimize (replace a jump with a breakpoint and remove the breakpoint | 475 | * Unoptimize (replace a jump with a breakpoint and remove the breakpoint |
| 476 | * if need) kprobes listed on unoptimizing_list. | 476 | * if need) kprobes listed on unoptimizing_list. |
| 477 | */ | 477 | */ |
| 478 | static __kprobes void do_unoptimize_kprobes(void) | 478 | static void do_unoptimize_kprobes(void) |
| 479 | { | 479 | { |
| 480 | struct optimized_kprobe *op, *tmp; | 480 | struct optimized_kprobe *op, *tmp; |
| 481 | 481 | ||
| @@ -507,7 +507,7 @@ static __kprobes void do_unoptimize_kprobes(void) | |||
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | /* Reclaim all kprobes on the free_list */ | 509 | /* Reclaim all kprobes on the free_list */ |
| 510 | static __kprobes void do_free_cleaned_kprobes(void) | 510 | static void do_free_cleaned_kprobes(void) |
| 511 | { | 511 | { |
| 512 | struct optimized_kprobe *op, *tmp; | 512 | struct optimized_kprobe *op, *tmp; |
| 513 | 513 | ||
| @@ -519,13 +519,13 @@ static __kprobes void do_free_cleaned_kprobes(void) | |||
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | /* Start optimizer after OPTIMIZE_DELAY passed */ | 521 | /* Start optimizer after OPTIMIZE_DELAY passed */ |
| 522 | static __kprobes void kick_kprobe_optimizer(void) | 522 | static void kick_kprobe_optimizer(void) |
| 523 | { | 523 | { |
| 524 | schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY); | 524 | schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | /* Kprobe jump optimizer */ | 527 | /* Kprobe jump optimizer */ |
| 528 | static __kprobes void kprobe_optimizer(struct work_struct *work) | 528 | static void kprobe_optimizer(struct work_struct *work) |
| 529 | { | 529 | { |
| 530 | mutex_lock(&kprobe_mutex); | 530 | mutex_lock(&kprobe_mutex); |
| 531 | /* Lock modules while optimizing kprobes */ | 531 | /* Lock modules while optimizing kprobes */ |
| @@ -561,7 +561,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) | |||
| 561 | } | 561 | } |
| 562 | 562 | ||
| 563 | /* Wait for completing optimization and unoptimization */ | 563 | /* Wait for completing optimization and unoptimization */ |
| 564 | static __kprobes void wait_for_kprobe_optimizer(void) | 564 | static void wait_for_kprobe_optimizer(void) |
| 565 | { | 565 | { |
| 566 | mutex_lock(&kprobe_mutex); | 566 | mutex_lock(&kprobe_mutex); |
| 567 | 567 | ||
| @@ -580,7 +580,7 @@ static __kprobes void wait_for_kprobe_optimizer(void) | |||
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | /* Optimize kprobe if p is ready to be optimized */ | 582 | /* Optimize kprobe if p is ready to be optimized */ |
| 583 | static __kprobes void optimize_kprobe(struct kprobe *p) | 583 | static void optimize_kprobe(struct kprobe *p) |
| 584 | { | 584 | { |
| 585 | struct optimized_kprobe *op; | 585 | struct optimized_kprobe *op; |
| 586 | 586 | ||
| @@ -614,7 +614,7 @@ static __kprobes void optimize_kprobe(struct kprobe *p) | |||
| 614 | } | 614 | } |
| 615 | 615 | ||
| 616 | /* Short cut to direct unoptimizing */ | 616 | /* Short cut to direct unoptimizing */ |
| 617 | static __kprobes void force_unoptimize_kprobe(struct optimized_kprobe *op) | 617 | static void force_unoptimize_kprobe(struct optimized_kprobe *op) |
| 618 | { | 618 | { |
| 619 | get_online_cpus(); | 619 | get_online_cpus(); |
| 620 | arch_unoptimize_kprobe(op); | 620 | arch_unoptimize_kprobe(op); |
| @@ -624,7 +624,7 @@ static __kprobes void force_unoptimize_kprobe(struct optimized_kprobe *op) | |||
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | /* Unoptimize a kprobe if p is optimized */ | 626 | /* Unoptimize a kprobe if p is optimized */ |
| 627 | static __kprobes void unoptimize_kprobe(struct kprobe *p, bool force) | 627 | static void unoptimize_kprobe(struct kprobe *p, bool force) |
| 628 | { | 628 | { |
| 629 | struct optimized_kprobe *op; | 629 | struct optimized_kprobe *op; |
| 630 | 630 | ||
| @@ -684,7 +684,7 @@ static void reuse_unused_kprobe(struct kprobe *ap) | |||
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | /* Remove optimized instructions */ | 686 | /* Remove optimized instructions */ |
| 687 | static void __kprobes kill_optimized_kprobe(struct kprobe *p) | 687 | static void kill_optimized_kprobe(struct kprobe *p) |
| 688 | { | 688 | { |
| 689 | s | ||
