Blame view

kernel/kprobes.c 37.5 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>
e38697929   Randy Dunlap   kprobes: fix spar...
38
  #include <linux/stddef.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #include <linux/module.h>
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
40
  #include <linux/moduleloader.h>
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
41
  #include <linux/kallsyms.h>
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
42
  #include <linux/freezer.h>
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
43
44
  #include <linux/seq_file.h>
  #include <linux/debugfs.h>
1eeb66a1b   Christoph Hellwig   move die notifier...
45
  #include <linux/kdebug.h>
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
46
  #include <linux/memory.h>
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
47

d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
48
  #include <asm-generic/sections.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
  #include <asm/cacheflush.h>
  #include <asm/errno.h>
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
51
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
  
  #define KPROBE_HASH_BITS 6
  #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
55
56
57
58
59
60
61
62
63
  
  /*
   * 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
ef53d9c5e   Srinivasa D S   kprobes: improve ...
64
  static int kprobes_initialized;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
66
  static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67

bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
68
  /* NOTE: change this value only with kprobe_mutex held */
e579abeb5   Masami Hiramatsu   kprobes: rename k...
69
  static bool kprobes_all_disarmed;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
70

129415607   Masami Hiramatsu   kprobes: add kpro...
71
  static DEFINE_MUTEX(kprobe_mutex);	/* Protects kprobe_table */
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
72
  static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
