Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Aug 2002 06:17:03 -0700 (PDT)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 15565 for review
Message-ID:  <200208051317.g75DH32N087809@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=15565

Change 15565 by rwatson@rwatson_tislabs on 2002/08/05 06:16:44

	Sync up label change policy with mac_biba, and improve on it.
	This adds support for relative label updates in MLS, seperates
	the decision making process concerning "allowed to make a label
	change on this object" and "allowed to make this MLS change on
	this object" so that updates without MLS components can be
	made subject to MLS's whim.  Some policy sync up on the Biba
	side is now required.

Affected files ...

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

Differences ...

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

@@ -123,6 +123,16 @@
 		atomic_add_int(&destroyed_not_inited, 1);
 }
 
+
+static int
+mls_atmostflags(struct mac_mls *mac_mls, int flags)
+{
+
+	if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
+		return (EINVAL);
+	return (0);
+}
+
 static int
 mac_mls_dominate_element(struct mac_mls_element *a,
     struct mac_mls_element *b)
@@ -245,6 +255,49 @@
 }
 
 static int
+mac_mls_contains_equal(struct mac_mls *mac_mls)
+{
+
+	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE)
+		if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
+			return (1);
+
+	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
+		if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
+			return (1);
+		if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
+			return (1);
+	}
+
+	return (0);
+}
+
+static int
+mac_mls_subject_equal_ok(struct mac_mls *mac_mls)
+{
+
+	KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH == MAC_MLS_FLAGS_BOTH),
+	    ("mac_mls_subject_equal_ok: subject doesn't have both labels"));
+
+	/* If the single is EQUAL, it's ok. */
+	if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
+		return (0);
+
+	/* If either range endpoint is EQUAL, it's ok. */
+	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
+	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
+		return (0);
+
+	/* If the range is low-high, it's ok. */
+	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
+	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
+		return (0);
+
+	/* It's not ok. */
+	return (EPERM);
+}
+
+static int
 mac_mls_valid(struct mac_mls *mac_mls)
 {
 
@@ -366,6 +419,16 @@
 	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
 }
 
+static void
+mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
+{
+
+	if (source->mm_flags & MAC_MLS_FLAG_SINGLE)
+		mac_mls_copy_single(source, dest);
+	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
+		mac_mls_copy_range(source, dest);
+}
+
 /*
  * Policy module operations.
  */
@@ -692,7 +755,7 @@
 	source = SLOT(label);
 	dest = SLOT(vnodelabel);
 
-	mac_mls_copy_single(source, dest);
+	mac_mls_copy(source, dest);
 }
 
 static void
@@ -820,8 +883,7 @@
 	source = SLOT(newlabel);
 	dest = SLOT(socketlabel);
 
-	mac_mls_copy_single(source, dest);
-	mac_mls_copy_range(source, dest);
+	mac_mls_copy(source, dest);
 }
 
 static void
@@ -833,7 +895,7 @@
 	source = SLOT(newlabel);
 	dest = SLOT(pipelabel);
 
-	mac_mls_copy_single(source, dest);
+	mac_mls_copy(source, dest);
 }
 
 static void
@@ -1024,8 +1086,7 @@
 	source = SLOT(newlabel);
 	dest = SLOT(ifnetlabel);
 
-	mac_mls_copy_single(source, dest);
-	mac_mls_copy_range(source, dest);
+	mac_mls_copy(source, dest);
 }
 
 static void
@@ -1102,8 +1163,7 @@
 	source = SLOT(newlabel);
 	dest = SLOT(&cred->cr_label);
 
-	mac_mls_copy_single(source, dest);
-	mac_mls_copy_range(source, dest);
+	mac_mls_copy(source, dest);
 }
 
 /*
@@ -1130,41 +1190,66 @@
 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
 {
 	struct mac_mls *subj, *new;
+	int error;
 
 	subj = SLOT(&cred->cr_label);
 	new = SLOT(newlabel);
 
-	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
-		return (EINVAL);
-
 	/*
-	 * XXX: Allow processes with root privilege to set labels outside
-	 * their range, so suid things like "su" work.  This WILL go away
-	 * when we figure out the 'correct' solution...
+	 * If there is an MLS label update for the credential, it may be
+	 * an update of single, range, or both.
 	 */
