¡¾ÌÖÂÛ¡¿Race Condition on task_struct
¹ØÓÚdo_exit()ÖжÔtask_struct½øÐзÃÎʲ»¼ÓËøµÄÎÊÌâ¡£ÎÒ½ñÌìÕÒµ½ÁËÒ»¸örace conditionµÄÀý×Ó£¬Ï£Íû¸ßÊÖÖ¸Õý¡£fastcall NORET_TYPE void do_exit(long code)
{
... ...
tsk->flags |= PF_EXITING;
/*
* Make sure we don't try to process any timer firings
* while we are already exiting.
*/
tsk->it_virt_expires = cputime_zero;
tsk->it_prof_expires = cputime_zero;
tsk->it_sched_expires = 0;
... ...
}
static void process_timer_rebalance(struct task_struct *p,
unsigned int clock_idx,
union cpu_time_count expires,
union cpu_time_count val)
{
... ...
do {
if (likely(!(t->flags & PF_EXITING))) {
ticks = cputime_add(virt_ticks(t), left);
if (cputime_eq(t->it_virt_expires,
cputime_zero) ||
cputime_gt(t->it_virt_expires, ticks)) {
t->it_virt_expires = ticks;
}
}
t = next_thread(t);
} while (t != p);
break;
... ...
}
ÉÏÃæÁ½¸öº¯Êý¶Ôit_virt_expiresµÄ·ÃÎÊ´æÔÚrace condition£¬ÆäÖ´ÐÐ˳Ðò¿ÉÄÜΪ£º
1. process_timer_rebalanc()¼ì²é
if (cputime_eq(t->it_virt_expires, cputime_zero) ||
cputime_gt(t->it_virt_expires, ticks))
2. do_exit()ÉèÖÃflags = PF_EXITING£¬it_virt_expirtes = 0¡£
3. process_timer_rebalanc()½«it_virt_expiresÉèÖÃΪticks¡£
ÖÁ´Ë£¬it_virt_expiresÔÚ½ø³Ì´¦ÓÚPF_EXITING״̬ʱÈÔÈ»²»Îª0¡£
Çë¸ßÊÖÖ¸ÕýÎÒ¶ÔÕâ¸örace conditon·ÖÎöµÃ¶Ô²»¶Ô¡£Õâ¸öÎÊÌâ¶ÔkernelÓÐûÓÐʵÖʵÄÓ°Ïì¡£
Ò³:
[1]