itimer: Serialize access to the p_itimers array
Fix the following race between itimer_proc_continue() and process exit. itimer_proc_continue() may be called via realitexpire(), the real interval timer. Note that exit1() drains this timer _after_ draining and freeing itimers. Moreover, itimers_exit() is called without the process lock held; it only acquires the proc lock when deleting individual itimers, so once they are drained we free p->p_itimers without any synchronization. Thus, itimer_proc_continue() may load a non-NULL p->p_itimers array and iterate over it after it has been freed. Fix the problem by using the process lock when clearing p->p_itimers, to synchronize with itimer_proc_continue(). Formally, accesses to this field should be protected by the process lock anyway, and since the array is allocated lazily this will not incur any overhead in the common case. Reported by: syzbot+c40aa8bf54fe333fc50b@syzkaller.appspotmail.com Reported by: syzbot+929be2f32503bbc3844f@syzkaller.appspotmail.com Reviewed by: kib MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31759
This commit is contained in:
@@ -1822,8 +1822,11 @@ itimers_event_exit_exec(int start_idx, struct proc *p)
|
||||
}
|
||||
if (its->its_timers[0] == NULL && its->its_timers[1] == NULL &&
|
||||
its->its_timers[2] == NULL) {
|
||||
free(its, M_SUBPROC);
|
||||
/* Synchronize with itimer_proc_continue(). */
|
||||
PROC_LOCK(p);
|
||||
p->p_itimers = NULL;
|
||||
PROC_UNLOCK(p);
|
||||
free(its, M_SUBPROC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user