From owner-p4-projects Fri Oct 4 14:11:15 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1DC7B37B404; Fri, 4 Oct 2002 14:11:00 -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 A611A37B401 for ; Fri, 4 Oct 2002 14:10:59 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 357D443E42 for ; Fri, 4 Oct 2002 14:10:59 -0700 (PDT) (envelope-from amigus@FreeBSD.org) Received: from freefall.freebsd.org (perforce@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id g94LAxCo056159 for ; Fri, 4 Oct 2002 14:10:59 -0700 (PDT) (envelope-from amigus@FreeBSD.org) Received: (from perforce@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id g94LAwkF056149 for perforce@freebsd.org; Fri, 4 Oct 2002 14:10:58 -0700 (PDT) Date: Fri, 4 Oct 2002 14:10:58 -0700 (PDT) Message-Id: <200210042110.g94LAwkF056149@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: perforce set sender to amigus@FreeBSD.org using -f From: Adam Migus Subject: PERFORCE change 18676 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://people.freebsd.org/~peter/p4db/chv.cgi?CH=18676 Change 18676 by amigus@amigus_ganymede on 2002/10/04 14:10:32 An implementation of compartments for the MAC/MLS confidentiality policy. The compartments are bits in a fixed sized bit set of size MAC_MLS_MAX_COMPARTMENTS which is declared in mac_mls.h. Elements of the label containing a level now take an additional string on the end of the form [:[i][,j][,...]] where i,j,... are numbers between 1 and MAC_MLS_MAX_COMPARTMENTS. The module is backward compatible in that if you specify a numeric level without a compartment list you are given that level with no compartments. By virtue this is semantically identical to the old model. LOW, HIGH and EQUAL also retain there original semantics and as such cannot be in any compartments. Eventually I will implement a userland mapping between symbolic names and compartment numbers. Please test/experiment and let me know if you have any questions or comments. Affected files ... .. //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#104 edit .. //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.h#6 edit Differences ... ==== //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#104 (text+ko) ==== @@ -103,6 +103,10 @@ TUNABLE_INT("security.mac.mls.revocation_enabled", &mac_mls_revocation_enabled); +static int mac_mls_max_compartments = MAC_MLS_MAX_COMPARTMENTS; +SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD, + &mac_mls_max_compartments, 0, "Maximum compartments the policy supports"); + static int mac_mls_slot; #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr) @@ -145,6 +149,7 @@ mac_mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b) { + int bit; switch(a->mme_type) { case MAC_MLS_TYPE_EQUAL: @@ -175,6 +180,11 @@ return (0); case MAC_MLS_TYPE_LEVEL: + for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) + if (!MAC_MLS_BIT_TEST(bit, + a->mme_compartments) && + MAC_MLS_BIT_TEST(bit, b->mme_compartments)) + return (0); return (a->mme_level >= b->mme_level); default: @@ -304,7 +314,9 @@ case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: - if (mac_mls->mm_single.mme_level != 0) + if (mac_mls->mm_single.mme_level != 0 || + !MAC_MLS_BIT_SET_EMPTY( + mac_mls->mm_single.mme_compartments)) return (EINVAL); break; @@ -324,7 +336,9 @@ case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: - if (mac_mls->mm_rangelow.mme_level != 0) + if (mac_mls->mm_rangelow.mme_level != 0 || + !MAC_MLS_BIT_SET_EMPTY( + mac_mls->mm_rangelow.mme_compartments)) return (EINVAL); break; @@ -339,7 +353,9 @@ case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: - if (mac_mls->mm_rangehigh.mme_level != 0) + if (mac_mls->mm_rangehigh.mme_level != 0 || + !MAC_MLS_BIT_SET_EMPTY( + mac_mls->mm_rangehigh.mme_compartments)) return (EINVAL); break; @@ -360,33 +376,53 @@ static void mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow, - u_short levellow, u_short typehigh, u_short levelhigh) + u_short levellow, u_char *compartmentslow, u_short typehigh, + u_short levelhigh, u_char *compartmentshigh) { mac_mls->mm_rangelow.mme_type = typelow; mac_mls->mm_rangelow.mme_level = levellow; + if (compartmentslow) + memcpy(mac_mls->mm_rangelow.mme_compartments, compartmentslow, + sizeof(mac_mls->mm_rangelow.mme_compartments)); mac_mls->mm_rangehigh.mme_type = typehigh; mac_mls->mm_rangehigh.mme_level = levelhigh; + if (compartmentshigh) + memcpy(mac_mls->mm_rangehigh.mme_compartments, compartmentshigh, + sizeof(mac_mls->mm_rangehigh.mme_compartments)); mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE; } static void -mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level) +mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level, + u_char *compartments) { mac_mls->mm_single.mme_type = type; mac_mls->mm_single.mme_level = level; + if (compartments) + memcpy(mac_mls->mm_single.mme_compartments, compartments, + sizeof(mac_mls->mm_single.mme_compartments)); mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE; } static void mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto) { + KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0, ("mac_mls_copy_range: labelfrom not range")); + memcpy(labelto->mm_rangelow.mme_compartments, + labelfrom->mm_rangelow.mme_compartments, + sizeof(labelfrom->mm_rangelow.mme_compartments)); labelto->mm_rangelow = labelfrom->mm_rangelow; + + memcpy(labelto->mm_rangehigh.mme_compartments, + labelfrom->mm_rangehigh.mme_compartments, + sizeof(labelfrom->mm_rangehigh.mme_compartments)); labelto->mm_rangehigh = labelfrom->mm_rangehigh; + labelto->mm_flags |= MAC_MLS_FLAG_RANGE; } @@ -397,7 +433,11 @@ KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, ("mac_mls_copy_single: labelfrom not single")); + memcpy(labelto->mm_single.mme_compartments, + labelfrom->mm_single.mme_compartments, + sizeof(labelfrom->mm_single.mme_compartments)); labelto->mm_single = labelfrom->mm_single; + labelto->mm_flags |= MAC_MLS_FLAG_SINGLE; } @@ -464,6 +504,7 @@ mac_mls_element_to_string(char *string, size_t size, struct mac_mls_element *element) { + int pos, bit = 1; switch (element->mme_type) { case MAC_MLS_TYPE_HIGH: @@ -476,7 +517,15 @@ return (snprintf(string, size, "equal")); case MAC_MLS_TYPE_LEVEL: - return (snprintf(string, size, "%d", element->mme_level)); + pos = snprintf(string, size, "%d:", element->mme_level); + for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) { + if (MAC_MLS_BIT_TEST(bit, element->mme_compartments)) + pos += snprintf(string + pos, size - pos, + "%d+", bit); + } + if (string[pos - 1] == '+' || string[pos - 1] == ':') + string[--pos] = NULL; + return (pos); default: panic("mac_mls_element_to_string: invalid type (%d)", @@ -605,13 +654,39 @@ element->mme_type = MAC_MLS_TYPE_EQUAL; element->mme_level = MAC_MLS_TYPE_UNDEF; } else { + char *p0, *p1; int d; - d = strtol(string, NULL, 10); + p0 = string; + d = strtol(p0, &p1, 10); + if (d < 0 || d > 65535) return (EINVAL); element->mme_type = MAC_MLS_TYPE_LEVEL; element->mme_level = d; + + if (*p1 != ':') { + if (p1 == p0 || *p1 != '\0') + return (EINVAL); + else + return (0); + } + else + if (*(p1 + 1) == '\0') + return (0); + + while ((p0 = ++p1)) { + d = strtol(p0, &p1, 10); + if (d < 1 || d > MAC_MLS_MAX_COMPARTMENTS) + return (EINVAL); + + MAC_MLS_BIT_SET(d, element->mme_compartments); + + if (*p1 == '\0') + break; + if (p1 == p0 || *p1 != '+') + return (EINVAL); + } } return (0); @@ -747,7 +822,7 @@ mls_type = MAC_MLS_TYPE_EQUAL; else mls_type = MAC_MLS_TYPE_LOW; - mac_mls_set_single(mac_mls, mls_type, 0); + mac_mls_set_single(mac_mls, mls_type, 0, NULL); } static void @@ -757,7 +832,7 @@ struct mac_mls *mac_mls; mac_mls = SLOT(label); - mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0); + mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); } static void @@ -816,9 +891,9 @@ /* Always mount root as high integrity. */ mac_mls = SLOT(fslabel); - mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0); + mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); mac_mls = SLOT(mntlabel); - mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0); + mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); } static void @@ -1024,8 +1099,8 @@ else level = MAC_MLS_TYPE_LOW; - mac_mls_set_single(dest, level, 0); - mac_mls_set_range(dest, level, 0, level, 0); + mac_mls_set_single(dest, level, 0, NULL); + mac_mls_set_range(dest, level, 0, NULL, level, 0, NULL); } static void @@ -1094,7 +1169,7 @@ dest = SLOT(mbuflabel); - mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0); + mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); } static void @@ -1221,8 +1296,9 @@ dest = SLOT(&cred->cr_label); - mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0); - mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0); + mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); + mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, + 0, NULL); } static void @@ -1232,8 +1308,9 @@ dest = SLOT(&cred->cr_label); - mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0); - mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0); + mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0, NULL); + mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, + 0, NULL); } static void ==== //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.h#6 (text+ko) ==== @@ -66,11 +66,20 @@ * Structures and constants associated with a Multi-Level Security policy. * mac_mls represents an MLS label, with mm_type determining its properties, * and mm_level represents the hierarchal sensitivity level if valid for the - * current mm_type. + * current mm_type. If compartments are used, the same semantics apply as + * long as the suject is in every compartment the object is in. LOW, EQUAL + * and HIGH cannot be in compartments. + */ + +/* + * MLS compartments bit set size (in bits). */ +#define MAC_MLS_MAX_COMPARTMMENTS 256 + struct mac_mls_element { u_short mme_type; u_short mme_level; + u_char mme_compartments[MAC_MLS_MAX_COMPARTMENTS >> 3]; }; /* @@ -86,4 +95,20 @@ }; #endif +/* + * MLS compartments bit test/set macros. + * The range is 1 to MAC_MLS_MAX_COMPARTMENTS. + */ +#define MAC_MLS_BIT_TEST(b, w) (w[((b - 1) >> 3)] & (1 << ((b - 1) & 7))) +#define MAC_MLS_BIT_SET(b, w) (w[((b - 1) >> 3)] |= (1 << ((b - 1) & 7))) + +static __inline int +MAC_MLS_BIT_SET_EMPTY(u_char *__set) { + int i; + for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++) + if (__set[i] != 0) + return (0); + return (1); +} + #endif /* !_SYS_SECURITY_MAC_MLS_H */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message