summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-02-11 15:22:01 +0000
committerrwatson <rwatson@FreeBSD.org>2009-02-11 15:22:01 +0000
commitced47d0a8e4610843f05ea493da7c712e17f9eb2 (patch)
tree4196bc49057cb7685a12918e5c71c6acb3143fe4 /sys/kern/kern_descrip.c
parent7f7a900649f0ccc1a1d1f9c9c65ded68f1fe215e (diff)
downloadFreeBSD-src-ced47d0a8e4610843f05ea493da7c712e17f9eb2.zip
FreeBSD-src-ced47d0a8e4610843f05ea493da7c712e17f9eb2.tar.gz
Modify fdcopy() so that, during fork(2), it won't copy file descriptors
from the parent to the child process if they have an operation vector of &badfileops. This narrows a set of races involving system calls that allocate a new file descriptor, potentially block for some extended period, and then return the file descriptor, when invoked by a threaded program that concurrently invokes fork(2). Similar approches are used in both Solaris and Linux, and the wideness of this race was introduced in FreeBSD when we moved to a more optimistic implementation of accept(2) in order to simplify locking. A small race necessarily remains because the fork(2) might occur after the finit() in accept(2) but before the system call has returned, but that appears unavoidable using current APIs. However, this race is vastly narrower. The fix can be validated using the newfileops_on_fork regression test. PR: kern/130348 Reported by: Ivan Shcheklein <shcheklein at gmail dot com> Reviewed by: jhb, kib MFC after: 1 week
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 648d27e..cfa2cb6 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1583,7 +1583,8 @@ fdcopy(struct filedesc *fdp)
newfdp->fd_freefile = -1;
for (i = 0; i <= fdp->fd_lastfile; ++i) {
if (fdisused(fdp, i) &&
- fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE) {
+ fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE &&
+ fdp->fd_ofiles[i]->f_ops != &badfileops) {
newfdp->fd_ofiles[i] = fdp->fd_ofiles[i];
newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
fhold(newfdp->fd_ofiles[i]);
OpenPOWER on IntegriCloud