git: 60311a50779d - stable/14 - fusefs: fix a memory leak

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Mon, 20 Jan 2025 16:52:21 UTC
The branch stable/14 has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=60311a50779d27467f4f1cc38d62cb098ed80607

commit 60311a50779d27467f4f1cc38d62cb098ed80607
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-12-23 20:26:11 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2025-01-20 16:51:44 +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.
    
    Sponsored by:   ConnectWise
    
    (cherry picked from commit 969d1aa4dbfcbccd8de965f7761203208bf04e46)
---
 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 4a4f9dac3fae..ce9c1d7fd946 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -566,7 +566,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)
 {