Add some temporary hacks into ptrace_check_attach() for now to make
it almost correct.

- check "child->parent == current" after ptrace_lookup_engine(),
  this way we can't race with ptrace_attach().

- check task_is_stopped_or_traced() before utrace_control(UTRACE_STOP),
  the child must be already stopped. This way we can't provoke the
  unnecessary stop unless (in the very unlikely case) we race with
  SIGCONT in between.

  The multitracing issues are ignored for now.

- Check "int kill". Again, this is not 100% right but hopefully enough
  to forget about ptrace_check_attach() problems until we resolve other
  issues and do the testing.

---

 kernel/ptrace.c |   25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

--- PU/kernel/ptrace.c~109_CHECK_ATTACH_ALMOST_FIX      2009-10-21 
12:29:47.000000000 +0200
+++ PU/kernel/ptrace.c  2009-10-21 14:37:44.000000000 +0200
@@ -535,26 +535,29 @@ int ptrace_check_attach(struct task_stru
 {
        struct utrace_engine *engine;
        struct utrace_examiner exam;
-       int ret;
-
-       if (child->parent != current)
-               return -ESRCH;
+       int ret = -ESRCH;
 
        engine = ptrace_lookup_engine(child);
        if (IS_ERR(engine))
-               return -ESRCH;
+               return ret;
+
+       if (child->parent != current)
+               goto out;
+
+       if (unlikely(kill))
+               ret = 0;
 
+       if (!task_is_stopped_or_traced(child))
+               goto out;
        /*
         * Make sure our engine has already stopped the child.
         * Then wait for it to be off the CPU.
         */
-       ret = 0;
-       if (utrace_control(child, engine, UTRACE_STOP) ||
-           utrace_prepare_examine(child, engine, &exam))
-               ret = -ESRCH;
-
+       if (!utrace_control(child, engine, UTRACE_STOP) &&
+           !utrace_prepare_examine(child, engine, &exam))
+               ret = 0;
+out:
        utrace_engine_put(engine);
-
        return ret;
 }
 

Reply via email to