xref: /openbmc/linux/kernel/kprobes.c (revision 4a296e07c3a410c09b9155da4c2fa84a07964f38)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  Kernel Probes (KProbes)
31da177e4SLinus Torvalds  *  kernel/kprobes.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
61da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
71da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
81da177e4SLinus Torvalds  * (at your option) any later version.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * This program is distributed in the hope that it will be useful,
111da177e4SLinus Torvalds  * but WITHOUT ANY WARRANTY; without even the implied warranty of
121da177e4SLinus Torvalds  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131da177e4SLinus Torvalds  * GNU General Public License for more details.
141da177e4SLinus Torvalds  *
151da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License
161da177e4SLinus Torvalds  * along with this program; if not, write to the Free Software
171da177e4SLinus Torvalds  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
181da177e4SLinus Torvalds  *
191da177e4SLinus Torvalds  * Copyright (C) IBM Corporation, 2002, 2004
201da177e4SLinus Torvalds  *
211da177e4SLinus Torvalds  * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
221da177e4SLinus Torvalds  *		Probes initial implementation (includes suggestions from
231da177e4SLinus Torvalds  *		Rusty Russell).
241da177e4SLinus Torvalds  * 2004-Aug	Updated by Prasanna S Panchamukhi <prasanna@in.ibm.com> with
251da177e4SLinus Torvalds  *		hlists and exceptions notifier as suggested by Andi Kleen.
261da177e4SLinus Torvalds  * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
271da177e4SLinus Torvalds  *		interface to access function arguments.
281da177e4SLinus Torvalds  * 2004-Sep	Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
291da177e4SLinus Torvalds  *		exceptions notifier to be first on the priority list.
30b94cce92SHien Nguyen  * 2005-May	Hien Nguyen <hien@us.ibm.com>, Jim Keniston
31b94cce92SHien Nguyen  *		<jkenisto@us.ibm.com> and Prasanna S Panchamukhi
32b94cce92SHien Nguyen  *		<prasanna@in.ibm.com> added function-return probes.
331da177e4SLinus Torvalds  */
341da177e4SLinus Torvalds #include <linux/kprobes.h>
351da177e4SLinus Torvalds #include <linux/hash.h>
361da177e4SLinus Torvalds #include <linux/init.h>
374e57b681STim Schmielau #include <linux/slab.h>
38e3869792SRandy Dunlap #include <linux/stddef.h>
391da177e4SLinus Torvalds #include <linux/module.h>
409ec4b1f3SAnanth N Mavinakayanahalli #include <linux/moduleloader.h>
413a872d89SAnanth N Mavinakayanahalli #include <linux/kallsyms.h>
42b4c6c34aSMasami Hiramatsu #include <linux/freezer.h>
43346fd59bSSrinivasa Ds #include <linux/seq_file.h>
44346fd59bSSrinivasa Ds #include <linux/debugfs.h>
451eeb66a1SChristoph Hellwig #include <linux/kdebug.h>
46bf8f6e5bSAnanth N Mavinakayanahalli 
47d0aaff97SPrasanna S Panchamukhi #include <asm-generic/sections.h>
481da177e4SLinus Torvalds #include <asm/cacheflush.h>
491da177e4SLinus Torvalds #include <asm/errno.h>
50bf8f6e5bSAnanth N Mavinakayanahalli #include <asm/uaccess.h>
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds #define KPROBE_HASH_BITS 6
531da177e4SLinus Torvalds #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
541da177e4SLinus Torvalds 
553a872d89SAnanth N Mavinakayanahalli 
563a872d89SAnanth N Mavinakayanahalli /*
573a872d89SAnanth N Mavinakayanahalli  * Some oddball architectures like 64bit powerpc have function descriptors
583a872d89SAnanth N Mavinakayanahalli  * so this must be overridable.
593a872d89SAnanth N Mavinakayanahalli  */
603a872d89SAnanth N Mavinakayanahalli #ifndef kprobe_lookup_name
613a872d89SAnanth N Mavinakayanahalli #define kprobe_lookup_name(name, addr) \
623a872d89SAnanth N Mavinakayanahalli 	addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
633a872d89SAnanth N Mavinakayanahalli #endif
643a872d89SAnanth N Mavinakayanahalli 
651da177e4SLinus Torvalds static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
66b94cce92SHien Nguyen static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
671da177e4SLinus Torvalds 
68bf8f6e5bSAnanth N Mavinakayanahalli /* NOTE: change this value only with kprobe_mutex held */
69bf8f6e5bSAnanth N Mavinakayanahalli static bool kprobe_enabled;
70bf8f6e5bSAnanth N Mavinakayanahalli 
717a7d1cf9SIngo Molnar DEFINE_MUTEX(kprobe_mutex);		/* Protects kprobe_table */
723516a460SAnanth N Mavinakayanahalli DEFINE_SPINLOCK(kretprobe_lock);	/* Protects kretprobe_inst_table */
73e6584523SAnanth N Mavinakayanahalli static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
741da177e4SLinus Torvalds 
753d8d996eSSrinivasa Ds /*
763d8d996eSSrinivasa Ds  * Normally, functions that we'd want to prohibit kprobes in, are marked
773d8d996eSSrinivasa Ds  * __kprobes. But, there are cases where such functions already belong to
783d8d996eSSrinivasa Ds  * a different section (__sched for preempt_schedule)
793d8d996eSSrinivasa Ds  *
803d8d996eSSrinivasa Ds  * For such cases, we now have a blacklist
813d8d996eSSrinivasa Ds  */
823d8d996eSSrinivasa Ds struct kprobe_blackpoint kprobe_blacklist[] = {
833d8d996eSSrinivasa Ds 	{"preempt_schedule",},
843d8d996eSSrinivasa Ds 	{NULL}    /* Terminator */
853d8d996eSSrinivasa Ds };
863d8d996eSSrinivasa Ds 
872d14e39dSAnil S Keshavamurthy #ifdef __ARCH_WANT_KPROBES_INSN_SLOT
889ec4b1f3SAnanth N Mavinakayanahalli /*
899ec4b1f3SAnanth N Mavinakayanahalli  * kprobe->ainsn.insn points to the copy of the instruction to be
909ec4b1f3SAnanth N Mavinakayanahalli  * single-stepped. x86_64, POWER4 and above have no-exec support and
919ec4b1f3SAnanth N Mavinakayanahalli  * stepping on the instruction on a vmalloced/kmalloced/data page
929ec4b1f3SAnanth N Mavinakayanahalli  * is a recipe for disaster
939ec4b1f3SAnanth N Mavinakayanahalli  */
949ec4b1f3SAnanth N Mavinakayanahalli #define INSNS_PER_PAGE	(PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
959ec4b1f3SAnanth N Mavinakayanahalli 
969ec4b1f3SAnanth N Mavinakayanahalli struct kprobe_insn_page {
979ec4b1f3SAnanth N Mavinakayanahalli 	struct hlist_node hlist;
989ec4b1f3SAnanth N Mavinakayanahalli 	kprobe_opcode_t *insns;		/* Page of instruction slots */
999ec4b1f3SAnanth N Mavinakayanahalli 	char slot_used[INSNS_PER_PAGE];
1009ec4b1f3SAnanth N Mavinakayanahalli 	int nused;
101b4c6c34aSMasami Hiramatsu 	int ngarbage;
1029ec4b1f3SAnanth N Mavinakayanahalli };
1039ec4b1f3SAnanth N Mavinakayanahalli 
104ab40c5c6SMasami Hiramatsu enum kprobe_slot_state {
105ab40c5c6SMasami Hiramatsu 	SLOT_CLEAN = 0,
106ab40c5c6SMasami Hiramatsu 	SLOT_DIRTY = 1,
107ab40c5c6SMasami Hiramatsu 	SLOT_USED = 2,
108ab40c5c6SMasami Hiramatsu };
109ab40c5c6SMasami Hiramatsu 
1109ec4b1f3SAnanth N Mavinakayanahalli static struct hlist_head kprobe_insn_pages;
111b4c6c34aSMasami Hiramatsu static int kprobe_garbage_slots;
112b4c6c34aSMasami Hiramatsu static int collect_garbage_slots(void);
113b4c6c34aSMasami Hiramatsu 
114b4c6c34aSMasami Hiramatsu static int __kprobes check_safety(void)
115b4c6c34aSMasami Hiramatsu {
116b4c6c34aSMasami Hiramatsu 	int ret = 0;
117b4c6c34aSMasami Hiramatsu #if defined(CONFIG_PREEMPT) && defined(CONFIG_PM)
118b4c6c34aSMasami Hiramatsu 	ret = freeze_processes();
119b4c6c34aSMasami Hiramatsu 	if (ret == 0) {
120b4c6c34aSMasami Hiramatsu 		struct task_struct *p, *q;
121b4c6c34aSMasami Hiramatsu 		do_each_thread(p, q) {
122b4c6c34aSMasami Hiramatsu 			if (p != current && p->state == TASK_RUNNING &&
123b4c6c34aSMasami Hiramatsu 			    p->pid != 0) {
124b4c6c34aSMasami Hiramatsu 				printk("Check failed: %s is running\n",p->comm);
125b4c6c34aSMasami Hiramatsu 				ret = -1;
126b4c6c34aSMasami Hiramatsu 				goto loop_end;
127b4c6c34aSMasami Hiramatsu 			}
128b4c6c34aSMasami Hiramatsu 		} while_each_thread(p, q);
129b4c6c34aSMasami Hiramatsu 	}
130b4c6c34aSMasami Hiramatsu loop_end:
131b4c6c34aSMasami Hiramatsu 	thaw_processes();
132b4c6c34aSMasami Hiramatsu #else
133b4c6c34aSMasami Hiramatsu 	synchronize_sched();
134b4c6c34aSMasami Hiramatsu #endif
135b4c6c34aSMasami Hiramatsu 	return ret;
136b4c6c34aSMasami Hiramatsu }
1379ec4b1f3SAnanth N Mavinakayanahalli 
1389ec4b1f3SAnanth N Mavinakayanahalli /**
1399ec4b1f3SAnanth N Mavinakayanahalli  * get_insn_slot() - Find a slot on an executable page for an instruction.
1409ec4b1f3SAnanth N Mavinakayanahalli  * We allocate an executable page if there's no room on existing ones.
1419ec4b1f3SAnanth N Mavinakayanahalli  */
142d0aaff97SPrasanna S Panchamukhi kprobe_opcode_t __kprobes *get_insn_slot(void)
1439ec4b1f3SAnanth N Mavinakayanahalli {
1449ec4b1f3SAnanth N Mavinakayanahalli 	struct kprobe_insn_page *kip;
1459ec4b1f3SAnanth N Mavinakayanahalli 	struct hlist_node *pos;
1469ec4b1f3SAnanth N Mavinakayanahalli 
147b4c6c34aSMasami Hiramatsu  retry:
148b0bb5016SChristoph Hellwig 	hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) {
1499ec4b1f3SAnanth N Mavinakayanahalli 		if (kip->nused < INSNS_PER_PAGE) {
1509ec4b1f3SAnanth N Mavinakayanahalli 			int i;
1519ec4b1f3SAnanth N Mavinakayanahalli 			for (i = 0; i < INSNS_PER_PAGE; i++) {
152ab40c5c6SMasami Hiramatsu 				if (kip->slot_used[i] == SLOT_CLEAN) {
153ab40c5c6SMasami Hiramatsu 					kip->slot_used[i] = SLOT_USED;
1549ec4b1f3SAnanth N Mavinakayanahalli 					kip->nused++;
1559ec4b1f3SAnanth N Mavinakayanahalli 					return kip->insns + (i * MAX_INSN_SIZE);
1569ec4b1f3SAnanth N Mavinakayanahalli 				}
1579ec4b1f3SAnanth N Mavinakayanahalli 			}
1589ec4b1f3SAnanth N Mavinakayanahalli 			/* Surprise!  No unused slots.  Fix kip->nused. */
1599ec4b1f3SAnanth N Mavinakayanahalli 			kip->nused = INSNS_PER_PAGE;
1609ec4b1f3SAnanth N Mavinakayanahalli 		}
1619ec4b1f3SAnanth N Mavinakayanahalli 	}
1629ec4b1f3SAnanth N Mavinakayanahalli 
163b4c6c34aSMasami Hiramatsu 	/* If there are any garbage slots, collect it and try again. */
164b4c6c34aSMasami Hiramatsu 	if (kprobe_garbage_slots && collect_garbage_slots() == 0) {
165b4c6c34aSMasami Hiramatsu 		goto retry;
166b4c6c34aSMasami Hiramatsu 	}
1679ec4b1f3SAnanth N Mavinakayanahalli 	/* All out of space.  Need to allocate a new page. Use slot 0. */
1689ec4b1f3SAnanth N Mavinakayanahalli 	kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
1696f716acdSChristoph Hellwig 	if (!kip)
1709ec4b1f3SAnanth N Mavinakayanahalli 		return NULL;
1719ec4b1f3SAnanth N Mavinakayanahalli 
1729ec4b1f3SAnanth N Mavinakayanahalli 	/*
1739ec4b1f3SAnanth N Mavinakayanahalli 	 * Use module_alloc so this page is within +/- 2GB of where the
1749ec4b1f3SAnanth N Mavinakayanahalli 	 * kernel image and loaded module images reside. This is required
1759ec4b1f3SAnanth N Mavinakayanahalli 	 * so x86_64 can correctly handle the %rip-relative fixups.
1769ec4b1f3SAnanth N Mavinakayanahalli 	 */
1779ec4b1f3SAnanth N Mavinakayanahalli 	kip->insns = module_alloc(PAGE_SIZE);
1789ec4b1f3SAnanth N Mavinakayanahalli 	if (!kip->insns) {
1799ec4b1f3SAnanth N Mavinakayanahalli 		kfree(kip);
1809ec4b1f3SAnanth N Mavinakayanahalli 		return NULL;
1819ec4b1f3SAnanth N Mavinakayanahalli 	}
1829ec4b1f3SAnanth N Mavinakayanahalli 	INIT_HLIST_NODE(&kip->hlist);
1839ec4b1f3SAnanth N Mavinakayanahalli 	hlist_add_head(&kip->hlist, &kprobe_insn_pages);
184ab40c5c6SMasami Hiramatsu 	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
185ab40c5c6SMasami Hiramatsu 	kip->slot_used[0] = SLOT_USED;
1869ec4b1f3SAnanth N Mavinakayanahalli 	kip->nused = 1;
187b4c6c34aSMasami Hiramatsu 	kip->ngarbage = 0;
1889ec4b1f3SAnanth N Mavinakayanahalli 	return kip->insns;
1899ec4b1f3SAnanth N Mavinakayanahalli }
1909ec4b1f3SAnanth N Mavinakayanahalli 
191b4c6c34aSMasami Hiramatsu /* Return 1 if all garbages are collected, otherwise 0. */
192b4c6c34aSMasami Hiramatsu static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
1939ec4b1f3SAnanth N Mavinakayanahalli {
194ab40c5c6SMasami Hiramatsu 	kip->slot_used[idx] = SLOT_CLEAN;
1959ec4b1f3SAnanth N Mavinakayanahalli 	kip->nused--;
1969ec4b1f3SAnanth N Mavinakayanahalli 	if (kip->nused == 0) {
1979ec4b1f3SAnanth N Mavinakayanahalli 		/*
1989ec4b1f3SAnanth N Mavinakayanahalli 		 * Page is no longer in use.  Free it unless
1999ec4b1f3SAnanth N Mavinakayanahalli 		 * it's the last one.  We keep the last one
2009ec4b1f3SAnanth N Mavinakayanahalli 		 * so as not to have to set it up again the
2019ec4b1f3SAnanth N Mavinakayanahalli 		 * next time somebody inserts a probe.
2029ec4b1f3SAnanth N Mavinakayanahalli 		 */
2039ec4b1f3SAnanth N Mavinakayanahalli 		hlist_del(&kip->hlist);
2049ec4b1f3SAnanth N Mavinakayanahalli 		if (hlist_empty(&kprobe_insn_pages)) {
2059ec4b1f3SAnanth N Mavinakayanahalli 			INIT_HLIST_NODE(&kip->hlist);
2069ec4b1f3SAnanth N Mavinakayanahalli 			hlist_add_head(&kip->hlist,
2079ec4b1f3SAnanth N Mavinakayanahalli 				       &kprobe_insn_pages);
2089ec4b1f3SAnanth N Mavinakayanahalli 		} else {
2099ec4b1f3SAnanth N Mavinakayanahalli 			module_free(NULL, kip->insns);
2109ec4b1f3SAnanth N Mavinakayanahalli 			kfree(kip);
2119ec4b1f3SAnanth N Mavinakayanahalli 		}
212b4c6c34aSMasami Hiramatsu 		return 1;
2139ec4b1f3SAnanth N Mavinakayanahalli 	}
214b4c6c34aSMasami Hiramatsu 	return 0;
2159ec4b1f3SAnanth N Mavinakayanahalli }
216b4c6c34aSMasami Hiramatsu 
217b4c6c34aSMasami Hiramatsu static int __kprobes collect_garbage_slots(void)
218b4c6c34aSMasami Hiramatsu {
219b4c6c34aSMasami Hiramatsu 	struct kprobe_insn_page *kip;
220b4c6c34aSMasami Hiramatsu 	struct hlist_node *pos, *next;
221b4c6c34aSMasami Hiramatsu 
222b4c6c34aSMasami Hiramatsu 	/* Ensure no-one is preepmted on the garbages */
223b4c6c34aSMasami Hiramatsu 	if (check_safety() != 0)
224b4c6c34aSMasami Hiramatsu 		return -EAGAIN;
225b4c6c34aSMasami Hiramatsu 
226b0bb5016SChristoph Hellwig 	hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) {
227b4c6c34aSMasami Hiramatsu 		int i;
228b4c6c34aSMasami Hiramatsu 		if (kip->ngarbage == 0)
229b4c6c34aSMasami Hiramatsu 			continue;
230b4c6c34aSMasami Hiramatsu 		kip->ngarbage = 0;	/* we will collect all garbages */
231b4c6c34aSMasami Hiramatsu 		for (i = 0; i < INSNS_PER_PAGE; i++) {
232ab40c5c6SMasami Hiramatsu 			if (kip->slot_used[i] == SLOT_DIRTY &&
233b4c6c34aSMasami Hiramatsu 			    collect_one_slot(kip, i))
234b4c6c34aSMasami Hiramatsu 				break;
235b4c6c34aSMasami Hiramatsu 		}
236b4c6c34aSMasami Hiramatsu 	}
237b4c6c34aSMasami Hiramatsu 	kprobe_garbage_slots = 0;
238b4c6c34aSMasami Hiramatsu 	return 0;
239b4c6c34aSMasami Hiramatsu }
240b4c6c34aSMasami Hiramatsu 
241b4c6c34aSMasami Hiramatsu void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
242b4c6c34aSMasami Hiramatsu {
243b4c6c34aSMasami Hiramatsu 	struct kprobe_insn_page *kip;
244b4c6c34aSMasami Hiramatsu 	struct hlist_node *pos;
245b4c6c34aSMasami Hiramatsu 
246b0bb5016SChristoph Hellwig 	hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) {
247b4c6c34aSMasami Hiramatsu 		if (kip->insns <= slot &&
248b4c6c34aSMasami Hiramatsu 		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
249b4c6c34aSMasami Hiramatsu 			int i = (slot - kip->insns) / MAX_INSN_SIZE;
250b4c6c34aSMasami Hiramatsu 			if (dirty) {
251ab40c5c6SMasami Hiramatsu 				kip->slot_used[i] = SLOT_DIRTY;
252b4c6c34aSMasami Hiramatsu 				kip->ngarbage++;
253b4c6c34aSMasami Hiramatsu 			} else {
254b4c6c34aSMasami Hiramatsu 				collect_one_slot(kip, i);
255b4c6c34aSMasami Hiramatsu 			}
256b4c6c34aSMasami Hiramatsu 			break;
257b4c6c34aSMasami Hiramatsu 		}
258b4c6c34aSMasami Hiramatsu 	}
2596f716acdSChristoph Hellwig 
2606f716acdSChristoph Hellwig 	if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)
261b4c6c34aSMasami Hiramatsu 		collect_garbage_slots();
2629ec4b1f3SAnanth N Mavinakayanahalli }
2632d14e39dSAnil S Keshavamurthy #endif
2649ec4b1f3SAnanth N Mavinakayanahalli 
265e6584523SAnanth N Mavinakayanahalli /* We have preemption disabled.. so it is safe to use __ versions */
266e6584523SAnanth N Mavinakayanahalli static inline void set_kprobe_instance(struct kprobe *kp)
267e6584523SAnanth N Mavinakayanahalli {
268e6584523SAnanth N Mavinakayanahalli 	__get_cpu_var(kprobe_instance) = kp;
269e6584523SAnanth N Mavinakayanahalli }
270e6584523SAnanth N Mavinakayanahalli 
271e6584523SAnanth N Mavinakayanahalli static inline void reset_kprobe_instance(void)
272e6584523SAnanth N Mavinakayanahalli {
273e6584523SAnanth N Mavinakayanahalli 	__get_cpu_var(kprobe_instance) = NULL;
274e6584523SAnanth N Mavinakayanahalli }
275e6584523SAnanth N Mavinakayanahalli 
2763516a460SAnanth N Mavinakayanahalli /*
2773516a460SAnanth N Mavinakayanahalli  * This routine is called either:
27849a2a1b8SAnil S Keshavamurthy  * 	- under the kprobe_mutex - during kprobe_[un]register()
2793516a460SAnanth N Mavinakayanahalli  * 				OR
280d217d545SAnanth N Mavinakayanahalli  * 	- with preemption disabled - from arch/xxx/kernel/kprobes.c
2813516a460SAnanth N Mavinakayanahalli  */
282d0aaff97SPrasanna S Panchamukhi struct kprobe __kprobes *get_kprobe(void *addr)
2831da177e4SLinus Torvalds {
2841da177e4SLinus Torvalds 	struct hlist_head *head;
2851da177e4SLinus Torvalds 	struct hlist_node *node;
2863516a460SAnanth N Mavinakayanahalli 	struct kprobe *p;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
2893516a460SAnanth N Mavinakayanahalli 	hlist_for_each_entry_rcu(p, node, head, hlist) {
2901da177e4SLinus Torvalds 		if (p->addr == addr)
2911da177e4SLinus Torvalds 			return p;
2921da177e4SLinus Torvalds 	}
2931da177e4SLinus Torvalds 	return NULL;
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds 
29664f562c6SAnanth N Mavinakayanahalli /*
29764f562c6SAnanth N Mavinakayanahalli  * Aggregate handlers for multiple kprobes support - these handlers
29864f562c6SAnanth N Mavinakayanahalli  * take care of invoking the individual kprobe handlers on p->list
29964f562c6SAnanth N Mavinakayanahalli  */
300d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
30164f562c6SAnanth N Mavinakayanahalli {
30264f562c6SAnanth N Mavinakayanahalli 	struct kprobe *kp;
30364f562c6SAnanth N Mavinakayanahalli 
3043516a460SAnanth N Mavinakayanahalli 	list_for_each_entry_rcu(kp, &p->list, list) {
30564f562c6SAnanth N Mavinakayanahalli 		if (kp->pre_handler) {
306e6584523SAnanth N Mavinakayanahalli 			set_kprobe_instance(kp);
3078b0914eaSPrasanna S Panchamukhi 			if (kp->pre_handler(kp, regs))
3088b0914eaSPrasanna S Panchamukhi 				return 1;
30964f562c6SAnanth N Mavinakayanahalli 		}
310e6584523SAnanth N Mavinakayanahalli 		reset_kprobe_instance();
31164f562c6SAnanth N Mavinakayanahalli 	}
31264f562c6SAnanth N Mavinakayanahalli 	return 0;
31364f562c6SAnanth N Mavinakayanahalli }
31464f562c6SAnanth N Mavinakayanahalli 
315d0aaff97SPrasanna S Panchamukhi static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
31664f562c6SAnanth N Mavinakayanahalli 					unsigned long flags)
31764f562c6SAnanth N Mavinakayanahalli {
31864f562c6SAnanth N Mavinakayanahalli 	struct kprobe *kp;
31964f562c6SAnanth N Mavinakayanahalli 
3203516a460SAnanth N Mavinakayanahalli 	list_for_each_entry_rcu(kp, &p->list, list) {
32164f562c6SAnanth N Mavinakayanahalli 		if (kp->post_handler) {
322e6584523SAnanth N Mavinakayanahalli 			set_kprobe_instance(kp);
32364f562c6SAnanth N Mavinakayanahalli 			kp->post_handler(kp, regs, flags);
324e6584523SAnanth N Mavinakayanahalli 			reset_kprobe_instance();
32564f562c6SAnanth N Mavinakayanahalli 		}
32664f562c6SAnanth N Mavinakayanahalli 	}
32764f562c6SAnanth N Mavinakayanahalli }
32864f562c6SAnanth N Mavinakayanahalli 
329d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
330b94cce92SHien Nguyen 					int trapnr)
33164f562c6SAnanth N Mavinakayanahalli {
332e6584523SAnanth N Mavinakayanahalli 	struct kprobe *cur = __get_cpu_var(kprobe_instance);
333e6584523SAnanth N Mavinakayanahalli 
33464f562c6SAnanth N Mavinakayanahalli 	/*
33564f562c6SAnanth N Mavinakayanahalli 	 * if we faulted "during" the execution of a user specified
33664f562c6SAnanth N Mavinakayanahalli 	 * probe handler, invoke just that probe's fault handler
33764f562c6SAnanth N Mavinakayanahalli 	 */
338e6584523SAnanth N Mavinakayanahalli 	if (cur && cur->fault_handler) {
339e6584523SAnanth N Mavinakayanahalli 		if (cur->fault_handler(cur, regs, trapnr))
34064f562c6SAnanth N Mavinakayanahalli 			return 1;
34164f562c6SAnanth N Mavinakayanahalli 	}
34264f562c6SAnanth N Mavinakayanahalli 	return 0;
34364f562c6SAnanth N Mavinakayanahalli }
34464f562c6SAnanth N Mavinakayanahalli 
345d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
3468b0914eaSPrasanna S Panchamukhi {
347e6584523SAnanth N Mavinakayanahalli 	struct kprobe *cur = __get_cpu_var(kprobe_instance);
348e6584523SAnanth N Mavinakayanahalli 	int ret = 0;
349e6584523SAnanth N Mavinakayanahalli 
350e6584523SAnanth N Mavinakayanahalli 	if (cur && cur->break_handler) {
351e6584523SAnanth N Mavinakayanahalli 		if (cur->break_handler(cur, regs))
352e6584523SAnanth N Mavinakayanahalli 			ret = 1;
3538b0914eaSPrasanna S Panchamukhi 	}
354e6584523SAnanth N Mavinakayanahalli 	reset_kprobe_instance();
355e6584523SAnanth N Mavinakayanahalli 	return ret;
3568b0914eaSPrasanna S Panchamukhi }
3578b0914eaSPrasanna S Panchamukhi 
358bf8d5c52SKeshavamurthy Anil S /* Walks the list and increments nmissed count for multiprobe case */
359bf8d5c52SKeshavamurthy Anil S void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
360bf8d5c52SKeshavamurthy Anil S {
361bf8d5c52SKeshavamurthy Anil S 	struct kprobe *kp;
362bf8d5c52SKeshavamurthy Anil S 	if (p->pre_handler != aggr_pre_handler) {
363bf8d5c52SKeshavamurthy Anil S 		p->nmissed++;
364bf8d5c52SKeshavamurthy Anil S 	} else {
365bf8d5c52SKeshavamurthy Anil S 		list_for_each_entry_rcu(kp, &p->list, list)
366bf8d5c52SKeshavamurthy Anil S 			kp->nmissed++;
367bf8d5c52SKeshavamurthy Anil S 	}
368bf8d5c52SKeshavamurthy Anil S 	return;
369bf8d5c52SKeshavamurthy Anil S }
370bf8d5c52SKeshavamurthy Anil S 
3713516a460SAnanth N Mavinakayanahalli /* Called with kretprobe_lock held */
37299219a3fSbibo,mao void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
37399219a3fSbibo,mao 				struct hlist_head *head)
374b94cce92SHien Nguyen {
375b94cce92SHien Nguyen 	/* remove rp inst off the rprobe_inst_table */
376b94cce92SHien Nguyen 	hlist_del(&ri->hlist);
377b94cce92SHien Nguyen 	if (ri->rp) {
378b94cce92SHien Nguyen 		/* remove rp inst off the used list */
379b94cce92SHien Nguyen 		hlist_del(&ri->uflist);
380b94cce92SHien Nguyen 		/* put rp inst back onto the free list */
381b94cce92SHien Nguyen 		INIT_HLIST_NODE(&ri->uflist);
382b94cce92SHien Nguyen 		hlist_add_head(&ri->uflist, &ri->rp->free_instances);
383b94cce92SHien Nguyen 	} else
384b94cce92SHien Nguyen 		/* Unregistering */
38599219a3fSbibo,mao 		hlist_add_head(&ri->hlist, head);
386b94cce92SHien Nguyen }
387b94cce92SHien Nguyen 
388d0aaff97SPrasanna S Panchamukhi struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
389b94cce92SHien Nguyen {
390b94cce92SHien Nguyen 	return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
391b94cce92SHien Nguyen }
392b94cce92SHien Nguyen 
393b94cce92SHien Nguyen /*
394c6fd91f0Sbibo mao  * This function is called from finish_task_switch when task tk becomes dead,
395c6fd91f0Sbibo mao  * so that we can recycle any function-return probe instances associated
396c6fd91f0Sbibo mao  * with this task. These left over instances represent probed functions
397c6fd91f0Sbibo mao  * that have been called but will never return.
398b94cce92SHien Nguyen  */
399d0aaff97SPrasanna S Panchamukhi void __kprobes kprobe_flush_task(struct task_struct *tk)
400b94cce92SHien Nguyen {
401802eae7cSRusty Lynch 	struct kretprobe_instance *ri;
40299219a3fSbibo,mao 	struct hlist_head *head, empty_rp;
403802eae7cSRusty Lynch 	struct hlist_node *node, *tmp;
4040aa55e4dSHien Nguyen 	unsigned long flags = 0;
405802eae7cSRusty Lynch 
40699219a3fSbibo,mao 	INIT_HLIST_HEAD(&empty_rp);
4073516a460SAnanth N Mavinakayanahalli 	spin_lock_irqsave(&kretprobe_lock, flags);
408c6fd91f0Sbibo mao 	head = kretprobe_inst_table_head(tk);
409802eae7cSRusty Lynch 	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
410802eae7cSRusty Lynch 		if (ri->task == tk)
41199219a3fSbibo,mao 			recycle_rp_inst(ri, &empty_rp);
412802eae7cSRusty Lynch 	}
4133516a460SAnanth N Mavinakayanahalli 	spin_unlock_irqrestore(&kretprobe_lock, flags);
41499219a3fSbibo,mao 
41599219a3fSbibo,mao 	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
41699219a3fSbibo,mao 		hlist_del(&ri->hlist);
41799219a3fSbibo,mao 		kfree(ri);
41899219a3fSbibo,mao 	}
419b94cce92SHien Nguyen }
420b94cce92SHien Nguyen 
421b94cce92SHien Nguyen static inline void free_rp_inst(struct kretprobe *rp)
422b94cce92SHien Nguyen {
423b94cce92SHien Nguyen 	struct kretprobe_instance *ri;
4244c4308cbSChristoph Hellwig 	struct hlist_node *pos, *next;
4254c4308cbSChristoph Hellwig 
4264c4308cbSChristoph Hellwig 	hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) {
427b94cce92SHien Nguyen 		hlist_del(&ri->uflist);
428b94cce92SHien Nguyen 		kfree(ri);
429b94cce92SHien Nguyen 	}
430b94cce92SHien Nguyen }
431b94cce92SHien Nguyen 
432*4a296e07SMasami Hiramatsu static void __kprobes cleanup_rp_inst(struct kretprobe *rp)
433*4a296e07SMasami Hiramatsu {
434*4a296e07SMasami Hiramatsu 	unsigned long flags;
435*4a296e07SMasami Hiramatsu 	struct kretprobe_instance *ri;
436*4a296e07SMasami Hiramatsu 	struct hlist_node *pos, *next;
437*4a296e07SMasami Hiramatsu 	/* No race here */
438*4a296e07SMasami Hiramatsu 	spin_lock_irqsave(&kretprobe_lock, flags);
439*4a296e07SMasami Hiramatsu 	hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
440*4a296e07SMasami Hiramatsu 		ri->rp = NULL;
441*4a296e07SMasami Hiramatsu 		hlist_del(&ri->uflist);
442*4a296e07SMasami Hiramatsu 	}
443*4a296e07SMasami Hiramatsu 	spin_unlock_irqrestore(&kretprobe_lock, flags);
444*4a296e07SMasami Hiramatsu 	free_rp_inst(rp);
445*4a296e07SMasami Hiramatsu }
446*4a296e07SMasami Hiramatsu 
44764f562c6SAnanth N Mavinakayanahalli /*
4488b0914eaSPrasanna S Panchamukhi  * Keep all fields in the kprobe consistent
4498b0914eaSPrasanna S Panchamukhi  */
4508b0914eaSPrasanna S Panchamukhi static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
4518b0914eaSPrasanna S Panchamukhi {
4528b0914eaSPrasanna S Panchamukhi 	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
4538b0914eaSPrasanna S Panchamukhi 	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
4548b0914eaSPrasanna S Panchamukhi }
4558b0914eaSPrasanna S Panchamukhi 
4568b0914eaSPrasanna S Panchamukhi /*
4578b0914eaSPrasanna S Panchamukhi * Add the new probe to old_p->list. Fail if this is the
4588b0914eaSPrasanna S Panchamukhi * second jprobe at the address - two jprobes can't coexist
4598b0914eaSPrasanna S Panchamukhi */
460d0aaff97SPrasanna S Panchamukhi static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
4618b0914eaSPrasanna S Panchamukhi {
4628b0914eaSPrasanna S Panchamukhi 	if (p->break_handler) {
46336721656Smao, bibo 		if (old_p->break_handler)
4648b0914eaSPrasanna S Panchamukhi 			return -EEXIST;
4653516a460SAnanth N Mavinakayanahalli 		list_add_tail_rcu(&p->list, &old_p->list);
46636721656Smao, bibo 		old_p->break_handler = aggr_break_handler;
4678b0914eaSPrasanna S Panchamukhi 	} else
4683516a460SAnanth N Mavinakayanahalli 		list_add_rcu(&p->list, &old_p->list);
46936721656Smao, bibo 	if (p->post_handler && !old_p->post_handler)
47036721656Smao, bibo 		old_p->post_handler = aggr_post_handler;
4718b0914eaSPrasanna S Panchamukhi 	return 0;
4728b0914eaSPrasanna S Panchamukhi }
4738b0914eaSPrasanna S Panchamukhi 
4748b0914eaSPrasanna S Panchamukhi /*
47564f562c6SAnanth N Mavinakayanahalli  * Fill in the required fields of the "manager kprobe". Replace the
47664f562c6SAnanth N Mavinakayanahalli  * earlier kprobe in the hlist with the manager kprobe
47764f562c6SAnanth N Mavinakayanahalli  */
47864f562c6SAnanth N Mavinakayanahalli static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
47964f562c6SAnanth N Mavinakayanahalli {
4808b0914eaSPrasanna S Panchamukhi 	copy_kprobe(p, ap);
481a9ad965eSbibo, mao 	flush_insn_slot(ap);
48264f562c6SAnanth N Mavinakayanahalli 	ap->addr = p->addr;
48364f562c6SAnanth N Mavinakayanahalli 	ap->pre_handler = aggr_pre_handler;
48464f562c6SAnanth N Mavinakayanahalli 	ap->fault_handler = aggr_fault_handler;
48536721656Smao, bibo 	if (p->post_handler)
48636721656Smao, bibo 		ap->post_handler = aggr_post_handler;
48736721656Smao, bibo 	if (p->break_handler)
4888b0914eaSPrasanna S Panchamukhi 		ap->break_handler = aggr_break_handler;
48964f562c6SAnanth N Mavinakayanahalli 
49064f562c6SAnanth N Mavinakayanahalli 	INIT_LIST_HEAD(&ap->list);
4913516a460SAnanth N Mavinakayanahalli 	list_add_rcu(&p->list, &ap->list);
49264f562c6SAnanth N Mavinakayanahalli 
493adad0f33SKeshavamurthy Anil S 	hlist_replace_rcu(&p->hlist, &ap->hlist);
49464f562c6SAnanth N Mavinakayanahalli }
49564f562c6SAnanth N Mavinakayanahalli 
49664f562c6SAnanth N Mavinakayanahalli /*
49764f562c6SAnanth N Mavinakayanahalli  * This is the second or subsequent kprobe at the address - handle
49864f562c6SAnanth N Mavinakayanahalli  * the intricacies
49964f562c6SAnanth N Mavinakayanahalli  */
500d0aaff97SPrasanna S Panchamukhi static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
501d0aaff97SPrasanna S Panchamukhi 					  struct kprobe *p)
50264f562c6SAnanth N Mavinakayanahalli {
50364f562c6SAnanth N Mavinakayanahalli 	int ret = 0;
50464f562c6SAnanth N Mavinakayanahalli 	struct kprobe *ap;
50564f562c6SAnanth N Mavinakayanahalli 
5068b0914eaSPrasanna S Panchamukhi 	if (old_p->pre_handler == aggr_pre_handler) {
5078b0914eaSPrasanna S Panchamukhi 		copy_kprobe(old_p, p);
5088b0914eaSPrasanna S Panchamukhi 		ret = add_new_kprobe(old_p, p);
50964f562c6SAnanth N Mavinakayanahalli 	} else {
510a0d50069SKeshavamurthy Anil S 		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
51164f562c6SAnanth N Mavinakayanahalli 		if (!ap)
51264f562c6SAnanth N Mavinakayanahalli 			return -ENOMEM;
51364f562c6SAnanth N Mavinakayanahalli 		add_aggr_kprobe(ap, old_p);
5148b0914eaSPrasanna S Panchamukhi 		copy_kprobe(ap, p);
5158b0914eaSPrasanna S Panchamukhi 		ret = add_new_kprobe(ap, p);
51664f562c6SAnanth N Mavinakayanahalli 	}
51764f562c6SAnanth N Mavinakayanahalli 	return ret;
51864f562c6SAnanth N Mavinakayanahalli }
51964f562c6SAnanth N Mavinakayanahalli 
520d0aaff97SPrasanna S Panchamukhi static int __kprobes in_kprobes_functions(unsigned long addr)
521d0aaff97SPrasanna S Panchamukhi {
5223d8d996eSSrinivasa Ds 	struct kprobe_blackpoint *kb;
5233d8d996eSSrinivasa Ds 
5246f716acdSChristoph Hellwig 	if (addr >= (unsigned long)__kprobes_text_start &&
5256f716acdSChristoph Hellwig 	    addr < (unsigned long)__kprobes_text_end)
526d0aaff97SPrasanna S Panchamukhi 		return -EINVAL;
5273d8d996eSSrinivasa Ds 	/*
5283d8d996eSSrinivasa Ds 	 * If there exists a kprobe_blacklist, verify and
5293d8d996eSSrinivasa Ds 	 * fail any probe registration in the prohibited area
5303d8d996eSSrinivasa Ds 	 */
5313d8d996eSSrinivasa Ds 	for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
5323d8d996eSSrinivasa Ds 		if (kb->start_addr) {
5333d8d996eSSrinivasa Ds 			if (addr >= kb->start_addr &&
5343d8d996eSSrinivasa Ds 			    addr < (kb->start_addr + kb->range))
5353d8d996eSSrinivasa Ds 				return -EINVAL;
5363d8d996eSSrinivasa Ds 		}
5373d8d996eSSrinivasa Ds 	}
538d0aaff97SPrasanna S Panchamukhi 	return 0;
539d0aaff97SPrasanna S Panchamukhi }
540d0aaff97SPrasanna S Panchamukhi 
541b2a5cd69SMasami Hiramatsu /*
542b2a5cd69SMasami Hiramatsu  * If we have a symbol_name argument, look it up and add the offset field
543b2a5cd69SMasami Hiramatsu  * to it. This way, we can specify a relative address to a symbol.
544b2a5cd69SMasami Hiramatsu  */
545b2a5cd69SMasami Hiramatsu static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
546b2a5cd69SMasami Hiramatsu {
547b2a5cd69SMasami Hiramatsu 	kprobe_opcode_t *addr = p->addr;
548b2a5cd69SMasami Hiramatsu 	if (p->symbol_name) {
549b2a5cd69SMasami Hiramatsu 		if (addr)
550b2a5cd69SMasami Hiramatsu 			return NULL;
551b2a5cd69SMasami Hiramatsu 		kprobe_lookup_name(p->symbol_name, addr);
552b2a5cd69SMasami Hiramatsu 	}
553b2a5cd69SMasami Hiramatsu 
554b2a5cd69SMasami Hiramatsu 	if (!addr)
555b2a5cd69SMasami Hiramatsu 		return NULL;
556b2a5cd69SMasami Hiramatsu 	return (kprobe_opcode_t *)(((char *)addr) + p->offset);
557b2a5cd69SMasami Hiramatsu }
558b2a5cd69SMasami Hiramatsu 
559df019b1dSKeshavamurthy Anil S static int __kprobes __register_kprobe(struct kprobe *p,
560df019b1dSKeshavamurthy Anil S 	unsigned long called_from)
5611da177e4SLinus Torvalds {
5621da177e4SLinus Torvalds 	int ret = 0;
56364f562c6SAnanth N Mavinakayanahalli 	struct kprobe *old_p;
564df019b1dSKeshavamurthy Anil S 	struct module *probed_mod;
565b2a5cd69SMasami Hiramatsu 	kprobe_opcode_t *addr;
5661da177e4SLinus Torvalds 
567b2a5cd69SMasami Hiramatsu 	addr = kprobe_addr(p);
568b2a5cd69SMasami Hiramatsu 	if (!addr)
5693a872d89SAnanth N Mavinakayanahalli 		return -EINVAL;
570b2a5cd69SMasami Hiramatsu 	p->addr = addr;
5713a872d89SAnanth N Mavinakayanahalli 
5726f716acdSChristoph Hellwig 	if (!kernel_text_address((unsigned long) p->addr) ||
573b3e55c72SMao, Bibo 	    in_kprobes_functions((unsigned long) p->addr))
574b3e55c72SMao, Bibo 		return -EINVAL;
575b3e55c72SMao, Bibo 
576df019b1dSKeshavamurthy Anil S 	p->mod_refcounted = 0;
5776f716acdSChristoph Hellwig 
5786f716acdSChristoph Hellwig 	/*
5796f716acdSChristoph Hellwig 	 * Check if are we probing a module.
580df019b1dSKeshavamurthy Anil S 	 */
5816f716acdSChristoph Hellwig 	probed_mod = module_text_address((unsigned long) p->addr);
5826f716acdSChristoph Hellwig 	if (probed_mod) {
5836f716acdSChristoph Hellwig 		struct module *calling_mod = module_text_address(called_from);
5846f716acdSChristoph Hellwig 		/*
5856f716acdSChristoph Hellwig 		 * We must allow modules to probe themself and in this case
5866f716acdSChristoph Hellwig 		 * avoid incrementing the module refcount, so as to allow
5876f716acdSChristoph Hellwig 		 * unloading of self probing modules.
5886f716acdSChristoph Hellwig 		 */
5896f716acdSChristoph Hellwig 		if (calling_mod && calling_mod != probed_mod) {
590df019b1dSKeshavamurthy Anil S 			if (unlikely(!try_module_get(probed_mod)))
591b3e55c72SMao, Bibo 				return -EINVAL;
592df019b1dSKeshavamurthy Anil S 			p->mod_refcounted = 1;
593df019b1dSKeshavamurthy Anil S 		} else
594df019b1dSKeshavamurthy Anil S 			probed_mod = NULL;
595df019b1dSKeshavamurthy Anil S 	}
596b3e55c72SMao, Bibo 
5973516a460SAnanth N Mavinakayanahalli 	p->nmissed = 0;
5989861668fSMasami Hiramatsu 	INIT_LIST_HEAD(&p->list);
5997a7d1cf9SIngo Molnar 	mutex_lock(&kprobe_mutex);
60064f562c6SAnanth N Mavinakayanahalli 	old_p = get_kprobe(p->addr);
60164f562c6SAnanth N Mavinakayanahalli 	if (old_p) {
60264f562c6SAnanth N Mavinakayanahalli 		ret = register_aggr_kprobe(old_p, p);
6031da177e4SLinus Torvalds 		goto out;
6041da177e4SLinus Torvalds 	}
6051da177e4SLinus Torvalds 
6066f716acdSChristoph Hellwig 	ret = arch_prepare_kprobe(p);
6076f716acdSChristoph Hellwig 	if (ret)
60849a2a1b8SAnil S Keshavamurthy 		goto out;
60949a2a1b8SAnil S Keshavamurthy 
61064f562c6SAnanth N Mavinakayanahalli 	INIT_HLIST_NODE(&p->hlist);
6113516a460SAnanth N Mavinakayanahalli 	hlist_add_head_rcu(&p->hlist,
6121da177e4SLinus Torvalds 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
6131da177e4SLinus Torvalds 
61474a0b576SChristoph Hellwig 	if (kprobe_enabled)
6157e1048b1SRusty Lynch 		arch_arm_kprobe(p);
61674a0b576SChristoph Hellwig 
6171da177e4SLinus Torvalds out:
6187a7d1cf9SIngo Molnar 	mutex_unlock(&kprobe_mutex);
61949a2a1b8SAnil S Keshavamurthy 
620df019b1dSKeshavamurthy Anil S 	if (ret && probed_mod)
621df019b1dSKeshavamurthy Anil S 		module_put(probed_mod);
6221da177e4SLinus Torvalds 	return ret;
6231da177e4SLinus Torvalds }
6241da177e4SLinus Torvalds 
6259861668fSMasami Hiramatsu /*
6269861668fSMasami Hiramatsu  * Unregister a kprobe without a scheduler synchronization.
6279861668fSMasami Hiramatsu  */
6289861668fSMasami Hiramatsu static int __kprobes __unregister_kprobe_top(struct kprobe *p)
629df019b1dSKeshavamurthy Anil S {
630f709b122SKeshavamurthy Anil S 	struct kprobe *old_p, *list_p;
63164f562c6SAnanth N Mavinakayanahalli 
63264f562c6SAnanth N Mavinakayanahalli 	old_p = get_kprobe(p->addr);
6339861668fSMasami Hiramatsu 	if (unlikely(!old_p))
6349861668fSMasami Hiramatsu 		return -EINVAL;
6359861668fSMasami Hiramatsu 
636f709b122SKeshavamurthy Anil S 	if (p != old_p) {
637f709b122SKeshavamurthy Anil S 		list_for_each_entry_rcu(list_p, &old_p->list, list)
638f709b122SKeshavamurthy Anil S 			if (list_p == p)
639f709b122SKeshavamurthy Anil S 			/* kprobe p is a valid probe */
640f709b122SKeshavamurthy Anil S 				goto valid_p;
6419861668fSMasami Hiramatsu 		return -EINVAL;
642f709b122SKeshavamurthy Anil S 	}
643f709b122SKeshavamurthy Anil S valid_p:
6446f716acdSChristoph Hellwig 	if (old_p == p ||
6456f716acdSChristoph Hellwig 	    (old_p->pre_handler == aggr_pre_handler &&
6469861668fSMasami Hiramatsu 	     list_is_singular(&old_p->list))) {
647bf8f6e5bSAnanth N Mavinakayanahalli 		/*
648bf8f6e5bSAnanth N Mavinakayanahalli 		 * Only probe on the hash list. Disarm only if kprobes are
649bf8f6e5bSAnanth N Mavinakayanahalli 		 * enabled - otherwise, the breakpoint would already have
650bf8f6e5bSAnanth N Mavinakayanahalli 		 * been removed. We save on flushing icache.
651bf8f6e5bSAnanth N Mavinakayanahalli 		 */
652bf8f6e5bSAnanth N Mavinakayanahalli 		if (kprobe_enabled)
65349a2a1b8SAnil S Keshavamurthy 			arch_disarm_kprobe(p);
65449a2a1b8SAnil S Keshavamurthy 		hlist_del_rcu(&old_p->hlist);
65549a2a1b8SAnil S Keshavamurthy 	} else {
6569861668fSMasami Hiramatsu 		if (p->break_handler)
6579861668fSMasami Hiramatsu 			old_p->break_handler = NULL;
6589861668fSMasami Hiramatsu 		if (p->post_handler) {
6599861668fSMasami Hiramatsu 			list_for_each_entry_rcu(list_p, &old_p->list, list) {
6609861668fSMasami Hiramatsu 				if ((list_p != p) && (list_p->post_handler))
6619861668fSMasami Hiramatsu 					goto noclean;
6629861668fSMasami Hiramatsu 			}
6639861668fSMasami Hiramatsu 			old_p->post_handler = NULL;
6649861668fSMasami Hiramatsu 		}
6659861668fSMasami Hiramatsu noclean:
66649a2a1b8SAnil S Keshavamurthy 		list_del_rcu(&p->list);
6679861668fSMasami Hiramatsu 	}
6689861668fSMasami Hiramatsu 	return 0;
66949a2a1b8SAnil S Keshavamurthy }
67049a2a1b8SAnil S Keshavamurthy 
6719861668fSMasami Hiramatsu static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
6729861668fSMasami Hiramatsu {
6739861668fSMasami Hiramatsu 	struct module *mod;
6749861668fSMasami Hiramatsu 	struct kprobe *old_p;
6753516a460SAnanth N Mavinakayanahalli 
6766f716acdSChristoph Hellwig 	if (p->mod_refcounted) {
6776f716acdSChristoph Hellwig 		mod = module_text_address((unsigned long)p->addr);
6786f716acdSChristoph Hellwig 		if (mod)
679b3e55c72SMao, Bibo 			module_put(mod);
6806f716acdSChristoph Hellwig 	}
681b3e55c72SMao, Bibo 
6829861668fSMasami Hiramatsu 	if (list_empty(&p->list) || list_is_singular(&p->list)) {
6839861668fSMasami Hiramatsu 		if (!list_empty(&p->list)) {
6849861668fSMasami Hiramatsu 			/* "p" is the last child of an aggr_kprobe */
6859861668fSMasami Hiramatsu 			old_p = list_entry(p->list.next, struct kprobe, list);
6869861668fSMasami Hiramatsu 			list_del(&p->list);
6873516a460SAnanth N Mavinakayanahalli 			kfree(old_p);
68849a2a1b8SAnil S Keshavamurthy 		}
6890498b635SAnanth N Mavinakayanahalli 		arch_remove_kprobe(p);
6909861668fSMasami Hiramatsu 	}
6919861668fSMasami Hiramatsu }
6929861668fSMasami Hiramatsu 
6939861668fSMasami Hiramatsu static int __register_kprobes(struct kprobe **kps, int num,
6949861668fSMasami Hiramatsu 	unsigned long called_from)
6959861668fSMasami Hiramatsu {
6969861668fSMasami Hiramatsu 	int i, ret = 0;
6979861668fSMasami Hiramatsu 
6989861668fSMasami Hiramatsu 	if (num <= 0)
6999861668fSMasami Hiramatsu 		return -EINVAL;
7009861668fSMasami Hiramatsu 	for (i = 0; i < num; i++) {
7019861668fSMasami Hiramatsu 		ret = __register_kprobe(kps[i], called_from);
7029861668fSMasami Hiramatsu 		if (ret < 0 && i > 0) {
7039861668fSMasami Hiramatsu 			unregister_kprobes(kps, i);
70436721656Smao, bibo 			break;
70536721656Smao, bibo 		}
70636721656Smao, bibo 	}
7079861668fSMasami Hiramatsu 	return ret;
70836721656Smao, bibo }
7099861668fSMasami Hiramatsu 
7109861668fSMasami Hiramatsu /*
7119861668fSMasami Hiramatsu  * Registration and unregistration functions for kprobe.
7129861668fSMasami Hiramatsu  */
7139861668fSMasami Hiramatsu int __kprobes register_kprobe(struct kprobe *p)
7149861668fSMasami Hiramatsu {
7159861668fSMasami Hiramatsu 	return __register_kprobes(&p, 1,
7169861668fSMasami Hiramatsu 				  (unsigned long)__builtin_return_address(0));
7179861668fSMasami Hiramatsu }
7189861668fSMasami Hiramatsu 
7199861668fSMasami Hiramatsu void __kprobes unregister_kprobe(struct kprobe *p)
7209861668fSMasami Hiramatsu {
7219861668fSMasami Hiramatsu 	unregister_kprobes(&p, 1);
7229861668fSMasami Hiramatsu }
7239861668fSMasami Hiramatsu 
7249861668fSMasami Hiramatsu int __kprobes register_kprobes(struct kprobe **kps, int num)
7259861668fSMasami Hiramatsu {
7269861668fSMasami Hiramatsu 	return __register_kprobes(kps, num,
7279861668fSMasami Hiramatsu 				  (unsigned long)__builtin_return_address(0));
7289861668fSMasami Hiramatsu }
7299861668fSMasami Hiramatsu 
7309861668fSMasami Hiramatsu void __kprobes unregister_kprobes(struct kprobe **kps, int num)
7319861668fSMasami Hiramatsu {
7329861668fSMasami Hiramatsu 	int i;
7339861668fSMasami Hiramatsu 
7349861668fSMasami Hiramatsu 	if (num <= 0)
7359861668fSMasami Hiramatsu 		return;
7369861668fSMasami Hiramatsu 	mutex_lock(&kprobe_mutex);
7379861668fSMasami Hiramatsu 	for (i = 0; i < num; i++)
7389861668fSMasami Hiramatsu 		if (__unregister_kprobe_top(kps[i]) < 0)
7399861668fSMasami Hiramatsu 			kps[i]->addr = NULL;
74036721656Smao, bibo 	mutex_unlock(&kprobe_mutex);
7419861668fSMasami Hiramatsu 
7429861668fSMasami Hiramatsu 	synchronize_sched();
7439861668fSMasami Hiramatsu 	for (i = 0; i < num; i++)
7449861668fSMasami Hiramatsu 		if (kps[i]->addr)
7459861668fSMasami Hiramatsu 			__unregister_kprobe_bottom(kps[i]);
7461da177e4SLinus Torvalds }
7471da177e4SLinus Torvalds 
7481da177e4SLinus Torvalds static struct notifier_block kprobe_exceptions_nb = {
7491da177e4SLinus Torvalds 	.notifier_call = kprobe_exceptions_notify,
7503d5631e0SAnil S Keshavamurthy 	.priority = 0x7fffffff /* we need to be notified first */
7513d5631e0SAnil S Keshavamurthy };
7523d5631e0SAnil S Keshavamurthy 
7533d7e3382SMichael Ellerman unsigned long __weak arch_deref_entry_point(void *entry)
7543d7e3382SMichael Ellerman {
7553d7e3382SMichael Ellerman 	return (unsigned long)entry;
7563d7e3382SMichael Ellerman }
7571da177e4SLinus Torvalds 
758d0aaff97SPrasanna S Panchamukhi int __kprobes register_jprobe(struct jprobe *jp)
7591da177e4SLinus Torvalds {
7603d7e3382SMichael Ellerman 	unsigned long addr = arch_deref_entry_point(jp->entry);
7613d7e3382SMichael Ellerman 
7623d7e3382SMichael Ellerman 	if (!kernel_text_address(addr))
7633d7e3382SMichael Ellerman 		return -EINVAL;
7643d7e3382SMichael Ellerman 
7651da177e4SLinus Torvalds 	/* Todo: Verify probepoint is a function entry point */
7661da177e4SLinus Torvalds 	jp->kp.pre_handler = setjmp_pre_handler;
7671da177e4SLinus Torvalds 	jp->kp.break_handler = longjmp_break_handler;
7681da177e4SLinus Torvalds 
769df019b1dSKeshavamurthy Anil S 	return __register_kprobe(&jp->kp,
770df019b1dSKeshavamurthy Anil S 		(unsigned long)__builtin_return_address(0));
7711da177e4SLinus Torvalds }
7721da177e4SLinus Torvalds 
773d0aaff97SPrasanna S Panchamukhi void __kprobes unregister_jprobe(struct jprobe *jp)
7741da177e4SLinus Torvalds {
7751da177e4SLinus Torvalds 	unregister_kprobe(&jp->kp);
7761da177e4SLinus Torvalds }
7771da177e4SLinus Torvalds 
7789edddaa2SAnanth N Mavinakayanahalli #ifdef CONFIG_KRETPROBES
779e65cefe8SAdrian Bunk /*
780e65cefe8SAdrian Bunk  * This kprobe pre_handler is registered with every kretprobe. When probe
781e65cefe8SAdrian Bunk  * hits it will set up the return probe.
782e65cefe8SAdrian Bunk  */
783e65cefe8SAdrian Bunk static int __kprobes pre_handler_kretprobe(struct kprobe *p,
784e65cefe8SAdrian Bunk 					   struct pt_regs *regs)
785e65cefe8SAdrian Bunk {
786e65cefe8SAdrian Bunk 	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
787e65cefe8SAdrian Bunk 	unsigned long flags = 0;
788e65cefe8SAdrian Bunk 
789e65cefe8SAdrian Bunk 	/*TODO: consider to only swap the RA after the last pre_handler fired */
790e65cefe8SAdrian Bunk 	spin_lock_irqsave(&kretprobe_lock, flags);
7914c4308cbSChristoph Hellwig 	if (!hlist_empty(&rp->free_instances)) {
7924c4308cbSChristoph Hellwig 		struct kretprobe_instance *ri;
7934c4308cbSChristoph Hellwig 
7944c4308cbSChristoph Hellwig 		ri = hlist_entry(rp->free_instances.first,
7954c4308cbSChristoph Hellwig 				 struct kretprobe_instance, uflist);
7964c4308cbSChristoph Hellwig 		ri->rp = rp;
7974c4308cbSChristoph Hellwig 		ri->task = current;
798f47cd9b5SAbhishek Sagar 
799f47cd9b5SAbhishek Sagar 		if (rp->entry_handler && rp->entry_handler(ri, regs)) {
800f47cd9b5SAbhishek Sagar 			spin_unlock_irqrestore(&kretprobe_lock, flags);
801f47cd9b5SAbhishek Sagar 			return 0;
802f47cd9b5SAbhishek Sagar 		}
803f47cd9b5SAbhishek Sagar 
8044c4308cbSChristoph Hellwig 		arch_prepare_kretprobe(ri, regs);
8054c4308cbSChristoph Hellwig 
8064c4308cbSChristoph Hellwig 		/* XXX(hch): why is there no hlist_move_head? */
8074c4308cbSChristoph Hellwig 		hlist_del(&ri->uflist);
8084c4308cbSChristoph Hellwig 		hlist_add_head(&ri->uflist, &ri->rp->used_instances);
8094c4308cbSChristoph Hellwig 		hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task));
8104c4308cbSChristoph Hellwig 	} else
8114c4308cbSChristoph Hellwig 		rp->nmissed++;
812e65cefe8SAdrian Bunk 	spin_unlock_irqrestore(&kretprobe_lock, flags);
813e65cefe8SAdrian Bunk 	return 0;
814e65cefe8SAdrian Bunk }
815e65cefe8SAdrian Bunk 
816*4a296e07SMasami Hiramatsu static int __kprobes __register_kretprobe(struct kretprobe *rp,
817*4a296e07SMasami Hiramatsu 					  unsigned long called_from)
818b94cce92SHien Nguyen {
819b94cce92SHien Nguyen 	int ret = 0;
820b94cce92SHien Nguyen 	struct kretprobe_instance *inst;
821b94cce92SHien Nguyen 	int i;
822b2a5cd69SMasami Hiramatsu 	void *addr;
823f438d914SMasami Hiramatsu 
824f438d914SMasami Hiramatsu 	if (kretprobe_blacklist_size) {
825b2a5cd69SMasami Hiramatsu 		addr = kprobe_addr(&rp->kp);
826b2a5cd69SMasami Hiramatsu 		if (!addr)
827b2a5cd69SMasami Hiramatsu 			return -EINVAL;
828f438d914SMasami Hiramatsu 
829f438d914SMasami Hiramatsu 		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
830f438d914SMasami Hiramatsu 			if (kretprobe_blacklist[i].addr == addr)
831f438d914SMasami Hiramatsu 				return -EINVAL;
832f438d914SMasami Hiramatsu 		}
833f438d914SMasami Hiramatsu 	}
834b94cce92SHien Nguyen 
835b94cce92SHien Nguyen 	rp->kp.pre_handler = pre_handler_kretprobe;
8367522a842SAnanth N Mavinakayanahalli 	rp->kp.post_handler = NULL;
8377522a842SAnanth N Mavinakayanahalli 	rp->kp.fault_handler = NULL;
8387522a842SAnanth N Mavinakayanahalli 	rp->kp.break_handler = NULL;
839b94cce92SHien Nguyen 
840b94cce92SHien Nguyen 	/* Pre-allocate memory for max kretprobe instances */
841b94cce92SHien Nguyen 	if (rp->maxactive <= 0) {
842b94cce92SHien Nguyen #ifdef CONFIG_PREEMPT
843b94cce92SHien Nguyen 		rp->maxactive = max(10, 2 * NR_CPUS);
844b94cce92SHien Nguyen #else
845b94cce92SHien Nguyen 		rp->maxactive = NR_CPUS;
846b94cce92SHien Nguyen #endif
847b94cce92SHien Nguyen 	}
848b94cce92SHien Nguyen 	INIT_HLIST_HEAD(&rp->used_instances);
849b94cce92SHien Nguyen 	INIT_HLIST_HEAD(&rp->free_instances);
850b94cce92SHien Nguyen 	for (i = 0; i < rp->maxactive; i++) {
851f47cd9b5SAbhishek Sagar 		inst = kmalloc(sizeof(struct kretprobe_instance) +
852f47cd9b5SAbhishek Sagar 			       rp->data_size, GFP_KERNEL);
853b94cce92SHien Nguyen 		if (inst == NULL) {
854b94cce92SHien Nguyen 			free_rp_inst(rp);
855b94cce92SHien Nguyen 			return -ENOMEM;
856b94cce92SHien Nguyen 		}
857b94cce92SHien Nguyen 		INIT_HLIST_NODE(&inst->uflist);
858b94cce92SHien Nguyen 		hlist_add_head(&inst->uflist, &rp->free_instances);
859b94cce92SHien Nguyen 	}
860b94cce92SHien Nguyen 
861b94cce92SHien Nguyen 	rp->nmissed = 0;
862b94cce92SHien Nguyen 	/* Establish function entry probe point */
863*4a296e07SMasami Hiramatsu 	ret = __register_kprobe(&rp->kp, called_from);
864*4a296e07SMasami Hiramatsu 	if (ret != 0)
865b94cce92SHien Nguyen 		free_rp_inst(rp);
866b94cce92SHien Nguyen 	return ret;
867b94cce92SHien Nguyen }
868b94cce92SHien Nguyen 
869*4a296e07SMasami Hiramatsu static int __register_kretprobes(struct kretprobe **rps, int num,
870*4a296e07SMasami Hiramatsu 	unsigned long called_from)
871*4a296e07SMasami Hiramatsu {
872*4a296e07SMasami Hiramatsu 	int ret = 0, i;
873*4a296e07SMasami Hiramatsu 
874*4a296e07SMasami Hiramatsu 	if (num <= 0)
875*4a296e07SMasami Hiramatsu 		return -EINVAL;
876*4a296e07SMasami Hiramatsu 	for (i = 0; i < num; i++) {
877*4a296e07SMasami Hiramatsu 		ret = __register_kretprobe(rps[i], called_from);
878*4a296e07SMasami Hiramatsu 		if (ret < 0 && i > 0) {
879*4a296e07SMasami Hiramatsu 			unregister_kretprobes(rps, i);
880*4a296e07SMasami Hiramatsu 			break;
881*4a296e07SMasami Hiramatsu 		}
882*4a296e07SMasami Hiramatsu 	}
883*4a296e07SMasami Hiramatsu 	return ret;
884*4a296e07SMasami Hiramatsu }
885*4a296e07SMasami Hiramatsu 
886*4a296e07SMasami Hiramatsu int __kprobes register_kretprobe(struct kretprobe *rp)
887*4a296e07SMasami Hiramatsu {
888*4a296e07SMasami Hiramatsu 	return __register_kretprobes(&rp, 1,
889*4a296e07SMasami Hiramatsu 			(unsigned long)__builtin_return_address(0));
890*4a296e07SMasami Hiramatsu }
891*4a296e07SMasami Hiramatsu 
892*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobe(struct kretprobe *rp)
893*4a296e07SMasami Hiramatsu {
894*4a296e07SMasami Hiramatsu 	unregister_kretprobes(&rp, 1);
895*4a296e07SMasami Hiramatsu }
896*4a296e07SMasami Hiramatsu 
897*4a296e07SMasami Hiramatsu int __kprobes register_kretprobes(struct kretprobe **rps, int num)
898*4a296e07SMasami Hiramatsu {
899*4a296e07SMasami Hiramatsu 	return __register_kretprobes(rps, num,
900*4a296e07SMasami Hiramatsu 			(unsigned long)__builtin_return_address(0));
901*4a296e07SMasami Hiramatsu }
902*4a296e07SMasami Hiramatsu 
903*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
904*4a296e07SMasami Hiramatsu {
905*4a296e07SMasami Hiramatsu 	int i;
906*4a296e07SMasami Hiramatsu 
907*4a296e07SMasami Hiramatsu 	if (num <= 0)
908*4a296e07SMasami Hiramatsu 		return;
909*4a296e07SMasami Hiramatsu 	mutex_lock(&kprobe_mutex);
910*4a296e07SMasami Hiramatsu 	for (i = 0; i < num; i++)
911*4a296e07SMasami Hiramatsu 		if (__unregister_kprobe_top(&rps[i]->kp) < 0)
912*4a296e07SMasami Hiramatsu 			rps[i]->kp.addr = NULL;
913*4a296e07SMasami Hiramatsu 	mutex_unlock(&kprobe_mutex);
914*4a296e07SMasami Hiramatsu 
915*4a296e07SMasami Hiramatsu 	synchronize_sched();
916*4a296e07SMasami Hiramatsu 	for (i = 0; i < num; i++) {
917*4a296e07SMasami Hiramatsu 		if (rps[i]->kp.addr) {
918*4a296e07SMasami Hiramatsu 			__unregister_kprobe_bottom(&rps[i]->kp);
919*4a296e07SMasami Hiramatsu 			cleanup_rp_inst(rps[i]);
920*4a296e07SMasami Hiramatsu 		}
921*4a296e07SMasami Hiramatsu 	}
922*4a296e07SMasami Hiramatsu }
923*4a296e07SMasami Hiramatsu 
9249edddaa2SAnanth N Mavinakayanahalli #else /* CONFIG_KRETPROBES */
925d0aaff97SPrasanna S Panchamukhi int __kprobes register_kretprobe(struct kretprobe *rp)
926b94cce92SHien Nguyen {
927b94cce92SHien Nguyen 	return -ENOSYS;
928b94cce92SHien Nguyen }
929b94cce92SHien Nguyen 
930*4a296e07SMasami Hiramatsu int __kprobes register_kretprobes(struct kretprobe **rps, int num)
931*4a296e07SMasami Hiramatsu {
932*4a296e07SMasami Hiramatsu 	return -ENOSYS;
933*4a296e07SMasami Hiramatsu }
934*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobe(struct kretprobe *rp)
935*4a296e07SMasami Hiramatsu {
936*4a296e07SMasami Hiramatsu }
937*4a296e07SMasami Hiramatsu 
938*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)
939*4a296e07SMasami Hiramatsu {
940*4a296e07SMasami Hiramatsu }
941*4a296e07SMasami Hiramatsu 
942346fd59bSSrinivasa Ds static int __kprobes pre_handler_kretprobe(struct kprobe *p,
943346fd59bSSrinivasa Ds 					   struct pt_regs *regs)
944346fd59bSSrinivasa Ds {
945346fd59bSSrinivasa Ds 	return 0;
946346fd59bSSrinivasa Ds }
947*4a296e07SMasami Hiramatsu 
9489edddaa2SAnanth N Mavinakayanahalli #endif /* CONFIG_KRETPROBES */
949b94cce92SHien Nguyen 
9501da177e4SLinus Torvalds static int __init init_kprobes(void)
9511da177e4SLinus Torvalds {
9521da177e4SLinus Torvalds 	int i, err = 0;
9533d8d996eSSrinivasa Ds 	unsigned long offset = 0, size = 0;
9543d8d996eSSrinivasa Ds 	char *modname, namebuf[128];
9553d8d996eSSrinivasa Ds 	const char *symbol_name;
9563d8d996eSSrinivasa Ds 	void *addr;
9573d8d996eSSrinivasa Ds 	struct kprobe_blackpoint *kb;
9581da177e4SLinus Torvalds 
9591da177e4SLinus Torvalds 	/* FIXME allocate the probe table, currently defined statically */
9601da177e4SLinus Torvalds 	/* initialize all list heads */
961b94cce92SHien Nguyen 	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
9621da177e4SLinus Torvalds 		INIT_HLIST_HEAD(&kprobe_table[i]);
963b94cce92SHien Nguyen 		INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
964b94cce92SHien Nguyen 	}
9651da177e4SLinus Torvalds 
9663d8d996eSSrinivasa Ds 	/*
9673d8d996eSSrinivasa Ds 	 * Lookup and populate the kprobe_blacklist.
9683d8d996eSSrinivasa Ds 	 *
9693d8d996eSSrinivasa Ds 	 * Unlike the kretprobe blacklist, we'll need to determine
9703d8d996eSSrinivasa Ds 	 * the range of addresses that belong to the said functions,
9713d8d996eSSrinivasa Ds 	 * since a kprobe need not necessarily be at the beginning
9723d8d996eSSrinivasa Ds 	 * of a function.
9733d8d996eSSrinivasa Ds 	 */
9743d8d996eSSrinivasa Ds 	for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
9753d8d996eSSrinivasa Ds 		kprobe_lookup_name(kb->name, addr);
9763d8d996eSSrinivasa Ds 		if (!addr)
9773d8d996eSSrinivasa Ds 			continue;
9783d8d996eSSrinivasa Ds 
9793d8d996eSSrinivasa Ds 		kb->start_addr = (unsigned long)addr;
9803d8d996eSSrinivasa Ds 		symbol_name = kallsyms_lookup(kb->start_addr,
9813d8d996eSSrinivasa Ds 				&size, &offset, &modname, namebuf);
9823d8d996eSSrinivasa Ds 		if (!symbol_name)
9833d8d996eSSrinivasa Ds 			kb->range = 0;
9843d8d996eSSrinivasa Ds 		else
9853d8d996eSSrinivasa Ds 			kb->range = size;
9863d8d996eSSrinivasa Ds 	}
9873d8d996eSSrinivasa Ds 
988f438d914SMasami Hiramatsu 	if (kretprobe_blacklist_size) {
989f438d914SMasami Hiramatsu 		/* lookup the function address from its name */
990f438d914SMasami Hiramatsu 		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
991f438d914SMasami Hiramatsu 			kprobe_lookup_name(kretprobe_blacklist[i].name,
992f438d914SMasami Hiramatsu 					   kretprobe_blacklist[i].addr);
993f438d914SMasami Hiramatsu 			if (!kretprobe_blacklist[i].addr)
994f438d914SMasami Hiramatsu 				printk("kretprobe: lookup failed: %s\n",
995f438d914SMasami Hiramatsu 				       kretprobe_blacklist[i].name);
996f438d914SMasami Hiramatsu 		}
997f438d914SMasami Hiramatsu 	}
998f438d914SMasami Hiramatsu 
999bf8f6e5bSAnanth N Mavinakayanahalli 	/* By default, kprobes are enabled */
1000bf8f6e5bSAnanth N Mavinakayanahalli 	kprobe_enabled = true;
1001bf8f6e5bSAnanth N Mavinakayanahalli 
10026772926bSRusty Lynch 	err = arch_init_kprobes();
1003802eae7cSRusty Lynch 	if (!err)
10041da177e4SLinus Torvalds 		err = register_die_notifier(&kprobe_exceptions_nb);
1005802eae7cSRusty Lynch 
10068c1c9356SAnanth N Mavinakayanahalli 	if (!err)
10078c1c9356SAnanth N Mavinakayanahalli 		init_test_probes();
10081da177e4SLinus Torvalds 	return err;
10091da177e4SLinus Torvalds }
10101da177e4SLinus Torvalds 
1011346fd59bSSrinivasa Ds #ifdef CONFIG_DEBUG_FS
1012346fd59bSSrinivasa Ds static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
1013346fd59bSSrinivasa Ds 		const char *sym, int offset,char *modname)
1014346fd59bSSrinivasa Ds {
1015346fd59bSSrinivasa Ds 	char *kprobe_type;
1016346fd59bSSrinivasa Ds 
1017346fd59bSSrinivasa Ds 	if (p->pre_handler == pre_handler_kretprobe)
1018346fd59bSSrinivasa Ds 		kprobe_type = "r";
1019346fd59bSSrinivasa Ds 	else if (p->pre_handler == setjmp_pre_handler)
1020346fd59bSSrinivasa Ds 		kprobe_type = "j";
1021346fd59bSSrinivasa Ds 	else
1022346fd59bSSrinivasa Ds 		kprobe_type = "k";
1023346fd59bSSrinivasa Ds 	if (sym)
1024346fd59bSSrinivasa Ds 		seq_printf(pi, "%p  %s  %s+0x%x  %s\n", p->addr, kprobe_type,
1025346fd59bSSrinivasa Ds 			sym, offset, (modname ? modname : " "));
1026346fd59bSSrinivasa Ds 	else
1027346fd59bSSrinivasa Ds 		seq_printf(pi, "%p  %s  %p\n", p->addr, kprobe_type, p->addr);
1028346fd59bSSrinivasa Ds }
1029346fd59bSSrinivasa Ds 
1030346fd59bSSrinivasa Ds static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
1031346fd59bSSrinivasa Ds {
1032346fd59bSSrinivasa Ds 	return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL;
1033346fd59bSSrinivasa Ds }
1034346fd59bSSrinivasa Ds 
1035346fd59bSSrinivasa Ds static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos)
1036346fd59bSSrinivasa Ds {
1037346fd59bSSrinivasa Ds 	(*pos)++;
1038346fd59bSSrinivasa Ds 	if (*pos >= KPROBE_TABLE_SIZE)
1039346fd59bSSrinivasa Ds 		return NULL;
1040346fd59bSSrinivasa Ds 	return pos;
1041346fd59bSSrinivasa Ds }
1042346fd59bSSrinivasa Ds 
1043346fd59bSSrinivasa Ds static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v)
1044346fd59bSSrinivasa Ds {
1045346fd59bSSrinivasa Ds 	/* Nothing to do */
1046346fd59bSSrinivasa Ds }
1047346fd59bSSrinivasa Ds 
1048346fd59bSSrinivasa Ds static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
1049346fd59bSSrinivasa Ds {
1050346fd59bSSrinivasa Ds 	struct hlist_head *head;
1051346fd59bSSrinivasa Ds 	struct hlist_node *node;
1052346fd59bSSrinivasa Ds 	struct kprobe *p, *kp;
1053346fd59bSSrinivasa Ds 	const char *sym = NULL;
1054346fd59bSSrinivasa Ds 	unsigned int i = *(loff_t *) v;
1055ffb45122SAlexey Dobriyan 	unsigned long offset = 0;
1056346fd59bSSrinivasa Ds 	char *modname, namebuf[128];
1057346fd59bSSrinivasa Ds 
1058346fd59bSSrinivasa Ds 	head = &kprobe_table[i];
1059346fd59bSSrinivasa Ds 	preempt_disable();
1060346fd59bSSrinivasa Ds 	hlist_for_each_entry_rcu(p, node, head, hlist) {
1061ffb45122SAlexey Dobriyan 		sym = kallsyms_lookup((unsigned long)p->addr, NULL,
1062346fd59bSSrinivasa Ds 					&offset, &modname, namebuf);
1063346fd59bSSrinivasa Ds 		if (p->pre_handler == aggr_pre_handler) {
1064346fd59bSSrinivasa Ds 			list_for_each_entry_rcu(kp, &p->list, list)
1065346fd59bSSrinivasa Ds 				report_probe(pi, kp, sym, offset, modname);
1066346fd59bSSrinivasa Ds 		} else
1067346fd59bSSrinivasa Ds 			report_probe(pi, p, sym, offset, modname);
1068346fd59bSSrinivasa Ds 	}
1069346fd59bSSrinivasa Ds 	preempt_enable();
1070346fd59bSSrinivasa Ds 	return 0;
1071346fd59bSSrinivasa Ds }
1072346fd59bSSrinivasa Ds 
1073346fd59bSSrinivasa Ds static struct seq_operations kprobes_seq_ops = {
1074346fd59bSSrinivasa Ds 	.start = kprobe_seq_start,
1075346fd59bSSrinivasa Ds 	.next  = kprobe_seq_next,
1076346fd59bSSrinivasa Ds 	.stop  = kprobe_seq_stop,
1077346fd59bSSrinivasa Ds 	.show  = show_kprobe_addr
1078346fd59bSSrinivasa Ds };
1079346fd59bSSrinivasa Ds 
1080346fd59bSSrinivasa Ds static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
1081346fd59bSSrinivasa Ds {
1082346fd59bSSrinivasa Ds 	return seq_open(filp, &kprobes_seq_ops);
1083346fd59bSSrinivasa Ds }
1084346fd59bSSrinivasa Ds 
1085346fd59bSSrinivasa Ds static struct file_operations debugfs_kprobes_operations = {
1086346fd59bSSrinivasa Ds 	.open           = kprobes_open,
1087346fd59bSSrinivasa Ds 	.read           = seq_read,
1088346fd59bSSrinivasa Ds 	.llseek         = seq_lseek,
1089346fd59bSSrinivasa Ds 	.release        = seq_release,
1090346fd59bSSrinivasa Ds };
1091346fd59bSSrinivasa Ds 
1092bf8f6e5bSAnanth N Mavinakayanahalli static void __kprobes enable_all_kprobes(void)
1093bf8f6e5bSAnanth N Mavinakayanahalli {
1094bf8f6e5bSAnanth N Mavinakayanahalli 	struct hlist_head *head;
1095bf8f6e5bSAnanth N Mavinakayanahalli 	struct hlist_node *node;
1096bf8f6e5bSAnanth N Mavinakayanahalli 	struct kprobe *p;
1097bf8f6e5bSAnanth N Mavinakayanahalli 	unsigned int i;
1098bf8f6e5bSAnanth N Mavinakayanahalli 
1099bf8f6e5bSAnanth N Mavinakayanahalli 	mutex_lock(&kprobe_mutex);
1100bf8f6e5bSAnanth N Mavinakayanahalli 
1101bf8f6e5bSAnanth N Mavinakayanahalli 	/* If kprobes are already enabled, just return */
1102bf8f6e5bSAnanth N Mavinakayanahalli 	if (kprobe_enabled)
1103bf8f6e5bSAnanth N Mavinakayanahalli 		goto already_enabled;
1104bf8f6e5bSAnanth N Mavinakayanahalli 
1105bf8f6e5bSAnanth N Mavinakayanahalli 	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1106bf8f6e5bSAnanth N Mavinakayanahalli 		head = &kprobe_table[i];
1107bf8f6e5bSAnanth N Mavinakayanahalli 		hlist_for_each_entry_rcu(p, node, head, hlist)
1108bf8f6e5bSAnanth N Mavinakayanahalli 			arch_arm_kprobe(p);
1109bf8f6e5bSAnanth N Mavinakayanahalli 	}
1110bf8f6e5bSAnanth N Mavinakayanahalli 
1111bf8f6e5bSAnanth N Mavinakayanahalli 	kprobe_enabled = true;
1112bf8f6e5bSAnanth N Mavinakayanahalli 	printk(KERN_INFO "Kprobes globally enabled\n");
1113bf8f6e5bSAnanth N Mavinakayanahalli 
1114bf8f6e5bSAnanth N Mavinakayanahalli already_enabled:
1115bf8f6e5bSAnanth N Mavinakayanahalli 	mutex_unlock(&kprobe_mutex);
1116bf8f6e5bSAnanth N Mavinakayanahalli 	return;
1117bf8f6e5bSAnanth N Mavinakayanahalli }
1118bf8f6e5bSAnanth N Mavinakayanahalli 
1119bf8f6e5bSAnanth N Mavinakayanahalli static void __kprobes disable_all_kprobes(void)
1120bf8f6e5bSAnanth N Mavinakayanahalli {
1121bf8f6e5bSAnanth N Mavinakayanahalli 	struct hlist_head *head;
1122bf8f6e5bSAnanth N Mavinakayanahalli 	struct hlist_node *node;
1123bf8f6e5bSAnanth N Mavinakayanahalli 	struct kprobe *p;
1124bf8f6e5bSAnanth N Mavinakayanahalli 	unsigned int i;
1125bf8f6e5bSAnanth N Mavinakayanahalli 
1126bf8f6e5bSAnanth N Mavinakayanahalli 	mutex_lock(&kprobe_mutex);
1127bf8f6e5bSAnanth N Mavinakayanahalli 
1128bf8f6e5bSAnanth N Mavinakayanahalli 	/* If kprobes are already disabled, just return */
1129bf8f6e5bSAnanth N Mavinakayanahalli 	if (!kprobe_enabled)
1130bf8f6e5bSAnanth N Mavinakayanahalli 		goto already_disabled;
1131bf8f6e5bSAnanth N Mavinakayanahalli 
1132bf8f6e5bSAnanth N Mavinakayanahalli 	kprobe_enabled = false;
1133bf8f6e5bSAnanth N Mavinakayanahalli 	printk(KERN_INFO "Kprobes globally disabled\n");
1134bf8f6e5bSAnanth N Mavinakayanahalli 	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
1135bf8f6e5bSAnanth N Mavinakayanahalli 		head = &kprobe_table[i];
1136bf8f6e5bSAnanth N Mavinakayanahalli 		hlist_for_each_entry_rcu(p, node, head, hlist) {
1137bf8f6e5bSAnanth N Mavinakayanahalli 			if (!arch_trampoline_kprobe(p))
1138bf8f6e5bSAnanth N Mavinakayanahalli 				arch_disarm_kprobe(p);
1139bf8f6e5bSAnanth N Mavinakayanahalli 		}
1140bf8f6e5bSAnanth N Mavinakayanahalli 	}
1141bf8f6e5bSAnanth N Mavinakayanahalli 
1142bf8f6e5bSAnanth N Mavinakayanahalli 	mutex_unlock(&kprobe_mutex);
1143bf8f6e5bSAnanth N Mavinakayanahalli 	/* Allow all currently running kprobes to complete */
1144bf8f6e5bSAnanth N Mavinakayanahalli 	synchronize_sched();
114574a0b576SChristoph Hellwig 	return;
1146bf8f6e5bSAnanth N Mavinakayanahalli 
1147bf8f6e5bSAnanth N Mavinakayanahalli already_disabled:
1148bf8f6e5bSAnanth N Mavinakayanahalli 	mutex_unlock(&kprobe_mutex);
1149bf8f6e5bSAnanth N Mavinakayanahalli 	return;
1150bf8f6e5bSAnanth N Mavinakayanahalli }
1151bf8f6e5bSAnanth N Mavinakayanahalli 
1152bf8f6e5bSAnanth N Mavinakayanahalli /*
1153bf8f6e5bSAnanth N Mavinakayanahalli  * XXX: The debugfs bool file interface doesn't allow for callbacks
1154bf8f6e5bSAnanth N Mavinakayanahalli  * when the bool state is switched. We can reuse that facility when
1155bf8f6e5bSAnanth N Mavinakayanahalli  * available
1156bf8f6e5bSAnanth N Mavinakayanahalli  */
1157bf8f6e5bSAnanth N Mavinakayanahalli static ssize_t read_enabled_file_bool(struct file *file,
1158bf8f6e5bSAnanth N Mavinakayanahalli 	       char __user *user_buf, size_t count, loff_t *ppos)
1159bf8f6e5bSAnanth N Mavinakayanahalli {
1160bf8f6e5bSAnanth N Mavinakayanahalli 	char buf[3];
1161bf8f6e5bSAnanth N Mavinakayanahalli 
1162bf8f6e5bSAnanth N Mavinakayanahalli 	if (kprobe_enabled)
1163bf8f6e5bSAnanth N Mavinakayanahalli 		buf[0] = '1';
1164bf8f6e5bSAnanth N Mavinakayanahalli 	else
1165bf8f6e5bSAnanth N Mavinakayanahalli 		buf[0] = '0';
1166bf8f6e5bSAnanth N Mavinakayanahalli 	buf[1] = '\n';
1167bf8f6e5bSAnanth N Mavinakayanahalli 	buf[2] = 0x00;
1168bf8f6e5bSAnanth N Mavinakayanahalli 	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
1169bf8f6e5bSAnanth N Mavinakayanahalli }
1170bf8f6e5bSAnanth N Mavinakayanahalli 
1171bf8f6e5bSAnanth N Mavinakayanahalli static ssize_t write_enabled_file_bool(struct file *file,
1172bf8f6e5bSAnanth N Mavinakayanahalli 	       const char __user *user_buf, size_t count, loff_t *ppos)
1173bf8f6e5bSAnanth N Mavinakayanahalli {
1174bf8f6e5bSAnanth N Mavinakayanahalli 	char buf[32];
1175bf8f6e5bSAnanth N Mavinakayanahalli 	int buf_size;
1176bf8f6e5bSAnanth N Mavinakayanahalli 
1177bf8f6e5bSAnanth N Mavinakayanahalli 	buf_size = min(count, (sizeof(buf)-1));
1178bf8f6e5bSAnanth N Mavinakayanahalli 	if (copy_from_user(buf, user_buf, buf_size))
1179bf8f6e5bSAnanth N Mavinakayanahalli 		return -EFAULT;
1180bf8f6e5bSAnanth N Mavinakayanahalli 
1181bf8f6e5bSAnanth N Mavinakayanahalli 	switch (buf[0]) {
1182bf8f6e5bSAnanth N Mavinakayanahalli 	case 'y':
1183bf8f6e5bSAnanth N Mavinakayanahalli 	case 'Y':
1184bf8f6e5bSAnanth N Mavinakayanahalli 	case '1':
1185bf8f6e5bSAnanth N Mavinakayanahalli 		enable_all_kprobes();
1186bf8f6e5bSAnanth N Mavinakayanahalli 		break;
1187bf8f6e5bSAnanth N Mavinakayanahalli 	case 'n':
1188bf8f6e5bSAnanth N Mavinakayanahalli 	case 'N':
1189bf8f6e5bSAnanth N Mavinakayanahalli 	case '0':
1190bf8f6e5bSAnanth N Mavinakayanahalli 		disable_all_kprobes();
1191bf8f6e5bSAnanth N Mavinakayanahalli 		break;
1192bf8f6e5bSAnanth N Mavinakayanahalli 	}
1193bf8f6e5bSAnanth N Mavinakayanahalli 
1194bf8f6e5bSAnanth N Mavinakayanahalli 	return count;
1195bf8f6e5bSAnanth N Mavinakayanahalli }
1196bf8f6e5bSAnanth N Mavinakayanahalli 
1197bf8f6e5bSAnanth N Mavinakayanahalli static struct file_operations fops_kp = {
1198bf8f6e5bSAnanth N Mavinakayanahalli 	.read =         read_enabled_file_bool,
1199bf8f6e5bSAnanth N Mavinakayanahalli 	.write =        write_enabled_file_bool,
1200bf8f6e5bSAnanth N Mavinakayanahalli };
1201bf8f6e5bSAnanth N Mavinakayanahalli 
1202346fd59bSSrinivasa Ds static int __kprobes debugfs_kprobe_init(void)
1203346fd59bSSrinivasa Ds {
1204346fd59bSSrinivasa Ds 	struct dentry *dir, *file;
1205bf8f6e5bSAnanth N Mavinakayanahalli 	unsigned int value = 1;
1206346fd59bSSrinivasa Ds 
1207346fd59bSSrinivasa Ds 	dir = debugfs_create_dir("kprobes", NULL);
1208346fd59bSSrinivasa Ds 	if (!dir)
1209346fd59bSSrinivasa Ds 		return -ENOMEM;
1210346fd59bSSrinivasa Ds 
1211e3869792SRandy Dunlap 	file = debugfs_create_file("list", 0444, dir, NULL,
1212346fd59bSSrinivasa Ds 				&debugfs_kprobes_operations);
1213346fd59bSSrinivasa Ds 	if (!file) {
1214346fd59bSSrinivasa Ds 		debugfs_remove(dir);
1215346fd59bSSrinivasa Ds 		return -ENOMEM;
1216346fd59bSSrinivasa Ds 	}
1217346fd59bSSrinivasa Ds 
1218bf8f6e5bSAnanth N Mavinakayanahalli 	file = debugfs_create_file("enabled", 0600, dir,
1219bf8f6e5bSAnanth N Mavinakayanahalli 					&value, &fops_kp);
1220bf8f6e5bSAnanth N Mavinakayanahalli 	if (!file) {
1221bf8f6e5bSAnanth N Mavinakayanahalli 		debugfs_remove(dir);
1222bf8f6e5bSAnanth N Mavinakayanahalli 		return -ENOMEM;
1223bf8f6e5bSAnanth N Mavinakayanahalli 	}
1224bf8f6e5bSAnanth N Mavinakayanahalli 
1225346fd59bSSrinivasa Ds 	return 0;
1226346fd59bSSrinivasa Ds }
1227346fd59bSSrinivasa Ds 
1228346fd59bSSrinivasa Ds late_initcall(debugfs_kprobe_init);
1229346fd59bSSrinivasa Ds #endif /* CONFIG_DEBUG_FS */
1230346fd59bSSrinivasa Ds 
1231346fd59bSSrinivasa Ds module_init(init_kprobes);
12321da177e4SLinus Torvalds 
12331da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(register_kprobe);
12341da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(unregister_kprobe);
12359861668fSMasami Hiramatsu EXPORT_SYMBOL_GPL(register_kprobes);
12369861668fSMasami Hiramatsu EXPORT_SYMBOL_GPL(unregister_kprobes);
12371da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(register_jprobe);
12381da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(unregister_jprobe);
1239cd5bfea2SPeter Chubb #ifdef CONFIG_KPROBES
12401da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(jprobe_return);
1241cd5bfea2SPeter Chubb #endif
1242cd5bfea2SPeter Chubb 
1243cd5bfea2SPeter Chubb #ifdef CONFIG_KPROBES
1244b94cce92SHien Nguyen EXPORT_SYMBOL_GPL(register_kretprobe);
1245b94cce92SHien Nguyen EXPORT_SYMBOL_GPL(unregister_kretprobe);
1246*4a296e07SMasami Hiramatsu EXPORT_SYMBOL_GPL(register_kretprobes);
1247*4a296e07SMasami Hiramatsu EXPORT_SYMBOL_GPL(unregister_kretprobes);
1248cd5bfea2SPeter Chubb #endif
1249