public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Steve French <stfrench@microsoft.com>,
	Bharath SM <bharathsm@microsoft.com>,
	Sasha Levin <sashal@kernel.org>,
	sfrench@samba.org, linux-cifs@vger.kernel.org,
	samba-technical@lists.samba.org
Subject: [PATCH AUTOSEL 6.6 28/29] smb3: fix broken reconnect when password changing on the server by allowing password rotation
Date: Mon, 22 Apr 2024 19:17:09 -0400	[thread overview]
Message-ID: <20240422231730.1601976-28-sashal@kernel.org> (raw)
In-Reply-To: <20240422231730.1601976-1-sashal@kernel.org>

From: Steve French <stfrench@microsoft.com>

[ Upstream commit 35f834265e0dc78b003aa0d1af65cafb89666b76 ]

There are various use cases that are becoming more common in which password
changes are scheduled on a server(s) periodically but the clients connected
to this server need to stay connected (even in the face of brief network
reconnects) due to mounts which can not be easily unmounted and mounted at
will, and servers that do password rotation do not always have the ability
to tell the clients exactly when to the new password will be effective,
so add support for an alt password ("password2=") on mount (and also
remount) so that we can anticipate the upcoming change to the server
without risking breaking existing mounts.

An alternative would have been to use the kernel keyring for this but the
processes doing the reconnect do not have access to the keyring but do
have access to the ses structure.

Reviewed-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/smb/client/cifsglob.h   |  1 +
 fs/smb/client/connect.c    |  8 ++++++++
 fs/smb/client/fs_context.c | 21 +++++++++++++++++++++
 fs/smb/client/fs_context.h |  2 ++
 fs/smb/client/misc.c       |  1 +
 fs/smb/client/smb2pdu.c    | 11 +++++++++++
 6 files changed, 44 insertions(+)

diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index a878b1e5aa313..1f6954b7311e3 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1049,6 +1049,7 @@ struct cifs_ses {
 				   and after mount option parsing we fill it */
 	char *domainName;
 	char *password;
+	char *password2; /* When key rotation used, new password may be set before it expires */
 	char workstation_name[CIFS_MAX_WORKSTATION_LEN];
 	struct session_key auth_key;
 	struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 97776dd12b6b8..7091885d5036d 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -2195,6 +2195,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
 	}
 
 	++delim;
+	/* BB consider adding support for password2 (Key Rotation) for multiuser in future */
 	ctx->password = kstrndup(delim, len, GFP_KERNEL);
 	if (!ctx->password) {
 		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
@@ -2218,6 +2219,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
 			kfree(ctx->username);
 			ctx->username = NULL;
 			kfree_sensitive(ctx->password);
+			/* no need to free ctx->password2 since not allocated in this path */
 			ctx->password = NULL;
 			goto out_key_put;
 		}
@@ -2329,6 +2331,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
 		if (!ses->password)
 			goto get_ses_fail;
 	}
+	/* ctx->password freed at unmount */
+	if (ctx->password2) {
+		ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
+		if (!ses->password2)
+			goto get_ses_fail;
+	}
 	if (ctx->domainname) {
 		ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
 		if (!ses->domainName)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 58567ae617b9f..9d485e7b85541 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -161,6 +161,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
 	fsparam_string("username", Opt_user),
 	fsparam_string("pass", Opt_pass),
 	fsparam_string("password", Opt_pass),
+	fsparam_string("password2", Opt_pass2),
 	fsparam_string("ip", Opt_ip),
 	fsparam_string("addr", Opt_ip),
 	fsparam_string("domain", Opt_domain),
@@ -314,6 +315,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
 	new_ctx->nodename = NULL;
 	new_ctx->username = NULL;
 	new_ctx->password = NULL;
+	new_ctx->password2 = NULL;
 	new_ctx->server_hostname = NULL;
 	new_ctx->domainname = NULL;
 	new_ctx->UNC = NULL;
@@ -326,6 +328,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
 	DUP_CTX_STR(prepath);
 	DUP_CTX_STR(username);
 	DUP_CTX_STR(password);
+	DUP_CTX_STR(password2);
 	DUP_CTX_STR(server_hostname);
 	DUP_CTX_STR(UNC);
 	DUP_CTX_STR(source);
@@ -874,6 +877,8 @@ static int smb3_reconfigure(struct fs_context *fc)
 	else  {
 		kfree_sensitive(ses->password);
 		ses->password = kstrdup(ctx->password, GFP_KERNEL);
+		kfree_sensitive(ses->password2);
+		ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
 	}
 	STEAL_STRING(cifs_sb, ctx, domainname);
 	STEAL_STRING(cifs_sb, ctx, nodename);
@@ -1271,6 +1276,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
 			goto cifs_parse_mount_err;
 		}
 		break;
