git: 969d1aa4dbfc - main - fusefs: fix a memory leak

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Mon, 23 Dec 2024 20:43:31 UTC
The branch main has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=969d1aa4dbfcbccd8de965f7761203208bf04e46

commit 969d1aa4dbfcbccd8de965f7761203208bf04e46
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-12-23 20:26:11 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-12-23 20:37:19 +0000

    fusefs: fix a memory leak
    
    Fix a leak of a fuse_ticket structure.  The leak mostly affected
    NFS-exported fuse file systems, and was triggered by a failure during
    FUSE_LOOKUP.
    
    MFC after:      2 weeks
    Sponsored by:   ConnectWise
---
 sys/fs/fuse/fuse_vfsops.c  |  2 +-
 tests/sys/fs/fusefs/nfs.cc | 30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index e60c9aa80cfa..0da51b865873 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -565,7 +565,7 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 	error = fdisp_wait_answ(&fdi);
 
 	if (error)
-		return error;
+		goto out;
 
 	feo = (struct fuse_entry_out *)fdi.answ;
 	if (feo->nodeid == 0) {
diff --git a/tests/sys/fs/fusefs/nfs.cc b/tests/sys/fs/fusefs/nfs.cc
index 79fead8e77cb..27ffc8f5cbc1 100644
--- a/tests/sys/fs/fusefs/nfs.cc
+++ b/tests/sys/fs/fusefs/nfs.cc
@@ -144,6 +144,36 @@ TEST_F(Fhstat, lookup_dot)
 	EXPECT_EQ(mode, sb.st_mode);
 }
 
+/* Gracefully handle failures to lookup ".". */
+TEST_F(Fhstat, lookup_dot_error)
+{
+	const char FULLPATH[] = "mountpoint/some_dir/.";
+	const char RELDIRPATH[] = "some_dir";
+	fhandle_t fhp;
+	struct stat sb;
+	const uint64_t ino = 42;
+	const mode_t mode = S_IFDIR | 0755;
+	const uid_t uid = 12345;
+
+	EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH)
+	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) {
+		SET_OUT_HEADER_LEN(out, entry);
+		out.body.entry.attr.mode = mode;
+		out.body.entry.nodeid = ino;
+		out.body.entry.generation = 1;
+		out.body.entry.attr.uid = uid;
+		out.body.entry.attr_valid = UINT64_MAX;
+		out.body.entry.entry_valid = 0;
+	})));
+
+	EXPECT_LOOKUP(ino, ".")
+	.WillOnce(Invoke(ReturnErrno(EDOOFUS)));
+
+	ASSERT_EQ(0, getfh(FULLPATH, &fhp)) << strerror(errno);
+	ASSERT_EQ(-1, fhstat(&fhp, &sb));
+	EXPECT_EQ(EDOOFUS, errno);
+}
+
 /* Use a file handle whose entry is still cached */
 TEST_F(Fhstat, cached)
 {