summaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2024-10-01 10:42:03 +0200
committerThomas Gleixner <tglx@linutronix.de>2024-10-29 11:43:18 +0100
commit4febce44cfebcb490b196d5d10ae9f403ca4c956 (patch)
treea1ac7f9b10ba6c4e62b24bf21350aedc16f81f76 /kernel/time
parentsignal: Cleanup flush_sigqueue_mask() (diff)
downloadlinux-4febce44cfebcb490b196d5d10ae9f403ca4c956.tar.xz
linux-4febce44cfebcb490b196d5d10ae9f403ca4c956.zip
posix-timers: Cure si_sys_private race
The si_sys_private member of the siginfo which is embedded in the preallocated sigqueue is used by the posix timer code to decide whether a timer must be reprogrammed on signal delivery. The handling of this is racy as a long standing comment in that code documents. It is modified with the timer lock held, but without sighand lock being held. The actual signal delivery code checks for it under sighand lock without holding the timer lock. Hand the new value to send_sigqueue() as argument and store it with sighand lock held. This is an intermediate change to address this issue. The arguments to this function will be cleanup in subsequent changes. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/all/20241001083835.434338954@linutronix.de
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/posix-timers.c15
1 files changed, 1 insertions, 14 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index d461a32b7260..05af074285fa 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -299,21 +299,8 @@ int posix_timer_queue_signal(struct k_itimer *timr)
if (timr->it_interval)
si_private = ++timr->it_requeue_pending;
- /*
- * FIXME: if ->sigq is queued we can race with
- * dequeue_signal()->posixtimer_rearm().
- *
- * If dequeue_signal() sees the "right" value of
- * si_sys_private it calls posixtimer_rearm().
- * We re-queue ->sigq and drop ->it_lock().
- * posixtimer_rearm() locks the timer
- * and re-schedules it while ->sigq is pending.
- * Not really bad, but not that we want.
- */
- timr->sigq->info.si_sys_private = si_private;
-
type = !(timr->it_sigev_notify & SIGEV_THREAD_ID) ? PIDTYPE_TGID : PIDTYPE_PID;
- ret = send_sigqueue(timr->sigq, timr->it_pid, type);
+ ret = send_sigqueue(timr->sigq, timr->it_pid, type, si_private);
/* If we failed to send the signal the timer stops. */
return ret > 0;
}