+	case Opt_pass2:
+		kfree_sensitive(ctx->password2);
+		ctx->password2 = NULL;
+		if (strlen(param->string) == 0)
+			break;
+
+		ctx->password2 = kstrdup(param->string, GFP_KERNEL);
+		if (ctx->password2 == NULL) {
+			cifs_errorf(fc, "OOM when copying password2 string\n");
+			goto cifs_parse_mount_err;
+		}
+		break;
 	case Opt_ip:
 		if (strlen(param->string) == 0) {
 			ctx->got_ip = false;
@@ -1570,6 +1587,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
  cifs_parse_mount_err:
 	kfree_sensitive(ctx->password);
 	ctx->password = NULL;
+	kfree_sensitive(ctx->password2);
+	ctx->password2 = NULL;
 	return -EINVAL;
 }
 
@@ -1672,6 +1691,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
 	ctx->username = NULL;
 	kfree_sensitive(ctx->password);
 	ctx->password = NULL;
+	kfree_sensitive(ctx->password2);
+	ctx->password2 = NULL;
 	kfree(ctx->server_hostname);
 	ctx->server_hostname = NULL;
 	kfree(ctx->UNC);
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
index 8cfc25b609b6b..e807bea49d41f 100644
--- a/fs/smb/client/fs_context.h
+++ b/fs/smb/client/fs_context.h
@@ -137,6 +137,7 @@ enum cifs_param {
 	Opt_source,
 	Opt_user,
 	Opt_pass,
+	Opt_pass2,
 	Opt_ip,
 	Opt_domain,
 	Opt_srcaddr,
@@ -168,6 +169,7 @@ struct smb3_fs_context {
 
 	char *username;
 	char *password;
+	char *password2;
 	char *domainname;
 	char *source;
 	char *server_hostname;
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
index ef573e3f8e52a..9f2a13083500e 100644
--- a/fs/smb/client/misc.c
+++ b/fs/smb/client/misc.c
@@ -101,6 +101,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
 	kfree(buf_to_free->serverDomain);
 	kfree(buf_to_free->serverNOS);
 	kfree_sensitive(buf_to_free->password);
+	kfree_sensitive(buf_to_free->password2);
 	kfree(buf_to_free->user_name);
 	kfree(buf_to_free->domainName);
 	kfree_sensitive(buf_to_free->auth_key.response);
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 94bd4c6d2d682..70530108b9bb9 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -367,6 +367,17 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
 		}
 
 		rc = cifs_setup_session(0, ses, server, nls_codepage);
+		if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
+			/*
+			 * Try alternate password for next reconnect (key rotation
+			 * could be enabled on the server e.g.) if an alternate
+			 * password is available and the current password is expired,
+			 * but do not swap on non pwd related errors like host down
+			 */
+			if (ses->password2)
+				swap(ses->password2, ses->password);
+		}
+
 		if ((rc == -EACCES) && !tcon->retry) {
 			mutex_unlock(&ses->session_mutex);
 			rc = -EHOSTDOWN;
-- 
2.43.0


  parent reply	other threads:[~2024-04-22 23:57 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-22 23:16 [PATCH AUTOSEL 6.6 01/29] tools/power turbostat: Fix added raw MSR output Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 02/29] tools/power turbostat: Increase the limit for fd opened Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 03/29] tools/power turbostat: Fix Bzy_MHz documentation typo Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 04/29] tools/power turbostat: Print ucode revision only if valid Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 05/29] tools/power turbostat: Fix warning upon failed /dev/cpu_dma_latency read Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 06/29] btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 07/29] btrfs: always clear PERTRANS metadata during commit Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 08/29] memblock tests: fix undefined reference to `early_pfn_to_nid' Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 09/29] memblock tests: fix undefined reference to `panic' Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 10/29] memblock tests: fix undefined reference to `BIT' Sasha Levin
2024-04-23  2:14   ` Suren Baghdasaryan
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 11/29] scsi: target: Fix SELinux error when systemd-modules loads the target module Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 12/29] scsi: hisi_sas: Handle the NCQ error returned by D2H frame Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 13/29] blk-iocost: avoid out of bounds shift Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 14/29] gpu: host1x: Do not setup DMA for virtual devices Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 15/29] MIPS: scall: Save thread_info.syscall unconditionally on entry Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 16/29] tools/power/turbostat: Fix uncore frequency file string Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 17/29] drm/amdgpu: Refine IB schedule error logging Sasha Levin
2024-04-22 23:16 ` [PATCH AUTOSEL 6.6 18/29] drm/amdgpu: implement IRQ_STATE_ENABLE for SDMA v4.4.2 Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 19/29] drm/amd/display: Skip on writeback when it's not applicable Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 20/29] drm/amdgpu: Fix VCN allocation in CPX partition Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 21/29] amd/amdkfd: sync all devices to wait all processes being evicted Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 22/29] selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 23/29] Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 24/29] Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 25/29] hv_netvsc: Don't free decrypted memory Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 26/29] uio_hv_generic: " Sasha Levin
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 27/29] Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted Sasha Levin
2024-04-22 23:17 ` Sasha Levin [this message]
2024-04-22 23:17 ` [PATCH AUTOSEL 6.6 29/29] iommu: mtk: fix module autoloading 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=20240422231730.1601976-28-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=bharathsm@microsoft.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=samba-technical@lists.samba.org \
    --cc=sfrench@samba.org \
    --cc=stable@vger.kernel.org \
    --cc=stfrench@microsoft.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