diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -563,16 +563,26 @@ if ((flags & RFTHREAD) != 0) { /* * Shared file descriptor table and - * shared process leaders. + * shared process leaders. Serialize the refcount + * bump with fdfree()'s decrement, which runs under + * the shared fd table's fd_spin (kern_descrip.c). + * p1->p_token is per-proc and does NOT serialize + * against peers sharing p_fd. */ fdtol = p1->p_fdtol; + spin_lock(&p1->p_fd->fd_spin); fdtol->fdl_refcount++; + spin_unlock(&p1->p_fd->fd_spin); } else { /* * Shared file descriptor table, and - * different process leaders + * different process leaders. filedesc_to_leader_alloc() + * splices the shared fdl list and must be serialized + * against fdfree()'s list walk (both under fd_spin). */ + spin_lock(&p1->p_fd->fd_spin); fdtol = filedesc_to_leader_alloc(p1->p_fdtol, p2); + spin_unlock(&p1->p_fd->fd_spin); } } p2->p_fdtol = fdtol;