From: Jeff Layton <jlayton@kernel.org>
To: Chuck Lever <cel@kernel.org>, NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: linux-nfs@vger.kernel.org, Chuck Lever <chuck.lever@oracle.com>
Subject: Re: [PATCH v1] nfsd: fix nfsd_file reference leak in nfsd4_add_rdaccess_to_wrdeleg()
Date: Tue, 02 Dec 2025 07:08:54 -0500 [thread overview]
Message-ID: <928e6aa79ece95012ce26d1341c930c3ffe4f7ae.camel@kernel.org> (raw)
In-Reply-To: <20251201220955.1949-1-cel@kernel.org>
On Mon, 2025-12-01 at 17:09 -0500, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> nfsd4_add_rdaccess_to_wrdeleg() unconditionally overwrites
> fp->fi_fds[O_RDONLY] with a newly acquired nfsd_file. However, if
> the file already has a READ open from a previous OPEN operation,
> this overwrites the existing pointer without releasing its reference,
> orphaning the previous reference.
>
> Additionally, the function originally stored the same nfsd_file
> pointer in both fp->fi_fds[O_RDONLY] and fp->fi_rdeleg_file with
> only a single reference. When put_deleg_file() runs, it clears
> fi_rdeleg_file and calls nfs4_file_put_access() to release the file.
>
> However, nfs4_file_put_access() only releases fi_fds[O_RDONLY] when
> the fi_access[O_RDONLY] counter drops to zero. If another READ open
> exists on the file, the counter remains elevated and the nfsd_file
> reference from the delegation is never released. This potentially
> causes open conflicts on that file.
>
> But, on server shutdown, these leaks cause __nfsd_file_cache_purge()
> to encounter files with an elevated reference count that cannot be
> cleaned up, ultimately triggering a BUG() in kmem_cache_destroy()
> because there are still nfsd_file objects allocated in that cache.
>
> Fixes: e7a8ebc305f2 ("NFSD: Offer write deleg for OPEN4_SHARE_ACCESS_WRITE")
> X-Cc: stable@vger.kernel.org
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> fs/nfsd/nfs4state.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 35004568d43e..11877b96dc4c 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1218,8 +1218,10 @@ static void put_deleg_file(struct nfs4_file *fp)
>
> if (nf)
> nfsd_file_put(nf);
> - if (rnf)
> + if (rnf) {
> + nfsd_file_put(rnf);
> nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ);
> + }
> }
>
> static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f)
> @@ -6231,10 +6233,14 @@ nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
> fp = stp->st_stid.sc_file;
> spin_lock(&fp->fi_lock);
> __nfs4_file_get_access(fp, NFS4_SHARE_ACCESS_READ);
> - fp = stp->st_stid.sc_file;
Weird. Just noticed the double assignment here.
> - fp->fi_fds[O_RDONLY] = nf;
> - fp->fi_rdeleg_file = nf;
> + if (!fp->fi_fds[O_RDONLY]) {
> + fp->fi_fds[O_RDONLY] = nf;
> + nf = NULL;
> + }
> + fp->fi_rdeleg_file = nfsd_file_get(fp->fi_fds[O_RDONLY]);
> spin_unlock(&fp->fi_lock);
> + if (nf)
> + nfsd_file_put(nf);
> }
> return true;
> }
I do so wish this refcounting were easier to get right, but I don't
have any great ideas around it yet.
Reviewed-by: Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2025-12-02 12:08 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-01 22:09 [PATCH v1] nfsd: fix nfsd_file reference leak in nfsd4_add_rdaccess_to_wrdeleg() Chuck Lever
2025-12-02 12:08 ` Jeff Layton [this message]
2025-12-02 13:34 ` Chuck Lever
2025-12-02 14:53 ` Jeff Layton
2025-12-02 19:13 ` Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=928e6aa79ece95012ce26d1341c930c3ffe4f7ae.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=dai.ngo@oracle.com \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.