diff options
author | Bodo Stroesser <bstroesser@fujitsu-siemens.com> | 2005-09-03 18:57:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:06:20 -0400 |
commit | c8c86cecd1d1a2722acb28a01d1babf7b6993697 (patch) | |
tree | e51097940d245b298278ffaac27d2992b0ac257b /arch/i386/kernel/ptrace.c | |
parent | ed75e8d58010fdc06e2c3a81bfbebae92314c7e3 (diff) |
[PATCH] Uml support: reorganize PTRACE_SYSEMU support
With this patch, we change the way we handle switching from PTRACE_SYSEMU to
PTRACE_{SINGLESTEP,SYSCALL}, to free TIF_SYSCALL_EMU from double use as a
preparation for PTRACE_SYSEMU_SINGLESTEP extension, without changing the
behavior of the host kernel.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/ptrace.c')
-rw-r--r-- | arch/i386/kernel/ptrace.c | 43 |
1 files changed, 14 insertions, 29 deletions
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 5b569dc1c227..18642f05dde1 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
@@ -515,21 +515,14 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) | |||
515 | ret = -EIO; | 515 | ret = -EIO; |
516 | if (!valid_signal(data)) | 516 | if (!valid_signal(data)) |
517 | break; | 517 | break; |
518 | /* If we came here with PTRACE_SYSEMU and now continue with | ||
519 | * PTRACE_SYSCALL, entry.S used to intercept the syscall return. | ||
520 | * But it shouldn't! | ||
521 | * So we don't clear TIF_SYSCALL_EMU, which is always unused in | ||
522 | * this special case, to remember, we came from SYSEMU. That | ||
523 | * flag will be cleared by do_syscall_trace(). | ||
524 | */ | ||
525 | if (request == PTRACE_SYSEMU) { | 518 | if (request == PTRACE_SYSEMU) { |
526 | set_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 519 | set_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
527 | } else if (request == PTRACE_CONT) { | 520 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
528 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 521 | } else if (request == PTRACE_SYSCALL) { |
529 | } | ||
530 | if (request == PTRACE_SYSCALL) { | ||
531 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 522 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
523 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
532 | } else { | 524 | } else { |
525 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
533 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 526 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
534 | } | 527 | } |
535 | child->exit_code = data; | 528 | child->exit_code = data; |
@@ -558,8 +551,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) | |||
558 | ret = -EIO; | 551 | ret = -EIO; |
559 | if (!valid_signal(data)) | 552 | if (!valid_signal(data)) |
560 | break; | 553 | break; |
561 | /*See do_syscall_trace to know why we don't clear | 554 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
562 | * TIF_SYSCALL_EMU.*/ | ||
563 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 555 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
564 | set_singlestep(child); | 556 | set_singlestep(child); |
565 | child->exit_code = data; | 557 | child->exit_code = data; |
@@ -694,7 +686,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | |||
694 | __attribute__((regparm(3))) | 686 | __attribute__((regparm(3))) |
695 | int do_syscall_trace(struct pt_regs *regs, int entryexit) | 687 | int do_syscall_trace(struct pt_regs *regs, int entryexit) |
696 | { | 688 | { |
697 | int is_sysemu, is_systrace, is_singlestep, ret = 0; | 689 | int is_sysemu, is_singlestep, ret = 0; |
698 | /* do the secure computing check first */ | 690 | /* do the secure computing check first */ |
699 | secure_computing(regs->orig_eax); | 691 | secure_computing(regs->orig_eax); |
700 | 692 | ||
@@ -705,25 +697,13 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit) | |||
705 | goto out; | 697 | goto out; |
706 | 698 | ||
707 | is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); | 699 | is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); |
708 | is_systrace = test_thread_flag(TIF_SYSCALL_TRACE); | ||
709 | is_singlestep = test_thread_flag(TIF_SINGLESTEP); | 700 | is_singlestep = test_thread_flag(TIF_SINGLESTEP); |
710 | 701 | ||
711 | /* We can detect the case of coming from PTRACE_SYSEMU and now running | ||
712 | * with PTRACE_SYSCALL or PTRACE_SINGLESTEP, by TIF_SYSCALL_EMU being | ||
713 | * set additionally. | ||
714 | * If so let's reset the flag and return without action (no singlestep | ||
715 | * nor syscall tracing, since no actual step has been executed). | ||
716 | */ | ||
717 | if (is_sysemu && (is_systrace || is_singlestep)) { | ||
718 | clear_thread_flag(TIF_SYSCALL_EMU); | ||
719 | goto out; | ||
720 | } | ||
721 | |||
722 | /* Fake a debug trap */ | 702 | /* Fake a debug trap */ |
723 | if (test_thread_flag(TIF_SINGLESTEP)) | 703 | if (is_singlestep) |
724 | send_sigtrap(current, regs, 0); | 704 | send_sigtrap(current, regs, 0); |
725 | 705 | ||
726 | if (!is_systrace && !is_sysemu) | 706 | if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu) |
727 | goto out; | 707 | goto out; |
728 | 708 | ||
729 | /* the 0x80 provides a way for the tracing parent to distinguish | 709 | /* the 0x80 provides a way for the tracing parent to distinguish |
@@ -745,5 +725,10 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit) | |||
745 | if (unlikely(current->audit_context) && !entryexit) | 725 | if (unlikely(current->audit_context) && !entryexit) |
746 | audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax, | 726 | audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax, |
747 | regs->ebx, regs->ecx, regs->edx, regs->esi); | 727 | regs->ebx, regs->ecx, regs->edx, regs->esi); |
748 | return ret; | 728 | if (ret == 0) |
729 | return 0; | ||
730 | |||
731 | if (unlikely(current->audit_context)) | ||
732 | audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax); | ||
733 | return 1; | ||
749 | } | 734 | } |