summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-12-04 20:49:39 +0000
committerkib <kib@FreeBSD.org>2012-12-04 20:49:39 +0000
commit54d4ef7790ac3f2922675f0defbaf3b2f5a54d7a (patch)
treebe5ca68461521c9d13f018cf6445647db4335cf1 /sys/kern/kern_time.c
parentf366a4aadf28f389a29d65d4ae42b4e84bc63720 (diff)
downloadFreeBSD-src-54d4ef7790ac3f2922675f0defbaf3b2f5a54d7a.zip
FreeBSD-src-54d4ef7790ac3f2922675f0defbaf3b2f5a54d7a.tar.gz
Fix a race between kern_setitimer() and realitexpire(), where the
callout is started before kern_setitimer() acquires process mutex, but looses a race and kern_setitimer() gets the process mutex before the callout. Then, assuming that new specified struct itimerval has it_interval zero, but it_value non-zero, the callout, after it starts executing again, clears p->p_realtimer.it_value, but kern_setitimer() already rescheduled the callout. As the result of the race, both p_realtimer is zero, and the callout is rescheduled. Then, in the exit1(), the exit code sees that it_value is zero and does not even try to stop the callout. This allows the struct proc to be reused and eventually the armed callout is re-initialized. The consequence is the corrupted callwheel tailq. Use process mutex to interlock the callout start, which fixes the race. Reported and tested by: pho Reviewed by: jhb MFC after: 2 weeks
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r--sys/kern/kern_time.c3
1 files changed, 0 insertions, 3 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index c0e7831..97c288d 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -788,13 +788,11 @@ realitexpire(void *arg)
struct timeval ctv, ntv;
p = (struct proc *)arg;
- PROC_LOCK(p);
kern_psignal(p, SIGALRM);
if (!timevalisset(&p->p_realtimer.it_interval)) {
timevalclear(&p->p_realtimer.it_value);
if (p->p_flag & P_WEXIT)
wakeup(&p->p_itcallout);
- PROC_UNLOCK(p);
return;
}
for (;;) {
@@ -806,7 +804,6 @@ realitexpire(void *arg)
timevalsub(&ntv, &ctv);
callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1,
realitexpire, p);
- PROC_UNLOCK(p);
return;
}
}
OpenPOWER on IntegriCloud