Blame view

kernel/kprobes.c 20.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   *  Kernel Probes (KProbes)
   *  kernel/kprobes.c
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
   * Copyright (C) IBM Corporation, 2002, 2004
   *
   * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
   *		Probes initial implementation (includes suggestions from
   *		Rusty Russell).
   * 2004-Aug	Updated by Prasanna S Panchamukhi <prasanna@in.ibm.com> with
   *		hlists and exceptions notifier as suggested by Andi Kleen.
   * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
   *		interface to access function arguments.
   * 2004-Sep	Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
   *		exceptions notifier to be first on the priority list.
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
30
31
32
   * 2005-May	Hien Nguyen <hien@us.ibm.com>, Jim Keniston
   *		<jkenisto@us.ibm.com> and Prasanna S Panchamukhi
   *		<prasanna@in.ibm.com> added function-return probes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
   */
  #include <linux/kprobes.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
  #include <linux/hash.h>
  #include <linux/init.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
37
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  #include <linux/module.h>
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
39
  #include <linux/moduleloader.h>
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
40
  #include <linux/kallsyms.h>
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
41
  #include <linux/freezer.h>
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
42
  #include <asm-generic/sections.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
  #include <asm/cacheflush.h>
  #include <asm/errno.h>
  #include <asm/kdebug.h>
  
  #define KPROBE_HASH_BITS 6
  #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
49
50
51
52
53
54
55
56
57
  
  /*
   * Some oddball architectures like 64bit powerpc have function descriptors
   * so this must be overridable.
   */
  #ifndef kprobe_lookup_name
  #define kprobe_lookup_name(name, addr) \
  	addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
59
  static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
60
  static atomic_t kprobe_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61

7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
62
  DEFINE_MUTEX(kprobe_mutex);		/* Protects kprobe_table */
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
63
  DEFINE_SPINLOCK(kretprobe_lock);	/* Protects kretprobe_inst_table */
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
64
  static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
66
67
68
69
  static struct notifier_block kprobe_page_fault_nb = {
  	.notifier_call = kprobe_exceptions_notify,
  	.priority = 0x7fffffff /* we need to notified first */
  };
2d14e39da   Anil S Keshavamurthy   [PATCH] kprobes: ...
70
  #ifdef __ARCH_WANT_KPROBES_INSN_SLOT
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
71
72
73
74
75
76
77
78
79
80
81
82
83
  /*
   * kprobe->ainsn.insn points to the copy of the instruction to be
   * single-stepped. x86_64, POWER4 and above have no-exec support and
   * stepping on the instruction on a vmalloced/kmalloced/data page
   * is a recipe for disaster
   */
  #define INSNS_PER_PAGE	(PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
  
  struct kprobe_insn_page {
  	struct hlist_node hlist;
  	kprobe_opcode_t *insns;		/* Page of instruction slots */
  	char slot_used[INSNS_PER_PAGE];
  	int nused;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
84
  	int ngarbage;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
85
  };
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
86
87
88
89
90
  enum kprobe_slot_state {
  	SLOT_CLEAN = 0,
  	SLOT_DIRTY = 1,
  	SLOT_USED = 2,
  };
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
91
  static struct hlist_head kprobe_insn_pages;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  static int kprobe_garbage_slots;
  static int collect_garbage_slots(void);
  
  static int __kprobes check_safety(void)
  {
  	int ret = 0;
  #if defined(CONFIG_PREEMPT) && defined(CONFIG_PM)
  	ret = freeze_processes();
  	if (ret == 0) {
  		struct task_struct *p, *q;
  		do_each_thread(p, q) {
  			if (p != current && p->state == TASK_RUNNING &&
  			    p->pid != 0) {
  				printk("Check failed: %s is running
  ",p->comm);
  				ret = -1;
  				goto loop_end;
  			}
  		} while_each_thread(p, q);
  	}
  loop_end:
  	thaw_processes();
  #else
  	synchronize_sched();
  #endif
  	return ret;
  }
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
119
120
121
122
123
  
  /**
   * get_insn_slot() - Find a slot on an executable page for an instruction.
   * We allocate an executable page if there's no room on existing ones.
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
124
  kprobe_opcode_t __kprobes *get_insn_slot(void)
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
125
126
127
  {
  	struct kprobe_insn_page *kip;
  	struct hlist_node *pos;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
128
        retry:
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
129
130
131
132
133
  	hlist_for_each(pos, &kprobe_insn_pages) {
  		kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
  		if (kip->nused < INSNS_PER_PAGE) {
  			int i;
  			for (i = 0; i < INSNS_PER_PAGE; i++) {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
134
135
  				if (kip->slot_used[i] == SLOT_CLEAN) {
  					kip->slot_used[i] = SLOT_USED;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
136
137
138
139
140
141
142
143
  					kip->nused++;
  					return kip->insns + (i * MAX_INSN_SIZE);
  				}
  			}
  			/* Surprise!  No unused slots.  Fix kip->nused. */
  			kip->nused = INSNS_PER_PAGE;
  		}
  	}
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
144
145
146
147
148
  	/* If there are any garbage slots, collect it and try again. */
  	if (kprobe_garbage_slots && collect_garbage_slots() == 0) {
  		goto retry;
  	}
  	/* All out of space.  Need to allocate a new page. Use slot 0. */
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  	kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
  	if (!kip) {
  		return NULL;
  	}
  
  	/*
  	 * Use module_alloc so this page is within +/- 2GB of where the
  	 * kernel image and loaded module images reside. This is required
  	 * so x86_64 can correctly handle the %rip-relative fixups.
  	 */
  	kip->insns = module_alloc(PAGE_SIZE);
  	if (!kip->insns) {
  		kfree(kip);
  		return NULL;
  	}
  	INIT_HLIST_NODE(&kip->hlist);
  	hlist_add_head(&kip->hlist, &kprobe_insn_pages);
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
166
167
  	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
  	kip->slot_used[0] = SLOT_USED;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
