diff options
author | 2020-08-09 19:15:47 +0000 | |
---|---|---|
committer | 2020-08-09 19:15:47 +0000 | |
commit | 3c86a58ec71566e00b1985a59e38d0e8890ad3b4 (patch) | |
tree | 67abc7483e75b30c22fb0b3a770c962375a20fd9 | |
parent | Fix some wrapping/indent. (diff) | |
download | wireguard-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.c | 16 |
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); |