Roland, but we forgot about UTRACE_DETACH. If we check ->utrace_flags != 0
before utrace_reap(), then utrace_reset() becomes unsafe: nothing protects
task/utrace form disappearing once utrace_reset() sets ->utrace_flags == 0.

I am starting to think we are going to add too much subtle complications
to avoid lock/unlock in release path :/

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---

 kernel/utrace.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

--- __UTRACE/kernel/utrace.c~3_RESET_CAN_RACE_WITH_RELEASE      2009-09-08 
22:21:57.000000000 +0200
+++ __UTRACE/kernel/utrace.c    2009-09-08 22:32:44.000000000 +0200
@@ -726,8 +726,6 @@ static bool utrace_reset(struct task_str
                clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE);
        }
 
-       task->utrace_flags = flags;
-
        if (!flags)
                /*
                 * No more engines, cleared out the utrace.
@@ -740,7 +738,16 @@ static bool utrace_reset(struct task_str
                 */
                utrace_wakeup(task, utrace);
 
+       /*
+        * In theory spin_lock() doesn't imply rcu_read_lock().
+        * Once we clear ->utrace_flags this task_struct can go away
+        * because tracehook_prepare_release_task() path does not take
+        * utrace->lock when ->utrace_flags == 0.
+        */
+       rcu_read_lock();
+       task->utrace_flags = flags;
        spin_unlock(&utrace->lock);
+       rcu_read_unlock();
 
        put_detached_list(&detached);
 

Reply via email to