Here's a diff to move FREF() just after fd_getfile() in sys_kevent(),
sys_lseek() and getvnode().

As explained recently [0], I'd like to make sure all operations
manipulating a 'struct file *' do so with a properly refcounted
element.

[0] https://marc.info/?l=openbsd-tech&m=152214234530708&w=2

Ok?

Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.84
diff -u -p -r1.84 kern_event.c
--- kern/kern_event.c   13 Jan 2018 12:58:40 -0000      1.84
+++ kern/kern_event.c   2 Apr 2018 10:25:10 -0000
@@ -479,11 +479,14 @@ sys_kevent(struct proc *p, void *v, regi
        int i, n, nerrors, error;
        struct kevent kev[KQ_NEVENTS];
 
-       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));
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.277
diff -u -p -r1.277 vfs_syscalls.c
--- kern/vfs_syscalls.c 28 Mar 2018 09:47:52 -0000      1.277
+++ kern/vfs_syscalls.c 2 Apr 2018 10:25:09 -0000
@@ -1612,12 +1612,12 @@ 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 = fp->f_data;
-       if (vp->v_type == VFIFO)
-               return (ESPIPE);
        FREF(fp);
+       vp = fp->f_data;
+       if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+               error = ESPIPE;
+               goto bad;
+       }
        if (vp->v_type == VCHR)
                special = 1;
        else
@@ -2896,15 +2896,19 @@ getvnode(struct proc *p, int fd, struct 
 
        if ((fp = fd_getfile(p->p_fd, fd)) == NULL)
                return (EBADF);
+       FREF(fp);
 
-       if (fp->f_type != DTYPE_VNODE)
+       if (fp->f_type != DTYPE_VNODE) {
+               FRELE(fp, p);
                return (EINVAL);
+       }
 
        vp = fp->f_data;
-       if (vp->v_type == VBAD)
+       if (vp->v_type == VBAD) {
+               FRELE(fp, p);
                return (EBADF);
+       }
 
-       FREF(fp);
        *fpp = fp;
 
        return (0);

Reply via email to