PERFORCE change 32171 for review
Robert Watson
rwatson at FreeBSD.org
Sat May 31 16:43:33 GMT 2003
http://perforce.freebsd.org/chv.cgi?CH=32171
Change 32171 by rwatson at 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);
}
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message
More information about the trustedbsd-cvs
mailing list