Skip to content
  • Oleg Nesterov's avatar
    [PATCH] posix-timers: fix posix_cpu_timer_set() vs run_posix_cpu_timers() race · a69ac4a7
    Oleg Nesterov authored
    
    
    This might be harmless, but looks like a race from code inspection (I
    was unable to trigger it).  I must admit, I don't understand why we
    can't return TIMER_RETRY after 'spin_unlock(&p->sighand->siglock)'
    without doing bump_cpu_timer(), but this is what original code does.
    
    posix_cpu_timer_set:
    
    	read_lock(&tasklist_lock);
    
    	spin_lock(&p->sighand->siglock);
    	list_del_init(&timer->it.cpu.entry);
    	spin_unlock(&p->sighand->siglock);
    
    We are probaly deleting the timer from run_posix_cpu_timers's 'firing'
    local list_head while run_posix_cpu_timers() does list_for_each_safe.
    
    Various bad things can happen, for example we can just delete this timer
    so that list_for_each() will not notice it and run_posix_cpu_timers()
    will not reset '->firing' flag. In that case,
    
    	....
    
    	if (timer->it.cpu.firing) {
    		read_unlock(&tasklist_lock);
    		timer->it.cpu.firing = -1;
    		return TIMER_RETRY;
    	}
    
    sys_timer_settime() goes to 'retry:', calls posix_cpu_timer_set() again,
    it returns TIMER_RETRY ...
    
    Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    a69ac4a7