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;

Reply via email to