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
This commit is contained in:
Mark Johnston 2025-03-31 01:22:14 +00:00
parent fe7fe3b175
commit a6268f89d5
2 changed files with 3 additions and 0 deletions

View file

@ -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);

View file

@ -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);