168
  	kip->nused = 1;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
169
  	kip->ngarbage = 0;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
170
171
  	return kip->insns;
  }
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
172
173
174
  /* Return 1 if all garbages are collected, otherwise 0. */
  static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
  {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
175
  	kip->slot_used[idx] = SLOT_CLEAN;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  	kip->nused--;
  	if (kip->nused == 0) {
  		/*
  		 * Page is no longer in use.  Free it unless
  		 * it's the last one.  We keep the last one
  		 * so as not to have to set it up again the
  		 * next time somebody inserts a probe.
  		 */
  		hlist_del(&kip->hlist);
  		if (hlist_empty(&kprobe_insn_pages)) {
  			INIT_HLIST_NODE(&kip->hlist);
  			hlist_add_head(&kip->hlist,
  				       &kprobe_insn_pages);
  		} else {
  			module_free(NULL, kip->insns);
  			kfree(kip);
  		}
  		return 1;
  	}
  	return 0;
  }
  
  static int __kprobes collect_garbage_slots(void)
  {
  	struct kprobe_insn_page *kip;
  	struct hlist_node *pos, *next;
  
  	/* Ensure no-one is preepmted on the garbages */
  	if (check_safety() != 0)
  		return -EAGAIN;
  
  	hlist_for_each_safe(pos, next, &kprobe_insn_pages) {
  		int i;
  		kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
  		if (kip->ngarbage == 0)
  			continue;
  		kip->ngarbage = 0;	/* we will collect all garbages */
  		for (i = 0; i < INSNS_PER_PAGE; i++) {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
214
  			if (kip->slot_used[i] == SLOT_DIRTY &&
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
215
216
217
218
219
220
221
222
223
  			    collect_one_slot(kip, i))
  				break;
  		}
  	}
  	kprobe_garbage_slots = 0;
  	return 0;
  }
  
  void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
224
225
226
227
228
229
230
231
232
  {
  	struct kprobe_insn_page *kip;
  	struct hlist_node *pos;
  
  	hlist_for_each(pos, &kprobe_insn_pages) {
  		kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
  		if (kip->insns <= slot &&
  		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
  			int i = (slot - kip->insns) / MAX_INSN_SIZE;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
233
  			if (dirty) {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
234
  				kip->slot_used[i] = SLOT_DIRTY;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
235
236
237
  				kip->ngarbage++;
  			} else {
  				collect_one_slot(kip, i);
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
238
  			}
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
239
  			break;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
240
241
  		}
  	}
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
242
243
244
  	if (dirty && (++kprobe_garbage_slots > INSNS_PER_PAGE)) {
  		collect_garbage_slots();
  	}
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
245
  }
2d14e39da   Anil S Keshavamurthy   [PATCH] kprobes: ...
246
  #endif
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
247

