git: a6268f89d58c - main - proc: Disallow re-enabling of process itimers during exit
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 31 Mar 2025 09:06:36 UTC
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=a6268f89d58c1962d2372a664a35eaecbf367fbb commit a6268f89d58c1962d2372a664a35eaecbf367fbb Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2025-03-31 01:22:14 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2025-03-31 09:01:09 +0000 proc: Disallow re-enabling of process itimers during exit During process exit, it's possible for the exiting thread to send a signal to its process, via killjobc(). This happens after the itimer is drained. If itimers are stopped, i.e., P2_ITSTOPPED is set, then itimer_proc_continue() will resume the callout after it has been drained. Fix the problem by simply clearing P2_ITSTOPPED as part of the drain. Then, a signal received after that point will not re-enable the callout. For good measure, also make sure that we don't reset the itimer callout in an exiting process. Reported by: syzkaller Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D49529 --- sys/kern/kern_exit.c | 1 + sys/kern/kern_time.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a67d6b422964..54e3044ab093 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -375,6 +375,7 @@ exit1(struct thread *td, int rval, int signo) * Stop the real interval timer. If the handler is currently * executing, prevent it from rearming itself and let it finish. */ + p->p_flag2 &= ~P2_ITSTOPPED; if (timevalisset(&p->p_realtimer.it_value) && callout_stop(&p->p_itcallout) == 0) { timevalclear(&p->p_realtimer.it_interval); diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index c94ae49b6923..d7dc78366292 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -884,6 +884,8 @@ realitexpire_reset_callout(struct proc *p, sbintime_t *isbtp) { sbintime_t prec; + if ((p->p_flag & P_WEXIT) != 0) + return; prec = isbtp == NULL ? tvtosbt(p->p_realtimer.it_interval) : *isbtp; callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value), prec >> tc_precexp, realitexpire, p, C_ABSOLUTE);