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"