summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2025-11-19 08:43:21 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-12-18 14:00:08 +0100
commit0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f (patch)
treeeb1b2fac575f0b2ed7e4340577e46b3a57561d64
parent34c0479db10884e10374fdd4a18eed2920561034 (diff)
downloadlinux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.tar.gz
linux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.tar.bz2
linux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.zip
NFS: Initialise verifiers for visible dentries in _nfs4_open_and_get_state
[ Upstream commit 0f900f11002ff52391fc2aa4a75e59f26ed1c242 ] Ensure that the verifiers are initialised before calling d_splice_alias() in _nfs4_open_and_get_state(). Reported-by: Michael Stoler <michael.stoler@vastdata.com> Fixes: cf5b4059ba71 ("NFSv4: Fix races between open and dentry revalidation") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/nfs/nfs4proc.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a1e95732fd03..106f0bf88137 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3174,18 +3174,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
if (opendata->o_res.rflags & NFS4_OPEN_RESULT_PRESERVE_UNLINKED)
set_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(state->inode)->flags);
- dentry = opendata->dentry;
- if (d_really_is_negative(dentry)) {
- struct dentry *alias;
- d_drop(dentry);
- alias = d_splice_alias(igrab(state->inode), dentry);
- /* d_splice_alias() can't fail here - it's a non-directory */
- if (alias) {
- dput(ctx->dentry);
- ctx->dentry = dentry = alias;
- }
- }
-
switch(opendata->o_arg.claim) {
default:
break;
@@ -3196,7 +3184,20 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
break;
if (opendata->o_res.delegation.type != 0)
dir_verifier = nfs_save_change_attribute(dir);
- nfs_set_verifier(dentry, dir_verifier);
+ }
+
+ dentry = opendata->dentry;
+ nfs_set_verifier(dentry, dir_verifier);
+ if (d_really_is_negative(dentry)) {
+ struct dentry *alias;
+ d_drop(dentry);
+ alias = d_splice_alias(igrab(state->inode), dentry);
+ /* d_splice_alias() can't fail here - it's a non-directory */
+ if (alias) {
+ dput(ctx->dentry);
+ nfs_set_verifier(alias, dir_verifier);
+ ctx->dentry = dentry = alias;
+ }
}
/* Parse layoutget results before we check for access */