Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3701

kernel-2.6.18-194.11.1.el5.src.rpm

From: Eric Paris <eparis@redhat.com>
Subject: [PATCH RHEL5] selinux: allow quoted commas for non-continguous catagories or sensitivity in context mounts
Date: Wed, 01 Nov 2006 12:15:56 -0500
Bugzilla: 211857
Message-Id: <1162401356.9655.22.camel@localhost.localdomain>
Changelog: selinux: allow quoted commas for certain catagories in context mounts


BZ 211857

There are a few kernel operations where the user can tell the kernel
what context to use.  An example would be when mounting a filesystem one
can use a context= option to set the selinux context for the new
filesystem and for all files in that filesystem.  With the introduction
of MLS and MCS a user may want to set the categories or sensitivity
levels of the mount point.  As a simple example lets say we want to set
the categories to be c1 and c3 and not include c2.  To do this we would
mount with something like

context=system_u:object_r:myfs_t:s0:c1,c3

But now the mount operation is going to see a comma and will think that
c3 is a separate mount option.  So userspace is implementing the ability
to quote a context string.  Thus giving

context="system_u:object_r:myfs_t:s0:c1,c3"

The routine selinux_sb_copy_data() was modified to mark a flag value
when it runs across a '"'.  This flag value is consulted each time a
comma is encountered during the processing of the mount options.  If the
flag indicates that the current option contains a quote it will move on
to the next character.  If the flag indicates that there is either a
matched set of quotes or no quotes at all then the option is taken.  If
the option happens to be an selinux option then the new routine
take_selinux_option() is called.  take_selinux_option() will copy the
option to the previously allocated selinux data page.  While it is doing
the copying it will skip any quotes present in the option so the data
page contains only the raw unquoted context.  The previously used comma
separator between options in the selinux data page was replaced with a
'|' character to allow try_context_mount() to properly extract whole
context option strings as well.

This (along with the userspace fix) has been tested by IBM and shown to
allow non-consecutive sensitivities and categories.  It is needed for
real MLS support to meet LSPP certification.  It is userspace compatible
with older userspace.

-Eric

 hooks.c |   33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

--- linux-2.6.18.i686/security/selinux/hooks.c.comma.category	2006-10-25 16:00:10.000000000 -0400
+++ linux-2.6.18.i686/security/selinux/hooks.c	2006-10-25 16:03:02.000000000 -0400
@@ -398,7 +398,7 @@ static int try_context_mount(struct supe
 		/* Standard string-based options. */
 		char *p, *options = data;
 
-		while ((p = strsep(&options, ",")) != NULL) {
+		while ((p = strsep(&options, "|")) != NULL) {
 			int token;
 			substring_t args[MAX_OPT_ARGS];
 
@@ -1958,11 +1958,34 @@ static inline void take_option(char **to
 	*to += len;
 }
 
+static inline void take_selinux_option(char **to, char *from, int *first, 
+		                       int len)
+{
+	int current_size = 0;
+
+	if (!*first) {
+		**to = '|';
+		*to += 1;
+	}
+	else
+		*first = 0;
+
+	while (current_size < len) {
+		if (*from != '"') {
+			**to = *from;
+			*to += 1;
+		}
+		from += 1;
+		current_size += 1;
+	}
+}
+
 static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
 {
 	int fnosec, fsec, rc = 0;
 	char *in_save, *in_curr, *in_end;
 	char *sec_curr, *nosec_save, *nosec;
+	int open_quote = 0;
 
 	in_curr = orig;
 	sec_curr = copy;
@@ -1984,11 +2007,15 @@ static int selinux_sb_copy_data(struct f
 	in_save = in_end = orig;
 
 	do {
-		if (*in_end == ',' || *in_end == '\0') {
+		if (*in_end == '"') {
+			open_quote = !open_quote;
+		}
+		if ((*in_end == ',' && open_quote == 0) ||
+				*in_end == '\0') {
 			int len = in_end - in_curr;
 
 			if (selinux_option(in_curr, len))
-				take_option(&sec_curr, in_curr, &fsec, len);
+				take_selinux_option(&sec_curr, in_curr, &fsec, len);
 			else
 				take_option(&nosec, in_curr, &fnosec, len);