stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>,
	Sasha Levin <sashal@kernel.org>,
	anna.schumaker@netapp.com, linux-nfs@vger.kernel.org
Subject: [PATCH AUTOSEL 5.15 05/65] NFS: Fix up nfs_ctx_key_to_expire()
Date: Tue, 16 Nov 2021 14:16:50 -0500	[thread overview]
Message-ID: <20211116191754.2419097-5-sashal@kernel.org> (raw)
In-Reply-To: <20211116191754.2419097-1-sashal@kernel.org>

From: Trond Myklebust <trond.myklebust@hammerspace.com>

[ Upstream commit ca05cbae2a0468e5d78e9b4605936a8bf5da328b ]

If the cached credential exists but doesn't have any expiration callback
then exit early.
Fix up atomicity issues when replacing the credential with a new one
since the existing code could lead to refcount leaks.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/nfs/inode.c         |  4 ++--
 fs/nfs/write.c         | 41 ++++++++++++++++++++++++++++-------------
 include/linux/nfs_fs.h |  2 +-
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 853213b3a2095..4f45281c47cfb 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1024,7 +1024,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
 		ctx->cred = get_cred(filp->f_cred);
 	else
 		ctx->cred = get_current_cred();
-	ctx->ll_cred = NULL;
+	rcu_assign_pointer(ctx->ll_cred, NULL);
 	ctx->state = NULL;
 	ctx->mode = f_mode;
 	ctx->flags = 0;
@@ -1063,7 +1063,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 	put_cred(ctx->cred);
 	dput(ctx->dentry);
 	nfs_sb_deactive(sb);
-	put_rpccred(ctx->ll_cred);
+	put_rpccred(rcu_dereference_protected(ctx->ll_cred, 1));
 	kfree(ctx->mdsthreshold);
 	kfree_rcu(ctx, rcu_head);
 }
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index eae9bf1140417..773ea2c8504d6 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1246,7 +1246,7 @@ nfs_key_timeout_notify(struct file *filp, struct inode *inode)
 	struct nfs_open_context *ctx = nfs_file_open_context(filp);
 
 	if (nfs_ctx_key_to_expire(ctx, inode) &&
-	    !ctx->ll_cred)
+	    !rcu_access_pointer(ctx->ll_cred))
 		/* Already expired! */
 		return -EACCES;
 	return 0;
@@ -1258,23 +1258,38 @@ nfs_key_timeout_notify(struct file *filp, struct inode *inode)
 bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx, struct inode *inode)
 {
 	struct rpc_auth *auth = NFS_SERVER(inode)->client->cl_auth;
-	struct rpc_cred *cred = ctx->ll_cred;
+	struct rpc_cred *cred, *new, *old = NULL;
 	struct auth_cred acred = {
 		.cred = ctx->cred,
 	};
+	bool ret = false;
 
-	if (cred && !cred->cr_ops->crmatch(&acred, cred, 0)) {
-		put_rpccred(cred);
-		ctx->ll_cred = NULL;
-		cred = NULL;
-	}
-	if (!cred)
-		cred = auth->au_ops->lookup_cred(auth, &acred, 0);
-	if (!cred || IS_ERR(cred))
+	rcu_read_lock();
+	cred = rcu_dereference(ctx->ll_cred);
+	if (cred && !(cred->cr_ops->crkey_timeout &&
+		      cred->cr_ops->crkey_timeout(cred)))
+		goto out;
+	rcu_read_unlock();
+
+	new = auth->au_ops->lookup_cred(auth, &acred, 0);
+	if (new == cred) {
+		put_rpccred(new);
 		return true;
-	ctx->ll_cred = cred;
-	return !!(cred->cr_ops->crkey_timeout &&
-		  cred->cr_ops->crkey_timeout(cred));
+	}
+	if (IS_ERR_OR_NULL(new)) {
+		new = NULL;
+		ret = true;
+	} else if (new->cr_ops->crkey_timeout &&
+		   new->cr_ops->crkey_timeout(new))
+		ret = true;
+
+	rcu_read_lock();
+	old = rcu_dereference_protected(xchg(&ctx->ll_cred,
+					     RCU_INITIALIZER(new)), 1);
+out:
+	rcu_read_unlock();
+	put_rpccred(old);
+	return ret;
 }
 
 /*
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b9a8b925db430..9b75448ce0df8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -81,7 +81,7 @@ struct nfs_open_context {
 	fl_owner_t flock_owner;
 	struct dentry *dentry;
 	const struct cred *cred;
-	struct rpc_cred *ll_cred;	/* low-level cred - use to check for expiry */
+	struct rpc_cred __rcu *ll_cred;	/* low-level cred - use to check for expiry */
 	struct nfs4_state *state;
 	fmode_t mode;
 
-- 
2.33.0


  parent reply	other threads:[~2021-11-16 19:18 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-16 19:16 [PATCH AUTOSEL 5.15 01/65] Input: cpcap-pwrbutton - handle errors from platform_get_irq() Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 02/65] kcsan: test: Fix flaky test case Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 03/65] backlight: Propagate errors from get_brightness() Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 04/65] UNRPC: Return specific error code on kmalloc failure Sasha Levin
2021-11-16 19:16 ` Sasha Levin [this message]
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 06/65] PCI: aardvark: Fix link training Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 07/65] fbdev: fbmem: Fix double free of 'fb_info->pixmap.addr' Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 08/65] drm/virtio: fix the missed drm_gem_object_put() in virtio_gpu_user_framebuffer_create() Sasha Levin
2021-11-16 19:16 ` [PATCH AUTOSEL 5.15 09/65] orangefs: Fix sb refcount leak when allocate sb info failed Sasha Levin
  -- strict thread matches above, loose matches on Subject: below --
2021-11-16 19:03 [PATCH AUTOSEL 5.15 01/65] Input: cpcap-pwrbutton - handle errors from platform_get_irq() Sasha Levin
2021-11-16 19:03 ` [PATCH AUTOSEL 5.15 05/65] NFS: Fix up nfs_ctx_key_to_expire() Sasha Levin

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=20211116191754.2419097-5-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=anna.schumaker@netapp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=trond.myklebust@hammerspace.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).