Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 May 2003 09:43:33 -0700 (PDT)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 32171 for review
Message-ID:  <200305311643.h4VGhXjw005899@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=32171

Change 32171 by rwatson@rwatson_tislabs on 2003/05/31 09:43:32

	Rewrite MLS externalization code to use sbufs instead of C strings
	internally; using C strings required a great many return value checks
	that obscured the conversion logic and made it difficult to determine   
	the correctness of it.
	
	While doing this, break out the printing of sequential compartments
	into a helper function, mac_mls_compartment_to_string().  This permits
	the main body of mac_mls_element_to_string() to only identify ranges
	rather than also taking care of counting '+'s.   
	
	Comment the semantics of each function, in particular the return
	values.   
	
	Once I've tested these changes a bit more, I'll make similar changes
	to the Biba code.

Affected files ...

.. //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#168 edit

Differences ...

==== //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#168 (text+ko) ====

@@ -49,6 +49,7 @@
 #include <sys/malloc.h>
 #include <sys/mount.h>
 #include <sys/proc.h>
+#include <sys/sbuf.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
 #include <sys/sysent.h>
@@ -493,126 +494,138 @@
 }
 
 /*
- * mac_mls_element_to_string() is basically an snprintf wrapper with
- * the same properties as snprintf().  It returns the length it would
- * have added to the string in the event the string is too short.
+ * mac_mls_compartment_to_string() takes an sbuf, range of compartments,
+ * and flag indicating whether this is the first entry in a list of
+ * compartments.  A string representing the compartment range will be
+ * appended to the sbuf, or -1 will be returned if there wasn't space.
+ */
+static int
+mac_mls_compartment_to_string(struct sbuf *sb, int start, int stop, int first)
+{
+	char *pluses, *prefix;
+
+	if (stop == start + 1)
+		pluses = "+";
+	else
+		pluses = "++";
+
+	if (first)
+		prefix = ":";
+	else
+		prefix = "+";
+
+	if (stop == start)
+		return (sbuf_printf(sb, "%s%d", prefix, start));
+	else
+		return (sbuf_printf(sb, "%s%d%s%d", prefix, start, pluses,
+		    stop));
+}
+
+/*
+ * mac_mls_element_to_string() accepts an sbuf and MLS element.  It
+ * converts the MLS element to a string and stores the result in the
+ * sbuf; if there isn't space in the sbuf, -1 is returned.
  */
-static size_t
-mac_mls_element_to_string(char *string, size_t size,
-    struct mac_mls_element *element)
+static int
+mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
 {
-	int r, bit, pbit;
-	size_t left, len;
-	char *p;
+	int i, first, start, stop, prevbit;
 
 	switch (element->mme_type) {
 	case MAC_MLS_TYPE_HIGH:
-		return (snprintf(string, size, "high"));
+		return (sbuf_printf(sb, "high"));
 
 	case MAC_MLS_TYPE_LOW:
-		return (snprintf(string, size, "low"));
+		return (sbuf_printf(sb, "low"));
 
 	case MAC_MLS_TYPE_EQUAL:
-		return (snprintf(string, size, "equal"));
+		return (sbuf_printf(sb, "equal"));
 
 	case MAC_MLS_TYPE_LEVEL:
-		bit = pbit = r = 0;
-		left = size;
+		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
+			return (-1);
 
-		p = string + (len = snprintf(string, left, "%d:",
-		    element->mme_level));
-		left -= len;
-
-		do {
-			pbit = bit++;
-			len = 0;
-			if (bit <= MAC_MLS_MAX_COMPARTMENTS &&
-			    MAC_MLS_BIT_TEST(bit, element->mme_compartments)) {
-				if (pbit == bit - 1) {
-					if (r == 0)
-						p += len = snprintf(p, left,
-						    "%d+", bit);
-					r++;
+		first = 1;		/* Need a ':' and no '+'. */
+		start = 0; stop = 0;	/* No starting range. */
+		prevbit = 0;		/* Was previous bit set? */
+		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
+			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
+				if (prevbit)
+					stop = i;
+				else {
+					start = i;
+					stop = i;
 				}
+				prevbit = 1;
 			} else {
-				if (r > 2)
-					p += len = snprintf(p, left, "+%d+",
-					    pbit);
-				else if (r > 1)
-					p += len = snprintf(p, left, "%d+",
-					    pbit);
-				r = 0;
+				if (prevbit) {
+					if (mac_mls_compartment_to_string(sb,
+					    start, stop, first) == -1)
+						return (-1);
+					if (first)
+						first = 0;
+				}
+				prevbit = 0;
 			}
-			left -= len;
-		} while(bit <= MAC_MLS_MAX_COMPARTMENTS);
+		}
+		/*
+		 * If the last bit was set, we need to close that range to
+		 * terminate the string.
+		 */
+		if (prevbit) {
+			if (mac_mls_compartment_to_string(sb, start, stop,
+			    first) == -1)
+				return (-1);
+		}
+		return (0);
 
-		len = size - left - 1;
-		if (len > 0 && len < size)
-			string[len] = '\0';
-		else
-			string[0] = '\0';
-		return (len);
-
 	default:
 		panic("mac_mls_element_to_string: invalid type (%d)",
 		    element->mme_type);
 	}
 }
 
-static size_t
+/*
+ * mac_mls_to_string() converts an MLS label to a string, placing the
+ * results in the passed string buffer.  It returns 0 on success,
+ * or EINVAL if there isn't room in the buffer.  The size of the
+ * string appended, leaving out the nul termination, is returned to
+ * the caller via *caller_len.  Eventually, we should expose the
+ * sbuf to the caller rather than using C strings at this layer.
+ */
+static int
 mac_mls_to_string(char *string, size_t size, size_t *caller_len,
     struct mac_mls *mac_mls)
 {
-	size_t left, len;
-	char *curptr;
+	struct sbuf sb;
 
-	bzero(string, size);
-	curptr = string;
-	left = size;
+	sbuf_new(&sb, string, size, SBUF_FIXEDLEN);
 
 	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
-		len = mac_mls_element_to_string(curptr, left,
-		    &mac_mls->mm_single);
-		if (len >= left)
+		if (mac_mls_element_to_string(&sb, &mac_mls->mm_single) == -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 	}
 
 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
-		len = snprintf(curptr, left, "(");
-		if (len >= left)
+		if (sbuf_putc(&sb, '(') == -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 
-		len = mac_mls_element_to_string(curptr, left,
-		    &mac_mls->mm_rangelow);
-		if (len >= left)
+		if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangelow) ==
+		    -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 
-		len = snprintf(curptr, left, "-");
-		if (len >= left)
+		if (sbuf_putc(&sb, '-') == -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 
-		len = mac_mls_element_to_string(curptr, left,
-		    &mac_mls->mm_rangehigh);
-		if (len >= left)
+		if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangehigh)
+		    == -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 
-		len = snprintf(curptr, left, ")");
-		if (len >= left)
+		if (sbuf_putc(&sb, ')') == -1)
 			return (EINVAL);
-		left -= len;
-		curptr += len;
 	}
 
+	sbuf_finish(&sb);
 	*caller_len = strlen(string);
 	return (0);
 }
@@ -635,7 +648,6 @@
 	if (error)
 		return (error);
 
-	*len = strlen(element_data);
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305311643.h4VGhXjw005899>