aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHien Nguyen <hien@us.ibm.com>2005-06-23 03:09:19 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-23 12:45:21 -0400
commitb94cce926b2b902b79380ccba370d6f9f2980de0 (patch)
treeda2680b1ec36eae6423ba446d09284d2642ae82b
parent2fa389c5eb8c97d621653184d2adf5fdbd4a3167 (diff)
[PATCH] kprobes: function-return probes
This patch adds function-return probes to kprobes for the i386 architecture. This enables you to establish a handler to be run when a function returns. 1. API Two new functions are added to kprobes: int register_kretprobe(struct kretprobe *rp); void unregister_kretprobe(struct kretprobe *rp); 2. Registration and unregistration 2.1 Register To register a function-return probe, the user populates the following fields in a kretprobe object and calls register_kretprobe() with the kretprobe address as an argument: kp.addr - the function's address handler - this function is run after the ret instruction executes, but before control returns to the return address in the caller. maxactive - The maximum number of instances of the probed function that can be active concurrently. For example, if the function is non- recursive and is called with a spinlock or mutex held, maxactive = 1 should be enough. If the function is non-recursive and can never relinquish the CPU (e.g., via a semaphore or preemption), NR_CPUS should be enough. maxactive is used to determine how many kretprobe_instance objects to allocate for this particular probed function. If maxactive <= 0, it is set to a default value (if CONFIG_PREEMPT maxactive=max(10, 2 * NR_CPUS) else maxactive=NR_CPUS) For example: struct kretprobe rp; rp.kp.addr = /* entrypoint address */ rp.handler = /*return probe handler */ rp.maxactive = /* e.g., 1 or NR_CPUS or 0, see the above explanation */ register_kretprobe(&rp); The following field may also be of interest: nmissed - Initialized to zero when the function-return probe is registered, and incremented every time the probed function is entered but there is no kretprobe_instance object available for establishing the function-return probe (i.e., because maxactive was set too low). 2.2 Unregister To unregiter a function-return probe, the user calls unregister_kretprobe() with the same kretprobe object as registered previously. If a probed function is running when the return probe is unregistered, the function will return as expected, but the handler won't be run. 3. Limitations 3.1 This patch supports only the i386 architecture, but patches for x86_64 and ppc64 are anticipated soon. 3.2 Return probes operates by replacing the return address in the stack (or in a known register, such as the lr register for ppc). This may cause __builtin_return_address(0), when invoked from the return-probed function, to return the address of the return-probes trampoline. 3.3 This implementation uses the "Multiprobes at an address" feature in 2.6.12-rc3-mm3. 3.4 Due to a limitation in multi-probes, you cannot currently establish a return probe and a jprobe on the same function. A patch to remove this limitation is being tested. This feature is required by SystemTap (http://sourceware.org/systemtap), and reflects ideas contributed by several SystemTap developers, including Will Cohen and Ananth Mavinakayanahalli. Signed-off-by: Hien Nguyen <hien@us.ibm.com> Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> Signed-off-by: Frederik Deweerdt <frederik.deweerdt@laposte.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/kprobes.c102
-rw-r--r--arch/i386/kernel/process.c15
-rw-r--r--include/asm-i386/kprobes.h3
-rw-r--r--include/linux/kprobes.h90
-rw-r--r--kernel/kprobes.c213
5 files changed, 415 insertions, 8 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 59ff9b455069..048f754bbe23 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -23,6 +23,9 @@
23 * Rusty Russell). 23 * Rusty Russell).
24 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes 24 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
25 * interface to access function arguments. 25 * interface to access function arguments.
26 * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
27 * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
28 * <prasanna@in.ibm.com> added function-return probes.
26 */ 29 */
27 30
28#include <linux/config.h> 31#include <linux/config.h>
@@ -91,6 +94,53 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
91 regs->eip = (unsigned long)&p->ainsn.insn; 94 regs->eip = (unsigned long)&p->ainsn.insn;
92} 95}
93 96
97struct task_struct *arch_get_kprobe_task(void *ptr)
98{
99 return ((struct thread_info *) (((unsigned long) ptr) &
100 (~(THREAD_SIZE -1))))->task;
101}
102
103void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
104{
105 unsigned long *sara = (unsigned long *)&regs->esp;
106 struct kretprobe_instance *ri;
107 static void *orig_ret_addr;
108
109 /*
110 * Save the return address when the return probe hits
111 * the first time, and use it to populate the (krprobe
112 * instance)->ret_addr for subsequent return probes at
113 * the same addrress since stack address would have
114 * the kretprobe_trampoline by then.
115 */
116 if (((void*) *sara) != kretprobe_trampoline)
117 orig_ret_addr = (void*) *sara;
118
119 if ((ri = get_free_rp_inst(rp)) != NULL) {
120 ri->rp = rp;
121 ri->stack_addr = sara;
122 ri->ret_addr = orig_ret_addr;
123 add_rp_inst(ri);
124 /* Replace the return addr with trampoline addr */
125 *sara = (unsigned long) &kretprobe_trampoline;
126 } else {
127 rp->nmissed++;
128 }
129}
130
131void arch_kprobe_flush_task(struct task_struct *tk, spinlock_t *kp_lock)
132{
133 unsigned long flags = 0;
134 struct kretprobe_instance *ri;
135 spin_lock_irqsave(kp_lock, flags);
136 while ((ri = get_rp_inst_tsk(tk)) != NULL) {
137 *((unsigned long *)(ri->stack_addr)) =
138 (unsigned long) ri->ret_addr;
139 recycle_rp_inst(ri);
140 }
141 spin_unlock_irqrestore(kp_lock, flags);
142}
143
94/* 144/*
95 * Interrupts are disabled on entry as trap3 is an interrupt gate and they 145 * Interrupts are disabled on entry as trap3 is an interrupt gate and they
96 * remain disabled thorough out this function. 146 * remain disabled thorough out this function.
@@ -184,6 +234,55 @@ no_kprobe:
184} 234}
185 235
186/* 236/*
237 * For function-return probes, init_kprobes() establishes a probepoint
238 * here. When a retprobed function returns, this probe is hit and
239 * trampoline_probe_handler() runs, calling the kretprobe's handler.
240 */
241 void kretprobe_trampoline_holder(void)
242 {
243 asm volatile ( ".global kretprobe_trampoline\n"
244 "kretprobe_trampoline: \n"
245 "nop\n");
246 }
247
248/*
249 * Called when we hit the probe point at kretprobe_trampoline
250 */
251int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
252{
253 struct task_struct *tsk;
254 struct kretprobe_instance *ri;
255 struct hlist_head *head;
256 struct hlist_node *node;
257 unsigned long *sara = ((unsigned long *) &regs->esp) - 1;
258
259 tsk = arch_get_kprobe_task(sara);
260 head = kretprobe_inst_table_head(tsk);
261
262 hlist_for_each_entry(ri, node, head, hlist) {
263 if (ri->stack_addr == sara && ri->rp) {
264 if (ri->rp->handler)
265 ri->rp->handler(ri, regs);
266 }
267 }
268 return 0;
269}
270
271void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
272 unsigned long flags)
273{
274 struct kretprobe_instance *ri;
275 /* RA already popped */
276 unsigned long *sara = ((unsigned long *)&regs->esp) - 1;
277
278 while ((ri = get_rp_inst(sara))) {
279 regs->eip = (unsigned long)ri->ret_addr;
280 recycle_rp_inst(ri);
281 }
282 regs->eflags &= ~TF_MASK;
283}
284
285/*
187 * Called after single-stepping. p->addr is the address of the 286 * Called after single-stepping. p->addr is the address of the
188 * instruction whose first byte has been replaced by the "int 3" 287 * instruction whose first byte has been replaced by the "int 3"
189 * instruction. To avoid the SMP problems that can occur when we 288 * instruction. To avoid the SMP problems that can occur when we
@@ -266,7 +365,8 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
266 if (current_kprobe->post_handler) 365 if (current_kprobe->post_handler)
267 current_kprobe->post_handler(current_kprobe, regs, 0); 366 current_kprobe->post_handler(current_kprobe, regs, 0);
268 367
269 resume_execution(current_kprobe, regs); 368 if (current_kprobe->post_handler != trampoline_post_handler)
369 resume_execution(current_kprobe, regs);
270 regs->eflags |= kprobe_saved_eflags; 370 regs->eflags |= kprobe_saved_eflags;
271 371
272 unlock_kprobes(); 372 unlock_kprobes();
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index be3efba7caf7..aea2ce1145df 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -37,6 +37,7 @@
37#include <linux/kallsyms.h> 37#include <linux/kallsyms.h>
38#include <linux/ptrace.h> 38#include <linux/ptrace.h>
39#include <linux/random.h> 39#include <linux/random.h>
40#include <linux/kprobes.h>
40 41
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42#include <asm/pgtable.h> 43#include <asm/pgtable.h>
@@ -339,6 +340,13 @@ void exit_thread(void)
339 struct task_struct *tsk = current; 340 struct task_struct *tsk = current;
340 struct thread_struct *t = &tsk->thread; 341 struct thread_struct *t = &tsk->thread;
341 342
343 /*
344 * Remove function-return probe instances associated with this task
345 * and put them back on the free list. Do not insert an exit probe for
346 * this function, it will be disabled by kprobe_flush_task if you do.
347 */
348 kprobe_flush_task(tsk);
349
342 /* The process may have allocated an io port bitmap... nuke it. */ 350 /* The process may have allocated an io port bitmap... nuke it. */
343 if (unlikely(NULL != t->io_bitmap_ptr)) { 351 if (unlikely(NULL != t->io_bitmap_ptr)) {
344 int cpu = get_cpu(); 352 int cpu = get_cpu();
@@ -362,6 +370,13 @@ void flush_thread(void)
362{ 370{
363 struct task_struct *tsk = current; 371 struct task_struct *tsk = current;
364 372
373 /*
374 * Remove function-return probe instances associated with this task
375 * and put them back on the free list. Do not insert an exit probe for
376 * this function, it will be disabled by kprobe_flush_task if you do.
377 */
378 kprobe_flush_task(tsk);
379
365 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); 380 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
366 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); 381 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
367 /* 382 /*
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 4092f68d123a..8b6d3a90cd78 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -39,6 +39,9 @@ typedef u8 kprobe_opcode_t;
39 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) 39 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
40 40
41#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 41#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
42#define ARCH_SUPPORTS_KRETPROBES
43
44void kretprobe_trampoline(void);
42 45
43/* Architecture specific copy of original instruction*/ 46/* Architecture specific copy of original instruction*/
44struct arch_specific_insn { 47struct arch_specific_insn {
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 99ddba5a4e00..fba39f87efec 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -25,21 +25,31 @@
25 * Rusty Russell). 25 * Rusty Russell).
26 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes 26 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
27 * interface to access function arguments. 27 * interface to access function arguments.
28 * 2005-May Hien Nguyen <hien@us.ibm.com> and Jim Keniston
29 * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
30 * <prasanna@in.ibm.com> added function-return probes.
28 */ 31 */
29#include <linux/config.h> 32#include <linux/config.h>
30#include <linux/list.h> 33#include <linux/list.h>
31#include <linux/notifier.h> 34#include <linux/notifier.h>
32#include <linux/smp.h> 35#include <linux/smp.h>
36#include <linux/spinlock.h>
37
33#include <asm/kprobes.h> 38#include <asm/kprobes.h>
34 39
35struct kprobe; 40struct kprobe;
36struct pt_regs; 41struct pt_regs;
42struct kretprobe;
43struct kretprobe_instance;
37typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *); 44typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
38typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *); 45typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
39typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *, 46typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
40 unsigned long flags); 47 unsigned long flags);
41typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *, 48typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
42 int trapnr); 49 int trapnr);
50typedef int (*kretprobe_handler_t) (struct kretprobe_instance *,
51 struct pt_regs *);
52
43struct kprobe { 53struct kprobe {
44 struct hlist_node hlist; 54 struct hlist_node hlist;
45 55
@@ -85,6 +95,62 @@ struct jprobe {
85 kprobe_opcode_t *entry; /* probe handling code to jump to */ 95 kprobe_opcode_t *entry; /* probe handling code to jump to */
86}; 96};
87 97
98#ifdef ARCH_SUPPORTS_KRETPROBES
99extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs);
100extern void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
101 unsigned long flags);
102extern struct task_struct *arch_get_kprobe_task(void *ptr);
103extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
104extern void arch_kprobe_flush_task(struct task_struct *tk, spinlock_t *kp_lock);
105#else /* ARCH_SUPPORTS_KRETPROBES */
106static inline void kretprobe_trampoline(void)
107{
108}
109static inline int trampoline_probe_handler(struct kprobe *p,
110 struct pt_regs *regs)
111{
112 return 0;
113}
114static inline void trampoline_post_handler(struct kprobe *p,
115 struct pt_regs *regs, unsigned long flags)
116{
117}
118static inline void arch_prepare_kretprobe(struct kretprobe *rp,
119 struct pt_regs *regs)
120{
121}
122static inline void arch_kprobe_flush_task(struct task_struct *tk)
123{
124}
125#define arch_get_kprobe_task(ptr) ((struct task_struct *)NULL)
126#endif /* ARCH_SUPPORTS_KRETPROBES */
127/*
128 * Function-return probe -
129 * Note:
130 * User needs to provide a handler function, and initialize maxactive.
131 * maxactive - The maximum number of instances of the probed function that
132 * can be active concurrently.
133 * nmissed - tracks the number of times the probed function's return was
134 * ignored, due to maxactive being too low.
135 *
136 */
137struct kretprobe {
138 struct kprobe kp;
139 kretprobe_handler_t handler;
140 int maxactive;
141 int nmissed;
142 struct hlist_head free_instances;
143 struct hlist_head used_instances;
144};
145
146struct kretprobe_instance {
147 struct hlist_node uflist; /* either on free list or used list */
148 struct hlist_node hlist;
149 struct kretprobe *rp;
150 void *ret_addr;
151 void *stack_addr;
152};
153
88#ifdef CONFIG_KPROBES 154#ifdef CONFIG_KPROBES
89/* Locks kprobe: irq must be disabled */ 155/* Locks kprobe: irq must be disabled */
90void lock_kprobes(void); 156void lock_kprobes(void);
@@ -104,6 +170,7 @@ extern void show_registers(struct pt_regs *regs);
104 170
105/* Get the kprobe at this addr (if any). Must have called lock_kprobes */ 171/* Get the kprobe at this addr (if any). Must have called lock_kprobes */
106struct kprobe *get_kprobe(void *addr); 172struct kprobe *get_kprobe(void *addr);
173struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
107 174
108int register_kprobe(struct kprobe *p); 175int register_kprobe(struct kprobe *p);
109void unregister_kprobe(struct kprobe *p); 176void unregister_kprobe(struct kprobe *p);
@@ -113,7 +180,16 @@ int register_jprobe(struct jprobe *p);
113void unregister_jprobe(struct jprobe *p); 180void unregister_jprobe(struct jprobe *p);
114void jprobe_return(void); 181void jprobe_return(void);
115 182
116#else 183int register_kretprobe(struct kretprobe *rp);
184void unregister_kretprobe(struct kretprobe *rp);
185
186struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
187struct kretprobe_instance *get_rp_inst(void *sara);
188struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk);
189void add_rp_inst(struct kretprobe_instance *ri);
190void kprobe_flush_task(struct task_struct *tk);
191void recycle_rp_inst(struct kretprobe_instance *ri);
192#else /* CONFIG_KPROBES */
117static inline int kprobe_running(void) 193static inline int kprobe_running(void)
118{ 194{
119 return 0; 195 return 0;
@@ -135,5 +211,15 @@ static inline void unregister_jprobe(struct jprobe *p)
135static inline void jprobe_return(void) 211static inline void jprobe_return(void)
136{ 212{
137} 213}
138#endif 214static inline int register_kretprobe(struct kretprobe *rp)
215{
216 return -ENOSYS;
217}
218static inline void unregister_kretprobe(struct kretprobe *rp)
219{
220}
221static inline void kprobe_flush_task(struct task_struct *tk)
222{
223}
224#endif /* CONFIG_KPROBES */
139#endif /* _LINUX_KPROBES_H */ 225#endif /* _LINUX_KPROBES_H */
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 037142b72a49..692fbf75ab49 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -27,6 +27,9 @@
27 * interface to access function arguments. 27 * interface to access function arguments.
28 * 2004-Sep Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes 28 * 2004-Sep Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
29 * exceptions notifier to be first on the priority list. 29 * exceptions notifier to be first on the priority list.
30 * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
31 * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
32 * <prasanna@in.ibm.com> added function-return probes.
30 */ 33 */
31#include <linux/kprobes.h> 34#include <linux/kprobes.h>
32#include <linux/spinlock.h> 35#include <linux/spinlock.h>
@@ -41,6 +44,7 @@
41#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) 44#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
42 45
43static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; 46static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
47static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
44 48
45unsigned int kprobe_cpu = NR_CPUS; 49unsigned int kprobe_cpu = NR_CPUS;
46static DEFINE_SPINLOCK(kprobe_lock); 50static DEFINE_SPINLOCK(kprobe_lock);
@@ -78,7 +82,7 @@ struct kprobe *get_kprobe(void *addr)
78 * Aggregate handlers for multiple kprobes support - these handlers 82 * Aggregate handlers for multiple kprobes support - these handlers
79 * take care of invoking the individual kprobe handlers on p->list 83 * take care of invoking the individual kprobe handlers on p->list
80 */ 84 */
81int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) 85static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
82{ 86{
83 struct kprobe *kp; 87 struct kprobe *kp;
84 88
@@ -92,8 +96,8 @@ int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
92 return 0; 96 return 0;
93} 97}
94 98
95void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, 99static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
96 unsigned long flags) 100 unsigned long flags)
97{ 101{
98 struct kprobe *kp; 102 struct kprobe *kp;
99 103
@@ -107,7 +111,8 @@ void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
107 return; 111 return;
108} 112}
109 113
110int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr) 114static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
115 int trapnr)
111{ 116{
112 /* 117 /*
113 * if we faulted "during" the execution of a user specified 118 * if we faulted "during" the execution of a user specified
@@ -120,6 +125,135 @@ int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
120 return 0; 125 return 0;
121} 126}
122 127
128struct kprobe trampoline_p = {
129 .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
130 .pre_handler = trampoline_probe_handler,
131 .post_handler = trampoline_post_handler
132};
133
134struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
135{
136 struct hlist_node *node;
137 struct kretprobe_instance *ri;
138 hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
139 return ri;
140 return NULL;
141}
142
143static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
144{
145 struct hlist_node *node;
146 struct kretprobe_instance *ri;
147 hlist_for_each_entry(ri, node, &rp->used_instances, uflist)
148 return ri;
149 return NULL;
150}
151
152struct kretprobe_instance *get_rp_inst(void *sara)
153{
154 struct hlist_head *head;
155 struct hlist_node *node;
156 struct task_struct *tsk;
157 struct kretprobe_instance *ri;
158
159 tsk = arch_get_kprobe_task(sara);
160 head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
161 hlist_for_each_entry(ri, node, head, hlist) {
162 if (ri->stack_addr == sara)
163 return ri;
164 }
165 return NULL;
166}
167
168void add_rp_inst(struct kretprobe_instance *ri)
169{
170 struct task_struct *tsk;
171 /*
172 * Remove rp inst off the free list -
173 * Add it back when probed function returns
174 */
175 hlist_del(&ri->uflist);
176 tsk = arch_get_kprobe_task(ri->stack_addr);
177 /* Add rp inst onto table */
178 INIT_HLIST_NODE(&ri->hlist);
179 hlist_add_head(&ri->hlist,
180 &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]);
181
182 /* Also add this rp inst to the used list. */
183 INIT_HLIST_NODE(&ri->uflist);
184 hlist_add_head(&ri->uflist, &ri->rp->used_instances);
185}
186
187void recycle_rp_inst(struct kretprobe_instance *ri)
188{
189 /* remove rp inst off the rprobe_inst_table */
190 hlist_del(&ri->hlist);
191 if (ri->rp) {
192 /* remove rp inst off the used list */
193 hlist_del(&ri->uflist);
194 /* put rp inst back onto the free list */
195 INIT_HLIST_NODE(&ri->uflist);
196 hlist_add_head(&ri->uflist, &ri->rp->free_instances);
197 } else
198 /* Unregistering */
199 kfree(ri);
200}
201
202struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
203{
204 return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
205}
206
207struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk)
208{
209 struct task_struct *tsk;
210 struct hlist_head *head;
211 struct hlist_node *node;
212 struct kretprobe_instance *ri;
213
214 head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)];
215
216 hlist_for_each_entry(ri, node, head, hlist) {
217 tsk = arch_get_kprobe_task(ri->stack_addr);
218 if (tsk == tk)
219 return ri;
220 }
221 return NULL;
222}
223
224/*
225 * This function is called from do_exit or do_execv when task tk's stack is
226 * about to be recycled. Recycle any function-return probe instances
227 * associated with this task. These represent probed functions that have
228 * been called but may never return.
229 */
230void kprobe_flush_task(struct task_struct *tk)
231{
232 arch_kprobe_flush_task(tk, &kprobe_lock);
233}
234
235/*
236 * This kprobe pre_handler is registered with every kretprobe. When probe
237 * hits it will set up the return probe.
238 */
239static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
240{
241 struct kretprobe *rp = container_of(p, struct kretprobe, kp);
242
243 /*TODO: consider to only swap the RA after the last pre_handler fired */
244 arch_prepare_kretprobe(rp, regs);
245 return 0;
246}
247
248static inline void free_rp_inst(struct kretprobe *rp)
249{
250 struct kretprobe_instance *ri;
251 while ((ri = get_free_rp_inst(rp)) != NULL) {
252 hlist_del(&ri->uflist);
253 kfree(ri);
254 }
255}
256
123/* 257/*
124 * Fill in the required fields of the "manager kprobe". Replace the 258 * Fill in the required fields of the "manager kprobe". Replace the
125 * earlier kprobe in the hlist with the manager kprobe 259 * earlier kprobe in the hlist with the manager kprobe
@@ -257,16 +391,82 @@ void unregister_jprobe(struct jprobe *jp)
257 unregister_kprobe(&jp->kp); 391 unregister_kprobe(&jp->kp);
258} 392}
259 393
394#ifdef ARCH_SUPPORTS_KRETPROBES
395
396int register_kretprobe(struct kretprobe *rp)
397{
398 int ret = 0;
399 struct kretprobe_instance *inst;
400 int i;
401
402 rp->kp.pre_handler = pre_handler_kretprobe;
403
404 /* Pre-allocate memory for max kretprobe instances */
405 if (rp->maxactive <= 0) {
406#ifdef CONFIG_PREEMPT
407 rp->maxactive = max(10, 2 * NR_CPUS);
408#else
409 rp->maxactive = NR_CPUS;
410#endif
411 }
412 INIT_HLIST_HEAD(&rp->used_instances);
413 INIT_HLIST_HEAD(&rp->free_instances);
414 for (i = 0; i < rp->maxactive; i++) {
415 inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
416 if (inst == NULL) {
417 free_rp_inst(rp);
418 return -ENOMEM;
419 }
420 INIT_HLIST_NODE(&inst->uflist);
421 hlist_add_head(&inst->uflist, &rp->free_instances);
422 }
423
424 rp->nmissed = 0;
425 /* Establish function entry probe point */
426 if ((ret = register_kprobe(&rp->kp)) != 0)
427 free_rp_inst(rp);
428 return ret;
429}
430
431#else /* ARCH_SUPPORTS_KRETPROBES */
432
433int register_kretprobe(struct kretprobe *rp)
434{
435 return -ENOSYS;
436}
437
438#endif /* ARCH_SUPPORTS_KRETPROBES */
439
440void unregister_kretprobe(struct kretprobe *rp)
441{
442 unsigned long flags;
443 struct kretprobe_instance *ri;
444
445 unregister_kprobe(&rp->kp);
446 /* No race here */
447 spin_lock_irqsave(&kprobe_lock, flags);
448 free_rp_inst(rp);
449 while ((ri = get_used_rp_inst(rp)) != NULL) {
450 ri->rp = NULL;
451 hlist_del(&ri->uflist);
452 }
453 spin_unlock_irqrestore(&kprobe_lock, flags);
454}
455
260static int __init init_kprobes(void) 456static int __init init_kprobes(void)
261{ 457{
262 int i, err = 0; 458 int i, err = 0;
263 459
264 /* FIXME allocate the probe table, currently defined statically */ 460 /* FIXME allocate the probe table, currently defined statically */
265 /* initialize all list heads */ 461 /* initialize all list heads */
266 for (i = 0; i < KPROBE_TABLE_SIZE; i++) 462 for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
267 INIT_HLIST_HEAD(&kprobe_table[i]); 463 INIT_HLIST_HEAD(&kprobe_table[i]);
464 INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
465 }
268 466
269 err = register_die_notifier(&kprobe_exceptions_nb); 467 err = register_die_notifier(&kprobe_exceptions_nb);
468 /* Register the trampoline probe for return probe */
469 register_kprobe(&trampoline_p);
270 return err; 470 return err;
271} 471}
272 472
@@ -277,3 +477,6 @@ EXPORT_SYMBOL_GPL(unregister_kprobe);
277EXPORT_SYMBOL_GPL(register_jprobe); 477EXPORT_SYMBOL_GPL(register_jprobe);
278EXPORT_SYMBOL_GPL(unregister_jprobe); 478EXPORT_SYMBOL_GPL(unregister_jprobe);
279EXPORT_SYMBOL_GPL(jprobe_return); 479EXPORT_SYMBOL_GPL(jprobe_return);
480EXPORT_SYMBOL_GPL(register_kretprobe);
481EXPORT_SYMBOL_GPL(unregister_kretprobe);
482