diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-03-15 23:24:14 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-03-15 23:24:14 +0000 |
commit | 7e196fdd6e6e603b0fa194e187cb4884cd865f6d (patch) | |
tree | f30a8458f1ec1fd1754c0ad912e7bd3409d03c51 /sys/kern/kern_fork.c | |
parent | abccf6f3e27b07055242c9c80666260c85d09e6a (diff) | |
download | FreeBSD-src-7e196fdd6e6e603b0fa194e187cb4884cd865f6d.zip FreeBSD-src-7e196fdd6e6e603b0fa194e187cb4884cd865f6d.tar.gz |
Fix a race between file operations and rfork(RFCFDG) by parking
all other threads at user boundary, the race can crash kernel
under stress testing.
Reviewed by: jhb
MFC after: 3 days
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r-- | sys/kern/kern_fork.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index dfbd315..c6724b7 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -220,6 +220,16 @@ fork1(td, flags, pages, procp) * certain parts of a process from itself. */ if ((flags & RFPROC) == 0) { + if ((p1->p_flag & P_HADTHREADS) && + (flags & (RFCFDG | RFFDG))) { + PROC_LOCK(p1); + if (thread_single(SINGLE_BOUNDARY)) { + PROC_UNLOCK(p1); + return (ERESTART); + } + PROC_UNLOCK(p1); + } + vm_forkproc(td, NULL, NULL, flags); /* @@ -237,6 +247,13 @@ fork1(td, flags, pages, procp) */ if (flags & RFFDG) fdunshare(p1, td); + + if ((p1->p_flag & P_HADTHREADS) && + (flags & (RFCFDG | RFFDG))) { + PROC_LOCK(p1); + thread_single_end(); + PROC_UNLOCK(p1); + } *procp = NULL; return (0); } |