The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=54f98c4dbf9b1203a4e3e1b13fd0738441226991

commit 54f98c4dbf9b1203a4e3e1b13fd0738441226991
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2021-04-19 10:25:30 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2021-04-21 15:06:51 +0000

    vn_open_vnode(): handle error when fp == NULL
    
    If VOP_ADD_WRITECOUNT() or adv locking failed, so VOP_CLOSE() needs to
    be called, we cannot use fp fo_close() when there is no fp.  This occurs
    when e.g. kernel code directly calls vn_open() instead of the open(2)
    syscall.
    
    In this case, VOP_CLOSE() can be called directly, after possible lock
    upgrade.
    
    Reported by:    nv...@gmx.com
    PR:     255119
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D29830
---
 sys/kern/vfs_vnops.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 9da35721def4..f715c9828d04 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -451,16 +451,34 @@ vn_open_vnode(struct vnode *vp, int fmode, struct ucred 
*cred,
        /*
         * Error from advlock or VOP_ADD_WRITECOUNT() still requires
         * calling VOP_CLOSE() to pair with earlier VOP_OPEN().
-        * Arrange for that by having fdrop() to use vn_closefile().
         */
        if (error != 0) {
-               fp->f_flag |= FOPENFAILED;
-               fp->f_vnode = vp;
-               if (fp->f_ops == &badfileops) {
-                       fp->f_type = DTYPE_VNODE;
-                       fp->f_ops = &vnops;
+               if (fp != NULL) {
+                       /*
+                        * Arrange the call by having fdrop() to use
+                        * vn_closefile().  This is to satisfy
+                        * filesystems like devfs or tmpfs, which
+                        * override fo_close().
+                        */
+                       fp->f_flag |= FOPENFAILED;
+                       fp->f_vnode = vp;
+                       if (fp->f_ops == &badfileops) {
+                               fp->f_type = DTYPE_VNODE;
+                               fp->f_ops = &vnops;
+                       }
+                       vref(vp);
+               } else {
+                       /*
+                        * If there is no fp, due to kernel-mode open,
+                        * we can call VOP_CLOSE() now.
+                        */
+                       if (vp->v_type != VFIFO && (fmode & FWRITE) != 0 &&
+                           !MNT_EXTENDED_SHARED(vp->v_mount) &&
+                           VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
+                               vn_lock(vp, LK_UPGRADE | LK_RETRY);
+                       (void)VOP_CLOSE(vp, fmode & (FREAD | FWRITE | FEXEC),
+                           cred, td);
                }
-               vref(vp);
        }
 
        ASSERT_VOP_LOCKED(vp, "vn_open_vnode");
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to