diff options
| -rw-r--r-- | Documentation/kprobes.txt | 81 | ||||
| -rw-r--r-- | include/linux/kprobes.h | 3 | ||||
| -rw-r--r-- | kernel/kprobes.c | 9 | ||||
| -rw-r--r-- | kernel/test_kprobes.c | 16 |
4 files changed, 94 insertions, 15 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 53a63890aea4..30c101761d0d 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
| @@ -96,7 +96,9 @@ or in registers (e.g., for x86_64 or for an i386 fastcall function). | |||
| 96 | The jprobe will work in either case, so long as the handler's | 96 | The jprobe will work in either case, so long as the handler's |
| 97 | prototype matches that of the probed function. | 97 | prototype matches that of the probed function. |
| 98 | 98 | ||
| 99 | 1.3 How Does a Return Probe Work? | 99 | 1.3 Return Probes |
| 100 | |||
| 101 | 1.3.1 How Does a Return Probe Work? | ||
| 100 | 102 | ||
| 101 | When you call register_kretprobe(), Kprobes establishes a kprobe at | 103 | When you call register_kretprobe(), Kprobes establishes a kprobe at |
| 102 | the entry to the function. When the probed function is called and this | 104 | the entry to the function. When the probed function is called and this |
| @@ -107,9 +109,9 @@ At boot time, Kprobes registers a kprobe at the trampoline. | |||
| 107 | 109 | ||
| 108 | When the probed function executes its return instruction, control | 110 | When the probed function executes its return instruction, control |
| 109 | passes to the trampoline and that probe is hit. Kprobes' trampoline | 111 | passes to the trampoline and that probe is hit. Kprobes' trampoline |
| 110 | handler calls the user-specified handler associated with the kretprobe, | 112 | handler calls the user-specified return handler associated with the |
| 111 | then sets the saved instruction pointer to the saved return address, | 113 | kretprobe, then sets the saved instruction pointer to the saved return |
| 112 | and that's where execution resumes upon return from the trap. | 114 | address, and that's where execution resumes upon return from the trap. |
| 113 | 115 | ||
| 114 | While the probed function is executing, its return address is | 116 | While the probed function is executing, its return address is |
| 115 | stored in an object of type kretprobe_instance. Before calling | 117 | stored in an object of type kretprobe_instance. Before calling |
| @@ -131,6 +133,30 @@ zero when the return probe is registered, and is incremented every | |||
| 131 | time the probed function is entered but there is no kretprobe_instance | 133 | time the probed function is entered but there is no kretprobe_instance |
| 132 | object available for establishing the return probe. | 134 | object available for establishing the return probe. |
| 133 | 135 | ||
| 136 | 1.3.2 Kretprobe entry-handler | ||
| 137 | |||
| 138 | Kretprobes also provides an optional user-specified handler which runs | ||
| 139 | on function entry. This handler is specified by setting the entry_handler | ||
| 140 | field of the kretprobe struct. Whenever the kprobe placed by kretprobe at the | ||
| 141 | function entry is hit, the user-defined entry_handler, if any, is invoked. | ||
| 142 | If the entry_handler returns 0 (success) then a corresponding return handler | ||
| 143 | is guaranteed to be called upon function return. If the entry_handler | ||
| 144 | returns a non-zero error then Kprobes leaves the return address as is, and | ||
| 145 | the kretprobe has no further effect for that particular function instance. | ||
| 146 | |||
| 147 | Multiple entry and return handler invocations are matched using the unique | ||
| 148 | kretprobe_instance object associated with them. Additionally, a user | ||
| 149 | may also specify per return-instance private data to be part of each | ||
| 150 | kretprobe_instance object. This is especially useful when sharing private | ||
| 151 | data between corresponding user entry and return handlers. The size of each | ||
| 152 | private data object can be specified at kretprobe registration time by | ||
| 153 | setting the data_size field of the kretprobe struct. This data can be | ||
| 154 | accessed through the data field of each kretprobe_instance object. | ||
| 155 | |||
| 156 | In case probed function is entered but there is no kretprobe_instance | ||
| 157 | object available, then in addition to incrementing the nmissed count, | ||
| 158 | the user entry_handler invocation is also skipped. | ||
| 159 | |||
| 134 | 2. Architectures Supported | 160 | 2. Architectures Supported |
| 135 | 161 | ||
| 136 | Kprobes, jprobes, and return probes are implemented on the following | 162 | Kprobes, jprobes, and return probes are implemented on the following |
| @@ -274,6 +300,8 @@ of interest: | |||
| 274 | - ret_addr: the return address | 300 | - ret_addr: the return address |
| 275 | - rp: points to the corresponding kretprobe object | 301 | - rp: points to the corresponding kretprobe object |
| 276 | - task: points to the corresponding task struct | 302 | - task: points to the corresponding task struct |
| 303 | - data: points to per return-instance private data; see "Kretprobe | ||
| 304 | entry-handler" for details. | ||
| 277 | 305 | ||
| 278 | The regs_return_value(regs) macro provides a simple abstraction to | 306 | The regs_return_value(regs) macro provides a simple abstraction to |
| 279 | extract the return value from the appropriate register as defined by | 307 | extract the return value from the appropriate register as defined by |
| @@ -556,23 +584,52 @@ report failed calls to sys_open(). | |||
| 556 | #include <linux/kernel.h> | 584 | #include <linux/kernel.h> |
| 557 | #include <linux/module.h> | 585 | #include <linux/module.h> |
| 558 | #include <linux/kprobes.h> | 586 | #include <linux/kprobes.h> |
| 587 | #include <linux/ktime.h> | ||
| 588 | |||
| 589 | /* per-instance private data */ | ||
| 590 | struct my_data { | ||
| 591 | ktime_t entry_stamp; | ||
| 592 | }; | ||
| 559 | 593 | ||
| 560 | static const char *probed_func = "sys_open"; | 594 | static const char *probed_func = "sys_open"; |
| 561 | 595 | ||
| 562 | /* Return-probe handler: If the probed function fails, log the return value. */ | 596 | /* Timestamp function entry. */ |
| 563 | static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | 597 | static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) |
| 598 | { | ||
| 599 | struct my_data *data; | ||
| 600 | |||
| 601 | if(!current->mm) | ||
| 602 | return 1; /* skip kernel threads */ | ||
| 603 | |||
| 604 | data = (struct my_data *)ri->data; | ||
| 605 | data->entry_stamp = ktime_get(); | ||
| 606 | return 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | /* If the probed function failed, log the return value and duration. | ||
| 610 | * Duration may turn out to be zero consistently, depending upon the | ||
| 611 | * granularity of time accounting on the platform. */ | ||
| 612 | static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
| 564 | { | 613 | { |
| 565 | int retval = regs_return_value(regs); | 614 | int retval = regs_return_value(regs); |
| 615 | struct my_data *data = (struct my_data *)ri->data; | ||
| 616 | s64 delta; | ||
| 617 | ktime_t now; | ||
| 618 | |||
| 566 | if (retval < 0) { | 619 | if (retval < 0) { |
| 567 | printk("%s returns %d\n", probed_func, retval); | 620 | now = ktime_get(); |
| 621 | delta = ktime_to_ns(ktime_sub(now, data->entry_stamp)); | ||
| 622 | printk("%s: return val = %d (duration = %lld ns)\n", | ||
| 623 | probed_func, retval, delta); | ||
| 568 | } | 624 | } |
| 569 | return 0; | 625 | return 0; |
| 570 | } | 626 | } |
| 571 | 627 | ||
| 572 | static struct kretprobe my_kretprobe = { | 628 | static struct kretprobe my_kretprobe = { |
| 573 | .handler = ret_handler, | 629 | .handler = return_handler, |
| 574 | /* Probe up to 20 instances concurrently. */ | 630 | .entry_handler = entry_handler, |
| 575 | .maxactive = 20 | 631 | .data_size = sizeof(struct my_data), |
| 632 | .maxactive = 20, /* probe up to 20 instances concurrently */ | ||
| 576 | }; | 633 | }; |
| 577 | 634 | ||
| 578 | static int __init kretprobe_init(void) | 635 | static int __init kretprobe_init(void) |
| @@ -584,7 +641,7 @@ static int __init kretprobe_init(void) | |||
| 584 | printk("register_kretprobe failed, returned %d\n", ret); | 641 | printk("register_kretprobe failed, returned %d\n", ret); |
| 585 | return -1; | 642 | return -1; |
| 586 | } | 643 | } |
| 587 | printk("Planted return probe at %p\n", my_kretprobe.kp.addr); | 644 | printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name); |
| 588 | return 0; | 645 | return 0; |
| 589 | } | 646 | } |
| 590 | 647 | ||
| @@ -594,7 +651,7 @@ static void __exit kretprobe_exit(void) | |||
| 594 | printk("kretprobe unregistered\n"); | 651 | printk("kretprobe unregistered\n"); |
| 595 | /* nmissed > 0 suggests that maxactive was set too low. */ | 652 | /* nmissed > 0 suggests that maxactive was set too low. */ |
| 596 | printk("Missed probing %d instances of %s\n", | 653 | printk("Missed probing %d instances of %s\n", |
| 597 | my_kretprobe.nmissed, probed_func); | 654 | my_kretprobe.nmissed, probed_func); |
| 598 | } | 655 | } |
| 599 | 656 | ||
| 600 | module_init(kretprobe_init) | 657 | module_init(kretprobe_init) |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6168c0a44172..4a6ce82ba039 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
| @@ -152,8 +152,10 @@ static inline int arch_trampoline_kprobe(struct kprobe *p) | |||
| 152 | struct kretprobe { | 152 | struct kretprobe { |
| 153 | struct kprobe kp; | 153 | struct kprobe kp; |
| 154 | kretprobe_handler_t handler; | 154 | kretprobe_handler_t handler; |
| 155 | kretprobe_handler_t entry_handler; | ||
| 155 | int maxactive; | 156 | int maxactive; |
| 156 | int nmissed; | 157 | int nmissed; |
| 158 | size_t data_size; | ||
| 157 | struct hlist_head free_instances; | 159 | struct hlist_head free_instances; |
| 158 | struct hlist_head used_instances; | 160 | struct hlist_head used_instances; |
| 159 | }; | 161 | }; |
| @@ -164,6 +166,7 @@ struct kretprobe_instance { | |||
| 164 | struct kretprobe *rp; | 166 | struct kretprobe *rp; |
| 165 | kprobe_opcode_t *ret_addr; | 167 | kprobe_opcode_t *ret_addr; |
| 166 | struct task_struct *task; | 168 | struct task_struct *task; |
| 169 | char data[0]; | ||
| 167 | }; | 170 | }; |
| 168 | 171 | ||
| 169 | struct kretprobe_blackpoint { | 172 | struct kretprobe_blackpoint { |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index d0493eafea3e..7a86e6432338 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -699,6 +699,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
| 699 | struct kretprobe_instance, uflist); | 699 | struct kretprobe_instance, uflist); |
| 700 | ri->rp = rp; | 700 | ri->rp = rp; |
| 701 | ri->task = current; | 701 | ri->task = current; |
| 702 | |||
| 703 | if (rp->entry_handler && rp->entry_handler(ri, regs)) { | ||
| 704 | spin_unlock_irqrestore(&kretprobe_lock, flags); | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 702 | arch_prepare_kretprobe(ri, regs); | 708 | arch_prepare_kretprobe(ri, regs); |
| 703 | 709 | ||
| 704 | /* XXX(hch): why is there no hlist_move_head? */ | 710 | /* XXX(hch): why is there no hlist_move_head? */ |
| @@ -745,7 +751,8 @@ int __kprobes register_kretprobe(struct kretprobe *rp) | |||
| 745 | INIT_HLIST_HEAD(&rp->used_instances); | 751 | INIT_HLIST_HEAD(&rp->used_instances); |
| 746 | INIT_HLIST_HEAD(&rp->free_instances); | 752 | INIT_HLIST_HEAD(&rp->free_instances); |
| 747 | for (i = 0; i < rp->maxactive; i++) { | 753 | for (i = 0; i < rp->maxactive; i++) { |
| 748 | inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL); | 754 | inst = kmalloc(sizeof(struct kretprobe_instance) + |
| 755 | rp->data_size, GFP_KERNEL); | ||
| 749 | if (inst == NULL) { | 756 | if (inst == NULL) { |
| 750 | free_rp_inst(rp); | 757 | free_rp_inst(rp); |
| 751 | return -ENOMEM; | 758 | return -ENOMEM; |
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index 88cdb109e13c..06b6395b45b2 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c | |||
| @@ -135,6 +135,12 @@ static int test_jprobe(void) | |||
| 135 | #ifdef CONFIG_KRETPROBES | 135 | #ifdef CONFIG_KRETPROBES |
| 136 | static u32 krph_val; | 136 | static u32 krph_val; |
| 137 | 137 | ||
| 138 | static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
| 139 | { | ||
| 140 | krph_val = (rand1 / div_factor); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 138 | static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | 144 | static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) |
| 139 | { | 145 | { |
| 140 | unsigned long ret = regs_return_value(regs); | 146 | unsigned long ret = regs_return_value(regs); |
| @@ -144,13 +150,19 @@ static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 144 | printk(KERN_ERR "Kprobe smoke test failed: " | 150 | printk(KERN_ERR "Kprobe smoke test failed: " |
| 145 | "incorrect value in kretprobe handler\n"); | 151 | "incorrect value in kretprobe handler\n"); |
| 146 | } | 152 | } |
| 153 | if (krph_val == 0) { | ||
| 154 | handler_errors++; | ||
| 155 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 156 | "call to kretprobe entry handler failed\n"); | ||
| 157 | } | ||
| 147 | 158 | ||
| 148 | krph_val = (rand1 / div_factor); | 159 | krph_val = rand1; |
| 149 | return 0; | 160 | return 0; |
| 150 | } | 161 | } |
| 151 | 162 | ||
| 152 | static struct kretprobe rp = { | 163 | static struct kretprobe rp = { |
| 153 | .handler = return_handler, | 164 | .handler = return_handler, |
| 165 | .entry_handler = entry_handler, | ||
| 154 | .kp.symbol_name = "kprobe_target" | 166 | .kp.symbol_name = "kprobe_target" |
| 155 | }; | 167 | }; |
| 156 | 168 | ||
| @@ -167,7 +179,7 @@ static int test_kretprobe(void) | |||
| 167 | 179 | ||
| 168 | ret = kprobe_target(rand1); | 180 | ret = kprobe_target(rand1); |
| 169 | unregister_kretprobe(&rp); | 181 | unregister_kretprobe(&rp); |
| 170 | if (krph_val == 0) { | 182 | if (krph_val != rand1) { |
| 171 | printk(KERN_ERR "Kprobe smoke test failed: " | 183 | printk(KERN_ERR "Kprobe smoke test failed: " |
| 172 | "kretprobe handler not called\n"); | 184 | "kretprobe handler not called\n"); |
| 173 | handler_errors++; | 185 | handler_errors++; |
