diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-03-23 10:14:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-25 13:53:29 -0400 |
commit | fee039a1d05c6e0f71b0fe270d847742a02d56c4 (patch) | |
tree | 8a876f852588e2ff4219ab29de4586b8a40556f9 /arch/x86/kernel/kprobes.c | |
parent | a524446fe82f7f38738403a5a080c4910af86a61 (diff) |
x86: kretprobe-booster interrupt emulation code fix
Fix interrupt emulation code in kretprobe-booster according to
pt_regs update (es/ds change and gs adding).
This issue has been reported on systemtap-bugzilla:
http://sources.redhat.com/bugzilla/show_bug.cgi?id=9965
| On a -tip kernel on x86_32, kretprobe_example (from samples) triggers the
| following backtrace when its retprobing a class of functions that cause a
| copy_from/to_user().
|
| BUG: sleeping function called from invalid context at mm/memory.c:3196
| in_atomic(): 0, irqs_disabled(): 1, pid: 2286, name: cat
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Tested-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Cc: systemtap-ml <systemtap@sources.redhat.com>
LKML-Reference: <49C7995C.2010601@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/kprobes.c')
-rw-r--r-- | arch/x86/kernel/kprobes.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 4558dd3918cf..759095d53a06 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
@@ -638,13 +638,13 @@ static void __used __kprobes kretprobe_trampoline_holder(void) | |||
638 | #else | 638 | #else |
639 | " pushf\n" | 639 | " pushf\n" |
640 | /* | 640 | /* |
641 | * Skip cs, ip, orig_ax. | 641 | * Skip cs, ip, orig_ax and gs. |
642 | * trampoline_handler() will plug in these values | 642 | * trampoline_handler() will plug in these values |
643 | */ | 643 | */ |
644 | " subl $12, %esp\n" | 644 | " subl $16, %esp\n" |
645 | " pushl %fs\n" | 645 | " pushl %fs\n" |
646 | " pushl %ds\n" | ||
647 | " pushl %es\n" | 646 | " pushl %es\n" |
647 | " pushl %ds\n" | ||
648 | " pushl %eax\n" | 648 | " pushl %eax\n" |
649 | " pushl %ebp\n" | 649 | " pushl %ebp\n" |
650 | " pushl %edi\n" | 650 | " pushl %edi\n" |
@@ -655,10 +655,10 @@ static void __used __kprobes kretprobe_trampoline_holder(void) | |||
655 | " movl %esp, %eax\n" | 655 | " movl %esp, %eax\n" |
656 | " call trampoline_handler\n" | 656 | " call trampoline_handler\n" |
657 | /* Move flags to cs */ | 657 | /* Move flags to cs */ |
658 | " movl 52(%esp), %edx\n" | 658 | " movl 56(%esp), %edx\n" |
659 | " movl %edx, 48(%esp)\n" | 659 | " movl %edx, 52(%esp)\n" |
660 | /* Replace saved flags with true return address. */ | 660 | /* Replace saved flags with true return address. */ |
661 | " movl %eax, 52(%esp)\n" | 661 | " movl %eax, 56(%esp)\n" |
662 | " popl %ebx\n" | 662 | " popl %ebx\n" |
663 | " popl %ecx\n" | 663 | " popl %ecx\n" |
664 | " popl %edx\n" | 664 | " popl %edx\n" |
@@ -666,8 +666,8 @@ static void __used __kprobes kretprobe_trampoline_holder(void) | |||
666 | " popl %edi\n" | 666 | " popl %edi\n" |
667 | " popl %ebp\n" | 667 | " popl %ebp\n" |
668 | " popl %eax\n" | 668 | " popl %eax\n" |
669 | /* Skip ip, orig_ax, es, ds, fs */ | 669 | /* Skip ds, es, fs, gs, orig_ax and ip */ |
670 | " addl $20, %esp\n" | 670 | " addl $24, %esp\n" |
671 | " popf\n" | 671 | " popf\n" |
672 | #endif | 672 | #endif |
673 | " ret\n"); | 673 | " ret\n"); |
@@ -691,6 +691,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
691 | regs->cs = __KERNEL_CS; | 691 | regs->cs = __KERNEL_CS; |
692 | #else | 692 | #else |
693 | regs->cs = __KERNEL_CS | get_kernel_rpl(); | 693 | regs->cs = __KERNEL_CS | get_kernel_rpl(); |
694 | regs->gs = 0; | ||
694 | #endif | 695 | #endif |
695 | regs->ip = trampoline_address; | 696 | regs->ip = trampoline_address; |
696 | regs->orig_ax = ~0UL; | 697 | regs->orig_ax = ~0UL; |