73
  static struct {
7e036d040   Andrew Morton   kernel/kprobes.c:...
74
  	spinlock_t lock ____cacheline_aligned_in_smp;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
75
76
77
78
79
80
  } kretprobe_table_locks[KPROBE_TABLE_SIZE];
  
  static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
  {
  	return &(kretprobe_table_locks[hash].lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81

3d8d996e0   Srinivasa Ds   kprobes: prevent ...
82
83
84
85
86
87
88
  /*
   * Normally, functions that we'd want to prohibit kprobes in, are marked
   * __kprobes. But, there are cases where such functions already belong to
   * a different section (__sched for preempt_schedule)
   *
   * For such cases, we now have a blacklist
   */
544304b20   Daniel Guilak   kernel/kprobes.c:...
89
  static struct kprobe_blackpoint kprobe_blacklist[] = {
3d8d996e0   Srinivasa Ds   kprobes: prevent ...
90
91
92
  	{"preempt_schedule",},
  	{NULL}    /* Terminator */
  };
2d14e39da   Anil S Keshavamurthy   [PATCH] kprobes: ...
93
  #ifdef __ARCH_WANT_KPROBES_INSN_SLOT
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
94
95
96
97
98
99
100
101
102
  /*
   * 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 {
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
103
  	struct list_head list;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
104
105
106
  	kprobe_opcode_t *insns;		/* Page of instruction slots */
  	char slot_used[INSNS_PER_PAGE];
  	int nused;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
107
  	int ngarbage;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
108
  };
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
109
110
111
112
113
  enum kprobe_slot_state {
  	SLOT_CLEAN = 0,
  	SLOT_DIRTY = 1,
  	SLOT_USED = 2,
  };
129415607   Masami Hiramatsu   kprobes: add kpro...
114
  static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_pages */
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
115
  static LIST_HEAD(kprobe_insn_pages);
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
116
117
118
119
120
121
  static int kprobe_garbage_slots;
  static int collect_garbage_slots(void);
  
  static int __kprobes check_safety(void)
  {
  	int ret = 0;
5a4ccaf37   Masami Hiramatsu   kprobes: check CO...
122
  #if defined(CONFIG_PREEMPT) && defined(CONFIG_FREEZER)
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  	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: ...
143
144
  
  /**
129415607   Masami Hiramatsu   kprobes: add kpro...
145
   * __get_insn_slot() - Find a slot on an executable page for an instruction.
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
146
147
   * We allocate an executable page if there's no room on existing ones.
   */
129415607   Masami Hiramatsu   kprobes: add kpro...
148
  static kprobe_opcode_t __kprobes *__get_insn_slot(void)
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
149
150
  {
  	struct kprobe_insn_page *kip;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
151

6f716acd5   Christoph Hellwig   kprobes: codingst...
152
   retry:
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
153
  	list_for_each_entry(kip, &kprobe_insn_pages, list) {
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
154
155
156
  		if (kip->nused < INSNS_PER_PAGE) {
  			int i;
  			for (i = 0; i < INSNS_PER_PAGE; i++) {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
157
158
  				if (kip->slot_used[i] == SLOT_CLEAN) {
  					kip->slot_used[i] = SLOT_USED;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
159
160
161
162
163
164
165
166
  					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: ...
167
168
169
170
171
  	/* 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: ...
172
  	kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
6f716acd5   Christoph Hellwig   kprobes: codingst...
173
  	if (!kip)
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
174
  		return NULL;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
175
176
177
178
179
180
181
182
183
184
185
  
  	/*
  	 * 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;
  	}
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
186
187
  	INIT_LIST_HEAD(&kip->list);
  	list_add(&kip->list, &kprobe_insn_pages);
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
188
189
  	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
  	kip->slot_used[0] = SLOT_USED;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
190
  	kip->nused = 1;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
191
  	kip->ngarbage = 0;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
192
193
  	return kip->insns;
  }
129415607   Masami Hiramatsu   kprobes: add kpro...
194
195
196
197
198
199
200
201
  kprobe_opcode_t __kprobes *get_insn_slot(void)
  {
  	kprobe_opcode_t *ret;
  	mutex_lock(&kprobe_insn_mutex);
  	ret = __get_insn_slot();
  	mutex_unlock(&kprobe_insn_mutex);
  	return ret;
  }
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
202
203
204
  /* 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: ...
205
  	kip->slot_used[idx] = SLOT_CLEAN;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
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.
  		 */
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
214
215
  		if (!list_is_singular(&kprobe_insn_pages)) {
  			list_del(&kip->list);
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
216
217
218
219
220
221
222
223
224
225
  			module_free(NULL, kip->insns);
  			kfree(kip);
  		}
  		return 1;
  	}
  	return 0;
  }
  
  static int __kprobes collect_garbage_slots(void)
  {
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
226
  	struct kprobe_insn_page *kip, *next;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
227
228
  
  	/* Ensure no-one is preepmted on the garbages */
4a2bb6fcc   Masami Hiramatsu   kprobes: No need ...
229
  	if (check_safety())
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
230
  		return -EAGAIN;
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
231
  	list_for_each_entry_safe(kip, next, &kprobe_insn_pages, list) {
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
232
  		int i;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
233
234
235
236
  		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: ...
237
  			if (kip->slot_used[i] == SLOT_DIRTY &&
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
238
239
240
241
242
243
244
245
246
  			    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: ...
247
248
  {
  	struct kprobe_insn_page *kip;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
249

129415607   Masami Hiramatsu   kprobes: add kpro...
250
  	mutex_lock(&kprobe_insn_mutex);
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
251
  	list_for_each_entry(kip, &kprobe_insn_pages, list) {
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
252
253
254
  		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: ...
255
  			if (dirty) {
ab40c5c6b   Masami Hiramatsu   [PATCH] kprobes: ...
256
  				kip->slot_used[i] = SLOT_DIRTY;
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
257
  				kip->ngarbage++;
c5cb5a2d8   Masami Hiramatsu   kprobes: Clean up...
258
  			} else
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
259
  				collect_one_slot(kip, i);
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
260
  			break;
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
261
262
  		}
  	}
6f716acd5   Christoph Hellwig   kprobes: codingst...
263
264
  
  	if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)
b4c6c34a5   Masami Hiramatsu   [PATCH] kprobes: ...
265
  		collect_garbage_slots();
129415607   Masami Hiramatsu   kprobes: add kpro...
266
267
  
  	mutex_unlock(&kprobe_insn_mutex);
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
268
  }
2d14e39da   Anil S Keshavamurthy   [PATCH] kprobes: ...
269
  #endif
9ec4b1f35   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
270

e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
271
272
273
274
275
276
277
278
279
280
  /* 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: ...
281
282
  /*
   * This routine is called either:
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
283
   * 	- under the kprobe_mutex - during kprobe_[un]register()
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
284
   * 				OR
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
285
   * 	- with preemption disabled - from arch/xxx/kernel/kprobes.c
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
286
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
287
  struct kprobe __kprobes *get_kprobe(void *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  {
  	struct hlist_head *head;
  	struct hlist_node *node;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
291
  	struct kprobe *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
  
  	head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
294
  	hlist_for_each_entry_rcu(p, node, head, hlist) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
  		if (p->addr == addr)
  			return p;
  	}
  	return NULL;
  }
201517a7f   Masami Hiramatsu   kprobes: fix to u...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  /* Arm a kprobe with text_mutex */
  static void __kprobes arm_kprobe(struct kprobe *kp)
  {
  	mutex_lock(&text_mutex);
  	arch_arm_kprobe(kp);
  	mutex_unlock(&text_mutex);
  }
  
  /* Disarm a kprobe with text_mutex */
  static void __kprobes disarm_kprobe(struct kprobe *kp)
  {
  	mutex_lock(&text_mutex);
  	arch_disarm_kprobe(kp);
  	mutex_unlock(&text_mutex);
  }
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
315
316
317
318
  /*
   * 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: ...
319
  static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
320
321
  {
  	struct kprobe *kp;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
322
  	list_for_each_entry_rcu(kp, &p->list, list) {
de5bd88d5   Masami Hiramatsu   kprobes: support ...
323
  		if (kp->pre_handler && likely(!kprobe_disabled(kp))) {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
324
  			set_kprobe_instance(kp);
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
325
326
  			if (kp->pre_handler(kp, regs))
  				return 1;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
327
  		}
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
328
  		reset_kprobe_instance();
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
329
330
331
  	}
  	return 0;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
332
333
  static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
  					unsigned long flags)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
334
335
  {
  	struct kprobe *kp;
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
336
  	list_for_each_entry_rcu(kp, &p->list, list) {
de5bd88d5   Masami Hiramatsu   kprobes: support ...
337
  		if (kp->post_handler && likely(!kprobe_disabled(kp))) {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
338
  			set_kprobe_instance(kp);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
339
  			kp->post_handler(kp, regs, flags);
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
340
  			reset_kprobe_instance();
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
341
342
  		}
  	}
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
343
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
344
345
  static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
  					int trapnr)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
346
  {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
347
  	struct kprobe *cur = __get_cpu_var(kprobe_instance);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
348
349
350
351
  	/*
  	 * 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: ...
352
353
  	if (cur && cur->fault_handler) {
  		if (cur->fault_handler(cur, regs, trapnr))
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
354
355
356
357
  			return 1;
  	}
  	return 0;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
358
  static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
359
  {
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
360
361
362
363
364
365
  	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: ...
366
  	}
e65845235   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
367
368
  	reset_kprobe_instance();
  	return ret;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
369
  }
bf8d5c52c   Keshavamurthy Anil S   [PATCH] kprobes: ...
370
371
372
373
374
375
376
377
378
379
380
381
  /* 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;
  }
99219a3fb   bibo,mao   [PATCH] kretprobe...
382
383
  void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
  				struct hlist_head *head)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
384
  {
ef53d9c5e   Srinivasa D S   kprobes: improve ...
385
  	struct kretprobe *rp = ri->rp;
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
386
387
  	/* remove rp inst off the rprobe_inst_table */
  	hlist_del(&ri->hlist);
ef53d9c5e   Srinivasa D S   kprobes: improve ...
388
389
390
391
392
  	INIT_HLIST_NODE(&ri->hlist);
  	if (likely(rp)) {
  		spin_lock(&rp->lock);
  		hlist_add_head(&ri->hlist, &rp->free_instances);
  		spin_unlock(&rp->lock);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
393
394
  	} else
  		/* Unregistering */
99219a3fb   bibo,mao   [PATCH] kretprobe...
395
  		hlist_add_head(&ri->hlist, head);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
396
  }
017c39bdb   Masami Hiramatsu   kprobes: add __kp...
397
  void __kprobes kretprobe_hash_lock(struct task_struct *tsk,
ef53d9c5e   Srinivasa D S   kprobes: improve ...
398
399
400
401
402
403
404
405
406
  			 struct hlist_head **head, unsigned long *flags)
  {
  	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
  	spinlock_t *hlist_lock;
  
  	*head = &kretprobe_inst_table[hash];
  	hlist_lock = kretprobe_table_lock_ptr(hash);
  	spin_lock_irqsave(hlist_lock, *flags);
  }
017c39bdb   Masami Hiramatsu   kprobes: add __kp...
407
408
  static void __kprobes kretprobe_table_lock(unsigned long hash,
  	unsigned long *flags)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
409
  {
ef53d9c5e   Srinivasa D S   kprobes: improve ...
410
411
412
  	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
  	spin_lock_irqsave(hlist_lock, *flags);
  }
017c39bdb   Masami Hiramatsu   kprobes: add __kp...
413
414
  void __kprobes kretprobe_hash_unlock(struct task_struct *tsk,
  	unsigned long *flags)
ef53d9c5e   Srinivasa D S   kprobes: improve ...
415
416
417
418
419
420
421
  {
  	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
  	spinlock_t *hlist_lock;
  
  	hlist_lock = kretprobe_table_lock_ptr(hash);
  	spin_unlock_irqrestore(hlist_lock, *flags);
  }
017c39bdb   Masami Hiramatsu   kprobes: add __kp...
422
  void __kprobes kretprobe_table_unlock(unsigned long hash, unsigned long *flags)
ef53d9c5e   Srinivasa D S   kprobes: improve ...
423
424
425
  {
  	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
  	spin_unlock_irqrestore(hlist_lock, *flags);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
426
  }
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
427
  /*
c6fd91f0b   bibo mao   [PATCH] kretprobe...
428
429
430
431
   * 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: ...
432
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
433
  void __kprobes kprobe_flush_task(struct task_struct *tk)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
434
  {
62c27be0d   bibo,mao   [PATCH] kprobe wh...
435
  	struct kretprobe_instance *ri;
99219a3fb   bibo,mao   [PATCH] kretprobe...
436
  	struct hlist_head *head, empty_rp;
802eae7c8   Rusty Lynch   [PATCH] Return pr...
437
  	struct hlist_node *node, *tmp;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
438
  	unsigned long hash, flags = 0;
802eae7c8   Rusty Lynch   [PATCH] Return pr...
439

ef53d9c5e   Srinivasa D S   kprobes: improve ...
440
441
442
443
444
445
446
  	if (unlikely(!kprobes_initialized))
  		/* Early boot.  kretprobe_table_locks not yet initialized. */
  		return;
  
  	hash = hash_ptr(tk, KPROBE_HASH_BITS);
  	head = &kretprobe_inst_table[hash];
  	kretprobe_table_lock(hash, &flags);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
447
448
  	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
  		if (ri->task == tk)
99219a3fb   bibo,mao   [PATCH] kretprobe...
449
  			recycle_rp_inst(ri, &empty_rp);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
450
  	}
ef53d9c5e   Srinivasa D S   kprobes: improve ...
451
452
  	kretprobe_table_unlock(hash, &flags);
  	INIT_HLIST_HEAD(&empty_rp);
99219a3fb   bibo,mao   [PATCH] kretprobe...
453
454
455
456
  	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
  		hlist_del(&ri->hlist);
  		kfree(ri);
  	}
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
457
  }
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
458
459
460
  static inline void free_rp_inst(struct kretprobe *rp)
  {
  	struct kretprobe_instance *ri;
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
461
  	struct hlist_node *pos, *next;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
462
463
  	hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, hlist) {
  		hlist_del(&ri->hlist);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
464
465
466
  		kfree(ri);
  	}
  }
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
467
468
  static void __kprobes cleanup_rp_inst(struct kretprobe *rp)
  {
ef53d9c5e   Srinivasa D S   kprobes: improve ...
469
  	unsigned long flags, hash;
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
470
471
  	struct kretprobe_instance *ri;
  	struct hlist_node *pos, *next;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
472
  	struct hlist_head *head;
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
473
  	/* No race here */
ef53d9c5e   Srinivasa D S   kprobes: improve ...
474
475
476
477
478
479
480
481
  	for (hash = 0; hash < KPROBE_TABLE_SIZE; hash++) {
  		kretprobe_table_lock(hash, &flags);
  		head = &kretprobe_inst_table[hash];
  		hlist_for_each_entry_safe(ri, pos, next, head, hlist) {
  			if (ri->rp == rp)
  				ri->rp = NULL;
  		}
  		kretprobe_table_unlock(hash, &flags);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
482
  	}
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
483
484
  	free_rp_inst(rp);
  }
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
485
  /*
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
486
487
488
489
490
491
492
493
494
   * 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));
  }
  
  /*
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
495
  * Add the new probe to ap->list. Fail if this is the
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
496
497
  * second jprobe at the address - two jprobes can't coexist
  */
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
498
  static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p)
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
499
  {
de5bd88d5   Masami Hiramatsu   kprobes: support ...
500
  	BUG_ON(kprobe_gone(ap) || kprobe_gone(p));
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
501
  	if (p->break_handler) {
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
502
  		if (ap->break_handler)
367216567   mao, bibo   [PATCH] Kprobe: m...
503
  			return -EEXIST;
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
504
505
  		list_add_tail_rcu(&p->list, &ap->list);
  		ap->break_handler = aggr_break_handler;
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
506
  	} else
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
507
508
509
  		list_add_rcu(&p->list, &ap->list);
  	if (p->post_handler && !ap->post_handler)
  		ap->post_handler = aggr_post_handler;
de5bd88d5   Masami Hiramatsu   kprobes: support ...
510
511
512
513
514
  
  	if (kprobe_disabled(ap) && !kprobe_disabled(p)) {
  		ap->flags &= ~KPROBE_FLAG_DISABLED;
  		if (!kprobes_all_disarmed)
  			/* Arm the breakpoint again. */
201517a7f   Masami Hiramatsu   kprobes: fix to u...
515
  			arm_kprobe(ap);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
516
  	}
8b0914ea7   Prasanna S Panchamukhi   [PATCH] jprobes: ...
517
518
519
520
  	return 0;
  }
  
  /*
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
521
522
523
524
525
   * 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: ...
526
  	copy_kprobe(p, ap);
a9ad965ea   bibo, mao   [PATCH] IA64: kpr...
527
  	flush_insn_slot(ap);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
528
  	ap->addr = p->addr;
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
529
  	ap->flags = p->flags;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
530
  	ap->pre_handler = aggr_pre_handler;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
531
  	ap->fault_handler = aggr_fault_handler;
e8386a0cb   Masami Hiramatsu   kprobes: support ...
532
533
  	/* We don't care the kprobe which has gone. */
  	if (p->post_handler && !kprobe_gone(p))
