aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/kprobes.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 6345b430b105..fd35039859e6 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -158,8 +158,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
158 kprobe_opcode_t *addr = NULL; 158 kprobe_opcode_t *addr = NULL;
159 unsigned long *lp; 159 unsigned long *lp;
160 160
161 /* We're in an interrupt, but this is clear and BUG()-safe. */
162 preempt_disable();
163 /* Check if the application is using LDT entry for its code segment and 161 /* Check if the application is using LDT entry for its code segment and
164 * calculate the address by reading the base address from the LDT entry. 162 * calculate the address by reading the base address from the LDT entry.
165 */ 163 */
@@ -232,6 +230,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
232 goto no_kprobe; 230 goto no_kprobe;
233 } 231 }
234 232
233 /*
234 * This preempt_disable() matches the preempt_enable_no_resched()
235 * in post_kprobe_handler()
236 */
237 preempt_disable();
235 kprobe_status = KPROBE_HIT_ACTIVE; 238 kprobe_status = KPROBE_HIT_ACTIVE;
236 set_current_kprobe(p, regs); 239 set_current_kprobe(p, regs);
237 240
@@ -245,7 +248,6 @@ ss_probe:
245 return 1; 248 return 1;
246 249
247no_kprobe: 250no_kprobe:
248 preempt_enable_no_resched();
249 return ret; 251 return ret;
250} 252}
251 253
@@ -313,11 +315,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
313 unlock_kprobes(); 315 unlock_kprobes();
314 preempt_enable_no_resched(); 316 preempt_enable_no_resched();
315 317
316 /* 318 /*
317 * By returning a non-zero value, we are telling 319 * By returning a non-zero value, we are telling
318 * kprobe_handler() that we have handled unlocking 320 * kprobe_handler() that we have handled unlocking
319 * and re-enabling preemption. 321 * and re-enabling preemption
320 */ 322 */
321 return 1; 323 return 1;
322} 324}
323 325
@@ -453,29 +455,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
453 unsigned long val, void *data) 455 unsigned long val, void *data)
454{ 456{
455 struct die_args *args = (struct die_args *)data; 457 struct die_args *args = (struct die_args *)data;
458 int ret = NOTIFY_DONE;
459
460 preempt_disable();
456 switch (val) { 461 switch (val) {
457 case DIE_INT3: 462 case DIE_INT3:
458 if (kprobe_handler(args->regs)) 463 if (kprobe_handler(args->regs))
459 return NOTIFY_STOP; 464 ret = NOTIFY_STOP;
460 break; 465 break;
461 case DIE_DEBUG: 466 case DIE_DEBUG:
462 if (post_kprobe_handler(args->regs)) 467 if (post_kprobe_handler(args->regs))
463 return NOTIFY_STOP; 468 ret = NOTIFY_STOP;
464 break; 469 break;
465 case DIE_GPF: 470 case DIE_GPF:
466 if (kprobe_running() &&
467 kprobe_fault_handler(args->regs, args->trapnr))
468 return NOTIFY_STOP;
469 break;
470 case DIE_PAGE_FAULT: 471 case DIE_PAGE_FAULT:
471 if (kprobe_running() && 472 if (kprobe_running() &&
472 kprobe_fault_handler(args->regs, args->trapnr)) 473 kprobe_fault_handler(args->regs, args->trapnr))
473 return NOTIFY_STOP; 474 ret = NOTIFY_STOP;
474 break; 475 break;
475 default: 476 default:
476 break; 477 break;
477 } 478 }
478 return NOTIFY_DONE; 479 preempt_enable();
480 return ret;
479} 481}
480 482
481int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 483int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -502,7 +504,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
502 504
503void __kprobes jprobe_return(void) 505void __kprobes jprobe_return(void)
504{ 506{
505 preempt_enable_no_resched();
506 asm volatile (" xchgl %%ebx,%%esp \n" 507 asm volatile (" xchgl %%ebx,%%esp \n"
507 " int3 \n" 508 " int3 \n"
508 " .globl jprobe_return_end \n" 509 " .globl jprobe_return_end \n"