sched/numa: Fix unsafe get_task_struct() in task_numa_assign()
[deliverable/linux.git] / kernel / sched / fair.c
index 0b069bf3e708e82ea0e08c5b204f931ca1d22a00..fbc0b8214af0a89fbde855e559884d6e3ca988fa 100644 (file)
@@ -1164,9 +1164,19 @@ static void task_numa_compare(struct task_numa_env *env,
        long moveimp = imp;
 
        rcu_read_lock();
-       cur = ACCESS_ONCE(dst_rq->curr);
-       if (cur->pid == 0) /* idle */
+
+       raw_spin_lock_irq(&dst_rq->lock);
+       cur = dst_rq->curr;
+       /*
+        * No need to move the exiting task, and this ensures that ->curr
+        * wasn't reaped and thus get_task_struct() in task_numa_assign()
+        * is safe under RCU read lock.
+        * Note that rcu_read_lock() itself can't protect from the final
+        * put_task_struct() after the last schedule().
+        */
+       if ((cur->flags & PF_EXITING) || is_idle_task(cur))
                cur = NULL;
+       raw_spin_unlock_irq(&dst_rq->lock);
 
        /*
         * "imp" is the fault differential for the source task between the
This page took 0.024842 seconds and 5 git commands to generate.