]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
sched: fix SCHED_FIFO tasks & FAIR_GROUP_SCHED
authorOleg Nesterov <oleg@tv-sign.ru>
Thu, 15 Nov 2007 19:57:40 +0000 (20:57 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 15 Nov 2007 19:57:40 +0000 (20:57 +0100)
Suppose that the SCHED_FIFO task does

switch_uid(new_user);

Now, p->se.cfs_rq and p->se.parent both point into the old
user_struct->tg because sched_move_task() doesn't call set_task_cfs_rq()
for !fair_sched_class case.

Suppose that old user_struct/task_group is freed/reused, and the task
does

sched_setscheduler(SCHED_NORMAL);

__setscheduler() sets fair_sched_class, but doesn't update
->se.cfs_rq/parent which point to the freed memory.

This means that check_preempt_wakeup() doing

while (!is_same_group(se, pse)) {
se = parent_entity(se);
pse = parent_entity(pse);
}

may OOPS in a similar way if rq->curr or p did something like above.

Perhaps we need something like the patch below, note that
__setscheduler() can't do set_task_cfs_rq().

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
kernel/sched.c

index 908335e1781af5f3435665a377f88fd025cdc4f8..d62b759753f35c7ee76fc9b73f841e59a57b60c2 100644 (file)
@@ -7087,8 +7087,10 @@ void sched_move_task(struct task_struct *tsk)
 
        rq = task_rq_lock(tsk, &flags);
 
-       if (tsk->sched_class != &fair_sched_class)
+       if (tsk->sched_class != &fair_sched_class) {
+               set_task_cfs_rq(tsk);
                goto done;
+       }
 
        update_rq_clock(rq);