aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r--arch/i386/kernel/kprobes.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index ad469299267a..32b0c24ab9a6 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -153,7 +153,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
153 int ret = 0; 153 int ret = 0;
154 kprobe_opcode_t *addr = NULL; 154 kprobe_opcode_t *addr = NULL;
155 unsigned long *lp; 155 unsigned long *lp;
156 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 156 struct kprobe_ctlblk *kcb;
157
158 /*
159 * We don't want to be preempted for the entire
160 * duration of kprobe processing
161 */
162 preempt_disable();
163 kcb = get_kprobe_ctlblk();
157 164
158 /* Check if the application is using LDT entry for its code segment and 165 /* Check if the application is using LDT entry for its code segment and
159 * calculate the address by reading the base address from the LDT entry. 166 * calculate the address by reading the base address from the LDT entry.
@@ -221,11 +228,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
221 goto no_kprobe; 228 goto no_kprobe;
222 } 229 }
223 230
224 /*
225 * This preempt_disable() matches the preempt_enable_no_resched()
226 * in post_kprobe_handler()
227 */
228 preempt_disable();
229 set_current_kprobe(p, regs, kcb); 231 set_current_kprobe(p, regs, kcb);
230 kcb->kprobe_status = KPROBE_HIT_ACTIVE; 232 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
231 233
@@ -239,6 +241,7 @@ ss_probe:
239 return 1; 241 return 1;
240 242
241no_kprobe: 243no_kprobe:
244 preempt_enable_no_resched();
242 return ret; 245 return ret;
243} 246}
244 247
@@ -310,8 +313,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
310 313
311 /* 314 /*
312 * By returning a non-zero value, we are telling 315 * By returning a non-zero value, we are telling
313 * kprobe_handler() that we have handled unlocking 316 * kprobe_handler() that we don't want the post_handler
314 * and re-enabling preemption 317 * to run (and have re-enabled preemption)
315 */ 318 */
316 return 1; 319 return 1;
317} 320}
@@ -455,7 +458,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
455 struct die_args *args = (struct die_args *)data; 458 struct die_args *args = (struct die_args *)data;
456 int ret = NOTIFY_DONE; 459 int ret = NOTIFY_DONE;
457 460
458 rcu_read_lock();
459 switch (val) { 461 switch (val) {
460 case DIE_INT3: 462 case DIE_INT3:
461 if (kprobe_handler(args->regs)) 463 if (kprobe_handler(args->regs))
@@ -467,14 +469,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
467 break; 469 break;
468 case DIE_GPF: 470 case DIE_GPF:
469 case DIE_PAGE_FAULT: 471 case DIE_PAGE_FAULT:
472 /* kprobe_running() needs smp_processor_id() */
473 preempt_disable();
470 if (kprobe_running() && 474 if (kprobe_running() &&
471 kprobe_fault_handler(args->regs, args->trapnr)) 475 kprobe_fault_handler(args->regs, args->trapnr))
472 ret = NOTIFY_STOP; 476 ret = NOTIFY_STOP;
477 preempt_enable();
473 break; 478 break;
474 default: 479 default:
475 break; 480 break;
476 } 481 }
477 rcu_read_unlock();
478 return ret; 482 return ret;
479} 483}
480 484
@@ -537,6 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
537 *regs = kcb->jprobe_saved_regs; 541 *regs = kcb->jprobe_saved_regs;
538 memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, 542 memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
539 MIN_STACK_SIZE(stack_addr)); 543 MIN_STACK_SIZE(stack_addr));
544 preempt_enable_no_resched();
540 return 1; 545 return 1;
541 } 546 }
542 return 0; 547 return 0;