-	if (!suser_cred(cred, 0))
-		return (0);
+	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
+	if (error)
+		return (error);
 
 	/*
-	 * The new single must be in the old range.
+	 * If the MLS label is to be changed, authorize as appropriate.
 	 */
-	if (!mac_mls_single_in_range(new, subj))
-		return (EPERM);
+	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
+		/*
+		 * Exempt traditional superuser processes from the MLS
+		 * relabel requirements. XXXMAC: This will go away.
+		 */
+		if (suser_cred(cred, 0) == 0)
+			return (0);
+
+		/*
+		 * To change the MLS single label on a credential, the
+		 * new single label must be in the current range.
+		 */
+		if (new->mm_flags & MAC_MLS_FLAG_SINGLE &&
+		    !mac_mls_single_in_range(new, subj))
+			return (EPERM);
+
+		/*
+		 * To change the MLS range label on a credential, the
+		 * new range label must be in the current range.
+		 */
+		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
+	 	   !mac_mls_range_in_range(new, subj))
+			return (EPERM);
 
-	/*
-	 * The new range must be in the old range.
-	 */
-	if (!mac_mls_range_in_range(new, subj))
-		return (EPERM);
+		/*
+		 * To have EQUAL in any component of the new credential
+		 * MLS label, the subject must already have EQUAL in
+		 * their label.
+		 */
+		if (mac_mls_contains_equal(new)) {
+			error = mac_mls_subject_equal_ok(subj);
+			if (error)
+				return (error);
+		}
 
-	/*
-	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
-	 */
+		/*
+		 * XXXMAC: Additional consistency tests regarding the single
+		 * and range of the new label might be performed here.
+		 */
+	}
 
 	return (0);
 }
 
-
 static int
 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
 {
@@ -1188,16 +1273,39 @@
     struct label *ifnetlabel, struct label *newlabel)
 {
 	struct mac_mls *subj, *new;
+	int error;
 
 	subj = SLOT(&cred->cr_label);
 	new = SLOT(newlabel);
 
-	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
-		return (EINVAL);
+	/*
+	 * If there is an MLS label update for the interface, it may
+	 * be an update of single, range, or both.
+	 */
+	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
+	if (error)
+		return (error);
+
+	/*
+	 * If the MLS label is to be changed, authorize as appropriate.
+	 */
+	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
+		/*
+		 * Rely on traditional superuser status for the MLS
+		 * interface relabel requirements.  XXX: This will go
+		 * away.
+		 */
+		error = suser_cred(cred, 0);
+		if (error)
+			return (EPERM);
 
-	/* XXX: privilege model here? */
+		/*
+		 * XXXMAC: Additional consistency tests regarding the single
+		 * and the range of the new label might be performed here.
+		 */
+	}
 
-	return (suser_cred(cred, 0));
+	return (0);
 }
 
 static int
@@ -1281,31 +1389,48 @@
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_mls *subj, *obj, *new;
+	int error;
 
 	new = SLOT(newlabel);
 	subj = SLOT(&cred->cr_label);
 	obj = SLOT(pipelabel);
 
-	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
-		return (EINVAL);
+	/*
+	 * If there is an MLS label update for a pipe, it must be a
+	 * single update.
+	 */
+	error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
+	if (error)
+		return (error);
 
 	/*
-	 * To relabel a pipe, the old pipe label must be in the subject
-	 * range.
+	 * To perform a relabel of a pipe (MLS label or not), MLS must
+	 * authorize the relabel.
 	 */
 	if (!mac_mls_single_in_range(obj, subj))
 		return (EPERM);
 
 	/*
-	 * To relabel a pipe, the new pipe label must be in the subject
-	 * range.
+	 * If the MLS label is to be changed, authorize as appropriate.
 	 */
-	if (!mac_mls_single_in_range(new, subj))
-		return (EPERM);
+	if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
+		/*
+		 * To change the MLS label on a pipe, the new pipe label
+		 * must be in the subject range.
+		 */
+		if (!mac_mls_single_in_range(new, subj))
+			return (EPERM);
 
