diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 35 | ||||
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 22 | ||||
-rw-r--r-- | arch/ppc64/kernel/kprobes.c | 11 | ||||
-rw-r--r-- | arch/sparc64/kernel/kprobes.c | 25 | ||||
-rw-r--r-- | arch/x86_64/kernel/kprobes.c | 28 |
5 files changed, 65 insertions, 56 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" |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 471086b808a4..1e80ec80dd21 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -395,7 +395,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
395 | /* | 395 | /* |
396 | * By returning a non-zero value, we are telling | 396 | * By returning a non-zero value, we are telling |
397 | * kprobe_handler() that we have handled unlocking | 397 | * kprobe_handler() that we have handled unlocking |
398 | * and re-enabling preemption. | 398 | * and re-enabling preemption |
399 | */ | 399 | */ |
400 | return 1; | 400 | return 1; |
401 | } | 401 | } |
@@ -607,8 +607,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) | |||
607 | struct pt_regs *regs = args->regs; | 607 | struct pt_regs *regs = args->regs; |
608 | kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); | 608 | kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); |
609 | 609 | ||
610 | preempt_disable(); | ||
611 | |||
612 | /* Handle recursion cases */ | 610 | /* Handle recursion cases */ |
613 | if (kprobe_running()) { | 611 | if (kprobe_running()) { |
614 | p = get_kprobe(addr); | 612 | p = get_kprobe(addr); |
@@ -665,6 +663,11 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) | |||
665 | goto no_kprobe; | 663 | goto no_kprobe; |
666 | } | 664 | } |
667 | 665 | ||
666 | /* | ||
667 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
668 | * in post_kprobes_handler() | ||
669 | */ | ||
670 | preempt_disable(); | ||
668 | kprobe_status = KPROBE_HIT_ACTIVE; | 671 | kprobe_status = KPROBE_HIT_ACTIVE; |
669 | set_current_kprobe(p); | 672 | set_current_kprobe(p); |
670 | 673 | ||
@@ -682,7 +685,6 @@ ss_probe: | |||
682 | return 1; | 685 | return 1; |
683 | 686 | ||
684 | no_kprobe: | 687 | no_kprobe: |
685 | preempt_enable_no_resched(); | ||
686 | return ret; | 688 | return ret; |
687 | } | 689 | } |
688 | 690 | ||
@@ -733,22 +735,26 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
733 | unsigned long val, void *data) | 735 | unsigned long val, void *data) |
734 | { | 736 | { |
735 | struct die_args *args = (struct die_args *)data; | 737 | struct die_args *args = (struct die_args *)data; |
738 | int ret = NOTIFY_DONE; | ||
739 | |||
740 | preempt_disable(); | ||
736 | switch(val) { | 741 | switch(val) { |
737 | case DIE_BREAK: | 742 | case DIE_BREAK: |
738 | if (pre_kprobes_handler(args)) | 743 | if (pre_kprobes_handler(args)) |
739 | return NOTIFY_STOP; | 744 | ret = NOTIFY_STOP; |
740 | break; | 745 | break; |
741 | case DIE_SS: | 746 | case DIE_SS: |
742 | if (post_kprobes_handler(args->regs)) | 747 | if (post_kprobes_handler(args->regs)) |
743 | return NOTIFY_STOP; | 748 | ret = NOTIFY_STOP; |
744 | break; | 749 | break; |
745 | case DIE_PAGE_FAULT: | 750 | case DIE_PAGE_FAULT: |
746 | if (kprobes_fault_handler(args->regs, args->trapnr)) | 751 | if (kprobes_fault_handler(args->regs, args->trapnr)) |
747 | return NOTIFY_STOP; | 752 | ret = NOTIFY_STOP; |
748 | default: | 753 | default: |
749 | break; | 754 | break; |
750 | } | 755 | } |
751 | return NOTIFY_DONE; | 756 | preempt_enable(); |
757 | return ret; | ||
752 | } | 758 | } |
753 | 759 | ||
754 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 760 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index ed876a5178ae..6071ee99f5cb 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c | |||
@@ -209,6 +209,11 @@ static inline int kprobe_handler(struct pt_regs *regs) | |||
209 | goto no_kprobe; | 209 | goto no_kprobe; |
210 | } | 210 | } |
211 | 211 | ||
212 | /* | ||
213 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
214 | * in post_kprobe_handler(). | ||
215 | */ | ||
216 | preempt_disable(); | ||
212 | kprobe_status = KPROBE_HIT_ACTIVE; | 217 | kprobe_status = KPROBE_HIT_ACTIVE; |
213 | current_kprobe = p; | 218 | current_kprobe = p; |
214 | kprobe_saved_msr = regs->msr; | 219 | kprobe_saved_msr = regs->msr; |
@@ -219,11 +224,6 @@ static inline int kprobe_handler(struct pt_regs *regs) | |||
219 | ss_probe: | 224 | ss_probe: |
220 | prepare_singlestep(p, regs); | 225 | prepare_singlestep(p, regs); |
221 | kprobe_status = KPROBE_HIT_SS; | 226 | kprobe_status = KPROBE_HIT_SS; |
222 | /* | ||
223 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
224 | * in post_kprobe_handler(). | ||
225 | */ | ||
226 | preempt_disable(); | ||
227 | return 1; | 227 | return 1; |
228 | 228 | ||
229 | no_kprobe: | 229 | no_kprobe: |
@@ -293,6 +293,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
293 | regs->nip = orig_ret_address; | 293 | regs->nip = orig_ret_address; |
294 | 294 | ||
295 | unlock_kprobes(); | 295 | unlock_kprobes(); |
296 | preempt_enable_no_resched(); | ||
296 | 297 | ||
297 | /* | 298 | /* |
298 | * By returning a non-zero value, we are telling | 299 | * By returning a non-zero value, we are telling |
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 0d66d07c8c6e..755a0d7d887f 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c | |||
@@ -118,8 +118,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
118 | void *addr = (void *) regs->tpc; | 118 | void *addr = (void *) regs->tpc; |
119 | int ret = 0; | 119 | int ret = 0; |
120 | 120 | ||
121 | preempt_disable(); | ||
122 | |||
123 | if (kprobe_running()) { | 121 | if (kprobe_running()) { |
124 | /* We *are* holding lock here, so this is safe. | 122 | /* We *are* holding lock here, so this is safe. |
125 | * Disarm the probe we just hit, and ignore it. | 123 | * Disarm the probe we just hit, and ignore it. |
@@ -171,6 +169,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
171 | goto no_kprobe; | 169 | goto no_kprobe; |
172 | } | 170 | } |
173 | 171 | ||
172 | /* | ||
173 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
174 | * in post_kprobes_handler() | ||
175 | */ | ||
176 | preempt_disable(); | ||
174 | set_current_kprobe(p, regs); | 177 | set_current_kprobe(p, regs); |
175 | kprobe_status = KPROBE_HIT_ACTIVE; | 178 | kprobe_status = KPROBE_HIT_ACTIVE; |
176 | if (p->pre_handler && p->pre_handler(p, regs)) | 179 | if (p->pre_handler && p->pre_handler(p, regs)) |
@@ -182,7 +185,6 @@ ss_probe: | |||
182 | return 1; | 185 | return 1; |
183 | 186 | ||
184 | no_kprobe: | 187 | no_kprobe: |
185 | preempt_enable_no_resched(); | ||
186 | return ret; | 188 | return ret; |
187 | } | 189 | } |
188 | 190 | ||
@@ -322,29 +324,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
322 | unsigned long val, void *data) | 324 | unsigned long val, void *data) |
323 | { | 325 | { |
324 | struct die_args *args = (struct die_args *)data; | 326 | struct die_args *args = (struct die_args *)data; |
327 | int ret = NOTIFY_DONE; | ||
328 | |||
329 | preempt_disable(); | ||
325 | switch (val) { | 330 | switch (val) { |
326 | case DIE_DEBUG: | 331 | case DIE_DEBUG: |
327 | if (kprobe_handler(args->regs)) | 332 | if (kprobe_handler(args->regs)) |
328 | return NOTIFY_STOP; | 333 | ret = NOTIFY_STOP; |
329 | break; | 334 | break; |
330 | case DIE_DEBUG_2: | 335 | case DIE_DEBUG_2: |
331 | if (post_kprobe_handler(args->regs)) | 336 | if (post_kprobe_handler(args->regs)) |
332 | return NOTIFY_STOP; | 337 | ret = NOTIFY_STOP; |
333 | break; | 338 | break; |
334 | case DIE_GPF: | 339 | case DIE_GPF: |
335 | if (kprobe_running() && | ||
336 | kprobe_fault_handler(args->regs, args->trapnr)) | ||
337 | return NOTIFY_STOP; | ||
338 | break; | ||
339 | case DIE_PAGE_FAULT: | 340 | case DIE_PAGE_FAULT: |
340 | if (kprobe_running() && | 341 | if (kprobe_running() && |
341 | kprobe_fault_handler(args->regs, args->trapnr)) | 342 | kprobe_fault_handler(args->regs, args->trapnr)) |
342 | return NOTIFY_STOP; | 343 | ret = NOTIFY_STOP; |
343 | break; | 344 | break; |
344 | default: | 345 | default: |
345 | break; | 346 | break; |
346 | } | 347 | } |
347 | return NOTIFY_DONE; | 348 | preempt_enable(); |
349 | return ret; | ||
348 | } | 350 | } |
349 | 351 | ||
350 | asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, | 352 | asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, |
@@ -396,7 +398,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
396 | 398 | ||
397 | void __kprobes jprobe_return(void) | 399 | void __kprobes jprobe_return(void) |
398 | { | 400 | { |
399 | preempt_enable_no_resched(); | ||
400 | __asm__ __volatile__( | 401 | __asm__ __volatile__( |
401 | ".globl jprobe_return_trap_instruction\n" | 402 | ".globl jprobe_return_trap_instruction\n" |
402 | "jprobe_return_trap_instruction:\n\t" | 403 | "jprobe_return_trap_instruction:\n\t" |
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 76a28b007be9..ebfa2c9241ca 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c | |||
@@ -302,9 +302,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
302 | int ret = 0; | 302 | int ret = 0; |
303 | kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); | 303 | kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); |
304 | 304 | ||
305 | /* We're in an interrupt, but this is clear and BUG()-safe. */ | ||
306 | preempt_disable(); | ||
307 | |||
308 | /* Check we're not actually recursing */ | 305 | /* Check we're not actually recursing */ |
309 | if (kprobe_running()) { | 306 | if (kprobe_running()) { |
310 | /* We *are* holding lock here, so this is safe. | 307 | /* We *are* holding lock here, so this is safe. |
@@ -372,6 +369,11 @@ int __kprobes kprobe_handler(struct pt_regs *regs) | |||
372 | goto no_kprobe; | 369 | goto no_kprobe; |
373 | } | 370 | } |
374 | 371 | ||
372 | /* | ||
373 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
374 | * in post_kprobe_handler() | ||
375 | */ | ||
376 | preempt_disable(); | ||
375 | kprobe_status = KPROBE_HIT_ACTIVE; | 377 | kprobe_status = KPROBE_HIT_ACTIVE; |
376 | set_current_kprobe(p, regs); | 378 | set_current_kprobe(p, regs); |
377 | 379 | ||
@@ -385,7 +387,6 @@ ss_probe: | |||
385 | return 1; | 387 | return 1; |
386 | 388 | ||
387 | no_kprobe: | 389 | no_kprobe: |
388 | preempt_enable_no_resched(); | ||
389 | return ret; | 390 | return ret; |
390 | } | 391 | } |
391 | 392 | ||
@@ -456,7 +457,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
456 | /* | 457 | /* |
457 | * By returning a non-zero value, we are telling | 458 | * By returning a non-zero value, we are telling |
458 | * kprobe_handler() that we have handled unlocking | 459 | * kprobe_handler() that we have handled unlocking |
459 | * and re-enabling preemption. | 460 | * and re-enabling preemption |
460 | */ | 461 | */ |
461 | return 1; | 462 | return 1; |
462 | } | 463 | } |
@@ -599,29 +600,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
599 | unsigned long val, void *data) | 600 | unsigned long val, void *data) |
600 | { | 601 | { |
601 | struct die_args *args = (struct die_args *)data; | 602 | struct die_args *args = (struct die_args *)data; |
603 | int ret = NOTIFY_DONE; | ||
604 | |||
605 | preempt_disable(); | ||
602 | switch (val) { | 606 | switch (val) { |
603 | case DIE_INT3: | 607 | case DIE_INT3: |
604 | if (kprobe_handler(args->regs)) | 608 | if (kprobe_handler(args->regs)) |
605 | return NOTIFY_STOP; | 609 | ret = NOTIFY_STOP; |
606 | break; | 610 | break; |
607 | case DIE_DEBUG: | 611 | case DIE_DEBUG: |
608 | if (post_kprobe_handler(args->regs)) | 612 | if (post_kprobe_handler(args->regs)) |
609 | return NOTIFY_STOP; | 613 | ret = NOTIFY_STOP; |
610 | break; | 614 | break; |
611 | case DIE_GPF: | 615 | case DIE_GPF: |
612 | if (kprobe_running() && | ||
613 | kprobe_fault_handler(args->regs, args->trapnr)) | ||
614 | return NOTIFY_STOP; | ||
615 | break; | ||
616 | case DIE_PAGE_FAULT: | 616 | case DIE_PAGE_FAULT: |
617 | if (kprobe_running() && | 617 | if (kprobe_running() && |
618 | kprobe_fault_handler(args->regs, args->trapnr)) | 618 | kprobe_fault_handler(args->regs, args->trapnr)) |
619 | return NOTIFY_STOP; | 619 | ret = NOTIFY_STOP; |
620 | break; | 620 | break; |
621 | default: | 621 | default: |
622 | break; | 622 | break; |
623 | } | 623 | } |
624 | return NOTIFY_DONE; | 624 | preempt_enable(); |
625 | return ret; | ||
625 | } | 626 | } |
626 | 627 | ||
627 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 628 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
@@ -647,7 +648,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
647 | 648 | ||
648 | void __kprobes jprobe_return(void) | 649 | void __kprobes jprobe_return(void) |
649 | { | 650 | { |
650 | preempt_enable_no_resched(); | ||
651 | asm volatile (" xchg %%rbx,%%rsp \n" | 651 | asm volatile (" xchg %%rbx,%%rsp \n" |
652 | " int3 \n" | 652 | " int3 \n" |
653 | " .globl jprobe_return_end \n" | 653 | " .globl jprobe_return_end \n" |