summaryrefslogtreecommitdiff
path: root/fs/lockd
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2026-05-14 16:56:06 -0400
committerChuck Lever <cel@kernel.org>2026-06-09 16:32:59 -0400
commit70a38f87bed7f0694fd07988b47b2db1e10d8df3 (patch)
tree3a2c5a4ade607a6b674e582adde8c235d3d6ad72 /fs/lockd
parentf16a1513452edb532fec81e591c64c320866719c (diff)
lockd: Plug nlm_file refcount leak on cached nlm_do_fopen() failure
The cached-file path in nlm_lookup_file() reaches the found: label unconditionally, even when nlm_do_fopen() fails. At that label *result and file->f_count are updated before the error is returned. The wrappers nlm3svc_lookup_file() and nlm4svc_lookup_file() then bail out of their switch without copying *result back to their caller, so the proc handler's local nlm_file pointer remains NULL and the cleanup path skips nlm_release_file(). The f_count increment is never released, and nlm_traverse_files() can no longer reap the file because its refcount never returns to zero between requests. Short-circuit the cached path so neither *result nor f_count is touched when nlm_do_fopen() fails on a hashed nlm_file. Fixes: 7f024fcd5c97 ("Keep read and write fds with each nlm_file") Cc: stable@vger.kernel.org Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/svcsubs.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 0b81d8db0919..58b87ec52930 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -150,6 +150,8 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
mutex_lock(&file->f_mutex);
nfserr = nlm_do_fopen(rqstp, file, mode);
mutex_unlock(&file->f_mutex);
+ if (nfserr)
+ goto out_unlock;
goto found;
}
nlm_debug_print_fh("creating file for", &lock->fh);