diff options
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 35 |
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 | ||
247 | no_kprobe: | 250 | no_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 | ||
481 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 483 | int __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 | ||
503 | void __kprobes jprobe_return(void) | 505 | void __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" |