aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/posix-cpu-timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r--kernel/posix-cpu-timers.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 71a07699a36b..9641958ddb3e 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -377,27 +377,32 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
377 */ 377 */
378static int posix_cpu_timer_del(struct k_itimer *timer) 378static int posix_cpu_timer_del(struct k_itimer *timer)
379{ 379{
380 struct task_struct *p = timer->it.cpu.task;
381 int ret = 0; 380 int ret = 0;
381 unsigned long flags;
382 struct sighand_struct *sighand;
383 struct task_struct *p = timer->it.cpu.task;
382 384
383 WARN_ON_ONCE(p == NULL); 385 WARN_ON_ONCE(p == NULL);
384 386
385 read_lock(&tasklist_lock); 387 /*
386 if (unlikely(p->sighand == NULL)) { 388 * Protect against sighand release/switch in exit/exec and process/
389 * thread timer list entry concurrent read/writes.
390 */
391 sighand = lock_task_sighand(p, &flags);
392 if (unlikely(sighand == NULL)) {
387 /* 393 /*
388 * We raced with the reaping of the task. 394 * We raced with the reaping of the task.
389 * The deletion should have cleared us off the list. 395 * The deletion should have cleared us off the list.
390 */ 396 */
391 BUG_ON(!list_empty(&timer->it.cpu.entry)); 397 BUG_ON(!list_empty(&timer->it.cpu.entry));
392 } else { 398 } else {
393 spin_lock(&p->sighand->siglock);
394 if (timer->it.cpu.firing) 399 if (timer->it.cpu.firing)
395 ret = TIMER_RETRY; 400 ret = TIMER_RETRY;
396 else 401 else
397 list_del(&timer->it.cpu.entry); 402 list_del(&timer->it.cpu.entry);
398 spin_unlock(&p->sighand->siglock); 403
404 unlock_task_sighand(p, &flags);
399 } 405 }
400 read_unlock(&tasklist_lock);
401 406
402 if (!ret) 407 if (!ret)
403 put_task_struct(p); 408 put_task_struct(p);