Skip to content

Commit

Permalink
Revert the blocked FIFO open fix, as there's either a race in the
Browse files Browse the repository at this point in the history
ref-count handling under handling, or blambert@ is messing with my head
  • Loading branch information
guenther committed Jul 11, 2012
1 parent 613d498 commit 4185654
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 47 deletions.
27 changes: 6 additions & 21 deletions sys/kern/kern_descrip.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: kern_descrip.c,v 1.97 2012/07/08 10:55:10 guenther Exp $ */
/* $OpenBSD: kern_descrip.c,v 1.98 2012/07/11 23:07:19 guenther Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */

/*
Expand Down Expand Up @@ -1196,22 +1196,20 @@ filedescopen(dev_t dev, int mode, int type, struct proc *p)
* Duplicate the specified descriptor to a free descriptor.
*/
int
dupfdopen(struct proc *p, int indx, struct file *fp, int mode)
dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
{
struct filedesc *fdp = p->p_fd;
struct file *wfp;
int dfd = p->p_dupfd;

fdpassertlocked(fdp);

/*
* Assume that the filename was user-specified; applications do
* not tend to open /dev/fd/# when they can just call dup()
*/
if ((p->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
if (p->p_descfd == 255)
if ((curproc->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
if (curproc->p_descfd == 255)
return (EPERM);
if (p->p_descfd != dfd)
if (curproc->p_descfd != curproc->p_dupfd)
return (EPERM);
}

Expand All @@ -1234,23 +1232,10 @@ dupfdopen(struct proc *p, int indx, struct file *fp, int mode)
if (wfp->f_count == LONG_MAX-2)
return (EDEADLK);

FREF(wfp);

/*
* Check whether the larval fd was close behind our back.
* If it was, we act like the open() completed before the
* close(): fake up a closef(), to provide POSIX lock semantics,
* then return success.
*/
if (fdp->fd_ofiles[indx] != fp) {
FREF(wfp); /* yes, again: closef() decrements it twice */
closef(wfp, p);
return (0);
}

fdp->fd_ofiles[indx] = wfp;
fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
(fdp->fd_ofileflags[dfd] & ~UF_EXCLOSE);
wfp->f_count++;
fd_used(fdp, indx);
return (0);
}
Expand Down
42 changes: 18 additions & 24 deletions sys/kern/vfs_syscalls.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: vfs_syscalls.c,v 1.186 2012/07/10 17:00:55 guenther Exp $ */
/* $OpenBSD: vfs_syscalls.c,v 1.187 2012/07/11 23:07:19 guenther Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */

/*
Expand Down Expand Up @@ -856,14 +856,12 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
struct nameidata nd;

fdplock(fdp);
if ((error = falloc(p, &fp, &indx)) != 0) {
fdpunlock(fdp);
return (error);
}

if ((error = falloc(p, &fp, &indx)) != 0)
goto out;
flags = FFLAGS(oflags);
if (flags & O_CLOEXEC)
fdp->fd_ofileflags[indx] |= UF_EXCLOSE;
fdpunlock(fdp);

cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
NDINITAT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fd, path, p);
Expand All @@ -873,16 +871,19 @@ 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 = dupfdopen(p, indx, fp, flags)) == 0) {
(error =
dupfdopen(fdp, indx, p->p_dupfd, flags)) == 0) {
closef(fp, p);
*retval = indx;
goto out;
}
if (error == ERESTART)
error = EINTR;
goto err;
fdremove(fdp, indx);
closef(fp, p);
goto out;
}
p->p_dupfd = 0;
vp = nd.ni_vp;
Expand All @@ -904,9 +905,10 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
VOP_UNLOCK(vp, 0, p);
error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
if (error) {
/* FRELE will vn_close the file for us. */
fdplock(fdp);
goto err;
/* closef will vn_close the file for us. */
fdremove(fdp, indx);
closef(fp, p);
goto out;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
Expand All @@ -925,25 +927,17 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
}
if (error) {
VOP_UNLOCK(vp, 0, p);
/* FRELE will close the file for us. */
fdplock(fdp);
goto err;
/* closef will close the file for us. */
fdremove(fdp, indx);
closef(fp, p);
goto out;
}
}
VOP_UNLOCK(vp, 0, p);
*retval = indx;
FILE_SET_MATURE(fp, p);
return (0);

err:
/* only remove the fd if the file didn't change behind out back */
if (fdp->fd_ofiles[indx] == fp) {
fdremove(fdp, indx);
FRELE(fp, p);
}
out:
fdpunlock(fdp);
FRELE(fp, p);
return (error);
}

Expand Down
4 changes: 2 additions & 2 deletions sys/sys/filedesc.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: filedesc.h,v 1.24 2012/07/08 10:55:10 guenther Exp $ */
/* $OpenBSD: filedesc.h,v 1.25 2012/07/11 23:07:19 guenther Exp $ */
/* $NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $ */

/*
Expand Down Expand Up @@ -121,7 +121,7 @@ struct filedesc0 {
* Kernel global variables and routines.
*/
void filedesc_init(void);
int dupfdopen(struct proc *, int, struct file *, int);
int dupfdopen(struct filedesc *, int, int, int);
int fdalloc(struct proc *p, int want, int *result);
void fdexpand(struct proc *);
int falloc(struct proc *p, struct file **resultfp, int *resultfd);
Expand Down

0 comments on commit 4185654

Please sign in to comment.