Add "int options" into struct ptrace_context. Will be used to hold
PT_XXX options. Currently is not used, but:

- ptrace_attach_task() has a new argument, "int options". Used by
  ptrace_clone_attach() which should copy the parent's options

- introduce __ptrace_set_options() helper which updates ->options
  and utrace events mask.

- change ptrace_attach_task() to use this new helper.

---

 kernel/ptrace.c |   51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

--- PU/kernel/ptrace.c~17_CTX_EVENTS    2009-09-02 19:48:53.000000000 +0200
+++ PU/kernel/ptrace.c  2009-09-02 19:53:06.000000000 +0200
@@ -25,8 +25,15 @@
 #include <linux/uaccess.h>
 
 struct ptrace_context {
+       int options;
 };
 
+static inline
+struct ptrace_context *ptrace_context(struct utrace_engine *engine)
+{
+       return engine->data;
+}
+
 /*
  * ptrace a task: make the debugger its new parent and
  * move it to the ptrace list.
@@ -41,7 +48,7 @@ void __ptrace_link(struct task_struct *c
 }
 
 static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */
-static int ptrace_attach_task(struct task_struct *tracee);
+static int ptrace_attach_task(struct task_struct *tracee, int options);
 static void ptrace_abort_attach(struct task_struct *tracee);
 
 static void ptrace_detach_task(struct task_struct *child, int sig)
@@ -216,14 +223,15 @@ static u32 ptrace_report_exit(enum utrac
 }
 
 static void ptrace_clone_attach(struct task_struct *parent,
-                               struct task_struct *child)
+                               struct task_struct *child,
+                               int options)
 {
        struct task_struct *tracer;
        bool abort = true;
 
        if (!parent->ptrace)
                return;
-       if (unlikely(ptrace_attach_task(child))) {
+       if (unlikely(ptrace_attach_task(child, options))) {
                WARN_ON(1);
                return;
        }
@@ -252,6 +260,7 @@ static u32 ptrace_report_clone(enum utra
                               unsigned long clone_flags,
                               struct task_struct *child)
 {
+       struct ptrace_context *context = ptrace_context(engine);
        int event;
 
        if ((clone_flags & CLONE_VFORK) &&
@@ -289,7 +298,7 @@ static u32 ptrace_report_clone(enum utra
         * So does CLONE_PTRACE, even with no event to report.
         */
        if (event || (clone_flags & CLONE_PTRACE))
-               ptrace_clone_attach(parent, child);
+               ptrace_clone_attach(parent, child, context->options);
 
        if (event)
                return utrace_ptrace_event(parent, event, child->pid);
@@ -485,15 +494,33 @@ static const struct utrace_engine_ops pt
        .release = ptrace_release,
 };
 
+static inline int __ptrace_set_options(struct task_struct *target,
+                                       struct utrace_engine *engine,
+                                       unsigned long options)
+{
+       struct ptrace_context *context = ptrace_context(engine);
+       /*
+        * We need QUIESCE for resume handling, CLONE to check
+        * for CLONE_PTRACE, other events are always reported.
+        */
+       unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) |
+                              UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL;
+
+       context->options = options;
+       if (options & PT_TRACE_EXIT)
+               events |= UTRACE_EVENT(EXIT);
+
+       return utrace_set_events(target, engine, events);
+}
+
 /*
  * Attach a utrace engine for ptrace and set up its event mask.
  * Returns error code or 0 on success.
  */
-static int ptrace_attach_task(struct task_struct *tracee)
+static int ptrace_attach_task(struct task_struct *tracee, int options)
 {
        struct ptrace_context *context;
        struct utrace_engine *engine;
-       unsigned long events;
        int err;
 
        context = kzalloc(sizeof(*context), GFP_KERNEL);
@@ -512,16 +539,10 @@ static int ptrace_attach_task(struct tas
                return err;
        }
        /*
-        * We need QUIESCE for resume handling, CLONE to check
-        * for CLONE_PTRACE, other events are always reported.
-        */
-       events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) |
-                UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL;
-       /*
         * It can fail only if the tracee is dead, the caller
         * must notice this before setting PT_PTRACED.
         */
-       err = utrace_set_events(tracee, engine, events);
+       err = __ptrace_set_options(tracee, engine, options);
        WARN_ON(err && !tracee->exit_state);
        utrace_engine_put(engine);
        return 0;
@@ -634,7 +655,7 @@ int ptrace_attach(struct task_struct *ta
        if (retval)
                goto unlock_creds;
 
-       retval = ptrace_attach_task(task);
+       retval = ptrace_attach_task(task, 0);
        if (unlikely(retval))
                goto unlock_creds;
 
@@ -669,7 +690,7 @@ out:
 int ptrace_traceme(void)
 {
        bool detach = true;
-       int ret = ptrace_attach_task(current);
+       int ret = ptrace_attach_task(current, 0);
 
        if (unlikely(ret))
                return ret;

Reply via email to