]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
lockd: Plug nlm_file refcount leak on cached nlm_do_fopen() failure
authorChuck Lever <chuck.lever@oracle.com>
Thu, 14 May 2026 20:56:06 +0000 (16:56 -0400)
committerChuck Lever <cel@kernel.org>
Tue, 9 Jun 2026 20:32:59 +0000 (16:32 -0400)
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>
fs/lockd/svcsubs.c

index 0b81d8db09191608ddbea36464ff803325316ece..58b87ec529308d871dac2114abee75c07e3e25d8 100644 (file)
@@ -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);