[PATCH] ITIMER_REAL: fix possible deadlock and race

As Steven Rostedt pointed out, there are 2 problems with ITIMER_REAL
timers.

1. do_setitimer() does not call del_timer_sync() in case
when the timer is not pending (it_real_value() returns 0).
This is wrong, the timer may still be running, and it can
rearm itself.

2. It calls del_timer_sync() with tsk->sighand->siglock held.
This is deadlockable, because timer's handler needs this
lock too.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Oleg Nesterov and committed by Linus Torvalds f01b1b0b b36bbb6c

+6 -2
+6 -2
kernel/itimer.c
··· 153 153 154 154 switch (which) { 155 155 case ITIMER_REAL: 156 + again: 156 157 spin_lock_irq(&tsk->sighand->siglock); 157 158 interval = tsk->signal->it_real_incr; 158 159 val = it_real_value(tsk->signal); 159 - if (val) 160 - del_timer_sync(&tsk->signal->real_timer); 160 + /* We are sharing ->siglock with it_real_fn() */ 161 + if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) { 162 + spin_unlock_irq(&tsk->sighand->siglock); 163 + goto again; 164 + } 161 165 tsk->signal->it_real_incr = 162 166 timeval_to_jiffies(&value->it_interval); 163 167 it_real_arm(tsk, timeval_to_jiffies(&value->it_value));