diff options
author | 2018-06-25 16:06:27 +0000 | |
---|---|---|
committer | 2018-06-25 16:06:27 +0000 | |
commit | 66ffb022a139ec2d1d12367235554aba25c7382c (patch) | |
tree | 8a5f8b228a2222d5e0342b8f9c44777bff9d200e | |
parent | Count $MAILCHECK with the monotonic clock. (diff) | |
download | wireguard-openbsd-66ffb022a139ec2d1d12367235554aba25c7382c.tar.xz wireguard-openbsd-66ffb022a139ec2d1d12367235554aba25c7382c.zip |
During open(2), release the fdp lock before calling vn_open(9).
This lets other threads of the process modify the file descriptor
table even if the vn_open(9) call blocks.
The change has an effect on dup2(2) and dup3(2). If the new descriptor
is the same as the one reserved by an unfinished open(2), the system
call will fail with error EBUSY. The accept(2) system call already
behaves like this.
Issue pointed out by art@ via mpi@
Tested in a bulk build by ajacoutot@
OK mpi@
-rw-r--r-- | lib/libc/sys/dup.2 | 6 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 8 |
2 files changed, 11 insertions, 3 deletions
diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2 index 2928890bb3a..948f1082a80 100644 --- a/lib/libc/sys/dup.2 +++ b/lib/libc/sys/dup.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dup.2,v 1.19 2018/05/28 08:55:11 mpi Exp $ +.\" $OpenBSD: dup.2,v 1.20 2018/06/25 16:06:27 visa Exp $ .\" $NetBSD: dup.2,v 1.4 1995/02/27 12:32:21 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)dup.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: May 28 2018 $ +.Dd $Mdocdate: June 25 2018 $ .Dt DUP 2 .Os .Sh NAME @@ -160,6 +160,8 @@ limit. .It Bq Er EBUSY A race condition with .Xr accept 2 +or +.Xr open 2 has been detected. .It Bq Er EINTR An interrupt was received. diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index aa031b6f8b7..ffc171b6576 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.290 2018/06/18 09:15:05 mpi Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.291 2018/06/25 16:06:27 visa Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -916,6 +916,8 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, fdplock(fdp); if ((error = falloc(p, &fp, &indx)) != 0) goto out; + fdpunlock(fdp); + flags = FFLAGS(oflags); if (flags & FREAD) ni_pledge |= PLEDGE_RPATH; @@ -935,6 +937,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, flags &= ~O_TRUNC; /* Must do truncate ourselves */ } if ((error = vn_open(&nd, flags, cmode)) != 0) { + fdplock(fdp); if (error == ENODEV && p->p_dupfd >= 0 && /* XXX from fdopen */ (error = @@ -969,6 +972,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, VOP_UNLOCK(vp); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); if (error) { + fdplock(fdp); /* closef will vn_close the file for us. */ fdremove(fdp, indx); closef(fp, p); @@ -991,6 +995,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, } if (error) { VOP_UNLOCK(vp); + fdplock(fdp); /* closef will close the file for us. */ fdremove(fdp, indx); closef(fp, p); @@ -999,6 +1004,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, } VOP_UNLOCK(vp); *retval = indx; + fdplock(fdp); fdinsert(fdp, indx, cloexec, fp); FRELE(fp, p); out: |