aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnanth N Mavinakayanahalli <ananth@in.ibm.com>2005-11-07 04:00:08 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:45 -0500
commit9a0e3a86837ac7542e601c18346102c9d9e65fa5 (patch)
tree0e58782bfe2be7c1dd82e254df9d4d0fea6781bd
parente65845235c8120be63001fc1a4ac00c819194bbe (diff)
[PATCH] Kprobes: Track kprobe on a per_cpu basis - i386 changes
I386 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu, using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/kprobes.c126
-rw-r--r--include/asm-i386/kprobes.h17
2 files changed, 86 insertions, 57 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index fd35039859e6..99565a66915d 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -37,16 +37,11 @@
37#include <asm/kdebug.h> 37#include <asm/kdebug.h>
38#include <asm/desc.h> 38#include <asm/desc.h>
39 39
40static struct kprobe *current_kprobe;
41static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
42static struct kprobe *kprobe_prev;
43static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
44static struct pt_regs jprobe_saved_regs;
45static long *jprobe_saved_esp;
46/* copy of the kernel stack at the probe fire time */
47static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
48void jprobe_return_end(void); 40void jprobe_return_end(void);
49 41
42DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
43DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
44
50/* 45/*
51 * returns non-zero if opcode modifies the interrupt flag. 46 * returns non-zero if opcode modifies the interrupt flag.
52 */ 47 */
@@ -91,29 +86,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
91{ 86{
92} 87}
93 88
94static inline void save_previous_kprobe(void) 89static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
95{ 90{
96 kprobe_prev = current_kprobe; 91 kcb->prev_kprobe.kp = kprobe_running();
97 kprobe_status_prev = kprobe_status; 92 kcb->prev_kprobe.status = kcb->kprobe_status;
98 kprobe_old_eflags_prev = kprobe_old_eflags; 93 kcb->prev_kprobe.old_eflags = kcb->kprobe_old_eflags;
99 kprobe_saved_eflags_prev = kprobe_saved_eflags; 94 kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
100} 95}
101 96
102static inline void restore_previous_kprobe(void) 97static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
103{ 98{
104 current_kprobe = kprobe_prev; 99 __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
105 kprobe_status = kprobe_status_prev; 100 kcb->kprobe_status = kcb->prev_kprobe.status;
106 kprobe_old_eflags = kprobe_old_eflags_prev; 101 kcb->kprobe_old_eflags = kcb->prev_kprobe.old_eflags;
107 kprobe_saved_eflags = kprobe_saved_eflags_prev; 102 kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
108} 103}
109 104
110static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) 105static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
106 struct kprobe_ctlblk *kcb)
111{ 107{
112 current_kprobe = p; 108 __get_cpu_var(current_kprobe) = p;
113 kprobe_saved_eflags = kprobe_old_eflags 109 kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags
114 = (regs->eflags & (TF_MASK | IF_MASK)); 110 = (regs->eflags & (TF_MASK | IF_MASK));
115 if (is_IF_modifier(p->opcode)) 111 if (is_IF_modifier(p->opcode))
116 kprobe_saved_eflags &= ~IF_MASK; 112 kcb->kprobe_saved_eflags &= ~IF_MASK;
117} 113}
118 114
119static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) 115static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -157,6 +153,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
157 int ret = 0; 153 int ret = 0;
158 kprobe_opcode_t *addr = NULL; 154 kprobe_opcode_t *addr = NULL;
159 unsigned long *lp; 155 unsigned long *lp;
156 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
160 157
161 /* Check if the application is using LDT entry for its code segment and 158 /* Check if the application is using LDT entry for its code segment and
162 * calculate the address by reading the base address from the LDT entry. 159 * calculate the address by reading the base address from the LDT entry.
@@ -175,10 +172,10 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
175 Disarm the probe we just hit, and ignore it. */ 172 Disarm the probe we just hit, and ignore it. */
176 p = get_kprobe(addr); 173 p = get_kprobe(addr);
177 if (p) { 174 if (p) {
178 if (kprobe_status == KPROBE_HIT_SS && 175 if (kcb->kprobe_status == KPROBE_HIT_SS &&
179 *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { 176 *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
180 regs->eflags &= ~TF_MASK; 177 regs->eflags &= ~TF_MASK;
181 regs->eflags |= kprobe_saved_eflags; 178 regs->eflags |= kcb->kprobe_saved_eflags;
182 unlock_kprobes(); 179 unlock_kprobes();
183 goto no_kprobe; 180 goto no_kprobe;
184 } 181 }
@@ -188,14 +185,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
188 * just single step on the instruction of the new probe 185 * just single step on the instruction of the new probe
189 * without calling any user handlers. 186 * without calling any user handlers.
190 */ 187 */
191 save_previous_kprobe(); 188 save_previous_kprobe(kcb);
192 set_current_kprobe(p, regs); 189 set_current_kprobe(p, regs, kcb);
193 p->nmissed++; 190 p->nmissed++;
194 prepare_singlestep(p, regs); 191 prepare_singlestep(p, regs);
195 kprobe_status = KPROBE_REENTER; 192 kcb->kprobe_status = KPROBE_REENTER;
196 return 1; 193 return 1;
197 } else { 194 } else {
198 p = current_kprobe; 195 p = __get_cpu_var(current_kprobe);
199 if (p->break_handler && p->break_handler(p, regs)) { 196 if (p->break_handler && p->break_handler(p, regs)) {
200 goto ss_probe; 197 goto ss_probe;
201 } 198 }
@@ -235,8 +232,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
235 * in post_kprobe_handler() 232 * in post_kprobe_handler()
236 */ 233 */
237 preempt_disable(); 234 preempt_disable();
238 kprobe_status = KPROBE_HIT_ACTIVE; 235 set_current_kprobe(p, regs, kcb);
239 set_current_kprobe(p, regs); 236 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
240 237
241 if (p->pre_handler && p->pre_handler(p, regs)) 238 if (p->pre_handler && p->pre_handler(p, regs))
242 /* handler has already set things up, so skip ss setup */ 239 /* handler has already set things up, so skip ss setup */
@@ -244,7 +241,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
244 241
245ss_probe: 242ss_probe:
246 prepare_singlestep(p, regs); 243 prepare_singlestep(p, regs);
247 kprobe_status = KPROBE_HIT_SS; 244 kcb->kprobe_status = KPROBE_HIT_SS;
248 return 1; 245 return 1;
249 246
250no_kprobe: 247no_kprobe:
@@ -312,6 +309,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
312 BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); 309 BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
313 regs->eip = orig_ret_address; 310 regs->eip = orig_ret_address;
314 311
312 reset_current_kprobe();
315 unlock_kprobes(); 313 unlock_kprobes();
316 preempt_enable_no_resched(); 314 preempt_enable_no_resched();
317 315
@@ -345,7 +343,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
345 * that is atop the stack is the address following the copied instruction. 343 * that is atop the stack is the address following the copied instruction.
346 * We need to make it the address following the original instruction. 344 * We need to make it the address following the original instruction.
347 */ 345 */
348static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) 346static void __kprobes resume_execution(struct kprobe *p,
347 struct pt_regs *regs, struct kprobe_ctlblk *kcb)
349{ 348{
350 unsigned long *tos = (unsigned long *)&regs->esp; 349 unsigned long *tos = (unsigned long *)&regs->esp;
351 unsigned long next_eip = 0; 350 unsigned long next_eip = 0;
@@ -355,7 +354,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
355 switch (p->ainsn.insn[0]) { 354 switch (p->ainsn.insn[0]) {
356 case 0x9c: /* pushfl */ 355 case 0x9c: /* pushfl */
357 *tos &= ~(TF_MASK | IF_MASK); 356 *tos &= ~(TF_MASK | IF_MASK);
358 *tos |= kprobe_old_eflags; 357 *tos |= kcb->kprobe_old_eflags;
359 break; 358 break;
360 case 0xc3: /* ret/lret */ 359 case 0xc3: /* ret/lret */
361 case 0xcb: 360 case 0xcb:
@@ -400,22 +399,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
400 */ 399 */
401static inline int post_kprobe_handler(struct pt_regs *regs) 400static inline int post_kprobe_handler(struct pt_regs *regs)
402{ 401{
403 if (!kprobe_running()) 402 struct kprobe *cur = kprobe_running();
403 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
404
405 if (!cur)
404 return 0; 406 return 0;
405 407
406 if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { 408 if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
407 kprobe_status = KPROBE_HIT_SSDONE; 409 kcb->kprobe_status = KPROBE_HIT_SSDONE;
408 current_kprobe->post_handler(current_kprobe, regs, 0); 410 cur->post_handler(cur, regs, 0);
409 } 411 }
410 412
411 resume_execution(current_kprobe, regs); 413 resume_execution(cur, regs, kcb);
412 regs->eflags |= kprobe_saved_eflags; 414 regs->eflags |= kcb->kprobe_saved_eflags;
413 415
414 /*Restore back the original saved kprobes variables and continue. */ 416 /*Restore back the original saved kprobes variables and continue. */
415 if (kprobe_status == KPROBE_REENTER) { 417 if (kcb->kprobe_status == KPROBE_REENTER) {
416 restore_previous_kprobe(); 418 restore_previous_kprobe(kcb);
417 goto out; 419 goto out;
418 } 420 }
421 reset_current_kprobe();
419 unlock_kprobes(); 422 unlock_kprobes();
420out: 423out:
421 preempt_enable_no_resched(); 424 preempt_enable_no_resched();
@@ -434,14 +437,17 @@ out:
434/* Interrupts disabled, kprobe_lock held. */ 437/* Interrupts disabled, kprobe_lock held. */
435static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) 438static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
436{ 439{
437 if (current_kprobe->fault_handler 440 struct kprobe *cur = kprobe_running();
438 && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) 441 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
442
443 if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
439 return 1; 444 return 1;
440 445
441 if (kprobe_status & KPROBE_HIT_SS) { 446 if (kcb->kprobe_status & KPROBE_HIT_SS) {
442 resume_execution(current_kprobe, regs); 447 resume_execution(cur, regs, kcb);
443 regs->eflags |= kprobe_old_eflags; 448 regs->eflags |= kcb->kprobe_old_eflags;
444 449
450 reset_current_kprobe();
445 unlock_kprobes(); 451 unlock_kprobes();
446 preempt_enable_no_resched(); 452 preempt_enable_no_resched();
447 } 453 }
@@ -484,10 +490,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
484{ 490{
485 struct jprobe *jp = container_of(p, struct jprobe, kp); 491 struct jprobe *jp = container_of(p, struct jprobe, kp);
486 unsigned long addr; 492 unsigned long addr;
493 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
487 494
488 jprobe_saved_regs = *regs; 495 kcb->jprobe_saved_regs = *regs;
489 jprobe_saved_esp = &regs->esp; 496 kcb->jprobe_saved_esp = &regs->esp;
490 addr = (unsigned long)jprobe_saved_esp; 497 addr = (unsigned long)(kcb->jprobe_saved_esp);
491 498
492 /* 499 /*
493 * TBD: As Linus pointed out, gcc assumes that the callee 500 * TBD: As Linus pointed out, gcc assumes that the callee
@@ -496,7 +503,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
496 * we also save and restore enough stack bytes to cover 503 * we also save and restore enough stack bytes to cover
497 * the argument area. 504 * the argument area.
498 */ 505 */
499 memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr)); 506 memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
507 MIN_STACK_SIZE(addr));
500 regs->eflags &= ~IF_MASK; 508 regs->eflags &= ~IF_MASK;
501 regs->eip = (unsigned long)(jp->entry); 509 regs->eip = (unsigned long)(jp->entry);
502 return 1; 510 return 1;
@@ -504,34 +512,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
504 512
505void __kprobes jprobe_return(void) 513void __kprobes jprobe_return(void)
506{ 514{
515 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
516
507 asm volatile (" xchgl %%ebx,%%esp \n" 517 asm volatile (" xchgl %%ebx,%%esp \n"
508 " int3 \n" 518 " int3 \n"
509 " .globl jprobe_return_end \n" 519 " .globl jprobe_return_end \n"
510 " jprobe_return_end: \n" 520 " jprobe_return_end: \n"
511 " nop \n"::"b" 521 " nop \n"::"b"
512 (jprobe_saved_esp):"memory"); 522 (kcb->jprobe_saved_esp):"memory");
513} 523}
514 524
515int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 525int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
516{ 526{
527 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
517 u8 *addr = (u8 *) (regs->eip - 1); 528 u8 *addr = (u8 *) (regs->eip - 1);
518 unsigned long stack_addr = (unsigned long)jprobe_saved_esp; 529 unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp);
519 struct jprobe *jp = container_of(p, struct jprobe, kp); 530 struct jprobe *jp = container_of(p, struct jprobe, kp);
520 531
521 if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { 532 if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
522 if (&regs->esp != jprobe_saved_esp) { 533 if (&regs->esp != kcb->jprobe_saved_esp) {
523 struct pt_regs *saved_regs = 534 struct pt_regs *saved_regs =
524 container_of(jprobe_saved_esp, struct pt_regs, esp); 535 container_of(kcb->jprobe_saved_esp,
536 struct pt_regs, esp);
525 printk("current esp %p does not match saved esp %p\n", 537 printk("current esp %p does not match saved esp %p\n",
526 &regs->esp, jprobe_saved_esp); 538 &regs->esp, kcb->jprobe_saved_esp);
527 printk("Saved registers for jprobe %p\n", jp); 539 printk("Saved registers for jprobe %p\n", jp);
528 show_registers(saved_regs); 540 show_registers(saved_regs);
529 printk("Current registers\n"); 541 printk("Current registers\n");
530 show_registers(regs); 542 show_registers(regs);
531 BUG(); 543 BUG();
532 } 544 }
533 *regs = jprobe_saved_regs; 545 *regs = kcb->jprobe_saved_regs;
534 memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack, 546 memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
535 MIN_STACK_SIZE(stack_addr)); 547 MIN_STACK_SIZE(stack_addr));
536 return 1; 548 return 1;
537 } 549 }
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 8b6d3a90cd78..ca916a892877 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -49,6 +49,23 @@ struct arch_specific_insn {
49 kprobe_opcode_t insn[MAX_INSN_SIZE]; 49 kprobe_opcode_t insn[MAX_INSN_SIZE];
50}; 50};
51 51
52struct prev_kprobe {
53 struct kprobe *kp;
54 unsigned long status;
55 unsigned long old_eflags;
56 unsigned long saved_eflags;
57};
58
59/* per-cpu kprobe control block */
60struct kprobe_ctlblk {
61 unsigned long kprobe_status;
62 unsigned long kprobe_old_eflags;
63 unsigned long kprobe_saved_eflags;
64 long *jprobe_saved_esp;
65 struct pt_regs jprobe_saved_regs;
66 kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
67 struct prev_kprobe prev_kprobe;
68};
52 69
53/* trap3/1 are intr gates for kprobes. So, restore the status of IF, 70/* trap3/1 are intr gates for kprobes. So, restore the status of IF,
54 * if necessary, before executing the original int3/1 (trap) handler. 71 * if necessary, before executing the original int3/1 (trap) handler.