367216567   mao, bibo   [PATCH] Kprobe: m...
534
  		ap->post_handler = aggr_post_handler;
e8386a0cb   Masami Hiramatsu   kprobes: support ...
535
  	if (p->break_handler && !kprobe_gone(p))
367216567   mao, bibo   [PATCH] Kprobe: m...
536
  		ap->break_handler = aggr_break_handler;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
537
538
  
  	INIT_LIST_HEAD(&ap->list);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
539
  	list_add_rcu(&p->list, &ap->list);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
540

adad0f331   Keshavamurthy Anil S   [PATCH] kprobes: ...
541
  	hlist_replace_rcu(&p->hlist, &ap->hlist);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
542
543
544
545
546
  }
  
  /*
   * This is the second or subsequent kprobe at the address - handle
   * the intricacies
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
547
   */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
548
549
  static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
  					  struct kprobe *p)
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
550
551
  {
  	int ret = 0;
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
552
  	struct kprobe *ap = old_p;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
553

b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
554
555
556
557
558
559
560
561
562
  	if (old_p->pre_handler != aggr_pre_handler) {
  		/* If old_p is not an aggr_probe, create new aggr_kprobe. */
  		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
  		if (!ap)
  			return -ENOMEM;
  		add_aggr_kprobe(ap, old_p);
  	}
  
  	if (kprobe_gone(ap)) {
e8386a0cb   Masami Hiramatsu   kprobes: support ...
563
564
565
566
567
568
  		/*
  		 * Attempting to insert new probe at the same location that
  		 * had a probe in the module vaddr area which already
  		 * freed. So, the instruction slot has already been
  		 * released. We need a new slot for the new probe.
  		 */
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
569
  		ret = arch_prepare_kprobe(ap);
e8386a0cb   Masami Hiramatsu   kprobes: support ...
570
  		if (ret)
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
571
572
573
574
575
  			/*
  			 * Even if fail to allocate new slot, don't need to
  			 * free aggr_probe. It will be used next time, or
  			 * freed by unregister_kprobe.
  			 */
e8386a0cb   Masami Hiramatsu   kprobes: support ...
576
  			return ret;
de5bd88d5   Masami Hiramatsu   kprobes: support ...
577

e8386a0cb   Masami Hiramatsu   kprobes: support ...
578
  		/*
de5bd88d5   Masami Hiramatsu   kprobes: support ...
579
580
  		 * Clear gone flag to prevent allocating new slot again, and
  		 * set disabled flag because it is not armed yet.
e8386a0cb   Masami Hiramatsu   kprobes: support ...
581
  		 */
de5bd88d5   Masami Hiramatsu   kprobes: support ...
582
583
  		ap->flags = (ap->flags & ~KPROBE_FLAG_GONE)
  			    | KPROBE_FLAG_DISABLED;
e8386a0cb   Masami Hiramatsu   kprobes: support ...
584
  	}
b918e5e60   Masami Hiramatsu   kprobes: cleanup ...
585
586
587
  
  	copy_kprobe(ap, p);
  	return add_new_kprobe(ap, p);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
588
  }
de5bd88d5   Masami Hiramatsu   kprobes: support ...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
  /* Try to disable aggr_kprobe, and return 1 if succeeded.*/
  static int __kprobes try_to_disable_aggr_kprobe(struct kprobe *p)
  {
  	struct kprobe *kp;
  
  	list_for_each_entry_rcu(kp, &p->list, list) {
  		if (!kprobe_disabled(kp))
  			/*
  			 * There is an active probe on the list.
  			 * We can't disable aggr_kprobe.
  			 */
  			return 0;
  	}
  	p->flags |= KPROBE_FLAG_DISABLED;
  	return 1;
  }
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
605
606
  static int __kprobes in_kprobes_functions(unsigned long addr)
  {
3d8d996e0   Srinivasa Ds   kprobes: prevent ...
607
  	struct kprobe_blackpoint *kb;
6f716acd5   Christoph Hellwig   kprobes: codingst...
608
609
  	if (addr >= (unsigned long)__kprobes_text_start &&
  	    addr < (unsigned long)__kprobes_text_end)
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
610
  		return -EINVAL;
3d8d996e0   Srinivasa Ds   kprobes: prevent ...
611
612
613
614
615
616
617
618
619
620
621
  	/*
  	 * If there exists a kprobe_blacklist, verify and
  	 * fail any probe registration in the prohibited area
  	 */
  	for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
  		if (kb->start_addr) {
  			if (addr >= kb->start_addr &&
  			    addr < (kb->start_addr + kb->range))
  				return -EINVAL;
  		}
  	}
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
622
623
  	return 0;
  }
