git: 03d5820f738d - main - mount: Check for !VDIR mount points before handling -o emptydir

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Wed, 13 Oct 2021 13:37:39 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=03d5820f738de130b2feb66833f18741b7f92a14

commit 03d5820f738de130b2feb66833f18741b7f92a14
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-10-13 00:11:02 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-10-13 13:33:35 +0000

    mount: Check for !VDIR mount points before handling -o emptydir
    
    To implement -o emptydir, vfs_emptydir() checks that the passed
    directory is empty.  This should be done after checking whether the
    vnode is of type VDIR, though, or vfs_emptydir() may end up calling
    VOP_READDIR on a non-directory.
    
    Reported by:    syzbot+4006732c69fb0f792b2c@syzkaller.appspotmail.com
    Reviewed by:    kib, imp
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32475
---
 sys/kern/vfs_mount.c | 10 ++--------
 sys/kern/vfs_subr.c  |  1 +
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 55c62b7fe491..2fc98d3cc6c8 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1095,14 +1095,6 @@ vfs_domount_first(
 	ASSERT_VOP_ELOCKED(vp, __func__);
 	KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
 
-	if ((fsflags & MNT_EMPTYDIR) != 0) {
-		error = vfs_emptydir(vp);
-		if (error != 0) {
-			vput(vp);
-			return (error);
-		}
-	}
-
 	/*
 	 * If the jail of the calling thread lacks permission for this type of
 	 * file system, or is trying to cover its own root, deny immediately.
@@ -1124,6 +1116,8 @@ vfs_domount_first(
 		error = vinvalbuf(vp, V_SAVE, 0, 0);
 	if (error == 0 && vp->v_type != VDIR)
 		error = ENOTDIR;
+	if (error == 0 && (fsflags & MNT_EMPTYDIR) != 0)
+		error = vfs_emptydir(vp);
 	if (error == 0) {
 		VI_LOCK(vp);
 		if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index d4b7ac71eb97..181d0004e940 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6300,6 +6300,7 @@ vfs_emptydir(struct vnode *vp)
 	eof = 0;
 
 	ASSERT_VOP_LOCKED(vp, "vfs_emptydir");
+	VNASSERT(vp->v_type == VDIR, vp, ("vp is not a directory"));
 
 	dirent = malloc(sizeof(struct dirent), M_TEMP, M_WAITOK);
 	iov.iov_base = dirent;