summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcheloha <cheloha@openbsd.org>2020-08-09 19:15:47 +0000
committercheloha <cheloha@openbsd.org>2020-08-09 19:15:47 +0000
commit3c86a58ec71566e00b1985a59e38d0e8890ad3b4 (patch)
tree67abc7483e75b30c22fb0b3a770c962375a20fd9
parentFix some wrapping/indent. (diff)
downloadwireguard-openbsd-3c86a58ec71566e00b1985a59e38d0e8890ad3b4.tar.xz
wireguard-openbsd-3c86a58ec71566e00b1985a59e38d0e8890ad3b4.zip
hardclock(9): fix race with setitimer(2) for ITIMER_VIRTUAL, ITIMER_PROF
The ITIMER_VIRTUAL and ITIMER_PROF per-process interval timers are updated from hardclock(9). If a timer for the parent process is enabled the hardclock(9) thread calls itimerdecr() to update and reload it as needed. However, in itimerdecr(), after entering itimer_mtx, the thread needs to double-check that the timer in question is still enabled. While the hardclock(9) thread is entering itimer_mtx a thread in setitimer(2) can take the mutex and disable the timer. If the timer is disabled, itimerdecr() should return 1 to indicate that the timer has not expired and that no action needs to be taken. ok kettenis@
-rw-r--r--sys/kern/kern_time.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index d1e5c53856a..2097c292788 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.134 2020/08/08 01:01:26 cheloha Exp $ */
+/* $OpenBSD: kern_time.c,v 1.135 2020/08/09 19:15:47 cheloha Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -682,6 +682,20 @@ itimerdecr(struct itimerspec *itp, long nsec)
NSEC_TO_TIMESPEC(nsec, &decrement);
mtx_enter(&itimer_mtx);
+
+ /*
+ * Double-check that the timer is enabled. A different thread
+ * in setitimer(2) may have disabled it while we were entering
+ * the mutex.
+ */
+ if (!timespecisset(&itp->it_value)) {
+ mtx_leave(&itimer_mtx);
+ return (1);
+ }
+
+ /*
+ * The timer is enabled. Update and reload it as needed.
+ */
timespecsub(&itp->it_value, &decrement, &itp->it_value);
if (itp->it_value.tv_sec >= 0 && timespecisset(&itp->it_value)) {
mtx_leave(&itimer_mtx);