All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC Patch 2/3] Context Mounts and Unsupported Contexts: util-linux
@ 2006-08-15 15:56 Cory Olmo
  0 siblings, 0 replies; only message in thread
From: Cory Olmo @ 2006-08-15 15:56 UTC (permalink / raw)
  To: selinux

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

This patch modifies the option parsing in parse_opts(), contained in 
mount.c, and parse_options(), contained in nfsmount.c, to take options 
after finding a comma only if it hasn't seen a quote or if the quotes 
are matched.  It also will strip the quotes from the context option prior 
to translation and then replace them after the translation.  

There's an unrelated update in the patch for parse_opt() which includes 
the latest rootcontext option.

 util-linux/mount/mount.c    |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 util-linux/mount/nfsmount.c |   34 +++++++++++++++++++++++--
 2 files changed, 103 insertions(+), 12 deletions(-)

[-- Attachment #2: util-linux-2.13-quoted_context.patch --]
[-- Type: text/x-patch, Size: 5487 bytes --]

diff --git a/mount/mount.c b/mount/mount.c
index dbbb92e..49a6c38 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -265,6 +265,32 @@ my_free(const void *s) {
 }
 
 #ifdef HAVE_LIBSELINUX
+/* strip quotes from a context string
+ * returns Null on error and char * to new string
+ * caller responsible for freeing returned memory
+ */
+static char *
+strip_quotes(const char *opt_str)
+{
+	char *new_str = NULL;
+	char *str_end = NULL;
+
+	if (*opt_str != '\"') {
+		new_str = xstrdup(opt_str);
+		return new_str;
+	}
+
+	str_end = rindex(opt_str, '\"');
+	if (!str_end || str_end == opt_str) {
+		printf(_("mount: improperly quoted context string '%s'\n"), 
+			opt_str);
+		return NULL;
+	}
+
+	new_str = xstrndup(opt_str+1, str_end - (opt_str+1));
+	return new_str;
+}
+
 /* translates SELinux context from human to raw format and 
  * appends it to the mount extra options.
  *
@@ -274,6 +300,7 @@ static int
 append_context(const char *optname, const char *optdata, char *extra_opts, int *len)
 {
 	security_context_t raw = NULL;
+	char *stripped_data = NULL;
 	char *buf = NULL;
 	int bufsz;
 	
@@ -284,19 +311,32 @@ append_context(const char *optname, cons
 	if (optdata==NULL || *optdata=='\0' || optname==NULL)
 		return -1;
 	
-	if (selinux_trans_to_raw_context(
-			(security_context_t) optdata, &raw)==-1 ||
-			raw==NULL)
-		return -1;
+	if (*optdata =='\"') {
+		stripped_data = strip_quotes(optdata);
+		if (!stripped_data) 
+			return -1;
+		if (selinux_trans_to_raw_context(
+				(security_context_t) stripped_data, &raw)==-1 ||
+				raw==NULL) {
+			my_free(stripped_data);
+			return -1;
+		}
+		my_free(stripped_data);
+	} else {
+		if (selinux_trans_to_raw_context(
+				(security_context_t) optdata, &raw)==-1 ||
+				raw==NULL)
+			return -1;
+	}
 	
 	if (verbose)
 		printf(_("mount: translated %s '%s' to '%s'\n"), 
 				optname, optdata, (char *) raw);
 
-	bufsz = strlen(optname) + strlen(raw) + 2;	/* 2 is \0 and '=' */ 
+	bufsz = strlen(optname) + strlen(raw) + 2 + 2;	/* 2 is \0 and '=' */ 
 	buf = xmalloc(bufsz);
 
-	snprintf(buf, bufsz, "%s=%s", optname, (char *) raw);
+	snprintf(buf, bufsz, "%s=\"%s\"", optname, (char *) raw);
 	freecon(raw);
 	
 	if ((*len -= bufsz-1) > 0)
@@ -378,6 +418,10 @@ parse_opt(const char *opt, int *mask, ch
 		if (append_context("defcontext", opt+11, extra_opts, &len)==0)
 			return;
 	}
+	if (strncmp(opt, "rootcontext=", 12)==0 && *(opt+12)) {
+		if (append_context("rootcontext", opt+12, extra_opts, &len)==0)
+			return;
+	}
 #endif
 	if ((len -= strlen(opt)) > 0)
 		strcat(extra_opts, opt);
@@ -396,13 +440,32 @@ parse_opts (const char *options, int *fl
 		char *opts = xstrdup(options);
 		char *opt;
 		int len = strlen(opts) + 256;
+		int open_quote = 0;
+		char *opt_start = NULL;
+		char *opt_end = NULL;
 
 		*extra_opts = xmalloc(len); 
 		**extra_opts = '\0';
 
-		for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
-			if (!parse_string_opt(opt))
-				parse_opt(opt, flags, *extra_opts, len);
+		opt_start = opt_end = opts;
+		do {
+			if ((*opt_end == '"')) {
+				if (open_quote < 0)
+					open_quote += 1;
+				else
+					open_quote -= 1;
+			}
+			if (((*opt_end == ',') && (open_quote == 0)) ||
+					*opt_end == '\0') {
+				opt = xstrndup(opt_start, opt_end - opt_start);
+				if (!parse_string_opt(opt))
+					parse_opt(opt, flags, *extra_opts, len);
+				opt_start = opt_end + 1;
+				free(opt);
+				opt = NULL;
+			}
+		} while (*opt_end++);
+
 
 		free(opts);
 	}
diff --git a/mount/nfsmount.c b/mount/nfsmount.c
index 362ef33..783994e 100644
--- a/mount/nfsmount.c
+++ b/mount/nfsmount.c
@@ -756,12 +756,28 @@ parse_options(char *old_opts, struct nfs
 	char *opt, *opteq;
 	char *mounthost = NULL;
 	char cbuf[128];
+	char *opt_start, *opt_end;
+	int open_quote = 0;
 
 	data->flags = 0;
 	*bg = 0;
 
 	len = strlen(new_opts);
-	for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
+	opt_start = opt_end = old_opts;
+	do {
+		if ((*opt_end == '"')) {
+			if (open_quote < 0)
+				open_quote += 1;
+			else
+				open_quote -= 1;
+		}
+		if (!(((*opt_end == ',') && (open_quote == 0)) ||
+				*opt_end == '\0')) {
+			continue;
+		}
+		opt = xstrndup(opt_start, opt_end - opt_start);
+		opt_start = opt_end + 1;
+
 		if (strlen(opt) >= sizeof(cbuf))
 			goto bad_parameter;
 		if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
@@ -877,12 +893,22 @@ parse_options(char *old_opts, struct nfs
 			 else if (!strcmp(opt, "context")) {
  				char *context = opteq + 1;
  				
+				/* XXX: The size of cbuf would have to be
+				 * more than doubled or NFS_MAX_CONTEXT_LEN
+				 * reduced to <128 before this would ever be 
+				 * a factor.
+				 */
  				if (strlen(context) > NFS_MAX_CONTEXT_LEN) {
  					printf(_("context parameter exceeds limit of %d\n"),
  						 NFS_MAX_CONTEXT_LEN);
 					goto bad_parameter;
  				}
- 				strncpy(data->context, context, NFS_MAX_CONTEXT_LEN);
+				/* The context string is in the format of
+				 * "system_u:object_r:...". We only want 
+				 * the context str between the quotes.
+				 */
+ 				strncpy(data->context, context+1, 
+						strlen(context)-2);
  			} else if (!sloppy)
 				goto bad_parameter;
 			sprintf(cbuf, "%s=%s,", opt, opteq+1);
@@ -988,7 +1014,9 @@ parse_options(char *old_opts, struct nfs
 			goto out_bad;
 		}
 		strcat(new_opts, cbuf);
-	}
+		free(opt);
+		opt = NULL;
+	} while (*opt_end++);
 	/* See if the nfs host = mount host. */
 	if (mounthost) {
 		if (!nfs_gethostbyname(mounthost, mnt_saddr))

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2006-08-15 15:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-15 15:56 [RFC Patch 2/3] Context Mounts and Unsupported Contexts: util-linux Cory Olmo

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.