DragonFlyBSD Kernel Audit
DF-0033 / fix.diff
← back to finding ↓ download raw
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;