Kill context->ev_array[].

Add the new members to struct ptrace_context:

        ->ev_mesg: for task_struct->ptrace_message

        ->ev_code: for task_struct->exit_code

        ->ev_name: this is unique identifier for ptrace_resume().

           We don't actually need both ev_code and ev_name, but
           ev_name makes things a bit clearer, at least for now.
           In particular, we can detect jctl stops because every
           other stop event has ev_name != 0.

           So, if a callback wants to stop it does

                context->ev_name = PTRACE_EVENT_XXX;
                context->ev_code = (PTRACE_EVENT_XXX << 8) | SIGTRAP;

           we need a helper, and we can move "(... << 8) | SIGTRAP"
           into ptrace_notify_stop().

           The patch also adds 3 new events which are not visible to
           the user-mode:

                PTRACE_EVENT_SYSCALL
                PTRACE_EVENT_SIGTRAP
                PTRACE_EVENT_SIGNAL

           The last 2 are not strictly needed, just for consistency.

Add the new helper, ev_pending(context) which just checks ->ev_name != 0,
ptrace_resume() sets context->ev_name == 0.

With this patch ptrace_resume(data) ignores "data" and doesn't implement
the stacked events, see the next patches.

---

 kernel/ptrace.c |  181 ++++++++++++++++----------------------------------------
 1 file changed, 54 insertions(+), 127 deletions(-)

--- PU/kernel/ptrace.c~53_KILL_EV_ARRAY 2009-10-01 19:35:49.000000000 +0200
+++ PU/kernel/ptrace.c  2009-10-01 21:53:01.000000000 +0200
@@ -24,57 +24,25 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-typedef void (*resume_func_t)(struct utrace_engine *,
-                               struct task_struct*, long);
-
-struct ptrace_event {
-       int             ev_code;
-       unsigned long   ev_message;
-       resume_func_t   ev_resume;
-
-       int             ev_options;
-};
-
 struct ptrace_context {
        int options;
 
        siginfo_t *siginfo;
 
-       struct ptrace_event ev_array[2];
-       unsigned int ev_first, ev_last;
+       int             ev_name;
+       int             ev_code;
+       unsigned long   ev_mesg;
 
        enum utrace_resume_action resume;
 };
 
-static inline bool ev_empty(struct ptrace_context *context)
-{
-       return context->ev_first == context->ev_last;
-}
-
-static inline struct ptrace_event *__ev_at(struct ptrace_context *context,
-                                               unsigned int idx)
-{
-       return context->ev_array + (idx % ARRAY_SIZE(context->ev_array));
-}
-
-static inline struct ptrace_event *ev_current(struct ptrace_context *context)
-{
-       WARN_ON(ev_empty(context));
-       return __ev_at(context, context->ev_first);
-}
-
-static inline struct ptrace_event *ev_pop(struct ptrace_context *context)
-{
-       WARN_ON(ev_empty(context));
-       return __ev_at(context, context->ev_first++);
-}
+#define PTRACE_EVENT_SYSCALL   100
+#define PTRACE_EVENT_SIGTRAP   101
+#define PTRACE_EVENT_SIGNAL    102
 
-static inline struct ptrace_event *ev_push(struct ptrace_context *context)
+static inline bool ev_pending(struct ptrace_context *context)
 {
-       struct ptrace_event *ev = __ev_at(context, context->ev_last++);
-       WARN_ON(context->ev_last - context->ev_first > 
ARRAY_SIZE(context->ev_array));
-       memset(ev, 0, sizeof(*ev));
-       return ev;
+       return context->ev_name != 0;
 }
 
 static inline struct ptrace_context *
@@ -144,11 +112,12 @@ static u32 ptrace_report_exit(enum utrac
                              long orig_code, long *code)
 {
        struct ptrace_context *context = ptrace_context(engine);
-       struct ptrace_event *ev;
 
-       ev = ev_push(context);
-       ev->ev_message = *code;
-       ev->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP;
+       WARN_ON(ev_pending(context));
+
+       context->ev_name = PTRACE_EVENT_EXIT;
+       context->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP;
+       context->ev_mesg = *code;
 
        return UTRACE_STOP;
 }
