diff options
author | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-04-07 15:26:09 +0000 |
---|---|---|
committer | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-04-07 15:26:09 +0000 |
commit | b68cf25fe65a9e79ed0bd1b34129fcd245d087d0 (patch) | |
tree | 6064a4b99420c0dc0525bd6f0aef8ee1284a7dc9 /sys | |
parent | 3550618d0bc8b8c7907784e1e3c7f9e02976cfe7 (diff) | |
download | src-b68cf25fe65a9e79ed0bd1b34129fcd245d087d0.tar.gz src-b68cf25fe65a9e79ed0bd1b34129fcd245d087d0.zip |
mqueue,ksem,shm: Fix race condition with setting UF_EXCLOSE.
POSIX mqueue, compatibility ksem and POSIX shm create a file descriptor that
has close-on-exec set. However, they do this incorrectly, leaving a window
where a thread may fork and exec while the flag has not been set yet. The
race is easily reproduced on a multicore system with one thread doing
shm_open and close and another thread doing posix_spawnp and waitpid.
Set UF_EXCLOSE via falloc()'s flags argument instead. This also simplifies
the code.
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=249233
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_mqueue.c | 6 | ||||
-rw-r--r-- | sys/kern/uipc_sem.c | 6 | ||||
-rw-r--r-- | sys/kern/uipc_shm.c | 6 |
3 files changed, 3 insertions, 15 deletions
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 2d18e77dc3e6..73579d30af5a 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -1977,7 +1977,7 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode, if (len < 2 || path[0] != '/' || strchr(path + 1, '/') != NULL) return (EINVAL); - error = falloc(td, &fp, &fd, 0); + error = falloc(td, &fp, &fd, O_CLOEXEC); if (error) return (error); @@ -2032,10 +2032,6 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode, finit(fp, flags & (FREAD | FWRITE | O_NONBLOCK), DTYPE_MQUEUE, pn, &mqueueops); - FILEDESC_XLOCK(fdp); - if (fdp->fd_ofiles[fd].fde_file == fp) - fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE; - FILEDESC_XUNLOCK(fdp); td->td_retval[0] = fd; fdrop(fp, td); return (0); diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 2de34092385f..509f32e909b7 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -485,7 +485,7 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, fdp = td->td_proc->p_fd; mode = (mode & ~fdp->fd_cmask) & ACCESSPERMS; - error = falloc(td, &fp, &fd, 0); + error = falloc(td, &fp, &fd, O_CLOEXEC); if (error) { if (name == NULL) error = ENOSPC; @@ -578,10 +578,6 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, finit(fp, FREAD | FWRITE, DTYPE_SEM, ks, &ksem_ops); - FILEDESC_XLOCK(fdp); - if (fdp->fd_ofiles[fd].fde_file == fp) - fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE; - FILEDESC_XUNLOCK(fdp); fdrop(fp, td); return (0); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index fc33de519edf..7a36a63c984c 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -534,7 +534,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap) fdp = td->td_proc->p_fd; cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS; - error = falloc(td, &fp, &fd, 0); + error = falloc(td, &fp, &fd, O_CLOEXEC); if (error) return (error); @@ -629,10 +629,6 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap) finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); - FILEDESC_XLOCK(fdp); - if (fdp->fd_ofiles[fd].fde_file == fp) - fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE; - FILEDESC_XUNLOCK(fdp); td->td_retval[0] = fd; fdrop(fp, td); |