From owner-p4-projects@FreeBSD.ORG Sat May 31 09:43:34 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6196C37B404; Sat, 31 May 2003 09:43:34 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 17B1E37B401 for ; Sat, 31 May 2003 09:43:34 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8D13643F85 for ; Sat, 31 May 2003 09:43:33 -0700 (PDT) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h4VGhX0U005902 for ; Sat, 31 May 2003 09:43:33 -0700 (PDT) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h4VGhXjw005899 for perforce@freebsd.org; Sat, 31 May 2003 09:43:33 -0700 (PDT) Date: Sat, 31 May 2003 09:43:33 -0700 (PDT) Message-Id: <200305311643.h4VGhXjw005899@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Subject: PERFORCE change 32171 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 May 2003 16:43:35 -0000 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 #include #include +#include #include #include #include @@ -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); }