linux-cifs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][SMB3] mount.cifs: use SUDO_UID env variable for cruid
@ 2020-09-16 10:00 Shyam Prasad N
  2020-09-16 10:56 ` Aurélien Aptel
  0 siblings, 1 reply; 11+ messages in thread
From: Shyam Prasad N @ 2020-09-16 10:00 UTC (permalink / raw)
  To: Pavel Shilovsky, Steve French, CIFS, sribhat.msa

[-- Attachment #1: Type: text/plain, Size: 366 bytes --]

Hi,

This is a fix for the scenario of a krb5 user running a "sudo mount".
Even if the user has cred cache populated, when the mount is run using
sudo, uid switches to 0. So cred cache for the root user will be
searched for, unless cruid is specified explicitly. This fix checks
for cruid=$SUDO_UID as a fallback option, when the mount fails with
ENOKEY.

--
-Shyam

[-- Attachment #2: 0001-mount.cifs-use-SUDO_UID-env-variable-for-cruid.patch --]
[-- Type: application/octet-stream, Size: 5619 bytes --]

From 15ac08056ec3c7175da1b6d20a50cae855189258 Mon Sep 17 00:00:00 2001
From: Shyam Prasad N <sprasad@microsoft.com>
Date: Wed, 16 Sep 2020 00:18:44 -0700
Subject: [PATCH] mount.cifs: use SUDO_UID env variable for cruid

In the current mount.cifs logic, when sudo is used for mount,
uid=0, so the mount command searches for cruid=0 unless explicitly
specified by the user. The user may already have cred cache populated
but mount.cifs would end up searching cred cache for uid=0.

mount.cifs can avoid this confusion by reading the cruid from SUDO_UID
environment variable. If it is set to non-zero, we can make cruid=$SUDO_UID.

However, to maintain backward compatibility, keeping this as a fallback option.
If mount fails with permission denied, then retry with this option.
To enable this fallback, I had to make a few minor changes in the flow.
---
 mount.cifs.c | 79 +++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 62 insertions(+), 17 deletions(-)

diff --git a/mount.cifs.c b/mount.cifs.c
index 4feb397..cf62c30 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -171,7 +171,11 @@
 
 #define NTFS_TIME_OFFSET ((unsigned long long)(369*365 + 89) * 24 * 3600 * 10000000)
 
-/* struct for holding parsed mount info for use by privileged process */
+/*
+* struct for holding parsed mount info for use by privileged process.
+* Please do not keep pointers in this struct.
+* That way, reinit of this struct is a simple memset.
+*/
 struct parsed_mount_info {
 	unsigned long flags;
 	char host[NI_MAXHOST + 1];
@@ -189,6 +193,7 @@ struct parsed_mount_info {
 	unsigned int verboseflag:1;
 	unsigned int nofail:1;
 	unsigned int got_domain:1;
+	uid_t sudo_uid;
 };
 
 static const char *thisprogram;
@@ -1199,6 +1204,10 @@ nocopy:
 		snprintf(out + out_len, word_len + 5, "uid=%s", txtbuf);
 		out_len = strlen(out);
 	}
+	if (parsed_info->sudo_uid) {
+		cruid = parsed_info->sudo_uid;
+		got_cruid = 1;
+	}
 	if (got_cruid) {
 		word_len = snprintf(txtbuf, sizeof(txtbuf), "%u", cruid);
 
@@ -2012,12 +2021,16 @@ int main(int argc, char **argv)
 	char *options = NULL;
 	char *orig_dev = NULL;
 	char *currentaddress, *nextaddress;
+	char *value = NULL;
+	char *ep = NULL;
 	int rc = 0;
 	int already_uppercased = 0;
 	int sloppy = 0;
 	size_t options_size = MAX_OPTIONS_LEN;
 	struct parsed_mount_info *parsed_info = NULL;
+	struct parsed_mount_info *reinit_parsed_info = NULL;
 	pid_t pid;
+	uid_t sudo_uid = 0;
 
 	rc = check_setuid();
 	if (rc)
@@ -2053,7 +2066,24 @@ int main(int argc, char **argv)
 		parsed_info = NULL;
 		fprintf(stderr, "Unable to allocate memory: %s\n",
 				strerror(errno));
-		return EX_SYSERR;
+		rc = EX_SYSERR;
+		goto mount_exit;
+	}
+
+	reinit_parsed_info = 
+		(struct parsed_mount_info *) malloc(sizeof(*reinit_parsed_info));
+	if (reinit_parsed_info == NULL) {
+		fprintf(stderr, "Unable to allocate memory: %s\n",
+				strerror(errno));
+		rc = EX_SYSERR;
+		goto mount_exit;
+	}
+
+	options = calloc(options_size, 1);
+	if (!options) {
+		fprintf(stderr, "Unable to allocate memory.\n");
+		rc = EX_SYSERR;
+		goto mount_exit;
 	}
 
 	/* add sharename in opts string as unc= parm */
@@ -2110,10 +2140,13 @@ int main(int argc, char **argv)
 	/* chdir into mountpoint as soon as possible */
 	rc = acquire_mountpoint(&mountpoint);
 	if (rc) {
-		free(orgoptions);
-		return rc;
+		goto mount_exit;
 	}
 
+	/* Before goto assemble_retry, reinitialize parsed_info with reinit_parsed_info */
+	memcpy(reinit_parsed_info, parsed_info,	sizeof(*reinit_parsed_info));
+
+assemble_retry:
 	/*
 	 * mount.cifs does privilege separation. Most of the code to handle
 	 * assembling the mount info is done in a child process that drops
@@ -2131,9 +2164,7 @@ int main(int argc, char **argv)
 		/* child */
 		rc = assemble_mountinfo(parsed_info, thisprogram, mountpoint,
 					orig_dev, orgoptions);
-		free(orgoptions);
-		free(mountpoint);
-		return rc;
+		goto mount_exit;
 	} else {
 		/* parent */
 		pid = wait(&rc);
@@ -2147,13 +2178,6 @@ int main(int argc, char **argv)
 			goto mount_exit;
 	}
 
-	options = calloc(options_size, 1);
-	if (!options) {
-		fprintf(stderr, "Unable to allocate memory.\n");
-		rc = EX_SYSERR;
-		goto mount_exit;
-	}
-
 	currentaddress = parsed_info->addrlist;
 	nextaddress = strchr(currentaddress, ',');
 	if (nextaddress)
@@ -2228,6 +2252,7 @@ mount_retry:
 				if (nextaddress)
 					*nextaddress++ = '\0';
 			}
+			memset(options, 0, sizeof(*options));
 			goto mount_retry;
 		case ENODEV:
 			fprintf(stderr,
@@ -2250,6 +2275,21 @@ mount_retry:
 				already_uppercased = 1;
 				goto mount_retry;
 			}
+			break;
+		case ENOKEY:
+			/* mount could have failed because cruid option was not passed when triggered with sudo */
+			value = getenv("SUDO_UID");
+			if (value && !parsed_info->sudo_uid) {
+				errno = 0;
+				sudo_uid = strtoul(value, &ep, 10);
+				if (errno == 0 && *ep == '\0' && sudo_uid) {
+					/* Reinitialize parsed_info and assemble options again with sudo_uid */
+					memcpy(parsed_info, reinit_parsed_info, sizeof(*parsed_info));
+					parsed_info->sudo_uid = sudo_uid;
+					goto assemble_retry;
+				}
+			}
+			break;
 		}
 		fprintf(stderr, "mount error(%d): %s\n", errno,
 			strerror(errno));
@@ -2276,8 +2316,13 @@ mount_exit:
 		memset(parsed_info->password, 0, sizeof(parsed_info->password));
 		munmap(parsed_info, sizeof(*parsed_info));
 	}
-	free(options);
-	free(orgoptions);
-	free(mountpoint);
+	if (reinit_parsed_info)
+		free(reinit_parsed_info);
+	if (options)
+		free(options);
+	if (orgoptions)
+		free(orgoptions);
+	if (mountpoint)
+		free(mountpoint);
 	return rc;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-12-09 19:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-16 10:00 [PATCH][SMB3] mount.cifs: use SUDO_UID env variable for cruid Shyam Prasad N
2020-09-16 10:56 ` Aurélien Aptel
2020-09-16 16:17   ` Shyam Prasad N
2020-09-17  8:57     ` Aurélien Aptel
2020-09-17  9:11       ` Shyam Prasad N
2020-09-17 10:13         ` Aurélien Aptel
2020-09-21  3:50           ` Shyam Prasad N
2020-09-21  8:19             ` Aurélien Aptel
2020-11-09 23:43               ` Pavel Shilovsky
2020-11-27 10:24                 ` Shyam Prasad N
2020-12-09 19:32                   ` Pavel Shilovsky

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).