Change ptrace_traceme() to use the new helpers. Kill the now unused
prepare_ptrace_attach/finish_ptrace_attach.

finish_ptrace_attach(ret) logic was wrong. If ->parent has PF_EXITING
we must UTRACE_DETACH but ret == 0. Fix this.

Note: we attach the new engine unconditionally, before security check.
Not good, another task can do ptrace_attach() and get EPERM. Hopefully
we can live with this race, or somehow fix it later.

But security_ptrace_traceme() is strange anyway, I never understood it.
It is called under tasklist_lock, but I can't see how this lock can
help. ->parent can change its creds right after the check.


Somehow with the last 2 patches the kernel survives after make xcheck.
A lot of warning from ptrace_resumed()->WARN_ON(task->last_siginfo != info)
but forget_original_parent()->BUG_ON(task_ptrace(p)) has gone away.
I don't understand how this was "fixed", this means I missed something :/


I am ignoring ptrace_report_clone() for now. I think it should not
rely on tracehook_finish_clone/tracehook_report_clone(). Instead it
should do all work itself, we have PF_STARTING. In that case it can
share the code with ptrace_traceme().

---

 kernel/ptrace.c |   53 +++++------------------------------------------------
 1 file changed, 5 insertions(+), 48 deletions(-)

--- PU/kernel/ptrace.c~08_TRACEME       2009-08-17 15:31:07.000000000 +0200
+++ PU/kernel/ptrace.c  2009-08-17 16:05:21.000000000 +0200
@@ -464,52 +464,6 @@ static const struct utrace_engine_ops pt
 };
 
 /*
- * Detach the utrace engine on error.  On success, set @engine->data to
- * the ptracer's task_struct pointer.  This distinguishes an engine for
- * attached ptrace from an engine left behind after a PTRACE_DETACH call
- * that left a parting signal to deliver.
- */
-static int finish_ptrace_attach(struct task_struct *task,
-                               struct utrace_engine *engine,
-                               int retval)
-{
-       if (retval) {
-               int error = utrace_control(task, engine, UTRACE_DETACH);
-               WARN_ON(error && error != -ESRCH && error != -EALREADY);
-       }
-
-       utrace_engine_put(engine);
-       return retval;
-}
-
-/*
- * Attach a utrace engine for ptrace and set up its event mask.
- * Returns the engine pointer or an IS_ERR() pointer.
- */
-static struct utrace_engine *prepare_ptrace_attach(
-       struct task_struct *child, struct task_struct *parent)
-{
-       struct utrace_engine *engine;
-
-       engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE |
-                                   UTRACE_ATTACH_EXCLUSIVE |
-                                   UTRACE_ATTACH_MATCH_OPS,
-                                   &ptrace_utrace_ops, NULL);
-
-       if (IS_ERR(engine)) {
-               if (engine != ERR_PTR(-ESRCH) &&
-                   engine != ERR_PTR(-ERESTARTNOINTR))
-                       engine = ERR_PTR(-EPERM);
-       } else {
-               int ret = ptrace_update_utrace(child, engine);
-               if (ret)
-                       engine = ERR_PTR(finish_ptrace_attach(child, engine,
-                                                             -ESRCH));
-       }
-       return engine;
-}
-
-/*
  * Attach a utrace engine for ptrace and set up its event mask.
  * Returns error code or 0 on success.
  */
@@ -688,13 +642,13 @@ out:
  */
 int ptrace_traceme(void)
 {
-       int ret = -EPERM;
-       struct utrace_engine *engine;
+       bool detach = true;
+       int ret = ptrace_attach_task(current);
 
-       engine = prepare_ptrace_attach(current, current->parent);
-       if (unlikely(IS_ERR(engine)))
-               return PTR_ERR(engine);
+       if (unlikely(ret))
+               return ret;
 
+       ret = -EPERM;
        write_lock_irq(&tasklist_lock);
        /* Are we already being traced? */
        if (!current->ptrace) {
@@ -707,11 +661,14 @@ int ptrace_traceme(void)
                if (!ret && !(current->real_parent->flags & PF_EXITING)) {
                        current->ptrace = PT_PTRACED;
                        __ptrace_link(current, current->real_parent);
+                       detach = false;
                }
        }
        write_unlock_irq(&tasklist_lock);
 
-       return finish_ptrace_attach(current, engine, ret);
+       if (detach)
+               ptrace_abort_attach(current);
+       return ret;
 }
 
 /*

Reply via email to