-	/*
-	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
-	 */
+		/*
+		 * To change the MLS label on a pipe to be EQUAL, the
+		 * subject must have appropriate privilege.
+		 */
+		if (mac_mls_contains_equal(new)) {
+			error = mac_mls_subject_equal_ok(subj);
+			if (error)
+				return (error);
+		}
+	}
 
 	return (0);
 }
@@ -1390,32 +1515,70 @@
     struct label *socketlabel, struct label *newlabel)
 {
 	struct mac_mls *subj, *obj, *new;
+	int error;
 
 	new = SLOT(newlabel);
 	subj = SLOT(&cred->cr_label);
 	obj = SLOT(socketlabel);
 
-	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
-		return (EINVAL);
+	/*
+	 * If there is an MLS label update for the socket, it may be
+	 * an update of single, range, or both.
+	 */
+	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
+	if (error)
+		return (error);
 
 	/*
-	 * To relabel a socket, the old socket label must be in the subject
+	 * To relabel a socket, the old socket single must be in the subject
 	 * range.
 	 */
 	if (!mac_mls_single_in_range(obj, subj))
 		return (EPERM);
 
 	/*
-	 * To relabel a socket, the new socket label must be in the subject
+	 * To relabel a socket, the old socket range must be in the subject
 	 * range.
 	 */
-	if (!mac_mls_single_in_range(new, subj))
+	if (!mac_mls_range_in_range(obj, subj))
 		return (EPERM);
 
 	/*
-	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
+	 * If the MLS label is to be changed, authorize as appropriate.
 	 */
+	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
+		/*
+		 * To relabel a socket, the new socket single must be in
+		 * the subject range.
+		 */
+		if (new->mm_flags & MAC_MLS_FLAG_SINGLE &&
+		    !mac_mls_single_in_range(new, subj))
+			return (EPERM);
+	
+		/*
+		 * To change the MLS range on the socket, the new socket
+		 * range must be in the subject range.
+		 */
+		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
+		    !mac_mls_range_in_range(new, subj))
+			return (EPERM);
+
+		/*
+		 * To change the MLS label on the socket to contain EQUAL,
+		 * the subject must have appropriate privilege.
+		 */
+		if (mac_mls_contains_equal(new)) {
+			error = mac_mls_subject_equal_ok(subj);
+			if (error)
+				return (error);
+		}
 
+		/*
+		 * XXXMAC: Additional consistency tests regarding the single
+		 * and range of the new label might be performed here.
+		 */
+	}
+
 	return (0);
 }
 
@@ -1679,33 +1842,50 @@
     struct label *vnodelabel, struct label *newlabel)
 {
 	struct mac_mls *old, *new, *subj;
+	int error;
 
 	old = SLOT(vnodelabel);
 	new = SLOT(newlabel);
 	subj = SLOT(&cred->cr_label);
 
-	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
-		return (EINVAL);
+	/*
+	 * If there is an MLS label update for the vnode, it must be a
+	 * single label.
+	 */
+	error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
+	if (error)
+		return (error);
 
 	/*
-	 * To relabel a vnode, the old vnode label must be in the subject
-	 * range.
+	 * To perform a relabel of the vnode (MLS label or not), MLS must
+	 * authorize the relabel.
 	 */
 	if (!mac_mls_single_in_range(old, subj))
 		return (EPERM);
 
 	/*
-	 * To relabel a vnode, the new vnode label must be in the subject
-	 * range.
+	 * If the MLS label is to be changed, authorize as appropriate.
 	 */
-	if (!mac_mls_single_in_range(new, subj))
-		return (EPERM);
+	if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
+		/*
+		 * To change the MLS label on a vnode, the new vnode label
+		 * must be in the subject range.
+		 */
+		if (!mac_mls_single_in_range(new, subj))
+			return (EPERM);
 
-	/*
-	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
-	 */
+		/*
+		 * To change the MLS label on the vnode to be EQUAL,
+		 * the subject must have appropriate privilege.
+		 */
+		if (mac_mls_contains_equal(new)) {
+			error = mac_mls_subject_equal_ok(subj);
+			if (error)
+				return (error);
+		}
+	}
 
-	return (suser_cred(cred, 0));
+	return (0);
 }
 
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




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