Date: Tue, 4 Dec 2012 20:49:40 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r243869 - head/sys/kern Message-ID: <201212042049.qB4Kneri053720@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Dec 4 20:49:39 2012 New Revision: 243869 URL: http://svnweb.freebsd.org/changeset/base/243869 Log: 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 Modified: head/sys/kern/init_main.c head/sys/kern/kern_fork.c head/sys/kern/kern_time.c Modified: head/sys/kern/init_main.c ============================================================================== --- head/sys/kern/init_main.c Tue Dec 4 20:49:04 2012 (r243868) +++ head/sys/kern/init_main.c Tue Dec 4 20:49:39 2012 (r243869) @@ -498,7 +498,7 @@ proc0_init(void *dummy __unused) strncpy(p->p_comm, "kernel", sizeof (p->p_comm)); strncpy(td->td_name, "swapper", sizeof (td->td_name)); - callout_init(&p->p_itcallout, CALLOUT_MPSAFE); + callout_init_mtx(&p->p_itcallout, &p->p_mtx, 0); callout_init_mtx(&p->p_limco, &p->p_mtx, 0); callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); Modified: head/sys/kern/kern_fork.c ============================================================================== --- head/sys/kern/kern_fork.c Tue Dec 4 20:49:04 2012 (r243868) +++ head/sys/kern/kern_fork.c Tue Dec 4 20:49:39 2012 (r243869) @@ -591,7 +591,7 @@ do_fork(struct thread *td, int flags, st LIST_INIT(&p2->p_children); LIST_INIT(&p2->p_orphans); - callout_init(&p2->p_itcallout, CALLOUT_MPSAFE); + callout_init_mtx(&p2->p_itcallout, &p2->p_mtx, 0); /* * If PF_FORK is set, the child process inherits the Modified: head/sys/kern/kern_time.c ============================================================================== --- head/sys/kern/kern_time.c Tue Dec 4 20:49:04 2012 (r243868) +++ head/sys/kern/kern_time.c Tue Dec 4 20:49:39 2012 (r243869) @@ -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; } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212042049.qB4Kneri053720>