diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2026-07-27 23:03:47 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2026-07-27 23:03:47 +0000 |
| commit | 8616b7dc3850758eb39a5b63f41f56c05403380b (patch) | |
| tree | 787534b70d0dda9b1b421fbf40f9204c91400955 | |
| parent | 95a3301ce144aecce5de88fb4e2905c440533fb8 (diff) | |
proc: Copy the p_reapsubtree field explicitly during fork
p_reapsubtree lives in the p_startcopy/p_endcopy block of struct proc,
which is copied during fork without any synchronization. However, the
field is not stable except when the proctree lock is held, and indeed
may change if p1's reaper exits or explicitly releases its reaper
status. This state change can race with fork() and leave the child with
an incorrect p_reapsubtree field.
Close the race: explicitly copy the field under the proctree lock during
fork.
Reported by: syzkaller
Reviewed by: kib
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D58482
| -rw-r--r-- | sys/kern/kern_fork.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 60d89c03f865..e3d7b39e687a 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -701,6 +701,13 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * if (p2->p_reaper == p1 && p1 != initproc) { p2->p_reapsubtree = p2->p_pid; proc_id_set_cond(PROC_ID_REAP, p2->p_pid); + } else { + /* + * Explicitly copy this field under the proctree lock, as it + * might have changed since the bulk copying of the parent's + * fields. + */ + p2->p_reapsubtree = p1->p_reapsubtree; } sx_xunlock(&proctree_lock); |
