Another test-case: #define WEVENT(s) ((s & 0xFF0000) >> 16)
int main(void) { int pid, stat; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); execl("/bin/false", "true", NULL); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXEC)); for (;;) { assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); if (WEVENT(stat) == PTRACE_EVENT_EXEC) break; } kill(pid, SIGINT); assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // must see SYSCALL_EXIT first, assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGTRAP); assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // then SIGINT assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGINT); return 0; } If the tracee enters PTRACE_EVENT_EXEC stop without TIF_SYSCALL_TRACE and then the tracer does ptrace(PTRACE_SYSCALL), we should report SYSCALL_EXIT event. --- kernel/ptrace.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) --- PU/kernel/ptrace.c~39_FIX_EXEC_SYSCALL 2009-09-15 18:36:40.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 19:47:50.000000000 +0200 @@ -335,6 +335,17 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; } +static void ptrace_resume_ck_syscall(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (context->options & PTRACE_O_TRACE_SYSCALL) { + if (ev_empty(context)) + push_syscall_event(context); + } +} + static u32 ptrace_report_exec(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, @@ -354,6 +365,7 @@ static u32 ptrace_report_exec(enum utrac } ev = ev_push(context); + ev->ev_resume = ptrace_resume_ck_syscall; ev->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; return UTRACE_STOP;