b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  /*
   * If we have a symbol_name argument, look it up and add the offset field
   * to it. This way, we can specify a relative address to a symbol.
   */
  static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
  {
  	kprobe_opcode_t *addr = p->addr;
  	if (p->symbol_name) {
  		if (addr)
  			return NULL;
  		kprobe_lookup_name(p->symbol_name, addr);
  	}
  
  	if (!addr)
  		return NULL;
  	return (kprobe_opcode_t *)(((char *)addr) + p->offset);
  }
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
641
  int __kprobes register_kprobe(struct kprobe *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
  {
  	int ret = 0;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
644
  	struct kprobe *old_p;
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
645
  	struct module *probed_mod;
b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
646
  	kprobe_opcode_t *addr;
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
647

b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
648
649
  	addr = kprobe_addr(p);
  	if (!addr)
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
650
  		return -EINVAL;
b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
651
  	p->addr = addr;
3a872d89b   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
652

a189d0350   Masami Hiramatsu   kprobes: disable ...
653
  	preempt_disable();
ec30c5f3a   Masami Hiramatsu   kprobes: Use kern...
654
  	if (!kernel_text_address((unsigned long) p->addr) ||
a189d0350   Masami Hiramatsu   kprobes: disable ...
655
656
  	    in_kprobes_functions((unsigned long) p->addr)) {
  		preempt_enable();
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
657
  		return -EINVAL;
a189d0350   Masami Hiramatsu   kprobes: disable ...
658
  	}
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
659

de5bd88d5   Masami Hiramatsu   kprobes: support ...
660
661
  	/* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
  	p->flags &= KPROBE_FLAG_DISABLED;
6f716acd5   Christoph Hellwig   kprobes: codingst...
662
663
664
  	/*
  	 * Check if are we probing a module.
  	 */
a189d0350   Masami Hiramatsu   kprobes: disable ...
665
  	probed_mod = __module_text_address((unsigned long) p->addr);
6f716acd5   Christoph Hellwig   kprobes: codingst...
666
  	if (probed_mod) {
6f716acd5   Christoph Hellwig   kprobes: codingst...
667
  		/*
e8386a0cb   Masami Hiramatsu   kprobes: support ...
668
669
  		 * We must hold a refcount of the probed module while updating
  		 * its code to prohibit unexpected unloading.
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
670
  		 */
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
671
672
673
674
  		if (unlikely(!try_module_get(probed_mod))) {
  			preempt_enable();
  			return -EINVAL;
  		}
f24659d96   Masami Hiramatsu   kprobes: support ...
675
676
677
678
679
680
681
682
683
684
  		/*
  		 * If the module freed .init.text, we couldn't insert
  		 * kprobes in there.
  		 */
  		if (within_module_init((unsigned long)p->addr, probed_mod) &&
  		    probed_mod->state != MODULE_STATE_COMING) {
  			module_put(probed_mod);
  			preempt_enable();
  			return -EINVAL;
  		}
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
685
  	}
a189d0350   Masami Hiramatsu   kprobes: disable ...
686
  	preempt_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
688
  	p->nmissed = 0;
9861668f7   Masami Hiramatsu   kprobes: add (un)...
689
  	INIT_LIST_HEAD(&p->list);
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
690
  	mutex_lock(&kprobe_mutex);
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
691
692
693
  	old_p = get_kprobe(p->addr);
  	if (old_p) {
  		ret = register_aggr_kprobe(old_p, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696

4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
697
  	mutex_lock(&text_mutex);
6f716acd5   Christoph Hellwig   kprobes: codingst...
698
699
  	ret = arch_prepare_kprobe(p);
  	if (ret)
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
700
  		goto out_unlock_text;
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
701

64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
702
  	INIT_HLIST_NODE(&p->hlist);
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
703
  	hlist_add_head_rcu(&p->hlist,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
705
  	if (!kprobes_all_disarmed && !kprobe_disabled(p))
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
706
  		arch_arm_kprobe(p);
74a0b5762   Christoph Hellwig   x86: optimize pag...
707

4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
708
709
  out_unlock_text:
  	mutex_unlock(&text_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  out:
7a7d1cf95   Ingo Molnar   [PATCH] sem2mutex...
711
  	mutex_unlock(&kprobe_mutex);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
712

e8386a0cb   Masami Hiramatsu   kprobes: support ...
713
  	if (probed_mod)
df019b1d8   Keshavamurthy Anil S   [PATCH] kprobes: ...
714
  		module_put(probed_mod);
e8386a0cb   Masami Hiramatsu   kprobes: support ...
715

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
  	return ret;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
718
  EXPORT_SYMBOL_GPL(register_kprobe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719

de5bd88d5   Masami Hiramatsu   kprobes: support ...
720
721
  /* Check passed kprobe is valid and return kprobe in kprobe_table. */
  static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  {
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
723
  	struct kprobe *old_p, *list_p;
64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
724

64f562c6d   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
725
  	old_p = get_kprobe(p->addr);
9861668f7   Masami Hiramatsu   kprobes: add (un)...
726
  	if (unlikely(!old_p))
de5bd88d5   Masami Hiramatsu   kprobes: support ...
727
  		return NULL;
9861668f7   Masami Hiramatsu   kprobes: add (un)...
728

f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
729
730
731
732
  	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 */
de5bd88d5   Masami Hiramatsu   kprobes: support ...
733
734
  				goto valid;
  		return NULL;
f709b1223   Keshavamurthy Anil S   [PATCH] kprobes-c...
735
  	}
de5bd88d5   Masami Hiramatsu   kprobes: support ...
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  valid:
  	return old_p;
  }
  
  /*
   * Unregister a kprobe without a scheduler synchronization.
   */
  static int __kprobes __unregister_kprobe_top(struct kprobe *p)
  {
  	struct kprobe *old_p, *list_p;
  
  	old_p = __get_valid_kprobe(p);
  	if (old_p == NULL)
  		return -EINVAL;
6f716acd5   Christoph Hellwig   kprobes: codingst...
750
751
  	if (old_p == p ||
  	    (old_p->pre_handler == aggr_pre_handler &&
9861668f7   Masami Hiramatsu   kprobes: add (un)...
752
  	     list_is_singular(&old_p->list))) {
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
753
754
  		/*
  		 * Only probe on the hash list. Disarm only if kprobes are
e8386a0cb   Masami Hiramatsu   kprobes: support ...
755
756
  		 * enabled and not gone - otherwise, the breakpoint would
  		 * already have been removed. We save on flushing icache.
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
757
  		 */
201517a7f   Masami Hiramatsu   kprobes: fix to u...
758
759
  		if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
  			disarm_kprobe(p);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
760
  		hlist_del_rcu(&old_p->hlist);
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
761
  	} else {
e8386a0cb   Masami Hiramatsu   kprobes: support ...
762
  		if (p->break_handler && !kprobe_gone(p))
9861668f7   Masami Hiramatsu   kprobes: add (un)...
763
  			old_p->break_handler = NULL;
e8386a0cb   Masami Hiramatsu   kprobes: support ...
764
  		if (p->post_handler && !kprobe_gone(p)) {
9861668f7   Masami Hiramatsu   kprobes: add (un)...
765
766
767
768
769
770
771
  			list_for_each_entry_rcu(list_p, &old_p->list, list) {
  				if ((list_p != p) && (list_p->post_handler))
  					goto noclean;
  			}
  			old_p->post_handler = NULL;
  		}
  noclean:
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
772
  		list_del_rcu(&p->list);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
773
774
775
  		if (!kprobe_disabled(old_p)) {
  			try_to_disable_aggr_kprobe(old_p);
  			if (!kprobes_all_disarmed && kprobe_disabled(old_p))
201517a7f   Masami Hiramatsu   kprobes: fix to u...
776
  				disarm_kprobe(old_p);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
777
  		}
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
778
  	}
9861668f7   Masami Hiramatsu   kprobes: add (un)...
779
780
  	return 0;
  }
3516a4604   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
781

9861668f7   Masami Hiramatsu   kprobes: add (un)...
782
783
  static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
  {
9861668f7   Masami Hiramatsu   kprobes: add (un)...
784
  	struct kprobe *old_p;
b3e55c727   Mao, Bibo   [PATCH] Kprobes: ...
785

e8386a0cb   Masami Hiramatsu   kprobes: support ...
786
  	if (list_empty(&p->list))
0498b6350   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
787
  		arch_remove_kprobe(p);
e8386a0cb   Masami Hiramatsu   kprobes: support ...
788
789
790
791
792
793
  	else if (list_is_singular(&p->list)) {
  		/* "p" is the last child of an aggr_kprobe */
  		old_p = list_entry(p->list.next, struct kprobe, list);
  		list_del(&p->list);
  		arch_remove_kprobe(old_p);
  		kfree(old_p);
9861668f7   Masami Hiramatsu   kprobes: add (un)...
794
795
  	}
  }
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
796
  int __kprobes register_kprobes(struct kprobe **kps, int num)
9861668f7   Masami Hiramatsu   kprobes: add (un)...
797
798
799
800
801
802
  {
  	int i, ret = 0;
  
  	if (num <= 0)
  		return -EINVAL;
  	for (i = 0; i < num; i++) {
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
803
  		ret = register_kprobe(kps[i]);
67dddaad5   Masami Hiramatsu   kprobes: fix erro...
804
805
806
  		if (ret < 0) {
  			if (i > 0)
  				unregister_kprobes(kps, i);
9861668f7   Masami Hiramatsu   kprobes: add (un)...
807
  			break;
367216567   mao, bibo   [PATCH] Kprobe: m...
808
  		}
49a2a1b83   Anil S Keshavamurthy   [PATCH] kprobes: ...
809
  	}
9861668f7   Masami Hiramatsu   kprobes: add (un)...
810
811
  	return ret;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
812
  EXPORT_SYMBOL_GPL(register_kprobes);
9861668f7   Masami Hiramatsu   kprobes: add (un)...
813

9861668f7   Masami Hiramatsu   kprobes: add (un)...
814
815
816
817
  void __kprobes unregister_kprobe(struct kprobe *p)
  {
  	unregister_kprobes(&p, 1);
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
818
  EXPORT_SYMBOL_GPL(unregister_kprobe);
9861668f7   Masami Hiramatsu   kprobes: add (un)...
819

9861668f7   Masami Hiramatsu   kprobes: add (un)...
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  void __kprobes unregister_kprobes(struct kprobe **kps, int num)
  {
  	int i;
  
  	if (num <= 0)
  		return;
  	mutex_lock(&kprobe_mutex);
  	for (i = 0; i < num; i++)
  		if (__unregister_kprobe_top(kps[i]) < 0)
  			kps[i]->addr = NULL;
  	mutex_unlock(&kprobe_mutex);
  
  	synchronize_sched();
  	for (i = 0; i < num; i++)
  		if (kps[i]->addr)
  			__unregister_kprobe_bottom(kps[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
837
  EXPORT_SYMBOL_GPL(unregister_kprobes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
  
  static struct notifier_block kprobe_exceptions_nb = {
  	.notifier_call = kprobe_exceptions_notify,
3d5631e06   Anil S Keshavamurthy   [PATCH] Kprobes r...
841
842
  	.priority = 0x7fffffff /* we need to be notified first */
  };
3d7e33825   Michael Ellerman   jprobes: make jpr...
843
844
845
846
  unsigned long __weak arch_deref_entry_point(void *entry)
  {
  	return (unsigned long)entry;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847

49ad2fd76   Masami Hiramatsu   kprobes: remove c...
848
  int __kprobes register_jprobes(struct jprobe **jps, int num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  {
26b31c190   Masami Hiramatsu   kprobes: add (un)...
850
851
  	struct jprobe *jp;
  	int ret = 0, i;
3d7e33825   Michael Ellerman   jprobes: make jpr...
852

26b31c190   Masami Hiramatsu   kprobes: add (un)...
853
  	if (num <= 0)
3d7e33825   Michael Ellerman   jprobes: make jpr...
854
  		return -EINVAL;
26b31c190   Masami Hiramatsu   kprobes: add (un)...
855
856
857
858
859
860
861
862
863
864
865
  	for (i = 0; i < num; i++) {
  		unsigned long addr;
  		jp = jps[i];
  		addr = arch_deref_entry_point(jp->entry);
  
  		if (!kernel_text_address(addr))
  			ret = -EINVAL;
  		else {
  			/* Todo: Verify probepoint is a function entry point */
  			jp->kp.pre_handler = setjmp_pre_handler;
  			jp->kp.break_handler = longjmp_break_handler;
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
866
  			ret = register_kprobe(&jp->kp);
26b31c190   Masami Hiramatsu   kprobes: add (un)...
867
  		}
67dddaad5   Masami Hiramatsu   kprobes: fix erro...
868
869
870
  		if (ret < 0) {
  			if (i > 0)
  				unregister_jprobes(jps, i);
26b31c190   Masami Hiramatsu   kprobes: add (un)...
871
872
873
874
875
  			break;
  		}
  	}
  	return ret;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
876
  EXPORT_SYMBOL_GPL(register_jprobes);
3d7e33825   Michael Ellerman   jprobes: make jpr...
877

26b31c190   Masami Hiramatsu   kprobes: add (un)...
878
879
  int __kprobes register_jprobe(struct jprobe *jp)
  {
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
880
  	return register_jprobes(&jp, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
882
  EXPORT_SYMBOL_GPL(register_jprobe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883

d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
884
  void __kprobes unregister_jprobe(struct jprobe *jp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
  {
26b31c190   Masami Hiramatsu   kprobes: add (un)...
886
887
  	unregister_jprobes(&jp, 1);
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
888
  EXPORT_SYMBOL_GPL(unregister_jprobe);
26b31c190   Masami Hiramatsu   kprobes: add (un)...
889

26b31c190   Masami Hiramatsu   kprobes: add (un)...
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
  void __kprobes unregister_jprobes(struct jprobe **jps, int num)
  {
  	int i;
  
  	if (num <= 0)
  		return;
  	mutex_lock(&kprobe_mutex);
  	for (i = 0; i < num; i++)
  		if (__unregister_kprobe_top(&jps[i]->kp) < 0)
  			jps[i]->kp.addr = NULL;
  	mutex_unlock(&kprobe_mutex);
  
  	synchronize_sched();
  	for (i = 0; i < num; i++) {
  		if (jps[i]->kp.addr)
  			__unregister_kprobe_bottom(&jps[i]->kp);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
908
  EXPORT_SYMBOL_GPL(unregister_jprobes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909

9edddaa20   Ananth N Mavinakayanahalli   Kprobes: indicate...
910
  #ifdef CONFIG_KRETPROBES
e65cefe87   Adrian Bunk   [PATCH] kernel/kp...
911
912
913
914
915
916
917
918
  /*
   * 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);
ef53d9c5e   Srinivasa D S   kprobes: improve ...
919
920
  	unsigned long hash, flags = 0;
  	struct kretprobe_instance *ri;
e65cefe87   Adrian Bunk   [PATCH] kernel/kp...
921
922
  
  	/*TODO: consider to only swap the RA after the last pre_handler fired */
ef53d9c5e   Srinivasa D S   kprobes: improve ...
923
924
  	hash = hash_ptr(current, KPROBE_HASH_BITS);
  	spin_lock_irqsave(&rp->lock, flags);
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
925
  	if (!hlist_empty(&rp->free_instances)) {
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
926
  		ri = hlist_entry(rp->free_instances.first,
ef53d9c5e   Srinivasa D S   kprobes: improve ...
927
928
929
  				struct kretprobe_instance, hlist);
  		hlist_del(&ri->hlist);
  		spin_unlock_irqrestore(&rp->lock, flags);
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
930
931
  		ri->rp = rp;
  		ri->task = current;
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
932

f02b8624f   Ananth N Mavinakayanahalli   kprobes: Fix lock...
933
  		if (rp->entry_handler && rp->entry_handler(ri, regs))
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
934
  			return 0;
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
935

4c4308cb9   Christoph Hellwig   kprobes: kretprob...
936
937
938
  		arch_prepare_kretprobe(ri, regs);
  
  		/* XXX(hch): why is there no hlist_move_head? */
ef53d9c5e   Srinivasa D S   kprobes: improve ...
939
940
941
942
943
  		INIT_HLIST_NODE(&ri->hlist);
  		kretprobe_table_lock(hash, &flags);
  		hlist_add_head(&ri->hlist, &kretprobe_inst_table[hash]);
  		kretprobe_table_unlock(hash, &flags);
  	} else {
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
944
  		rp->nmissed++;
ef53d9c5e   Srinivasa D S   kprobes: improve ...
945
946
  		spin_unlock_irqrestore(&rp->lock, flags);
  	}
e65cefe87   Adrian Bunk   [PATCH] kernel/kp...
947
948
  	return 0;
  }
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
949
  int __kprobes register_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
950
951
952
953
  {
  	int ret = 0;
  	struct kretprobe_instance *inst;
  	int i;
b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
954
  	void *addr;
f438d914b   Masami Hiramatsu   kprobes: support ...
955
956
  
  	if (kretprobe_blacklist_size) {
b2a5cd693   Masami Hiramatsu   kprobes: fix a nu...
957
958
959
  		addr = kprobe_addr(&rp->kp);
  		if (!addr)
  			return -EINVAL;
f438d914b   Masami Hiramatsu   kprobes: support ...
960
961
962
963
964
965
  
  		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
  			if (kretprobe_blacklist[i].addr == addr)
  				return -EINVAL;
  		}
  	}
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
966
967
  
  	rp->kp.pre_handler = pre_handler_kretprobe;
7522a8423   Ananth N Mavinakayanahalli   [PATCH] kprobes: ...
968
969
970
  	rp->kp.post_handler = NULL;
  	rp->kp.fault_handler = NULL;
  	rp->kp.break_handler = NULL;
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
971
972
973
974
975
976
977
978
979
  
  	/* 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
  	}
ef53d9c5e   Srinivasa D S   kprobes: improve ...
980
  	spin_lock_init(&rp->lock);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
981
982
  	INIT_HLIST_HEAD(&rp->free_instances);
  	for (i = 0; i < rp->maxactive; i++) {
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
983
984
  		inst = kmalloc(sizeof(struct kretprobe_instance) +
  			       rp->data_size, GFP_KERNEL);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
985
986
987
988
  		if (inst == NULL) {
  			free_rp_inst(rp);
  			return -ENOMEM;
  		}
ef53d9c5e   Srinivasa D S   kprobes: improve ...
989
990
  		INIT_HLIST_NODE(&inst->hlist);
  		hlist_add_head(&inst->hlist, &rp->free_instances);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
991
992
993
994
  	}
  
  	rp->nmissed = 0;
  	/* Establish function entry probe point */
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
995
  	ret = register_kprobe(&rp->kp);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
996
  	if (ret != 0)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
997
998
999
  		free_rp_inst(rp);
  	return ret;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1000
  EXPORT_SYMBOL_GPL(register_kretprobe);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1001

49ad2fd76   Masami Hiramatsu   kprobes: remove c...
1002
  int __kprobes register_kretprobes(struct kretprobe **rps, int num)
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1003
1004
1005
1006
1007
1008
  {
  	int ret = 0, i;
  
  	if (num <= 0)
  		return -EINVAL;
  	for (i = 0; i < num; i++) {
49ad2fd76   Masami Hiramatsu   kprobes: remove c...
1009
  		ret = register_kretprobe(rps[i]);
67dddaad5   Masami Hiramatsu   kprobes: fix erro...
1010
1011
1012
  		if (ret < 0) {
  			if (i > 0)
  				unregister_kretprobes(rps, i);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1013
1014
1015
1016
1017
  			break;
  		}
  	}
  	return ret;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1018
  EXPORT_SYMBOL_GPL(register_kretprobes);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1019

4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1020
1021
1022
1023
  void __kprobes unregister_kretprobe(struct kretprobe *rp)
  {
  	unregister_kretprobes(&rp, 1);
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1024
  EXPORT_SYMBOL_GPL(unregister_kretprobe);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1025

4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
  {
  	int i;
  
  	if (num <= 0)
  		return;
  	mutex_lock(&kprobe_mutex);
  	for (i = 0; i < num; i++)
  		if (__unregister_kprobe_top(&rps[i]->kp) < 0)
  			rps[i]->kp.addr = NULL;
  	mutex_unlock(&kprobe_mutex);
  
  	synchronize_sched();
  	for (i = 0; i < num; i++) {
  		if (rps[i]->kp.addr) {
  			__unregister_kprobe_bottom(&rps[i]->kp);
  			cleanup_rp_inst(rps[i]);
  		}
  	}
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1046
  EXPORT_SYMBOL_GPL(unregister_kretprobes);
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1047

9edddaa20   Ananth N Mavinakayanahalli   Kprobes: indicate...
1048
  #else /* CONFIG_KRETPROBES */
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
1049
  int __kprobes register_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1050
1051
1052
  {
  	return -ENOSYS;
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1053
  EXPORT_SYMBOL_GPL(register_kretprobe);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1054

4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1055
  int __kprobes register_kretprobes(struct kretprobe **rps, int num)
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1056
  {
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1057
  	return -ENOSYS;
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1058
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1059
  EXPORT_SYMBOL_GPL(register_kretprobes);
d0aaff979   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
1060
  void __kprobes unregister_kretprobe(struct kretprobe *rp)
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1061
  {
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1062
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1063
  EXPORT_SYMBOL_GPL(unregister_kretprobe);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1064

4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1065
1066
1067
  void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
  {
  }
99081ab55   Masami Hiramatsu   kprobes: move EXP...
1068
  EXPORT_SYMBOL_GPL(unregister_kretprobes);
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
1069

4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1070
1071
1072
1073
  static int __kprobes pre_handler_kretprobe(struct kprobe *p,
  					   struct pt_regs *regs)
  {
  	return 0;
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1074
  }
4a296e07c   Masami Hiramatsu   kprobes: add (un)...
1075
  #endif /* CONFIG_KRETPROBES */
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1076
1077
1078
1079
  /* Set the kprobe gone and remove its instruction buffer. */
  static void __kprobes kill_kprobe(struct kprobe *p)
  {
  	struct kprobe *kp;
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1080

e8386a0cb   Masami Hiramatsu   kprobes: support ...
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
  	p->flags |= KPROBE_FLAG_GONE;
  	if (p->pre_handler == aggr_pre_handler) {
  		/*
  		 * If this is an aggr_kprobe, we have to list all the
  		 * chained probes and mark them GONE.
  		 */
  		list_for_each_entry_rcu(kp, &p->list, list)
  			kp->flags |= KPROBE_FLAG_GONE;
  		p->post_handler = NULL;
  		p->break_handler = NULL;
  	}
  	/*
  	 * Here, we can remove insn_slot safely, because no thread calls
  	 * the original probed function (which will be freed soon) any more.
  	 */
  	arch_remove_kprobe(p);
  }
  
  /* Module notifier call back, checking kprobes on the module */
  static int __kprobes kprobes_module_callback(struct notifier_block *nb,
  					     unsigned long val, void *data)
  {
  	struct module *mod = data;
  	struct hlist_head *head;
  	struct hlist_node *node;
  	struct kprobe *p;
  	unsigned int i;
f24659d96   Masami Hiramatsu   kprobes: support ...
1108
  	int checkcore = (val == MODULE_STATE_GOING);
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1109

f24659d96   Masami Hiramatsu   kprobes: support ...
1110
  	if (val != MODULE_STATE_GOING && val != MODULE_STATE_LIVE)
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1111
1112
1113
  		return NOTIFY_DONE;
  
  	/*
f24659d96   Masami Hiramatsu   kprobes: support ...
1114
1115
1116
1117
  	 * When MODULE_STATE_GOING was notified, both of module .text and
  	 * .init.text sections would be freed. When MODULE_STATE_LIVE was
  	 * notified, only .init.text section would be freed. We need to
  	 * disable kprobes which have been inserted in the sections.
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1118
1119
1120
1121
1122
  	 */
  	mutex_lock(&kprobe_mutex);
  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
  		head = &kprobe_table[i];
  		hlist_for_each_entry_rcu(p, node, head, hlist)
f24659d96   Masami Hiramatsu   kprobes: support ...
1123
1124
1125
  			if (within_module_init((unsigned long)p->addr, mod) ||
  			    (checkcore &&
  			     within_module_core((unsigned long)p->addr, mod))) {
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
  				/*
  				 * The vaddr this probe is installed will soon
  				 * be vfreed buy not synced to disk. Hence,
  				 * disarming the breakpoint isn't needed.
  				 */
  				kill_kprobe(p);
  			}
  	}
  	mutex_unlock(&kprobe_mutex);
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block kprobe_module_nb = {
  	.notifier_call = kprobes_module_callback,
  	.priority = 0
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
1143
1144
  static int __init init_kprobes(void)
  {
  	int i, err = 0;
3d8d996e0   Srinivasa Ds   kprobes: prevent ...
1145
1146
1147
1148
1149
  	unsigned long offset = 0, size = 0;
  	char *modname, namebuf[128];
  	const char *symbol_name;
  	void *addr;
  	struct kprobe_blackpoint *kb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
1151
1152
  
  	/* FIXME allocate the probe table, currently defined statically */
  	/* initialize all list heads */
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1153
  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
  		INIT_HLIST_HEAD(&kprobe_table[i]);
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1155
  		INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
ef53d9c5e   Srinivasa D S   kprobes: improve ...
1156
  		spin_lock_init(&(kretprobe_table_locks[i].lock));
b94cce926   Hien Nguyen   [PATCH] kprobes: ...
1157
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158

3d8d996e0   Srinivasa Ds   kprobes: prevent ...
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
  	/*
  	 * Lookup and populate the kprobe_blacklist.
  	 *
  	 * Unlike the kretprobe blacklist, we'll need to determine
  	 * the range of addresses that belong to the said functions,
  	 * since a kprobe need not necessarily be at the beginning
  	 * of a function.
  	 */
  	for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
  		kprobe_lookup_name(kb->name, addr);
  		if (!addr)
  			continue;
  
  		kb->start_addr = (unsigned long)addr;
  		symbol_name = kallsyms_lookup(kb->start_addr,
  				&size, &offset, &modname, namebuf);
  		if (!symbol_name)
  			kb->range = 0;
  		else
  			kb->range = size;
  	}
f438d914b   Masami Hiramatsu   kprobes: support ...
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
  	if (kretprobe_blacklist_size) {
  		/* lookup the function address from its name */
  		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
  			kprobe_lookup_name(kretprobe_blacklist[i].name,
  					   kretprobe_blacklist[i].addr);
  			if (!kretprobe_blacklist[i].addr)
  				printk("kretprobe: lookup failed: %s
  ",
  				       kretprobe_blacklist[i].name);
  		}
  	}
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1191
1192
  	/* By default, kprobes are armed */
  	kprobes_all_disarmed = false;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1193

6772926be   Rusty Lynch   [PATCH] kprobes: ...
1194
  	err = arch_init_kprobes();
802eae7c8   Rusty Lynch   [PATCH] Return pr...
1195
1196
  	if (!err)
  		err = register_die_notifier(&kprobe_exceptions_nb);
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1197
1198
  	if (!err)
  		err = register_module_notifier(&kprobe_module_nb);
ef53d9c5e   Srinivasa D S   kprobes: improve ...
1199
  	kprobes_initialized = (err == 0);
802eae7c8   Rusty Lynch   [PATCH] Return pr...
1200

8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
1201
1202
  	if (!err)
  		init_test_probes();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
  	return err;
  }
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1205
1206
  #ifdef CONFIG_DEBUG_FS
  static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1207
  		const char *sym, int offset,char *modname)
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
  {
  	char *kprobe_type;
  
  	if (p->pre_handler == pre_handler_kretprobe)
  		kprobe_type = "r";
  	else if (p->pre_handler == setjmp_pre_handler)
  		kprobe_type = "j";
  	else
  		kprobe_type = "k";
  	if (sym)
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1218
1219
1220
1221
1222
1223
1224
  		seq_printf(pi, "%p  %s  %s+0x%x  %s %s%s
  ",
  			p->addr, kprobe_type, sym, offset,
  			(modname ? modname : " "),
  			(kprobe_gone(p) ? "[GONE]" : ""),
  			((kprobe_disabled(p) && !kprobe_gone(p)) ?
  			 "[DISABLED]" : ""));
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1225
  	else
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1226
1227
1228
1229
1230
1231
  		seq_printf(pi, "%p  %s  %p %s%s
  ",
  			p->addr, kprobe_type, p->addr,
  			(kprobe_gone(p) ? "[GONE]" : ""),
  			((kprobe_disabled(p) && !kprobe_gone(p)) ?
  			 "[DISABLED]" : ""));
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  }
  
  static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
  {
  	return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL;
  }
  
  static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos)
  {
  	(*pos)++;
  	if (*pos >= KPROBE_TABLE_SIZE)
  		return NULL;
  	return pos;
  }
  
  static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v)
  {
  	/* Nothing to do */
  }
  
  static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
  {
  	struct hlist_head *head;
  	struct hlist_node *node;
  	struct kprobe *p, *kp;
  	const char *sym = NULL;
  	unsigned int i = *(loff_t *) v;
ffb451227   Alexey Dobriyan   Simplify kallsyms...
1259
  	unsigned long offset = 0;
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1260
1261
1262
1263
1264
  	char *modname, namebuf[128];
  
  	head = &kprobe_table[i];
  	preempt_disable();
  	hlist_for_each_entry_rcu(p, node, head, hlist) {
ffb451227   Alexey Dobriyan   Simplify kallsyms...
1265
  		sym = kallsyms_lookup((unsigned long)p->addr, NULL,
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  					&offset, &modname, namebuf);
  		if (p->pre_handler == aggr_pre_handler) {
  			list_for_each_entry_rcu(kp, &p->list, list)
  				report_probe(pi, kp, sym, offset, modname);
  		} else
  			report_probe(pi, p, sym, offset, modname);
  	}
  	preempt_enable();
  	return 0;
  }
88e9d34c7   James Morris   seq_file: constif...
1276
  static const struct seq_operations kprobes_seq_ops = {
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  	.start = kprobe_seq_start,
  	.next  = kprobe_seq_next,
  	.stop  = kprobe_seq_stop,
  	.show  = show_kprobe_addr
  };
  
  static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
  {
  	return seq_open(filp, &kprobes_seq_ops);
  }
828c09509   Alexey Dobriyan   const: constify r...
1287
  static const struct file_operations debugfs_kprobes_operations = {
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1288
1289
1290
1291
1292
  	.open           = kprobes_open,
  	.read           = seq_read,
  	.llseek         = seq_lseek,
  	.release        = seq_release,
  };
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  /* Disable one kprobe */
  int __kprobes disable_kprobe(struct kprobe *kp)
  {
  	int ret = 0;
  	struct kprobe *p;
  
  	mutex_lock(&kprobe_mutex);
  
  	/* Check whether specified probe is valid. */
  	p = __get_valid_kprobe(kp);
  	if (unlikely(p == NULL)) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	/* If the probe is already disabled (or gone), just return */
  	if (kprobe_disabled(kp))
  		goto out;
  
  	kp->flags |= KPROBE_FLAG_DISABLED;
  	if (p != kp)
  		/* When kp != p, p is always enabled. */
  		try_to_disable_aggr_kprobe(p);
  
  	if (!kprobes_all_disarmed && kprobe_disabled(p))
201517a7f   Masami Hiramatsu   kprobes: fix to u...
1318
  		disarm_kprobe(p);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
  out:
  	mutex_unlock(&kprobe_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(disable_kprobe);
  
  /* Enable one kprobe */
  int __kprobes enable_kprobe(struct kprobe *kp)
  {
  	int ret = 0;
  	struct kprobe *p;
  
  	mutex_lock(&kprobe_mutex);
  
  	/* Check whether specified probe is valid. */
  	p = __get_valid_kprobe(kp);
  	if (unlikely(p == NULL)) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	if (kprobe_gone(kp)) {
  		/* This kprobe has gone, we couldn't enable it. */
  		ret = -EINVAL;
  		goto out;
  	}
  
  	if (!kprobes_all_disarmed && kprobe_disabled(p))
201517a7f   Masami Hiramatsu   kprobes: fix to u...
1347
  		arm_kprobe(p);
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1348
1349
1350
1351
1352
1353
1354
1355
1356
  
  	p->flags &= ~KPROBE_FLAG_DISABLED;
  	if (p != kp)
  		kp->flags &= ~KPROBE_FLAG_DISABLED;
  out:
  	mutex_unlock(&kprobe_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(enable_kprobe);
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1357
  static void __kprobes arm_all_kprobes(void)
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1358
1359
1360
1361
1362
1363
1364
  {
  	struct hlist_head *head;
  	struct hlist_node *node;
  	struct kprobe *p;
  	unsigned int i;
  
  	mutex_lock(&kprobe_mutex);
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1365
1366
  	/* If kprobes are armed, just return */
  	if (!kprobes_all_disarmed)
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1367
  		goto already_enabled;
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
1368
  	mutex_lock(&text_mutex);
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1369
1370
1371
  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
  		head = &kprobe_table[i];
  		hlist_for_each_entry_rcu(p, node, head, hlist)
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1372
  			if (!kprobe_disabled(p))
e8386a0cb   Masami Hiramatsu   kprobes: support ...
1373
  				arch_arm_kprobe(p);
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1374
  	}
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
1375
  	mutex_unlock(&text_mutex);
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1376

e579abeb5   Masami Hiramatsu   kprobes: rename k...
1377
  	kprobes_all_disarmed = false;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1378
1379
1380
1381
1382
1383
1384
  	printk(KERN_INFO "Kprobes globally enabled
  ");
  
  already_enabled:
  	mutex_unlock(&kprobe_mutex);
  	return;
  }
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1385
  static void __kprobes disarm_all_kprobes(void)
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1386
1387
1388
1389
1390
1391
1392
  {
  	struct hlist_head *head;
  	struct hlist_node *node;
  	struct kprobe *p;
  	unsigned int i;
  
  	mutex_lock(&kprobe_mutex);
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1393
1394
  	/* If kprobes are already disarmed, just return */
  	if (kprobes_all_disarmed)
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1395
  		goto already_disabled;
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1396
  	kprobes_all_disarmed = true;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1397
1398
  	printk(KERN_INFO "Kprobes globally disabled
  ");
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
1399
  	mutex_lock(&text_mutex);
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1400
1401
1402
  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
  		head = &kprobe_table[i];
  		hlist_for_each_entry_rcu(p, node, head, hlist) {
de5bd88d5   Masami Hiramatsu   kprobes: support ...
1403
  			if (!arch_trampoline_kprobe(p) && !kprobe_disabled(p))
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1404
1405
1406
  				arch_disarm_kprobe(p);
  		}
  	}
4460fdad8   Mathieu Desnoyers   tracing, Text Edi...
1407
  	mutex_unlock(&text_mutex);
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1408
1409
1410
  	mutex_unlock(&kprobe_mutex);
  	/* Allow all currently running kprobes to complete */
  	synchronize_sched();
74a0b5762   Christoph Hellwig   x86: optimize pag...
1411
  	return;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
  
  already_disabled:
  	mutex_unlock(&kprobe_mutex);
  	return;
  }
  
  /*
   * XXX: The debugfs bool file interface doesn't allow for callbacks
   * when the bool state is switched. We can reuse that facility when
   * available
   */
  static ssize_t read_enabled_file_bool(struct file *file,
  	       char __user *user_buf, size_t count, loff_t *ppos)
  {
  	char buf[3];
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1427
  	if (!kprobes_all_disarmed)
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
  		buf[0] = '1';
  	else
  		buf[0] = '0';
  	buf[1] = '
  ';
  	buf[2] = 0x00;
  	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
  }
  
  static ssize_t write_enabled_file_bool(struct file *file,
  	       const char __user *user_buf, size_t count, loff_t *ppos)
  {
  	char buf[32];
  	int buf_size;
  
  	buf_size = min(count, (sizeof(buf)-1));
  	if (copy_from_user(buf, user_buf, buf_size))
  		return -EFAULT;
  
  	switch (buf[0]) {
  	case 'y':
  	case 'Y':
  	case '1':
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1451
  		arm_all_kprobes();
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1452
1453
1454
1455
  		break;
  	case 'n':
  	case 'N':
  	case '0':
e579abeb5   Masami Hiramatsu   kprobes: rename k...
1456
  		disarm_all_kprobes();
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1457
1458
1459
1460
1461
  		break;
  	}
  
  	return count;
  }
828c09509   Alexey Dobriyan   const: constify r...
1462
  static const struct file_operations fops_kp = {
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1463
1464
1465
  	.read =         read_enabled_file_bool,
  	.write =        write_enabled_file_bool,
  };
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1466
1467
1468
  static int __kprobes debugfs_kprobe_init(void)
  {
  	struct dentry *dir, *file;
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1469
  	unsigned int value = 1;
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1470
1471
1472
1473
  
  	dir = debugfs_create_dir("kprobes", NULL);
  	if (!dir)
  		return -ENOMEM;
e38697929   Randy Dunlap   kprobes: fix spar...
1474
  	file = debugfs_create_file("list", 0444, dir, NULL,
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1475
1476
1477
1478
1479
  				&debugfs_kprobes_operations);
  	if (!file) {
  		debugfs_remove(dir);
  		return -ENOMEM;
  	}
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1480
1481
1482
1483
1484
1485
  	file = debugfs_create_file("enabled", 0600, dir,
  					&value, &fops_kp);
  	if (!file) {
  		debugfs_remove(dir);
  		return -ENOMEM;
  	}
346fd59ba   Srinivasa Ds   [PATCH] kprobes: ...
1486
1487
1488
1489
1490
1491
1492
  	return 0;
  }
  
  late_initcall(debugfs_kprobe_init);
  #endif /* CONFIG_DEBUG_FS */
  
  module_init(init_kprobes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493

99081ab55   Masami Hiramatsu   kprobes: move EXP...
1494
  /* defined in arch/.../kernel/kprobes.c */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
  EXPORT_SYMBOL_GPL(jprobe_return);