@@ -193,7 +162,7 @@ static u32 ptrace_report_clone(enum utra
        struct ptrace_context *context = ptrace_context(engine);
        int event, ret = UTRACE_RESUME;
 
-       WARN_ON(!ev_empty(context));
+       WARN_ON(ev_pending(context));
 
        // XXX: WRONG!!!
        if (clone_flags & CLONE_UNTRACED)
@@ -219,21 +188,16 @@ static u32 ptrace_report_clone(enum utra
 
        // XXX: child->pid is wrong! use tracer's pid_ns
        if (event) {
-               struct ptrace_event *ev = ev_push(context);
-
-               ev->ev_message = child->pid;
-               ev->ev_code = (event << 8) | SIGTRAP;
+               context->ev_name = event;
+               context->ev_code = (event << 8) | SIGTRAP;
+               context->ev_mesg = child->pid;
 
                ret = UTRACE_STOP;
-       }
-
-       if ((clone_flags & CLONE_VFORK) &&
-           (context->options & PTRACE_O_TRACEVFORKDONE)) {
-               struct ptrace_event *ev = ev_push(context);
-
-               ev->ev_message = child->pid;
-               ev->ev_options = PTRACE_O_TRACEVFORKDONE;
-               ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP;
+       } else if ((clone_flags & CLONE_VFORK) &&
+                       (context->options & PTRACE_O_TRACEVFORKDONE)) {
+               context->ev_name = PTRACE_EVENT_VFORK_DONE;
+               context->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP;
+               context->ev_mesg = child->pid;
 
                ret = UTRACE_STOP;
        }
@@ -253,26 +217,18 @@ static void ptrace_resume_syscall(struct
        }
 }
 
-#define PTRACE_O_TRACE_SYSCALL 0x100
-
-static void push_syscall_event(struct ptrace_context *context)
-{
-       struct ptrace_event *ev = ev_push(context);
-
-       BUILD_BUG_ON(PTRACE_O_TRACE_SYSCALL & PTRACE_O_MASK);
-
-       ev->ev_options = PTRACE_O_TRACE_SYSCALL;
-       ev->ev_resume = ptrace_resume_syscall;
-       ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
-                       (SIGTRAP | 0x80) : SIGTRAP;
-}
-
 static u32 ptrace_report_syscall_entry(u32 action,
                                       struct utrace_engine *engine,
                                       struct task_struct *task,
                                       struct pt_regs *regs)
 {
-       push_syscall_event(ptrace_context(engine));
+       struct ptrace_context *context = ptrace_context(engine);
+
+       WARN_ON(ev_pending(context));
+
+       context->ev_name = PTRACE_EVENT_SYSCALL;
+       context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
+                               (SIGTRAP | 0x80) : SIGTRAP;
        return UTRACE_SYSCALL_RUN | UTRACE_STOP;
 }
 
@@ -281,19 +237,15 @@ static u32 ptrace_report_syscall_exit(en
                                      struct task_struct *task,
                                      struct pt_regs *regs)
 {
-       push_syscall_event(ptrace_context(engine));
-       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);
-       }
+       if (ev_pending(context))
+               return UTRACE_STOP;
+
+       context->ev_name = PTRACE_EVENT_SYSCALL;
+       context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
+                               (SIGTRAP | 0x80) : SIGTRAP;
+       return UTRACE_STOP;
 }
 
 static u32 ptrace_report_exec(enum utrace_resume_action action,
@@ -304,7 +256,8 @@ static u32 ptrace_report_exec(enum utrac
                              struct pt_regs *regs)
 {
        struct ptrace_context *context = ptrace_context(engine);
-       struct ptrace_event *ev;
+
+       WARN_ON(ev_pending(context));
 
        if (!(context->options & PTRACE_O_TRACEEXEC)) {
                /*
@@ -314,9 +267,8 @@ static u32 ptrace_report_exec(enum utrac
                return UTRACE_RESUME;
        }
 
-       ev = ev_push(context);
-       ev->ev_resume = ptrace_resume_ck_syscall;
-       ev->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP;
+       context->ev_name = PTRACE_EVENT_EXEC;
+       context->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP;
 
        return UTRACE_STOP;
 }
@@ -351,10 +303,9 @@ static u32 ptrace_report_signal(u32 acti
 {
        struct ptrace_context *context = ptrace_context(engine);
        enum utrace_resume_action resume = context->resume;
-       struct ptrace_event *ev;
 
-       if (!ev_empty(context)) {
-               WARN_ON(!ev_current(context)->ev_code && 
!fatal_signal_pending(task));
+       if (ev_pending(context)) {
+               WARN_ON(!context->ev_code && !fatal_signal_pending(task));
                action = utrace_signal_action(action);
                WARN_ON(action != UTRACE_SIGNAL_REPORT);
                return action | UTRACE_STOP;
@@ -366,8 +317,8 @@ static u32 ptrace_report_signal(u32 acti
                        if (WARN_ON(context->siginfo))
                                context->siginfo = NULL;
 
-                       ev = ev_push(context);
-                       ev->ev_code = SIGTRAP;
+                       context->ev_name = PTRACE_EVENT_SIGTRAP;
+                       context->ev_code = SIGTRAP;
 
                        return UTRACE_STOP | UTRACE_SIGNAL_IGN;
                }
@@ -403,9 +354,8 @@ static u32 ptrace_report_signal(u32 acti
                // will clear context->siginfo
                utrace_control(task, engine, UTRACE_INTERRUPT);
 
-               ev = ev_push(context);
-               ev->ev_resume = ptrace_resume_signal;
-               ev->ev_code = info->si_signo;
+               context->ev_name = PTRACE_EVENT_SIGNAL;
+               context->ev_code = info->si_signo;
 
                return UTRACE_STOP | UTRACE_SIGNAL_IGN;
        }
@@ -418,8 +368,8 @@ static u32 ptrace_report_quiesce(u32 act
 {
        struct ptrace_context *context = ptrace_context(engine);
 
-       if (!ev_empty(context)) {
-               WARN_ON(!ev_current(context)->ev_code && 
!fatal_signal_pending(task) && !(task->flags & PF_EXITING));
+       if (ev_pending(context)) {
+               WARN_ON(!context->ev_code && !fatal_signal_pending(task) && 
!(task->flags & PF_EXITING));
                return UTRACE_STOP;
        }
 
@@ -886,14 +836,12 @@ static int ptrace_setsiginfo(struct utra
 static void do_ptrace_notify_stop(struct ptrace_context *context,
                                        struct task_struct *tracee)
 {
-       struct ptrace_event *ev = ev_current(context);
-
-       tracee->ptrace_message = ev->ev_message;
-       tracee->exit_code = ev->ev_code;
+       tracee->ptrace_message = context->ev_mesg;
+       tracee->exit_code = context->ev_code;
 
        // XXX: for debug only
-       WARN_ON(ev->ev_code == 0);
-       ev->ev_code = 0;
+       WARN_ON(!context->ev_code);
+       context->ev_code = 0;
 
        // XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!!
        read_lock(&tasklist_lock);
@@ -913,7 +861,7 @@ void ptrace_notify_stop(struct task_stru
        }
 
        context = ptrace_context(engine);
-       if (WARN_ON(ev_empty(context)))
+       if (WARN_ON(!ev_pending(context)))
                return;
        do_ptrace_notify_stop(context, tracee);
 }
@@ -943,28 +891,7 @@ static void do_ptrace_resume(struct utra
 {
        struct ptrace_context *context = ptrace_context(engine);
 
-       if (request == PTRACE_SYSCALL)
-               context->options |=  PTRACE_O_TRACE_SYSCALL;
-       else
-               context->options &= ~PTRACE_O_TRACE_SYSCALL;
-
-       if (!ev_empty(context)) {
-               struct ptrace_event *ev = ev_pop(context);
-
-               WARN_ON(ev->ev_code); // XXX: debug
-               if (ev->ev_resume)
-                       ev->ev_resume(engine, tracee, data);
-
-               while (!ev_empty(context)) {
-                       int ev_o = ev_current(context)->ev_options;
-                       if (!ev_o || (ev_o & context->options)) {
-                               do_ptrace_notify_stop(context, tracee);
-                               return;
-                       }
-                       ev_pop(context);
-               }
-       }
-
+       context->ev_name = 0;
        context->resume = action;
        ptrace_wake_up(engine, tracee, action);
 }

Reply via email to