e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
248
249
250
251
252
253
254
255
256
257
  /* We have preemption disabled.. so it is safe to use __ versions */
  static inline void set_kprobe_instance(struct kprobe *kp)
  {
  	__get_cpu_var(kprobe_instance) = kp;
  }
  
  static inline void reset_kprobe_instance(void)
  {
  	__get_cpu_var(kprobe_instance) = NULL;
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
258
259
  /*
   * This routine is called either:
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
260
   * 	- under the kprobe_mutex - during kprobe_[un]register()
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
261
   * 				OR
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
262
   * 	- with preemption disabled - from arch/xxx/kernel/kprobes.c
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
263
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
264
  struct kprobe __kprobes *get_kprobe(void *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  {
  	struct hlist_head *head;
  	struct hlist_node *node;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
268
  	struct kprobe *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  
  	head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
271
  	hlist_for_each_entry_rcu(p, node, head, hlist) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
  		if (p->addr == addr)
  			return p;
  	}
  	return NULL;
  }
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
277
278
279
280
  /*
   * Aggregate handlers for multiple kprobes support - these handlers
   * take care of invoking the individual kprobe handlers on p->list
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
281
  static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
282
283
  {
  	struct kprobe *kp;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
284
  	list_for_each_entry_rcu(kp, &p->list, list) {
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
285
  		if (kp->pre_handler) {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
286
  			set_kprobe_instance(kp);
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
287
288
  			if (kp->pre_handler(kp, regs))
  				return 1;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
289
  		}
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
290
  		reset_kprobe_instance();
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
291
292
293
  	}
  	return 0;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
294
295
  static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
  					unsigned long flags)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
296
297
  {
  	struct kprobe *kp;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
298
  	list_for_each_entry_rcu(kp, &p->list, list) {
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
299
  		if (kp->post_handler) {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
300
  			set_kprobe_instance(kp);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
301
  			kp->post_handler(kp, regs, flags);
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
302
  			reset_kprobe_instance();
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
303
304
305
306
  		}
  	}
  	return;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
307
308
  static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
  					int trapnr)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
309
  {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
310
  	struct kprobe *cur = __get_cpu_var(kprobe_instance);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
311
312
313
314
  	/*
  	 * if we faulted "during" the execution of a user specified
  	 * probe handler, invoke just that probe's fault handler
  	 */
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
315
316
  	if (cur && cur->fault_handler) {
  		if (cur->fault_handler(cur, regs, trapnr))
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
317
318
319
320
  			return 1;
  	}
  	return 0;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
321
  static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
322
  {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
323
324
325
326
327
328
  	struct kprobe *cur = __get_cpu_var(kprobe_instance);
  	int ret = 0;
  
  	if (cur && cur->break_handler) {
  		if (cur->break_handler(cur, regs))
  			ret = 1;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
329
  	}
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
330
331
  	reset_kprobe_instance();
  	return ret;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
332
  }
bf8d5c52c   Keshavamurthy Anil S   [PATCH] kprobes: ...
333
334
335
336
337
338
339
340
341
342
343
344
  /* Walks the list and increments nmissed count for multiprobe case */
  void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
  {
  	struct kprobe *kp;
  	if (p->pre_handler != aggr_pre_handler) {
  		p->nmissed++;
  	} else {
  		list_for_each_entry_rcu(kp, &p->list, list)
  			kp->nmissed++;
  	}
  	return;
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
345
  /* Called with kretprobe_lock held */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
346
  struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
347
348
349
350
351
352
353
  {
  	struct hlist_node *node;
  	struct kretprobe_instance *ri;
  	hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
  		return ri;
  	return NULL;
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
354
  /* Called with kretprobe_lock held */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
355
356
  static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
  							      *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
357
358
359
360
361
362
363
  {
  	struct hlist_node *node;
  	struct kretprobe_instance *ri;
  	hlist_for_each_entry(ri, node, &rp->used_instances, uflist)
  		return ri;
  	return NULL;
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
364
  /* Called with kretprobe_lock held */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
365
  void __kprobes add_rp_inst(struct kretprobe_instance *ri)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
366
  {
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
367
368
369
370
371
  	/*
  	 * Remove rp inst off the free list -
  	 * Add it back when probed function returns
  	 */
  	hlist_del(&ri->uflist);
802eae7c8   Rusty Lynch   [PATCH] Return pr...
372

b94cce926   Hien Nguyen   [PATCH] kprobes: ...
373
374
375
  	/* Add rp inst onto table */
  	INIT_HLIST_NODE(&ri->hlist);
  	hlist_add_head(&ri->hlist,
802eae7c8   Rusty Lynch   [PATCH] Return pr...
376
  			&kretprobe_inst_table[hash_ptr(ri->task, KPROBE_HASH_BITS)]);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
377
378
379
380
381
  
  	/* Also add this rp inst to the used list. */
  	INIT_HLIST_NODE(&ri->uflist);
  	hlist_add_head(&ri->uflist, &ri->rp->used_instances);
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
382
  /* Called with kretprobe_lock held */
99219a3fb   bibo,mao   [PATCH] kretprobe...
383
384
  void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
  				struct hlist_head *head)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
385
386
387
388
389
390
391
392
393
394
395
  {
  	/* remove rp inst off the rprobe_inst_table */
  	hlist_del(&ri->hlist);
  	if (ri->rp) {
  		/* remove rp inst off the used list */
  		hlist_del(&ri->uflist);
  		/* put rp inst back onto the free list */
  		INIT_HLIST_NODE(&ri->uflist);
  		hlist_add_head(&ri->uflist, &ri->rp->free_instances);
  	} else
  		/* Unregistering */
99219a3fb   bibo,mao   [PATCH] kretprobe...
396
  		hlist_add_head(&ri->hlist, head);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
397
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
398
  struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
399
400
401
  {
  	return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
  }
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
402
  /*
c6fd91f0b   bibo mao   [PATCH] kretprobe...
403
404
405
406
   * This function is called from finish_task_switch when task tk becomes dead,
   * so that we can recycle any function-return probe instances associated
   * with this task. These left over instances represent probed functions
   * that have been called but will never return.
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
407
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
408
  void __kprobes kprobe_flush_task(struct task_struct *tk)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
409
  {
62c27be0d   bibo,mao   [PATCH] kprobe wh...
410
  	struct kretprobe_instance *ri;
99219a3fb   bibo,mao   [PATCH] kretprobe...
411
  	struct hlist_head *head, empty_rp;
802eae7c8   Rusty Lynch   [PATCH] Return pr...
412
  	struct hlist_node *node, *tmp;
0aa55e4d7   Hien Nguyen   [PATCH] kprobes: ...
413
  	unsigned long flags = 0;
802eae7c8   Rusty Lynch   [PATCH] Return pr...
414

99219a3fb   bibo,mao   [PATCH] kretprobe...
415
  	INIT_HLIST_HEAD(&empty_rp);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
416
  	spin_lock_irqsave(&kretprobe_lock, flags);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
417
418
419
  	head = kretprobe_inst_table_head(tk);
  	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
  		if (ri->task == tk)
99219a3fb   bibo,mao   [PATCH] kretprobe...
420
  			recycle_rp_inst(ri, &empty_rp);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
421
  	}
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
422
  	spin_unlock_irqrestore(&kretprobe_lock, flags);
99219a3fb   bibo,mao   [PATCH] kretprobe...
423
424
425
426
427
  
  	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
  		hlist_del(&ri->hlist);
  		kfree(ri);
  	}
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
428
  }
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
429
430
431
432
433
434
435
436
  static inline void free_rp_inst(struct kretprobe *rp)
  {
  	struct kretprobe_instance *ri;
  	while ((ri = get_free_rp_inst(rp)) != NULL) {
  		hlist_del(&ri->uflist);
  		kfree(ri);
  	}
  }
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
437
  /*
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
438
439
440
441
442
443
444
445
446
447
448
449
   * Keep all fields in the kprobe consistent
   */
  static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
  {
  	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
  	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
  }
  
  /*
  * Add the new probe to old_p->list. Fail if this is the
  * second jprobe at the address - two jprobes can't coexist
  */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
450
  static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
451
  {
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
452
  	if (p->break_handler) {
367216567   mao, bibo   [PATCH] Kprobe: m...
453
454
  		if (old_p->break_handler)
  			return -EEXIST;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
455
  		list_add_tail_rcu(&p->list, &old_p->list);
367216567   mao, bibo   [PATCH] Kprobe: m...
456
  		old_p->break_handler = aggr_break_handler;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
457
  	} else
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
458
  		list_add_rcu(&p->list, &old_p->list);
367216567   mao, bibo   [PATCH] Kprobe: m...
459
460
  	if (p->post_handler && !old_p->post_handler)
  		old_p->post_handler = aggr_post_handler;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
461
462
463
464
  	return 0;
  }
  
  /*
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
465
466
467
468
469
   * Fill in the required fields of the "manager kprobe". Replace the
   * earlier kprobe in the hlist with the manager kprobe
   */
  static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
  {
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
470
  	copy_kprobe(p, ap);
a9ad965ea   bibo, mao   [PATCH] IA64: kpr...
471
  	flush_insn_slot(ap);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
472
  	ap->addr = p->addr;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
473
  	ap->pre_handler = aggr_pre_handler;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
474
  	ap->fault_handler = aggr_fault_handler;
367216567   mao, bibo   [PATCH] Kprobe: m...
475
476
477
478
  	if (p->post_handler)
  		ap->post_handler = aggr_post_handler;
  	if (p->break_handler)
  		ap->break_handler = aggr_break_handler;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
479
480
  
  	INIT_LIST_HEAD(&ap->list);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
481
  	list_add_rcu(&p->list, &ap->list);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
482

adad0f331   Keshavamurthy Anil S   [PATCH] kprobes: ...
483
  	hlist_replace_rcu(&p->hlist, &ap->hlist);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
484
485
486
487
488
  }
  
  /*
   * This is the second or subsequent kprobe at the address - handle
   * the intricacies
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
489
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
490
491
  static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
  					  struct kprobe *p)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
492
493
494
  {
  	int ret = 0;
  	struct kprobe *ap;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
495
496
497
  	if (old_p->pre_handler == aggr_pre_handler) {
  		copy_kprobe(old_p, p);
  		ret = add_new_kprobe(old_p, p);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
498
  	} else {
a0d50069e   Keshavamurthy Anil S   [PATCH] Kprobes: ...
499
  		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
500
501
502
  		if (!ap)
  			return -ENOMEM;
  		add_aggr_kprobe(ap, old_p);
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
503
504
  		copy_kprobe(ap, p);
  		ret = add_new_kprobe(ap, p);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
505
506
507
  	}
  	return ret;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
508
509
510
511
512
513
514
  static int __kprobes in_kprobes_functions(unsigned long addr)
  {
  	if (addr >= (unsigned long)__kprobes_text_start
  		&& addr < (unsigned long)__kprobes_text_end)
  		return -EINVAL;
  	return 0;
  }
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
515
516
  static int __kprobes __register_kprobe(struct kprobe *p,
  	unsigned long called_from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
  {
  	int ret = 0;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
519
  	struct kprobe *old_p;
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
520
  	struct module *probed_mod;
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
521

3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  	/*
  	 * If we have a symbol_name argument look it up,
  	 * and add it to the address.  That way the addr
  	 * field can either be global or relative to a symbol.
  	 */
  	if (p->symbol_name) {
  		if (p->addr)
  			return -EINVAL;
  		kprobe_lookup_name(p->symbol_name, p->addr);
  	}
  
  	if (!p->addr)
  		return -EINVAL;
  	p->addr = (kprobe_opcode_t *)(((char *)p->addr)+ p->offset);
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
536
537
538
  	if ((!kernel_text_address((unsigned long) p->addr)) ||
  		in_kprobes_functions((unsigned long) p->addr))
  		return -EINVAL;
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  	p->mod_refcounted = 0;
  	/* Check are we probing a module */
  	if ((probed_mod = module_text_address((unsigned long) p->addr))) {
  		struct module *calling_mod = module_text_address(called_from);
  		/* We must allow modules to probe themself and
  		 * in this case avoid incrementing the module refcount,
  		 * so as to allow unloading of self probing modules.
  		 */
  		if (calling_mod && (calling_mod != probed_mod)) {
  			if (unlikely(!try_module_get(probed_mod)))
  				return -EINVAL;
  			p->mod_refcounted = 1;
  		} else
  			probed_mod = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554

3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
555
  	p->nmissed = 0;
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
556
  	mutex_lock(&kprobe_mutex);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
557
558
559
  	old_p = get_kprobe(p->addr);
  	if (old_p) {
  		ret = register_aggr_kprobe(old_p, p);
e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
560
561
  		if (!ret)
  			atomic_inc(&kprobe_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564

49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
565
566
  	if ((ret = arch_prepare_kprobe(p)) != 0)
  		goto out;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
567
  	INIT_HLIST_NODE(&p->hlist);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
568
  	hlist_add_head_rcu(&p->hlist,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
570
571
572
  	if (atomic_add_return(1, &kprobe_count) == \
  				(ARCH_INACTIVE_KPROBE_COUNT + 1))
  		register_page_fault_notifier(&kprobe_page_fault_nb);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
573
  	arch_arm_kprobe(p);
7e1048b11   Rusty Lynch   [PATCH] Move kpro...
574

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  out:
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
576
  	mutex_unlock(&kprobe_mutex);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
577

df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
578
579
  	if (ret && probed_mod)
  		module_put(probed_mod);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  	return ret;
  }
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
582
583
584
585
586
  int __kprobes register_kprobe(struct kprobe *p)
  {
  	return __register_kprobe(p,
  		(unsigned long)__builtin_return_address(0));
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
587
  void __kprobes unregister_kprobe(struct kprobe *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  {
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
589
  	struct module *mod;
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
590
591
  	struct kprobe *old_p, *list_p;
  	int cleanup_p;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
592

7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
593
  	mutex_lock(&kprobe_mutex);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
594
  	old_p = get_kprobe(p->addr);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
595
  	if (unlikely(!old_p)) {
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
596
  		mutex_unlock(&kprobe_mutex);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
597
598
  		return;
  	}
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
599
600
601
602
603
  	if (p != old_p) {
  		list_for_each_entry_rcu(list_p, &old_p->list, list)
  			if (list_p == p)
  			/* kprobe p is a valid probe */
  				goto valid_p;
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
604
  		mutex_unlock(&kprobe_mutex);
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
605
606
607
608
  		return;
  	}
  valid_p:
  	if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
609
  		(p->list.next == &old_p->list) &&
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
610
611
  		(p->list.prev == &old_p->list))) {
  		/* Only probe on the hash list */
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
612
613
  		arch_disarm_kprobe(p);
  		hlist_del_rcu(&old_p->hlist);
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
614
  		cleanup_p = 1;
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
615
616
  	} else {
  		list_del_rcu(&p->list);
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
617
  		cleanup_p = 0;
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
618
  	}
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
619

7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
620
  	mutex_unlock(&kprobe_mutex);
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
621

49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
622
  	synchronize_sched();
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
623
624
  	if (p->mod_refcounted &&
  	    (mod = module_text_address((unsigned long)p->addr)))
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
625
  		module_put(mod);
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
626

49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
627
  	if (cleanup_p) {
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
628
  		if (p != old_p) {
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
629
  			list_del_rcu(&p->list);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
630
  			kfree(old_p);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
631
  		}
0498b6350   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
632
  		arch_remove_kprobe(p);
367216567   mao, bibo   [PATCH] Kprobe: m...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  	} else {
  		mutex_lock(&kprobe_mutex);
  		if (p->break_handler)
  			old_p->break_handler = NULL;
  		if (p->post_handler){
  			list_for_each_entry_rcu(list_p, &old_p->list, list){
  				if (list_p->post_handler){
  					cleanup_p = 2;
  					break;
  				}
  			}
  			if (cleanup_p == 0)
  				old_p->post_handler = NULL;
  		}
  		mutex_unlock(&kprobe_mutex);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
648
  	}
e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
649
650
651
652
653
654
655
656
657
658
  
  	/* Call unregister_page_fault_notifier()
  	 * if no probes are active
  	 */
  	mutex_lock(&kprobe_mutex);
  	if (atomic_add_return(-1, &kprobe_count) == \
  				ARCH_INACTIVE_KPROBE_COUNT)
  		unregister_page_fault_notifier(&kprobe_page_fault_nb);
  	mutex_unlock(&kprobe_mutex);
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
  }
  
  static struct notifier_block kprobe_exceptions_nb = {
  	.notifier_call = kprobe_exceptions_notify,
3d5631e06   Anil S Keshavamurthy   [PATCH] Kprobes r...
663
664
  	.priority = 0x7fffffff /* we need to be notified first */
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665

d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
666
  int __kprobes register_jprobe(struct jprobe *jp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
  {
  	/* Todo: Verify probepoint is a function entry point */
  	jp->kp.pre_handler = setjmp_pre_handler;
  	jp->kp.break_handler = longjmp_break_handler;
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
671
672
  	return __register_kprobe(&jp->kp,
  		(unsigned long)__builtin_return_address(0));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
674
  void __kprobes unregister_jprobe(struct jprobe *jp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
  {
  	unregister_kprobe(&jp->kp);
  }
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
678
  #ifdef ARCH_SUPPORTS_KRETPROBES
e65cefe87   Adrian Bunk   [PATCH] kernel/kp...
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  /*
   * This kprobe pre_handler is registered with every kretprobe. When probe
   * hits it will set up the return probe.
   */
  static int __kprobes pre_handler_kretprobe(struct kprobe *p,
  					   struct pt_regs *regs)
  {
  	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
  	unsigned long flags = 0;
  
  	/*TODO: consider to only swap the RA after the last pre_handler fired */
  	spin_lock_irqsave(&kretprobe_lock, flags);
  	arch_prepare_kretprobe(rp, regs);
  	spin_unlock_irqrestore(&kretprobe_lock, flags);
  	return 0;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
695
  int __kprobes register_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
696
697
698
699
700
701
  {
  	int ret = 0;
  	struct kretprobe_instance *inst;
  	int i;
  
  	rp->kp.pre_handler = pre_handler_kretprobe;
7522a8423   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
702
703
704
  	rp->kp.post_handler = NULL;
  	rp->kp.fault_handler = NULL;
  	rp->kp.break_handler = NULL;
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
  
  	/* Pre-allocate memory for max kretprobe instances */
  	if (rp->maxactive <= 0) {
  #ifdef CONFIG_PREEMPT
  		rp->maxactive = max(10, 2 * NR_CPUS);
  #else
  		rp->maxactive = NR_CPUS;
  #endif
  	}
  	INIT_HLIST_HEAD(&rp->used_instances);
  	INIT_HLIST_HEAD(&rp->free_instances);
  	for (i = 0; i < rp->maxactive; i++) {
  		inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
  		if (inst == NULL) {
  			free_rp_inst(rp);
  			return -ENOMEM;
  		}
  		INIT_HLIST_NODE(&inst->uflist);
  		hlist_add_head(&inst->uflist, &rp->free_instances);
  	}
  
  	rp->nmissed = 0;
  	/* Establish function entry probe point */
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
728
729
  	if ((ret = __register_kprobe(&rp->kp,
  		(unsigned long)__builtin_return_address(0))) != 0)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
730
731
732
733
734
  		free_rp_inst(rp);
  	return ret;
  }
  
  #else /* ARCH_SUPPORTS_KRETPROBES */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
735
  int __kprobes register_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
736
737
738
739
740
  {
  	return -ENOSYS;
  }
  
  #endif /* ARCH_SUPPORTS_KRETPROBES */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
741
  void __kprobes unregister_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
742
743
744
745
746
747
  {
  	unsigned long flags;
  	struct kretprobe_instance *ri;
  
  	unregister_kprobe(&rp->kp);
  	/* No race here */
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
748
  	spin_lock_irqsave(&kretprobe_lock, flags);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
749
750
751
752
  	while ((ri = get_used_rp_inst(rp)) != NULL) {
  		ri->rp = NULL;
  		hlist_del(&ri->uflist);
  	}
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
753
  	spin_unlock_irqrestore(&kretprobe_lock, flags);
278ff9537   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
754
  	free_rp_inst(rp);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
755
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
759
760
761
  static int __init init_kprobes(void)
  {
  	int i, err = 0;
  
  	/* FIXME allocate the probe table, currently defined statically */
  	/* initialize all list heads */
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
762
  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  		INIT_HLIST_HEAD(&kprobe_table[i]);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
764
765
  		INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
  	}
e6f47f978   Anil S Keshavamurthy   [PATCH] Notify pa...
766
  	atomic_set(&kprobe_count, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767

6772926be   Rusty Lynch   [PATCH] kprobes: ...
768
  	err = arch_init_kprobes();
802eae7c8   Rusty Lynch   [PATCH] Return pr...
769
770
  	if (!err)
  		err = register_die_notifier(&kprobe_exceptions_nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
774
775
776
777
778
779
780
  	return err;
  }
  
  __initcall(init_kprobes);
  
  EXPORT_SYMBOL_GPL(register_kprobe);
  EXPORT_SYMBOL_GPL(unregister_kprobe);
  EXPORT_SYMBOL_GPL(register_jprobe);
  EXPORT_SYMBOL_GPL(unregister_jprobe);
  EXPORT_SYMBOL_GPL(jprobe_return);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
781
782
  EXPORT_SYMBOL_GPL(register_kretprobe);
  EXPORT_SYMBOL_GPL(unregister_kretprobe);