Here's diff a that moves FRELE() inside fd_getfile(). This is some
plumbing to help unlocking code paths manipulating fp. The idea is
to guarantee to the callers of fd_getfile() that the returned fp has
the necessary reference counts and will not disappear while it is
being manipulated.
Some code paths are more tricky than others so comments are appreciated.
Index: arch/i386/i386/linux_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/linux_machdep.c,v
retrieving revision 1.46
diff -u -p -r1.46 linux_machdep.c
--- arch/i386/i386/linux_machdep.c 16 Dec 2014 18:30:03 -0000 1.46
+++ arch/i386/i386/linux_machdep.c 14 Jul 2015 21:19:26 -0000
@@ -428,7 +428,6 @@ linux_machdepioctl(struct proc *p, void
struct vt_mode lvt;
caddr_t bvtp, sg;
#endif
- struct filedesc *fdp;
struct file *fp;
int fd;
int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
@@ -439,9 +438,10 @@ linux_machdepioctl(struct proc *p, void
SCARG(&bia, data) = SCARG(uap, data);
com = SCARG(uap, com);
- fdp = p->p_fd;
- if ((fp = fd_getfile(fdp, fd)) == NULL)
+ if ((fp = fd_getfile(p->p_fd, fd)) == NULL)
return (EBADF);
+ FRELE(fp, p);
+ fp = NULL;
switch (com) {
#if (NWSDISPLAY > 0 && defined(WSDISPLAY_COMPAT_USL))
@@ -568,7 +568,8 @@ linux_machdepioctl(struct proc *p, void
* XXX hack: if the function returns EJUSTRETURN,
* it has stuffed a sysctl return value in pt.data.
*/
- FREF(fp);
+ if ((fp = fd_getfile(p->p_fd, fd)) == NULL)
+ return (EBADF);
ioctlf = fp->f_ops->fo_ioctl;
pt.com = SCARG(uap, com);
pt.data = SCARG(uap, data);
Index: compat/linux/linux_blkio.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_blkio.c,v
retrieving revision 1.9
diff -u -p -r1.9 linux_blkio.c
--- compat/linux/linux_blkio.c 22 Apr 2012 05:43:14 -0000 1.9
+++ compat/linux/linux_blkio.c 14 Jul 2015 21:19:26 -0000
@@ -72,7 +72,6 @@ linux_ioctl_blkio(struct proc *p, struct
fdp = p->p_fd;
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- FREF(fp);
error = 0;
ioctlf = fp->f_ops->fo_ioctl;
com = SCARG(uap, com);
Index: compat/linux/linux_cdrom.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_cdrom.c,v
retrieving revision 1.12
diff -u -p -r1.12 linux_cdrom.c
--- compat/linux/linux_cdrom.c 30 Apr 2015 09:20:51 -0000 1.12
+++ compat/linux/linux_cdrom.c 14 Jul 2015 21:19:26 -0000
@@ -77,7 +77,6 @@ linux_ioctl_cdrom(p, v, retval)
syscallarg(caddr_t) data;
} */ *uap = v;
struct file *fp;
- struct filedesc *fdp;
caddr_t sg;
u_long com, arg;
struct sys_ioctl_args ia;
@@ -107,10 +106,8 @@ linux_ioctl_cdrom(p, v, retval)
} tmpl;
- fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
return (EBADF);
- FREF(fp);
com = SCARG(uap, com);
retval[0] = 0;
Index: compat/linux/linux_fdio.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_fdio.c,v
retrieving revision 1.7
diff -u -p -r1.7 linux_fdio.c
--- compat/linux/linux_fdio.c 22 Apr 2012 05:43:14 -0000 1.7
+++ compat/linux/linux_fdio.c 14 Jul 2015 21:19:26 -0000
@@ -78,7 +78,6 @@ linux_ioctl_fdio(struct proc *p, struct
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- FREF(fp);
com = SCARG(uap, com);
ioctlf = fp->f_ops->fo_ioctl;
Index: compat/linux/linux_file.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_file.c,v
retrieving revision 1.30
diff -u -p -r1.30 linux_file.c
--- compat/linux/linux_file.c 26 Mar 2014 05:23:42 -0000 1.30
+++ compat/linux/linux_file.c 14 Jul 2015 21:19:26 -0000
@@ -198,7 +198,6 @@ linux_sys_open(p, v, retval)
if ((fp = fd_getfile(fdp, *retval)) == NULL)
return (EBADF);
- FREF(fp);
if (fp->f_type == DTYPE_VNODE)
(fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
FRELE(fp, p);
@@ -420,12 +419,14 @@ linux_sys_fcntl(p, v, retval)
return (EBADF);
if (fp->f_type == DTYPE_SOCKET) {
cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
+ FRELE(fp, p);
break;
}
vp = (struct vnode *)fp->f_data;
- if (vp->v_type != VCHR)
+ if (vp->v_type != VCHR) {
+ FRELE(fp, p);
return EINVAL;
- FREF(fp);
+ }
error = VOP_GETATTR(vp, &va, p->p_ucred, p);
FRELE(fp, p);
if (error)
Index: compat/linux/linux_hdio.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_hdio.c,v
retrieving revision 1.9
diff -u -p -r1.9 linux_hdio.c
--- compat/linux/linux_hdio.c 26 Mar 2014 05:23:42 -0000 1.9
+++ compat/linux/linux_hdio.c 14 Jul 2015 21:19:26 -0000
@@ -81,7 +81,6 @@ linux_ioctl_hdio(struct proc *p, struct
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- FREF(fp);
com = SCARG(uap, com);
ioctlf = fp->f_ops->fo_ioctl;
retval[0] = error = 0;
Index: compat/linux/linux_socket.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.61
diff -u -p -r1.61 linux_socket.c
--- compat/linux/linux_socket.c 6 May 2015 08:52:17 -0000 1.61
+++ compat/linux/linux_socket.c 14 Jul 2015 21:19:26 -0000
@@ -1372,7 +1372,6 @@ linux_ioctl_socket(p, v, retval)
fdp = p->p_fd;
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- FREF(fp);
if (fp->f_type == DTYPE_VNODE) {
vp = (struct vnode *)fp->f_data;
Index: compat/linux/linux_termios.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_termios.c,v
retrieving revision 1.18
diff -u -p -r1.18 linux_termios.c
--- compat/linux/linux_termios.c 30 Apr 2015 09:20:51 -0000 1.18
+++ compat/linux/linux_termios.c 14 Jul 2015 21:19:26 -0000
@@ -449,7 +449,6 @@ linux_ioctl_termios(p, v, retval)
syscallarg(caddr_t) data;
} */ *uap = v;
struct file *fp;
- struct filedesc *fdp;
u_long com;
struct linux_termio tmplt;
struct linux_termios tmplts;
@@ -460,10 +459,8 @@ linux_ioctl_termios(p, v, retval)
char tioclinux;
int error = 0;
- fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
return (EBADF);
- FREF(fp);
com = SCARG(uap, com);
retval[0] = 0;
Index: dev/systrace.c
===================================================================
RCS file: /cvs/src/sys/dev/systrace.c,v
retrieving revision 1.75
diff -u -p -r1.75 systrace.c
--- dev/systrace.c 14 Mar 2015 03:38:46 -0000 1.75
+++ dev/systrace.c 14 Jul 2015 21:19:26 -0000
@@ -1058,9 +1058,10 @@ systrace_processready(struct str_process
int
systrace_getcwd(struct fsystrace *fst, struct str_process *strp, int atfd)
{
+ struct file *fp = NULL;
struct filedesc *myfdp, *fdp;
struct vnode *dvp, *odvp;
- int error;
+ int error = 0;
DPRINTF(("%s: %d\n", __func__, strp->pid));
@@ -1073,15 +1074,21 @@ systrace_getcwd(struct fsystrace *fst, s
if (myfdp == NULL || fdp == NULL)
return (EINVAL);
- if (atfd == AT_FDCWD)
- dvp = fdp->fd_cdir;
- else {
- struct file *fp = fd_getfile(fdp, atfd);
- if (fp == NULL || fp->f_type != DTYPE_VNODE)
+ if (atfd != AT_FDCWD) {
+ if ((fp = fd_getfile(fdp, atfd)) == NULL)
return (EINVAL);
+
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EINVAL;
+ goto out;
+ }
dvp = (struct vnode *)fp->f_data;
- if (dvp->v_type != VDIR)
- return (EINVAL);
+ if (dvp->v_type != VDIR) {
+ error = EINVAL;
+ goto out;
+ }
+ } else {
+ dvp = fdp->fd_cdir;
}
/* Is there a STRIOCGETCWD currently in effect? */
@@ -1107,7 +1114,11 @@ systrace_getcwd(struct fsystrace *fst, s
if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL)
vref(myfdp->fd_rdir);
- return (0);
+out:
+ if (fp != NULL)
+ FRELE(fp, strp->proc);
+
+ return (error);
}
int
Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.120
diff -u -p -r1.120 kern_descrip.c
--- kern/kern_descrip.c 17 May 2015 01:22:01 -0000 1.120
+++ kern/kern_descrip.c 14 Jul 2015 21:19:26 -0000
@@ -189,20 +189,24 @@ fd_getfile(struct filedesc *fdp, int fd)
if (!FILE_IS_USABLE(fp))
return (NULL);
+ FREF(fp);
return (fp);
}
struct file *
-fd_getfile_mode(struct filedesc *fdp, int fd, int mode)
+fd_getfile_mode(struct proc *p, int fd, int mode)
{
struct file *fp;
KASSERT(mode != 0);
- fp = fd_getfile(fdp, fd);
+ if ((fp = fd_getfile(p->p_fd, fd)) == NULL)
+ return (NULL);
- if (fp == NULL || (fp->f_flag & mode) == 0)
+ if ((fp->f_flag & mode) == 0) {
+ FRELE(fp, p);
return (NULL);
+ }
return (fp);
}
@@ -230,7 +234,6 @@ sys_dup(struct proc *p, void *v, registe
restart:
if ((fp = fd_getfile(fdp, old)) == NULL)
return (EBADF);
- FREF(fp);
fdplock(fdp);
if ((error = fdalloc(p, 0, &new)) != 0) {
FRELE(fp, p);
@@ -287,11 +290,11 @@ dodup3(struct proc *p, int old, int new,
int i, error;
restart:
- if ((fp = fd_getfile(fdp, old)) == NULL)
- return (EBADF);
if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
(u_int)new >= maxfiles)
return (EBADF);
+ if ((fp = fd_getfile(fdp, old)) == NULL)
+ return (EBADF);
if (old == new) {
/*
* NOTE! This doesn't clear the close-on-exec flag. This might
@@ -299,9 +302,9 @@ restart:
* this is what everyone else does.
*/
*retval = new;
+ FRELE(fp, p);
return (0);
}
- FREF(fp);
fdplock(fdp);
if (new >= fdp->fd_nfiles) {
if ((error = fdalloc(p, new, &i)) != 0) {
@@ -341,16 +344,16 @@ sys_fcntl(struct proc *p, void *v, regis
} */ *uap = v;
int fd = SCARG(uap, fd);
struct filedesc *fdp = p->p_fd;
- struct file *fp;
+ struct file *fp, *fp0;
struct vnode *vp;
int i, tmp, newmin, flg = F_POSIX;
struct flock fl;
- int error = 0;
+ int lost, error = 0;
restart:
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
- FREF(fp);
+
switch (SCARG(uap, cmd)) {
case F_DUPFD:
@@ -508,7 +511,11 @@ restart:
goto out;
}
- if (fp != fd_getfile(fdp, fd)) {
+ fp0 = fd_getfile(fdp, fd);
+ lost = (fp != fp0);
+ if (fp0 != NULL)
+ FRELE(fp0, p);
+ if (lost) {
/*
* We have lost the race with close() or dup2();
* unlock, pretend that we've won the race and that
@@ -648,12 +655,15 @@ sys_close(struct proc *p, void *v, regis
struct sys_close_args /* {
syscallarg(int) fd;
} */ *uap = v;
- int fd = SCARG(uap, fd), error;
+ int fd = SCARG(uap, fd);
struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ int error;
- if (fd_getfile(fdp, fd) == NULL)
+ if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
fdplock(fdp);
+ FRELE(fp, p);
error = fdrelease(p, fd);
fdpunlock(fdp);
@@ -678,7 +688,6 @@ sys_fstat(struct proc *p, void *v, regis
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
- FREF(fp);
error = (*fp->f_ops->fo_stat)(fp, &ub, p);
FRELE(fp, p);
if (error == 0) {
@@ -717,7 +726,6 @@ sys_fpathconf(struct proc *p, void *v, r
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
- FREF(fp);
switch (fp->f_type) {
case DTYPE_PIPE:
case DTYPE_SOCKET:
@@ -1175,9 +1183,10 @@ sys_flock(struct proc *p, void *v, regis
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
- if (fp->f_type != DTYPE_VNODE)
- return (EOPNOTSUPP);
- FREF(fp);
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
vp = (struct vnode *)fp->f_data;
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -1235,8 +1244,10 @@ filedescopen(dev_t dev, int mode, int ty
* Duplicate the specified descriptor to a free descriptor.
*/
int
-dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
+dupfdopen(struct proc *p, int indx, int mode)
{
+ struct filedesc *fdp = p->p_fd;
+ int dfd = p->p_dupfd;
struct file *wfp;
fdpassertlocked(fdp);
@@ -1245,10 +1256,10 @@ dupfdopen(struct filedesc *fdp, int indx
* Assume that the filename was user-specified; applications do
* not tend to open /dev/fd/# when they can just call dup()
*/
- if ((curproc->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
- if (curproc->p_descfd == 255)
+ if ((p->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
+ if (p->p_descfd == 255)
return (EPERM);
- if (curproc->p_descfd != curproc->p_dupfd)
+ if (p->p_descfd != p->p_dupfd)
return (EPERM);
}
@@ -1266,16 +1277,19 @@ dupfdopen(struct filedesc *fdp, int indx
* Check that the mode the file is being opened for is a
* subset of the mode of the existing descriptor.
*/
- if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
+ if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
+ FRELE(wfp, p);
return (EACCES);
- if (wfp->f_count == LONG_MAX-2)
+ }
+ if (wfp->f_count == LONG_MAX-2) {
+ FRELE(wfp, p);
return (EDEADLK);
-
+ }
fdp->fd_ofiles[indx] = wfp;
fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
- (fdp->fd_ofileflags[dfd] & ~UF_EXCLOSE);
- wfp->f_count++;
+ (fdp->fd_ofileflags[p->p_dupfd] & ~UF_EXCLOSE);
fd_used(fdp, indx);
+
return (0);
}
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.61
diff -u -p -r1.61 kern_event.c
--- kern/kern_event.c 19 Dec 2014 05:59:21 -0000 1.61
+++ kern/kern_event.c 14 Jul 2015 21:19:26 -0000
@@ -480,11 +480,13 @@ sys_kevent(struct proc *p, void *v, regi
struct timespec ts;
int i, n, nerrors, error;
- if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL ||
- (fp->f_type != DTYPE_KQUEUE))
+ if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- FREF(fp);
+ if (fp->f_type != DTYPE_KQUEUE) {
+ error = EBADF;
+ goto done;
+ }
if (SCARG(uap, timeout) != NULL) {
error = copyin(SCARG(uap, timeout), &ts, sizeof(ts));
@@ -575,7 +577,6 @@ kqueue_register(struct kqueue *kq, struc
/* validate descriptor */
if ((fp = fd_getfile(fdp, kev->ident)) == NULL)
return (EBADF);
- FREF(fp);
if (kev->ident < fdp->fd_knlistsize) {
SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link)
Index: kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.161
diff -u -p -r1.161 kern_exec.c
--- kern/kern_exec.c 14 Mar 2015 03:38:50 -0000 1.161
+++ kern/kern_exec.c 14 Jul 2015 21:19:26 -0000
@@ -606,7 +606,10 @@ sys_execve(struct proc *p, void *v, regi
fp->f_ops = &vnops;
fp->f_data = (caddr_t)vp;
FILE_SET_MATURE(fp, p);
+ } else {
+ FRELE(fp, p);
}
+
}
fdpunlock(p->p_fd);
if (error)
Index: kern/sys_generic.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.98
diff -u -p -r1.98 sys_generic.c
--- kern/sys_generic.c 10 May 2015 22:35:38 -0000 1.98
+++ kern/sys_generic.c 14 Jul 2015 21:19:26 -0000
@@ -85,16 +85,13 @@ sys_read(struct proc *p, void *v, regist
struct iovec iov;
int fd = SCARG(uap, fd);
struct file *fp;
- struct filedesc *fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, fd, FREAD)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FREAD)) == NULL)
return (EBADF);
iov.iov_base = SCARG(uap, buf);
iov.iov_len = SCARG(uap, nbyte);
- FREF(fp);
-
/* dofilereadv() will FRELE the descriptor for us */
return (dofilereadv(p, fd, fp, &iov, 1, 0, &fp->f_offset, retval));
}
@@ -112,11 +109,9 @@ sys_readv(struct proc *p, void *v, regis
} */ *uap = v;
int fd = SCARG(uap, fd);
struct file *fp;
- struct filedesc *fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, fd, FREAD)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FREAD)) == NULL)
return (EBADF);
- FREF(fp);
/* dofilereadv() will FRELE the descriptor for us */
return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 1,
@@ -233,16 +228,13 @@ sys_write(struct proc *p, void *v, regis
struct iovec iov;
int fd = SCARG(uap, fd);
struct file *fp;
- struct filedesc *fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, fd, FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FWRITE)) == NULL)
return (EBADF);
iov.iov_base = (void *)SCARG(uap, buf);
iov.iov_len = SCARG(uap, nbyte);
- FREF(fp);
-
/* dofilewritev() will FRELE the descriptor for us */
return (dofilewritev(p, fd, fp, &iov, 1, 0, &fp->f_offset, retval));
}
@@ -260,11 +252,9 @@ sys_writev(struct proc *p, void *v, regi
} */ *uap = v;
int fd = SCARG(uap, fd);
struct file *fp;
- struct filedesc *fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, fd, FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FWRITE)) == NULL)
return (EBADF);
- FREF(fp);
/* dofilewritev() will FRELE the descriptor for us */
return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 1,
@@ -383,17 +373,16 @@ sys_ioctl(struct proc *p, void *v, regis
syscallarg(void *) data;
} */ *uap = v;
struct file *fp;
- struct filedesc *fdp;
+ struct filedesc *fdp = p->p_fd;
u_long com;
int error;
u_int size;
- caddr_t data, memp;
+ caddr_t data, memp = NULL;
int tmp;
#define STK_PARAMS 128
long long stkbuf[STK_PARAMS / sizeof(long long)];
- fdp = p->p_fd;
- if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, SCARG(uap, fd), FREAD|FWRITE)) == NULL)
return (EBADF);
switch (com = SCARG(uap, com)) {
@@ -405,6 +394,7 @@ sys_ioctl(struct proc *p, void *v, regis
else
fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
fdpunlock(fdp);
+ FRELE(fp, p);
return (0);
}
@@ -413,10 +403,11 @@ sys_ioctl(struct proc *p, void *v, regis
* copied to/from the user's address space.
*/
size = IOCPARM_LEN(com);
- if (size > IOCPARM_MAX)
- return (ENOTTY);
- FREF(fp);
- memp = NULL;
+ if (size > IOCPARM_MAX) {
+ error = ENOTTY;
+ goto out;
+ }
+
if (size > sizeof (stkbuf)) {
memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
data = memp;
@@ -724,7 +715,6 @@ selscan(struct proc *p, fd_set *ibits, f
bits &= ~(1 << j);
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
- FREF(fp);
if ((*fp->f_ops->fo_poll)(fp, flag[msk], p)) {
FD_SET(fd, pobits);
n++;
@@ -822,7 +812,6 @@ pollscan(struct proc *p, struct pollfd *
n++;
continue;
}
- FREF(fp);
pl->revents = (*fp->f_ops->fo_poll)(fp, pl->events, p);
FRELE(fp, p);
if (pl->revents != 0)
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.102
diff -u -p -r1.102 uipc_syscalls.c
--- kern/uipc_syscalls.c 21 May 2015 13:35:15 -0000 1.102
+++ kern/uipc_syscalls.c 14 Jul 2015 21:19:26 -0000
@@ -1022,10 +1022,11 @@ getsock(struct proc *p, int fdes, struct
if ((fp = fd_getfile(p->p_fd, fdes)) == NULL)
return (EBADF);
- if (fp->f_type != DTYPE_SOCKET)
+ if (fp->f_type != DTYPE_SOCKET) {
+ FRELE(fp, p);
return (ENOTSOCK);
+ }
*fpp = fp;
- FREF(fp);
return (0);
}
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.81
diff -u -p -r1.81 uipc_usrreq.c
--- kern/uipc_usrreq.c 30 Jun 2015 15:30:17 -0000 1.81
+++ kern/uipc_usrreq.c 14 Jul 2015 21:19:26 -0000
@@ -826,18 +826,19 @@ morespace:
}
if (fp->f_count == LONG_MAX-2 ||
fp->f_msgcount == LONG_MAX-2) {
+ FRELE(fp, p);
error = EDEADLK;
goto fail;
}
/* kq and systrace descriptors cannot be copied */
if (fp->f_type == DTYPE_KQUEUE ||
fp->f_type == DTYPE_SYSTRACE) {
+ FRELE(fp, p);
error = EINVAL;
goto fail;
}
memcpy(rp, &fp, sizeof fp);
rp--;
- fp->f_count++;
fp->f_msgcount++;
unp_rights++;
}
@@ -847,9 +848,9 @@ fail:
for ( ; i > 0; i--) {
rp++;
memcpy(&fp, rp, sizeof(fp));
- fp->f_count--;
fp->f_msgcount--;
unp_rights--;
+ FRELE(fp, p);
}
return (error);
Index: kern/vfs_lookup.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.53
diff -u -p -r1.53 vfs_lookup.c
--- kern/vfs_lookup.c 23 Apr 2015 02:55:15 -0000 1.53
+++ kern/vfs_lookup.c 14 Jul 2015 21:19:26 -0000
@@ -86,6 +86,7 @@
int
namei(struct nameidata *ndp)
{
+ struct file *fp = NULL;
struct filedesc *fdp; /* pointer to file descriptor state */
char *cp; /* pointer into pathname argument */
struct vnode *dp; /* the directory we are searching */
@@ -104,7 +105,7 @@ namei(struct nameidata *ndp)
if (cnp->cn_flags & OPMASK)
panic ("namei: flags contaminated with nameiops");
#endif
- fdp = cnp->cn_proc->p_fd;
+ fdp = p->p_fd;
/*
* Get a buffer for the name to be translated, and copy the
@@ -174,7 +175,7 @@ namei(struct nameidata *ndp)
dp = fdp->fd_cdir;
vref(dp);
} else {
- struct file *fp = fd_getfile(fdp, ndp->ni_dirfd);
+ fp = fd_getfile(fdp, ndp->ni_dirfd);
if (fp == NULL) {
pool_put(&namei_pool, cnp->cn_pnbuf);
return (EBADF);
@@ -182,7 +183,8 @@ namei(struct nameidata *ndp)
dp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || dp->v_type != VDIR) {
pool_put(&namei_pool, cnp->cn_pnbuf);
- return (ENOTDIR);
+ error = ENOTDIR;
+ goto out;
}
vref(dp);
}
@@ -190,13 +192,14 @@ namei(struct nameidata *ndp)
if (!dp->v_mount) {
/* Give up if the directory is no longer mounted */
pool_put(&namei_pool, cnp->cn_pnbuf);
- return (ENOENT);
+ error = ENOENT;
+ goto out;
}
cnp->cn_nameptr = cnp->cn_pnbuf;
ndp->ni_startdir = dp;
if ((error = vfs_lookup(ndp)) != 0) {
pool_put(&namei_pool, cnp->cn_pnbuf);
- return (error);
+ goto out;
}
/*
* If not a symbolic link, return search result.
@@ -206,7 +209,8 @@ namei(struct nameidata *ndp)
pool_put(&namei_pool, cnp->cn_pnbuf);
else
cnp->cn_flags |= HASBUF;
- return (0);
+ error = 0;
+ goto out;
}
if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
VOP_UNLOCK(ndp->ni_dvp, 0, p);
@@ -265,6 +269,10 @@ badlink:
vrele(ndp->ni_dvp);
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
+
+out:
+ if (fp)
+ FRELE(fp, p);
return (error);
}
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.220
diff -u -p -r1.220 vfs_syscalls.c
--- kern/vfs_syscalls.c 7 May 2015 08:53:33 -0000 1.220
+++ kern/vfs_syscalls.c 14 Jul 2015 21:19:26 -0000
@@ -683,13 +683,15 @@ sys_fchdir(struct proc *p, void *v, regi
struct vnode *vp, *tdp, *old_cdir;
struct mount *mp;
struct file *fp;
- int error;
+ int error = 0;
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
vp = (struct vnode *)fp->f_data;
- if (fp->f_type != DTYPE_VNODE || vp->v_type != VDIR)
- return (ENOTDIR);
+ if (fp->f_type != DTYPE_VNODE || vp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ }
vref(vp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
@@ -706,13 +708,15 @@ sys_fchdir(struct proc *p, void *v, regi
}
if (error) {
vput(vp);
- return (error);
+ goto out;
}
VOP_UNLOCK(vp, 0, p);
old_cdir = fdp->fd_cdir;
fdp->fd_cdir = vp;
vrele(old_cdir);
- return (0);
+out:
+ FRELE(fp, p);
+ return (error);
}
/*
@@ -863,7 +867,7 @@ doopenat(struct proc *p, int fd, const c
if (error == ENODEV &&
p->p_dupfd >= 0 && /* XXX from fdopen */
(error =
- dupfdopen(fdp, indx, p->p_dupfd, flags)) == 0) {
+ dupfdopen(p, indx, flags)) == 0) {
closef(fp, p);
*retval = indx;
goto out;
@@ -1534,12 +1538,11 @@ sys_lseek(struct proc *p, void *v, regis
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- if (fp->f_type != DTYPE_VNODE)
- return (ESPIPE);
vp = (struct vnode *)fp->f_data;
- if (vp->v_type == VFIFO)
- return (ESPIPE);
- FREF(fp);
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ error = ESPIPE;
+ goto bad;
+ }
if (vp->v_type == VCHR)
special = 1;
else
@@ -2791,14 +2794,17 @@ getvnode(struct proc *p, int fd, struct
if ((fp = fd_getfile(p->p_fd, fd)) == NULL)
return (EBADF);
- if (fp->f_type != DTYPE_VNODE)
+ if (fp->f_type != DTYPE_VNODE) {
+ FRELE(fp, p);
return (EINVAL);
+ }
vp = (struct vnode *)fp->f_data;
- if (vp->v_type == VBAD)
+ if (vp->v_type == VBAD) {
+ FRELE(fp, p);
return (EBADF);
+ }
- FREF(fp);
*fpp = fp;
return (0);
@@ -2818,18 +2824,18 @@ sys_pread(struct proc *p, void *v, regis
syscallarg(off_t) offset;
} */ *uap = v;
struct iovec iov;
- struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
off_t offset;
int fd = SCARG(uap, fd);
- if ((fp = fd_getfile_mode(fdp, fd, FREAD)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FREAD)) == NULL)
return (EBADF);
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO ||
(vp->v_flag & VISTTY)) {
+ FRELE(fp, p);
return (ESPIPE);
}
@@ -2837,10 +2843,10 @@ sys_pread(struct proc *p, void *v, regis
iov.iov_len = SCARG(uap, nbyte);
offset = SCARG(uap, offset);
- if (offset < 0 && vp->v_type != VCHR)
+ if (offset < 0 && vp->v_type != VCHR) {
+ FRELE(fp, p);
return (EINVAL);
-
- FREF(fp);
+ }
/* dofilereadv() will FRELE the descriptor for us */
return (dofilereadv(p, fd, fp, &iov, 1, 0, &offset, retval));
@@ -2859,26 +2865,26 @@ sys_preadv(struct proc *p, void *v, regi
syscallarg(int) pad;
syscallarg(off_t) offset;
} */ *uap = v;
- struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
off_t offset;
int fd = SCARG(uap, fd);
- if ((fp = fd_getfile_mode(fdp, fd, FREAD)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FREAD)) == NULL)
return (EBADF);
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO ||
(vp->v_flag & VISTTY)) {
+ FRELE(fp, p);
return (ESPIPE);
}
offset = SCARG(uap, offset);
- if (offset < 0 && vp->v_type != VCHR)
+ if (offset < 0 && vp->v_type != VCHR) {
+ FRELE(fp, p);
return (EINVAL);
-
- FREF(fp);
+ }
/* dofilereadv() will FRELE the descriptor for us */
return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 1,
@@ -2899,18 +2905,18 @@ sys_pwrite(struct proc *p, void *v, regi
syscallarg(off_t) offset;
} */ *uap = v;
struct iovec iov;
- struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
off_t offset;
int fd = SCARG(uap, fd);
- if ((fp = fd_getfile_mode(fdp, fd, FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FWRITE)) == NULL)
return (EBADF);
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO ||
(vp->v_flag & VISTTY)) {
+ FRELE(fp, p);
return (ESPIPE);
}
@@ -2918,10 +2924,10 @@ sys_pwrite(struct proc *p, void *v, regi
iov.iov_len = SCARG(uap, nbyte);
offset = SCARG(uap, offset);
- if (offset < 0 && vp->v_type != VCHR)
+ if (offset < 0 && vp->v_type != VCHR) {
+ FRELE(fp, p);
return (EINVAL);
-
- FREF(fp);
+ }
/* dofilewritev() will FRELE the descriptor for us */
return (dofilewritev(p, fd, fp, &iov, 1, 0, &offset, retval));
@@ -2940,26 +2946,26 @@ sys_pwritev(struct proc *p, void *v, reg
syscallarg(int) pad;
syscallarg(off_t) offset;
} */ *uap = v;
- struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
off_t offset;
int fd = SCARG(uap, fd);
- if ((fp = fd_getfile_mode(fdp, fd, FWRITE)) == NULL)
+ if ((fp = fd_getfile_mode(p, fd, FWRITE)) == NULL)
return (EBADF);
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO ||
(vp->v_flag & VISTTY)) {
+ FRELE(fp, p);
return (ESPIPE);
}
offset = SCARG(uap, offset);
- if (offset < 0 && vp->v_type != VCHR)
+ if (offset < 0 && vp->v_type != VCHR) {
+ FRELE(fp, p);
return (EINVAL);
-
- FREF(fp);
+ }
/* dofilewritev() will FRELE the descriptor for us */
return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
Index: miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v
retrieving revision 1.15
diff -u -p -r1.15 fuse_vfsops.c
--- miscfs/fuse/fuse_vfsops.c 23 Dec 2014 04:54:45 -0000 1.15
+++ miscfs/fuse/fuse_vfsops.c 14 Jul 2015 21:19:26 -0000
@@ -76,7 +76,7 @@ fusefs_mount(struct mount *mp, const cha
struct fusefs_args args;
struct vnode *vp;
struct file *fp;
- int error;
+ int error = 0;
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
@@ -88,12 +88,16 @@ fusefs_mount(struct mount *mp, const cha
if ((fp = fd_getfile(p->p_fd, args.fd)) == NULL)
return (EBADF);
- if (fp->f_type != DTYPE_VNODE)
- return (EINVAL);
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EINVAL;
+ goto out;
+ }
vp = fp->f_data;
- if (vp->v_type != VCHR)
- return (EBADF);
+ if (vp->v_type != VCHR) {
+ error = EBADF;
+ goto out;
+ }
fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
fmp->mp = mp;
@@ -119,7 +123,9 @@ fusefs_mount(struct mount *mp, const cha
/* cannot tsleep on mount */
fuse_device_queue_fbuf(fmp->dev, fbuf);
- return (0);
+out:
+ FRELE(fp, p);
+ return (error);
}
int
Index: sys/filedesc.h
===================================================================
RCS file: /cvs/src/sys/sys/filedesc.h,v
retrieving revision 1.30
diff -u -p -r1.30 filedesc.h
--- sys/filedesc.h 6 May 2015 08:52:17 -0000 1.30
+++ sys/filedesc.h 14 Jul 2015 21:19:26 -0000
@@ -121,7 +121,7 @@ struct filedesc0 {
* Kernel global variables and routines.
*/
void filedesc_init(void);
-int dupfdopen(struct filedesc *, int, int, int);
+int dupfdopen(struct proc *, 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);
@@ -133,7 +133,7 @@ int fdrelease(struct proc *p, int);
void fdremove(struct filedesc *, int);
void fdcloseexec(struct proc *);
struct file *fd_getfile(struct filedesc *, int);
-struct file *fd_getfile_mode(struct filedesc *, int, int);
+struct file *fd_getfile_mode(struct proc *, int, int);
int closef(struct file *, struct proc *);
int getsock(struct proc *, int, struct file **);
Index: uvm/uvm_mmap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_mmap.c,v
retrieving revision 1.109
diff -u -p -r1.109 uvm_mmap.c
--- uvm/uvm_mmap.c 7 May 2015 08:53:33 -0000 1.109
+++ uvm/uvm_mmap.c 14 Jul 2015 21:19:26 -0000
@@ -389,8 +389,6 @@ sys_mmap(struct proc *p, void *v, regist
return (EBADF);
}
- FREF(fp);
-
if (fp->f_type != DTYPE_VNODE) {
error = ENODEV; /* only mmap vnodes! */
goto out;