From: Bodo Stroesser This patch is based on 2.6.9-vanilla + host-skas3-2.6.9-v7.patch It reorganizes the code without changing the behavior of the host kernel. This is done to free TIF_SYSCALL_EMU from double use as a preparation for SYSEMU_SINGLESTEP extension. Signed-off-by: Bodo Stroesser Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- clean-linux-2.6.11-paolo/arch/i386/kernel/entry.S | 8 +++ clean-linux-2.6.11-paolo/arch/i386/kernel/ptrace.c | 43 +++++++-------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff -puN arch/i386/kernel/entry.S~sysemu-reorganize arch/i386/kernel/entry.S --- clean-linux-2.6.11/arch/i386/kernel/entry.S~sysemu-reorganize 2005-07-10 16:55:37.000000000 +0200 +++ clean-linux-2.6.11-paolo/arch/i386/kernel/entry.S 2005-07-10 16:57:35.000000000 +0200 @@ -305,12 +305,18 @@ syscall_trace_entry: xorl %edx,%edx call do_syscall_trace cmpl $0, %eax - jne syscall_exit # ret != 0 -> running under PTRACE_SYSEMU, + jne syscall_skip # ret != 0 -> running under PTRACE_SYSEMU, # so must skip actual syscall movl ORIG_EAX(%esp), %eax cmpl $(nr_syscalls), %eax jnae syscall_call jmp syscall_exit +syscall_skip: + cli # make sure we don't miss an interrupt + # setting need_resched or sigpending + # between sampling and the iret + movl TI_flags(%ebp), %ecx + jmp work_pending # perform syscall exit tracing ALIGN diff -puN arch/i386/kernel/ptrace.c~sysemu-reorganize arch/i386/kernel/ptrace.c --- clean-linux-2.6.11/arch/i386/kernel/ptrace.c~sysemu-reorganize 2005-07-10 16:55:37.000000000 +0200 +++ clean-linux-2.6.11-paolo/arch/i386/kernel/ptrace.c 2005-07-10 16:57:37.000000000 +0200 @@ -514,21 +514,16 @@ asmlinkage int sys_ptrace(long request, ret = -EIO; if ((unsigned long) data > _NSIG) break; - /* If we came here with PTRACE_SYSEMU and now continue with - * PTRACE_SYSCALL, entry.S used to intercept the syscall return. - * But it shouldn't! - * So we don't clear TIF_SYSCALL_EMU, which is always unused in - * this special case, to remember, we came from SYSEMU. That - * flag will be cleared by do_syscall_trace(). - */ if (request == PTRACE_SYSEMU) { set_tsk_thread_flag(child, TIF_SYSCALL_EMU); - } else if (request == PTRACE_CONT) { - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } - if (request == PTRACE_SYSCALL) { + else if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } else { + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } child->exit_code = data; @@ -557,8 +552,7 @@ asmlinkage int sys_ptrace(long request, ret = -EIO; if ((unsigned long) data > _NSIG) break; - /*See do_syscall_trace to know why we don't clear - * TIF_SYSCALL_EMU.*/ + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_singlestep(child); child->exit_code = data; @@ -745,7 +739,7 @@ void send_sigtrap(struct task_struct *ts __attribute__((regparm(3))) int do_syscall_trace(struct pt_regs *regs, int entryexit) { - int is_sysemu, is_systrace, is_singlestep; + int is_sysemu, is_singlestep; if (unlikely(current->audit_context)) { if (!entryexit) audit_syscall_entry(current, regs->orig_eax, @@ -758,22 +752,10 @@ int do_syscall_trace(struct pt_regs *reg return 0; is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); - is_systrace = test_thread_flag(TIF_SYSCALL_TRACE); is_singlestep = test_thread_flag(TIF_SINGLESTEP); - /* We can detect the case of coming from PTRACE_SYSEMU and now running - * with PTRACE_SYSCALL or PTRACE_SINGLESTEP, by TIF_SYSCALL_EMU being - * set additionally. - * If so let's reset the flag and return without action (no singlestep - * nor syscall tracing, since no actual step has been executed). - */ - if (is_sysemu && (is_systrace || is_singlestep)) { - clear_thread_flag(TIF_SYSCALL_EMU); - return 0; - } - /* Fake a debug trap */ - if (test_thread_flag(TIF_SINGLESTEP)) + if (is_singlestep) send_sigtrap(current, regs, 0); if (!test_thread_flag(TIF_SYSCALL_TRACE)) @@ -794,5 +776,10 @@ int do_syscall_trace(struct pt_regs *reg current->exit_code = 0; } /* != 0 if nullifying the syscall, 0 if running it normally */ - return is_sysemu; + if ( !is_sysemu ) + return 0; + + if (unlikely(current->audit_context)) + audit_syscall_exit(current, regs->eax); + return 1; } _