[PATCH 01/19] nfs/localio: fix nfsd_file ref leak on nfs_local_doio() init failure

Jeff Layton <[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.kernel,gmane.linux.network
Message-ID <[email protected]>
Two early return paths in nfs_local_doio() fail to release the localio
(nfsd_file) reference passed in by the caller:

- When hdr->args.count is zero, the function returns 0 without calling
  nfs_local_file_put().

- When nfs_local_iocb_init() fails (e.g. -ENOMEM from allocation or
  -EOPNOTSUPP if the file lacks read_iter/write_iter), the function
  returns the error without releasing localio or completing the hdr
  lifecycle.

A leaked nfsd_file pins the associated net namespace reference,
blocking network namespace teardown, and holds a reference on the
exported filesystem, preventing unmount.

Fix the zero-count path by adding the missing nfs_local_file_put()
call. Fix the iocb init failure path by jumping to a new cleanup label
that releases localio, sets hdr->task.tk_status, and calls
nfs_local_hdr_release() -- matching the existing error handling pattern
for the post-iocb error path.

Fixes: e77c464c31b3 ("nfs/nfsd: add "local io" support")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jeff Layton <[email protected]>
---
 fs/nfs/localio.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index e55c5977fcc3..63cf6e2cc745 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -970,12 +970,16 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
 	struct nfs_local_kiocb *iocb;
 	int status = 0;
 
-	if (!hdr->args.count)
+	if (!hdr->args.count) {
+		nfs_local_file_put(localio);
 		return 0;
+	}
 
 	iocb = nfs_local_iocb_init(hdr, localio);
-	if (IS_ERR(iocb))
-		return PTR_ERR(iocb);
+	if (IS_ERR(iocb)) {
+		status = PTR_ERR(iocb);
+		goto out_put_localio;
+	}
 
 	switch (hdr->rw_mode) {
 	case FMODE_READ:
@@ -996,6 +1000,12 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
 		nfs_local_hdr_release(hdr, call_ops);
 	}
 	return status;
+
+out_put_localio:
+	nfs_local_file_put(localio);
+	hdr->task.tk_status = status;
+	nfs_local_hdr_release(hdr, call_ops);
+	return status;
 }
 
 static void

-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.