aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kprobes.h31
-rw-r--r--kernel/kprobes.c43
2 files changed, 50 insertions, 24 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index e30afdca7917..6720305a31e8 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -33,6 +33,7 @@
33#include <linux/list.h> 33#include <linux/list.h>
34#include <linux/notifier.h> 34#include <linux/notifier.h>
35#include <linux/smp.h> 35#include <linux/smp.h>
36#include <linux/percpu.h>
36 37
37#include <asm/kprobes.h> 38#include <asm/kprobes.h>
38 39
@@ -106,6 +107,9 @@ struct jprobe {
106 kprobe_opcode_t *entry; /* probe handling code to jump to */ 107 kprobe_opcode_t *entry; /* probe handling code to jump to */
107}; 108};
108 109
110DECLARE_PER_CPU(struct kprobe *, current_kprobe);
111DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
112
109#ifdef ARCH_SUPPORTS_KRETPROBES 113#ifdef ARCH_SUPPORTS_KRETPROBES
110extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); 114extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
111#else /* ARCH_SUPPORTS_KRETPROBES */ 115#else /* ARCH_SUPPORTS_KRETPROBES */
@@ -146,13 +150,6 @@ struct kretprobe_instance {
146void lock_kprobes(void); 150void lock_kprobes(void);
147void unlock_kprobes(void); 151void unlock_kprobes(void);
148 152
149/* kprobe running now on this CPU? */
150static inline int kprobe_running(void)
151{
152 extern unsigned int kprobe_cpu;
153 return kprobe_cpu == smp_processor_id();
154}
155
156extern int arch_prepare_kprobe(struct kprobe *p); 153extern int arch_prepare_kprobe(struct kprobe *p);
157extern void arch_copy_kprobe(struct kprobe *p); 154extern void arch_copy_kprobe(struct kprobe *p);
158extern void arch_arm_kprobe(struct kprobe *p); 155extern void arch_arm_kprobe(struct kprobe *p);
@@ -167,6 +164,22 @@ extern void free_insn_slot(kprobe_opcode_t *slot);
167struct kprobe *get_kprobe(void *addr); 164struct kprobe *get_kprobe(void *addr);
168struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); 165struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
169 166
167/* kprobe_running() will just return the current_kprobe on this CPU */
168static inline struct kprobe *kprobe_running(void)
169{
170 return (__get_cpu_var(current_kprobe));
171}
172
173static inline void reset_current_kprobe(void)
174{
175 __get_cpu_var(current_kprobe) = NULL;
176}
177
178static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
179{
180 return (&__get_cpu_var(kprobe_ctlblk));
181}
182
170int register_kprobe(struct kprobe *p); 183int register_kprobe(struct kprobe *p);
171void unregister_kprobe(struct kprobe *p); 184void unregister_kprobe(struct kprobe *p);
172int setjmp_pre_handler(struct kprobe *, struct pt_regs *); 185int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
@@ -183,9 +196,9 @@ void add_rp_inst(struct kretprobe_instance *ri);
183void kprobe_flush_task(struct task_struct *tk); 196void kprobe_flush_task(struct task_struct *tk);
184void recycle_rp_inst(struct kretprobe_instance *ri); 197void recycle_rp_inst(struct kretprobe_instance *ri);
185#else /* CONFIG_KPROBES */ 198#else /* CONFIG_KPROBES */
186static inline int kprobe_running(void) 199static inline struct kprobe *kprobe_running(void)
187{ 200{
188 return 0; 201 return NULL;
189} 202}
190static inline int register_kprobe(struct kprobe *p) 203static inline int register_kprobe(struct kprobe *p)
191{ 204{
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ce4915dd683a..6da8f9b33d1e 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -51,7 +51,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
51 51
52unsigned int kprobe_cpu = NR_CPUS; 52unsigned int kprobe_cpu = NR_CPUS;
53static DEFINE_SPINLOCK(kprobe_lock); 53static DEFINE_SPINLOCK(kprobe_lock);
54static struct kprobe *curr_kprobe; 54static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
55 55
56/* 56/*
57 * kprobe->ainsn.insn points to the copy of the instruction to be 57 * kprobe->ainsn.insn points to the copy of the instruction to be
@@ -188,6 +188,17 @@ void __kprobes unlock_kprobes(void)
188 local_irq_restore(flags); 188 local_irq_restore(flags);
189} 189}
190 190
191/* We have preemption disabled.. so it is safe to use __ versions */
192static inline void set_kprobe_instance(struct kprobe *kp)
193{
194 __get_cpu_var(kprobe_instance) = kp;
195}
196
197static inline void reset_kprobe_instance(void)
198{
199 __get_cpu_var(kprobe_instance) = NULL;
200}
201
191/* You have to be holding the kprobe_lock */ 202/* You have to be holding the kprobe_lock */
192struct kprobe __kprobes *get_kprobe(void *addr) 203struct kprobe __kprobes *get_kprobe(void *addr)
193{ 204{
@@ -213,11 +224,11 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
213 224
214 list_for_each_entry(kp, &p->list, list) { 225 list_for_each_entry(kp, &p->list, list) {
215 if (kp->pre_handler) { 226 if (kp->pre_handler) {
216 curr_kprobe = kp; 227 set_kprobe_instance(kp);
217 if (kp->pre_handler(kp, regs)) 228 if (kp->pre_handler(kp, regs))
218 return 1; 229 return 1;
219 } 230 }
220 curr_kprobe = NULL; 231 reset_kprobe_instance();
221 } 232 }
222 return 0; 233 return 0;
223} 234}
@@ -229,9 +240,9 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
229 240
230 list_for_each_entry(kp, &p->list, list) { 241 list_for_each_entry(kp, &p->list, list) {
231 if (kp->post_handler) { 242 if (kp->post_handler) {
232 curr_kprobe = kp; 243 set_kprobe_instance(kp);
233 kp->post_handler(kp, regs, flags); 244 kp->post_handler(kp, regs, flags);
234 curr_kprobe = NULL; 245 reset_kprobe_instance();
235 } 246 }
236 } 247 }
237 return; 248 return;
@@ -240,12 +251,14 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
240static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, 251static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
241 int trapnr) 252 int trapnr)
242{ 253{
254 struct kprobe *cur = __get_cpu_var(kprobe_instance);
255
243 /* 256 /*
244 * if we faulted "during" the execution of a user specified 257 * if we faulted "during" the execution of a user specified
245 * probe handler, invoke just that probe's fault handler 258 * probe handler, invoke just that probe's fault handler
246 */ 259 */
247 if (curr_kprobe && curr_kprobe->fault_handler) { 260 if (cur && cur->fault_handler) {
248 if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr)) 261 if (cur->fault_handler(cur, regs, trapnr))
249 return 1; 262 return 1;
250 } 263 }
251 return 0; 264 return 0;
@@ -253,15 +266,15 @@ static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
253 266
254static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) 267static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
255{ 268{
256 struct kprobe *kp = curr_kprobe; 269 struct kprobe *cur = __get_cpu_var(kprobe_instance);
257 if (curr_kprobe && kp->break_handler) { 270 int ret = 0;
258 if (kp->break_handler(kp, regs)) { 271
259 curr_kprobe = NULL; 272 if (cur && cur->break_handler) {
260 return 1; 273 if (cur->break_handler(cur, regs))
261 } 274 ret = 1;
262 } 275 }
263 curr_kprobe = NULL; 276 reset_kprobe_instance();
264 return 0; 277 return ret;
265} 278}
266 279
267struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) 280struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)