Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Aug 2006 21:14:50 GMT
From:      Todd Miller <millert@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 105363 for review
Message-ID:  <200608302114.k7ULEon6035973@repoman.freebsd.org>

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

Change 105363 by millert@millert_g4tower on 2006/08/30 21:14:40

	Add the concept of a mac policy "handle" which is returned
	by the mac_policy_register() and which acts as a unique
	identifier for that policy.  In this implementation the
	handle is the index into an array containing struct mac_policy_conf.
	To use the handle as an index we replace the two policy
	lists with a single array and resize it as needed (though
	in practice this is not really needed).
	
	MAC routines that previously passed around the mpc now
	pass in the policy's handle instead.

Affected files ...

.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_audit.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#5 edit
.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.h#2 edit
.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_internal.h#5 edit
.. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_policy.h#4 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/basetest/mac_basetest.c#3 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/console/mac_console.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/count/mac_count.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/extattr_test/mac_extattr_test.c#3 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/fwinteg/mac_fwinteg.c#3 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/ipctrace/module/ipctrace.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/mls/mac_mls.c#6 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/multilabel/multilabel.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/none/mac_none.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/readonly/mac_readonly.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.c#9 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.h#3 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/stacktrace/module/mac_stacktrace.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/stub/mac_stub.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/test/mac_test.c#4 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/vanity/vanity.c#2 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/xattr/xattr.c#2 edit

Differences ...

==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_audit.c#2 (text+ko) ====

@@ -129,7 +129,7 @@
  * 
  */
 int
-mac_audit_data(int len, u_char *data, struct mac_policy_conf *caller)
+mac_audit_data(int len, u_char *data, mac_policy_handle_t handle)
 {
 	char *sanitized;
 
@@ -150,13 +150,15 @@
  * terminated ASCII text to the current audit record.
  */
 int
-mac_audit_text(char *text, struct mac_policy_conf *caller)
+mac_audit_text(char *text, mac_policy_handle_t handle)
 {
 	char *sanitized;
+	const char *name;
 	int i, allocd, plen, len;
 
+	name = mac_get_mpc(handle)->mpc_name;
 	len = strlen(text);
-	plen = 2 + strlen(caller->mpc_name);
+	plen = 2 + strlen(name);
 	if (plen + len >= MAC_AUDIT_DATA_LIMIT)
 		return (EINVAL);
 
@@ -173,7 +175,7 @@
 	if (sanitized == NULL)
 		return (ENOMEM);
 
-	strcpy(sanitized, caller->mpc_name);
+	strcpy(sanitized, name);
 	strcat(sanitized, ": ");
 	strcat(sanitized, text);
 
@@ -184,21 +186,30 @@
 mac_audit_preselect(struct ucred *cred, unsigned short syscode, void *args)
 {
 	struct mac_policy_conf *mpc;
-	int ret, error, entrycount;
+	int ret, error;
+	u_int i;
 
 	ret = MAC_AUDIT_DEFAULT;
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
+	for (i = 0; i < mac_policy_list.staticmax; i++) {
+		mpc = mac_policy_list.entries[i].mpc;
+		if (mpc == NULL)
+			continue;
+
 		if (mpc->mpc_ops->mpo_audit_preselect != NULL) {
-			error = mpc->mpc_ops->mpo_audit_preselect(cred, syscode,
-				args);
+			error = mpc->mpc_ops->mpo_audit_preselect(cred,
+			    syscode, args);
 			ret = (ret > error ? ret : error);
 		}
 	}
-	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
+	if (mac_policy_list_conditional_busy() != 0) {
+		for (; i <= mac_policy_list.maxindex; i++) {
+			mpc = mac_policy_list.entries[i].mpc;
+			if (mpc == NULL)
+				continue;
+
 			if (mpc->mpc_ops->mpo_audit_preselect != NULL) {
-				error = mpc->mpc_ops->mpo_audit_preselect(cred, syscode,
-					args);
+				error = mpc->mpc_ops->mpo_audit_preselect(cred,
+				    syscode, args);
 				ret = (ret > error ? ret : error);
 			}
 		}
@@ -213,7 +224,8 @@
     void *args, int error, int retval, int mac_forced)
 {
 	struct mac_policy_conf *mpc;
-	int ret, mac_error, entrycount;
+	int ret, mac_error;
+	u_int i;
 
 	/*
 	 * If the audit was forced by a MAC policy by mac_audit_preselect(),
@@ -223,18 +235,26 @@
 		return (MAC_AUDIT_YES);
 
 	ret = MAC_AUDIT_DEFAULT;
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
+	for (i = 0; i < mac_policy_list.staticmax; i++) {
+		mpc = mac_policy_list.entries[i].mpc;
+		if (mpc == NULL)
+			continue;
+
 		if (mpc->mpc_ops->mpo_audit_postselect != NULL) {
-			mac_error = mpc->mpc_ops->mpo_audit_postselect(cred, syscode,
-				args, error, retval);
+			mac_error = mpc->mpc_ops->mpo_audit_postselect(cred,
+			    syscode, args, error, retval);
 			ret = (ret > mac_error ? ret : mac_error);
 		}
 	}
-	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
+	if (mac_policy_list_conditional_busy() != 0) {
+		for (; i <= mac_policy_list.maxindex; i++) {
+			mpc = mac_policy_list.entries[i].mpc;
+			if (mpc == NULL)
+				continue;
+
 			if (mpc->mpc_ops->mpo_audit_postselect != NULL) {
-				mac_error = mpc->mpc_ops->mpo_audit_postselect(cred, syscode,
-					args, error, retval);
+				mac_error = mpc->mpc_ops->mpo_audit_postselect(cred,
+				    syscode, args, error, retval);
 				ret = (ret > mac_error ? ret : mac_error);
 			}
 		}

==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#5 (text+ko) ====

@@ -160,28 +160,36 @@
 struct mac_policy_conf *mac_static_base_mpc = NULL;
 
 /*
- * mac_static_policy_list holds a list of policy modules that are not
- * loaded while the system is "live", and cannot be unloaded.  These
- * policies can be invoked without holding the busy count.
+ * mac_policy_list holds the list of policy modules.  Modules with a
+ * handle lower than staticmax are considered "static" and cannot be
+ * unloaded.  Such policies can be invoked without holding the busy count.
  *
- * mac_policy_list stores the list of dynamic policies.  A busy count is
- * maintained for the list, stored in mac_policy_count.  The busy count
- * is protected by mac_policy_mtx; the list may be modified only
- * while the busy count is 0, requiring that the lock be held to
- * prevent new references to the list from being acquired.  For almost
- * all operations, incrementing the busy count is sufficient to
- * guarantee consistency, as the list cannot be modified while the
- * busy count is elevated.  For a few special operations involving a
- * change to the list of active policies, the mtx itself must be held.
- * A condition variable, mac_policy_cv, is used to signal potential
- * exclusive consumers that they should try to acquire the lock if a
- * first attempt at exclusive access fails.
+ * Modules with a handle at or above the staticmax high water mark
+ * are considered to be "dynamic" policies.  A busy count is maintained
+ * for the list, stored in mac_policy_busy.  The busy count is protected
+ * by mac_policy_mtx; the list may be modified only while the busy
+ * count is 0, requiring that the lock be held to prevent new references
+ * to the list from being acquired.  For almost all operations,
+ * incrementing the busy count is sufficient to guarantee consistency,
+ * as the list cannot be modified while the busy count is elevated.
+ * For a few special operations involving a change to the list of
+ * active policies, the mtx itself must be held.  A condition variable,
+ * mac_policy_cv, is used to signal potential exclusive consumers
+ * that they should try to acquire the lock if a first attempt at
+ * exclusive access fails.
  */
 static mutex_t *mac_policy_mtx;
 static struct cv mac_policy_cv;
-static int mac_policy_count;
-struct mac_policy_list_t mac_policy_list;
-struct mac_policy_list_t mac_static_policy_list;
+
+/*
+ * Policy list array allocation chunk size. Trying to set this so that we
+ * allocate a page at a time.
+ */
+#define MAC_POLICY_LIST_CHUNKSIZE 512
+
+static int mac_policy_busy;
+
+mac_policy_list_t mac_policy_list;
 
 /*
  * mac_label_element_list holds the master list of label namespaces for
@@ -312,7 +320,7 @@
 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
  	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
 	mutex_lock(mac_policy_mtx);
-	while (mac_policy_count != 0)
+	while (mac_policy_busy != 0)
 		cv_wait(&mac_policy_cv, mac_policy_mtx);
 }
 
@@ -320,7 +328,7 @@
 mac_policy_assert_exclusive(void)
 {
 	mtx_assert(&mac_policy_mtx, MA_OWNED);
-	KASSERT(mac_policy_count == 0,
+	KASSERT(mac_policy_busy == 0,
 	    ("mac_policy_assert_exclusive(): not exclusive"));
 }
 
@@ -328,7 +336,7 @@
 mac_policy_release_exclusive(void)
 {
 
-	KASSERT(mac_policy_count == 0,
+	KASSERT(mac_policy_busy == 0,
 	    ("mac_policy_release_exclusive(): not exclusive"));
 	mutex_unlock(mac_policy_mtx);
 	cv_signal(&mac_policy_cv);
@@ -338,7 +346,7 @@
 mac_policy_list_busy(void)
 {
         mutex_lock(mac_policy_mtx);
-	mac_policy_count++;
+	mac_policy_busy++;
 	mutex_unlock(mac_policy_mtx);
 }
 
@@ -349,8 +357,9 @@
 
 	if (!mutex_try(mac_policy_mtx))
 		return (-1);
-	if (!LIST_EMPTY(&mac_policy_list)) {
-		mac_policy_count++;
+
+	if (mac_policy_list.numloaded > mac_policy_list.staticmax) {
+		mac_policy_busy++;
 		ret = 1;
 	} else
 		ret = 0;
@@ -364,8 +373,8 @@
 	int ret;
 
 	mutex_lock(mac_policy_mtx);
-	if (!LIST_EMPTY(&mac_policy_list)) {
-		mac_policy_count++;
+	if (mac_policy_list.numloaded > mac_policy_list.staticmax) {
+		mac_policy_busy++;
 		ret = 1;
 	} else
 		ret = 0;
@@ -377,9 +386,9 @@
 mac_policy_list_unbusy(void)
 {
 	mutex_lock(mac_policy_mtx);
-	mac_policy_count--;
-	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
-	if (mac_policy_count == 0)
+	mac_policy_busy--;
+	KASSERT(mac_policy_busy >= 0, ("MAC_POLICY_LIST_LOCK"));
+	if (mac_policy_busy == 0)
 		cv_signal(&mac_policy_cv);
 	mutex_unlock(mac_policy_mtx);
 }
@@ -390,8 +399,17 @@
 void
 mac_init(void)
 {
-	LIST_INIT(&mac_static_policy_list);
-	LIST_INIT(&mac_policy_list);
+
+	mac_policy_list.numloaded = 0;
+	mac_policy_list.max = MAC_POLICY_LIST_CHUNKSIZE;
+	mac_policy_list.maxindex = 0;
+	mac_policy_list.staticmax = 0;
+	mac_policy_list.freehint = 0;
+	mac_policy_list.chunks = 1;
+
+	mac_policy_list.entries = kalloc(sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
+	bzero(mac_policy_list.entries, sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE); 
+
 	LIST_INIT(&mac_label_element_list);
 	LIST_INIT(&mac_static_label_element_list);
 	TAILQ_INIT(&mac_label_journal_list);
@@ -427,6 +445,9 @@
 void
 mac_init_bsd(void)
 {
+	struct mac_policy_conf *mpc;
+	u_int i;
+
 	if (mac_static_base_mpc == NULL)
 		panic("Base MAC policy is not registered");
 	else 
@@ -447,20 +468,17 @@
 
 	/* Call bsd init functions of already loaded policies */
 
-	/* Using the exclusive lock means no other framework entry
-	   points can proceed while initializations are running. This
-	   may not be necessary. */
-
+	/*
+	 * Using the exclusive lock means no other framework entry
+	 * points can proceed while initializations are running.
+	 * This may not be necessary.
+	 */
 	mac_policy_grab_exclusive();
-	struct mac_policy_conf *mpc;
 
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
-		if (mpc->mpc_ops->mpo_init_bsd != NULL)
-		        (*(mpc->mpc_ops->mpo_init_bsd))(mpc);
-	}
-	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
-		if (mpc->mpc_ops->mpo_init_bsd != NULL)
-		        (*(mpc->mpc_ops->mpo_init_bsd))(mpc);
+	for (i = 0; i <= mac_policy_list.maxindex; i++) {
+		mpc = mac_get_mpc(i);
+		if ((mpc != NULL) && (mpc->mpc_ops->mpo_init_bsd != NULL))
+			(*(mpc->mpc_ops->mpo_init_bsd))(mpc);
 	}
 
 	mac_policy_release_exclusive();
@@ -473,80 +491,87 @@
  * the lists.
  */
 void
-mac_policy_addto_labellist(struct mac_policy_conf *mpc, int static_entry)
+mac_policy_addto_labellist(mac_policy_handle_t handle, int static_entry)
 {
+	struct mac_label_element **new_mles;
 	struct mac_label_element *mle;
 	struct mac_label_element_list_t *list;
+	struct mac_policy_conf *mpc;
 	const char *name;
 	int found;
 	u_int idx;
 	int midx;
 
+	mpc = mac_get_mpc(handle);
+
 	if (mpc->mpc_labelnames == NULL)
 		return;
 
 	if (mpc->mpc_labelname_count == 0)
 		return;
 
+	/* XXX - do we really need two lists? slight advantage when removing. */
 	if (static_entry)
 		list = &mac_static_label_element_list;
 	else
 		list = &mac_label_element_list;
-	{
-		/* Before we grab the policy list lock, allocate enough memory
-		 * to contain the potential new elements so we don't have to 
-		 * give up the lock, or allocate with the lock held.
-		 */
-		struct mac_label_element *new_mles[mpc->mpc_labelname_count];
 
-		for (idx = 0; idx < mpc->mpc_labelname_count; idx++)
-			MALLOC(new_mles[idx], struct mac_label_element *, 
-			    sizeof(struct mac_label_element),
-			    M_MACTEMP, M_WAITOK);
-		midx = 0;
+	/*
+	 * Before we grab the policy list lock, allocate enough memory
+	 * to contain the potential new elements so we don't have to 
+	 * give up the lock, or allocate with the lock held.
+	 */
+	MALLOC(new_mles, struct mac_label_element **,
+	    sizeof(struct mac_label_element *) *
+	    mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK);
+	for (idx = 0; idx < mpc->mpc_labelname_count; idx++)
+		MALLOC(new_mles[idx], struct mac_label_element *, 
+		    sizeof(struct mac_label_element),
+		    M_MACTEMP, M_WAITOK);
+	midx = 0;
 
-		if (mac_late)
-			mac_policy_grab_exclusive();
-		for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
+	if (mac_late)
+		mac_policy_grab_exclusive();
+	for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
 
-			name = mpc->mpc_labelnames[idx];
+		name = mpc->mpc_labelnames[idx];
 
-			/* Check both label element lists and add to the 
-			 * appropriate list only if not already on a list
-			 */
-			found = FALSE;
-			LIST_FOREACH(mle, &mac_static_label_element_list, 
-			    mle_list) {
+		/* Check both label element lists and add to the 
+		 * appropriate list only if not already on a list
+		 */
+		found = FALSE;
+		LIST_FOREACH(mle, &mac_static_label_element_list, 
+		    mle_list) {
+			if (strcmp(name, mle->mle_name) == 0) {
+				/* ref count unused for static list */
+				found = TRUE;
+				break;
+			}
+		}
+		if (!found)
+			LIST_FOREACH(mle, 
+			    &mac_label_element_list, mle_list) {
 				if (strcmp(name, mle->mle_name) == 0) {
-					/* ref count unused for static list */
+					mle->mle_refs++;
 					found = TRUE;
 					break;
 				}
 			}
-			if (!found)
-				LIST_FOREACH(mle, 
-				    &mac_label_element_list, mle_list) {
-					if (strcmp(name, mle->mle_name) == 0) {
-						mle->mle_refs++;
-						found = TRUE;
-						break;
-					}
-				}
-			if (!found) {
-				strcpy(new_mles[midx]->mle_name, name);
-				new_mles[midx]->mle_refs = 1;
-				LIST_INSERT_HEAD(list, new_mles[midx], 
-				    mle_list);
-				midx++;
-			}
+		if (!found) {
+			strcpy(new_mles[midx]->mle_name, name);
+			new_mles[midx]->mle_refs = 1;
+			LIST_INSERT_HEAD(list, new_mles[midx], 
+			    mle_list);
+			midx++;
 		}
-		if (mac_late)
-			mac_policy_release_exclusive();
+	}
+	if (mac_late)
+		mac_policy_release_exclusive();
 
-		/* Free up any unused label elements */
-		for (idx = midx; idx < mpc->mpc_labelname_count; idx++)
-			FREE(new_mles[idx], M_MACTEMP);
-	}
+	/* Free up any unused label elements */
+	for (idx = midx; idx < mpc->mpc_labelname_count; idx++)
+		FREE(new_mles[idx], M_MACTEMP);
+	FREE(new_mles, M_MACTEMP);
 }
 
 /*
@@ -556,12 +581,15 @@
  * namespace.
  */
 void
-mac_policy_removefrom_labellist(struct mac_policy_conf *mpc)
+mac_policy_removefrom_labellist(mac_policy_handle_t handle)
 {
 	struct mac_label_element *mle;
+	struct mac_policy_conf *mpc;
 	const char *name;
 	u_int idx;
 
+	mpc = mac_get_mpc(handle);
+
 	if (mpc->mpc_labelnames == NULL)
 		return;
 
@@ -606,6 +634,7 @@
 
 	labelmbufs = 0;
 
+	/* XXX - convert to new list structure */
 	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
 			labelmbufs++;
@@ -621,7 +650,8 @@
 static void
 mac_base_policy_register(struct mac_policy_conf *mpc)
 {
-	int error;
+	int error; 
+	u_int i;
 	struct mac_policy_conf *lmpc;
 
 	if (mac_static_base_mpc != NULL)
@@ -635,7 +665,14 @@
 	 * responsible for halting the system, if desired. Otherwise
 	 * the previously loaded module will stay in place.
 	 */
-	LIST_FOREACH(lmpc, &mac_static_policy_list, mpc_list) {
+	for (i = 0; i < mac_policy_list.staticmax; i++) {
+		lmpc = mac_get_mpc(i);
+		if (lmpc == NULL) 
+			continue;
+		/* For now we'll check every policy regardless of dynamic flag.
+		   If by some freak occurance a dynamic policy is loaded at
+		   this point it needs to be approved as well. 
+		*/ 
 		error =
 		    mac_static_base_mpc->mpc_ops->mpo_approve_module_load(lmpc);
 		if (error != 0)
@@ -645,10 +682,12 @@
 }
 
 int
-mac_policy_register(struct mac_policy_conf *mpc, void *xd)
+mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep,
+    void *xd)
 {
-	struct mac_policy_conf *tmpc;
-	int error, slot, static_entry;
+	struct mac_policy_list_element *tmac_policy_list_element;
+	int error, slot, static_entry = 0;
+	u_int i;
 
 	/*
 	 * Some preliminary checks to make sure the policy's conf structure
@@ -668,12 +707,14 @@
 
 	error = 0;
 
-	/*
-	 * We don't technically need exclusive access while !mac_late,
-	 * but hold it for assertion consistency.
-	 */
-	if (mac_late)
+	if (mac_late) {
+		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE) {
+			printf("Module %s does not support late loading.\n",
+			    mpc->mpc_name);
+			return (EPERM);
+		}
 		mac_policy_grab_exclusive();
+	}
 
 	/* Call the base module to approve the loading of this MAC module. */
 	if (mac_static_base_mpc != NULL) {
@@ -686,30 +727,41 @@
 		}
 	}
 
-	/*
-	 * If the module can potentially be unloaded, or we're loading
-	 * late, we have to stick it in the non-static list and pay
-	 * an extra performance overhead.  Otherwise, we can pay a
-	 * light locking cost and stick it in the static list.
-	 */
-	static_entry = (!mac_late &&
-	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
+	if (mac_policy_list.numloaded >= mac_policy_list.max) {
+		/* allocate new policy list array, zero new chunk */
+		tmac_policy_list_element = kalloc((sizeof(struct mac_policy_list_element) *
+		    MAC_POLICY_LIST_CHUNKSIZE) * (mac_policy_list.chunks + 1));
+		bzero(&tmac_policy_list_element[mac_policy_list.max],
+		    sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
+		
+		/* copy old entries into new list */
+		memcpy(tmac_policy_list_element, mac_policy_list.entries, 
+		   sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE *
+		   mac_policy_list.chunks);
+	
+		/* free old array */
+		kfree(mac_policy_list.entries,
+		    sizeof(mac_policy_list_t) * mac_policy_busy);
+		
+		mac_policy_list.entries = tmac_policy_list_element;
+
+		/* Update maximums, etc */
+		mac_policy_list.max += MAC_POLICY_LIST_CHUNKSIZE;
+		mac_policy_list.chunks++;
+	}
+
+	/* Check for policy with same name already loaded */
+	for (i = 0; i <= mac_policy_list.maxindex; i++) {
+		if (mac_policy_list.entries[i].mpc == NULL) 
+			continue;	
 
-	if (static_entry) {
-		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
-			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
-				error = EEXIST;
-				goto out;
-			}
+		if (strcmp(mac_policy_list.entries[i].mpc->mpc_name,
+		    mpc->mpc_name) == 0) {
+			error = EEXIST;
+			goto out;
 		}
-	} else {
-		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
-			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
-				error = EEXIST;
-				goto out;
-			}
-		}
 	}
+
 	if (mpc->mpc_field_off != NULL) {
 		slot = ffs(mac_slot_offsets_free);
 		if (slot == 0) {
@@ -724,7 +776,6 @@
 
 	if (xd) {
 		struct mac_module_data *mmd = xd; /* module data from plist */
-		unsigned int i;
 		char *strtab;
 
 		/* Make a copy of the data. */
@@ -744,18 +795,36 @@
 		}
 	}
 
+	/* Find the first free handle in the list (using our hint). */
+	for (i = mac_policy_list.freehint; i < mac_policy_list.max; i++) {
+		if (mac_policy_list.entries[i].mpc == NULL) {
+			*handlep = i;
+			mac_policy_list.freehint = ++i;
+			break;
+		}
+	}
+
 	/*
-	 * If we're loading a MAC module after the framework has
-	 * initialized, it has to go into the dynamic list.  If
-	 * we're loading it before we've finished initializing,
-	 * it can go into the static list with weaker locking
-	 * requirements.
+	 * If we are loading a MAC module before the framework has
+	 * finished initializing or the module is not unloadable and
+	 * we can place its handle adjacent to the last static entry,
+	 * bump the static policy high water mark.
+	 * Static policies can get by with weaker locking requirements.
 	 */
-	if (static_entry)
-		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
-	else
-		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
+	if (!mac_late ||
+	    ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0 &&
+	    *handlep == mac_policy_list.staticmax)) {
+		static_entry = 1;
+		mac_policy_list.staticmax++;
+	}
+
+	mac_policy_list.entries[*handlep].mpc = mpc;
 
+	/* Update counters, etc */
+	if (*handlep > mac_policy_list.maxindex) 
+		mac_policy_list.maxindex = *handlep;
+	mac_policy_list.numloaded++;
+	
 	/* Per-policy initialization. */
 	printf ("calling mpo_init for %s\n", mpc->mpc_name);
 	if (mpc->mpc_ops->mpo_init != NULL)
@@ -774,7 +843,7 @@
 	if (mac_late)
 		mac_policy_release_exclusive();
 
-	mac_policy_addto_labellist(mpc, static_entry);
+	mac_policy_addto_labellist(*handlep, static_entry);
 
 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
 	    mpc->mpc_name);
@@ -789,8 +858,9 @@
 }
 
 int
-mac_policy_unregister(struct mac_policy_conf *mpc)
+mac_policy_unregister(mac_policy_handle_t handle)
 {
+	struct mac_policy_conf *mpc;
 	int error;
 
 	/*
@@ -799,6 +869,7 @@
 	 * silently succeed.
 	 */
 	mac_policy_grab_exclusive();
+	mpc = mac_get_mpc(handle);
 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
 		mac_policy_release_exclusive();
 		return (0);
@@ -832,16 +903,21 @@
 		mac_policy_release_exclusive();
 		return (EBUSY);
 	}
+
+	mac_get_mpc(handle) = NULL;
+	if (handle < mac_policy_list.freehint &&
+	    handle >= mac_policy_list.staticmax)
+		mac_policy_list.freehint = handle;
+
 	if (mpc->mpc_ops->mpo_destroy != NULL)
 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
 
-	LIST_REMOVE(mpc, mpc_list);
 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
 	mac_policy_updateflags();
 
 	mac_policy_release_exclusive();
 
-	mac_policy_removefrom_labellist(mpc);
+	mac_policy_removefrom_labellist(handle);
 
 	if (mpc->mpc_data) {
 		struct mac_module_data *mmd = mpc->mpc_data;
@@ -1544,7 +1620,8 @@
 {
 	struct mac_policy_conf *mpc;
 	char target[MAC_MAX_POLICY_NAME];
-	int entrycount, error;
+	int error;
+	u_int i;
 	size_t ulen;
 
 	error = copyinstr(CAST_USER_ADDR_T(uap->policy), target, sizeof(target), &ulen);
@@ -1552,17 +1629,25 @@
 		return (error);
 
 	error = ENOSYS;
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
+
+	for (i = 0; i < mac_policy_list.staticmax; i++) {
+		mpc = mac_policy_list.entries[i].mpc;
+		if (mpc == NULL)
+			continue;
+
 		if (strcmp(mpc->mpc_name, target) == 0 &&
 		    mpc->mpc_ops->mpo_syscall != NULL) {
 			error = mpc->mpc_ops->mpo_syscall(p,
 			    uap->call, uap->arg);
-			goto out;
+			break;
 		}
 	}
+	if (mac_policy_list_conditional_busy() != 0) {
+		for (; i <= mac_policy_list.maxindex; i++) {
+			mpc = mac_policy_list.entries[i].mpc;
+			if (mpc == NULL)
+				continue;
 
-	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
 			if (strcmp(mpc->mpc_name, target) == 0 &&
 			    mpc->mpc_ops->mpo_syscall != NULL) {
 				error = mpc->mpc_ops->mpo_syscall(p,
@@ -1572,21 +1657,22 @@
 		}
 		mac_policy_list_unbusy();
 	}
-out:
+
 	return (error);
 }
 
 #else /* MAC */
 
 int
-mac_policy_register(struct mac_policy_conf *mpc)
+mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep,
+    void *xd)
 {
 
 	return (0);
 }
 
 int
-mac_policy_unregister(struct mac_policy_conf *mpc)
+mac_policy_unregister(mac_policy_handle_t handle)
 {
 
 	return (0);

==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.c#2 (text+ko) ====

@@ -29,34 +29,16 @@
 #include "mac_internal.h"
 
 int
-mac_find_module_data(const char *target, const char *key,
+mac_find_module_data(const mac_policy_handle_t handle, const char *key,
     void **valp, size_t *sizep)
 {
 	struct mac_policy_conf *mpc;
-	struct mac_module_data *mmd = NULL;
+	struct mac_module_data *mmd;
 	int error = ENOENT;
 	unsigned int i;
 
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
-		if (strcmp(mpc->mpc_name, target) == 0 &&
-		    mpc->mpc_data != NULL) {
-			mmd = mpc->mpc_data;
-			break;
-		}
-	}
-
-	if (mmd == NULL && mac_policy_list_conditional_busy() != 0) {
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
-			if (strcmp(mpc->mpc_name, target) == 0 &&
-			    mpc->mpc_data != NULL) {
-				mmd = mpc->mpc_data;
-				break;
-			}
-		}
-		mac_policy_list_unbusy();
-	}
-
-	if (mmd != NULL) {
+	if ((mpc = mac_get_mpc(handle)) != NULL &&
+	    (mmd = mpc->mpc_data) != NULL) {
 		for (i = 0; i < mmd->count; i++) {
 			if (strcmp(key, mmd->data[i].key) == 0) {
 				*valp = mmd->data[i].value;

==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.h#2 (text+ko) ====

@@ -59,8 +59,10 @@
 	struct mac_module_data_element data[1];	/* actually bigger */
 };
 
-struct mac_policy_conf;
-int mac_find_module_data(const char *target, const char *key,
+#ifdef _SECURITY_MAC_POLICY_H_
+/* XXX mac_policy_handle_t is defined in mac_policy.h, move prototype there? */
+int mac_find_module_data(const mac_policy_handle_t, const char *key,
     void **valp, size_t *sizep);
+#endif
 
 #endif /* !_SECURITY_MAC_DATA_H_ */

==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_internal.h#5 (text+ko) ====

@@ -68,7 +68,21 @@
 
 extern int mac_late;
 
-LIST_HEAD(mac_policy_list_t, mac_policy_conf);
+struct mac_policy_list_element {
+        struct mac_policy_conf *mpc;
+};    
+
+struct mac_policy_list {
+	u_int				numloaded;
+	u_int 				max;
+	u_int				maxindex;
+	u_int				staticmax;
+	u_int				chunks;
+	u_int				freehint;
+	struct mac_policy_list_element	*entries;
+};
+
+typedef struct mac_policy_list mac_policy_list_t;
 
 
 /*
@@ -125,18 +139,17 @@
  * MAC Framework global variables.
  */
 
-extern struct mac_policy_list_t mac_policy_list;
-extern struct mac_policy_list_t mac_static_policy_list;
 extern struct mac_label_element_list_t mac_label_element_list;
 extern struct mac_label_element_list_t mac_static_label_element_list;
 extern struct mac_label_journal_list_t mac_label_journal_list;
 
+extern struct mac_policy_list mac_policy_list;
+
 extern int mac_enforce_fs;
 extern int mac_enforce_process;
 extern int mac_enforce_system;
 extern int mac_enforce_vm;
 
-
 /*
  * MAC Framework infrastructure functions.
  */
@@ -184,17 +197,25 @@
  */
 #define	MAC_CHECK(check, args...) do {					\
 	struct mac_policy_conf *mpc;					\
-	int entrycount;							\
+	u_int i;                                               		\
 									\
 	error = 0;							\
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
+	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
+		mpc = mac_policy_list.entries[i].mpc;              	\
+		if (mpc == NULL)                                	\
+			continue;                               	\
+									\
 		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
 			error = mac_error_select(      			\
 			    mpc->mpc_ops->mpo_ ## check (args),		\
 			    error);					\
 	}								\
-	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
+	if (mac_policy_list_conditional_busy() != 0) {			\
+		for (; i <= mac_policy_list.maxindex; i++) {		\
+			mpc = mac_policy_list.entries[i].mpc;		\
+			if (mpc == NULL)                                \
+				continue;                               \
+                                                                        \
 			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
 				error = mac_error_select(      		\
 				    mpc->mpc_ops->mpo_ ## check (args),	\
@@ -213,25 +234,33 @@
  */
 #define	MAC_CHECK_NOBLOCK(check, args...) do {					\
 	struct mac_policy_conf *mpc;					\
-	int entrycount;							\
+	int busy;							\
+	u_int i;							\
 									\
 	error = 0;							\
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
+	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
+		mpc = mac_policy_list_entries[i].mpc;			\
+		if (mpc == NULL)                                	\
+			continue;                               	\
+									\
 		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
 			error = mac_error_select(      			\
 			    mpc->mpc_ops->mpo_ ## check (args),		\
 			    error);					\
 	}								\
-	if ((entrycount = mac_policy_list_conditional_busy_noblock()) > 0) { \
-		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
+	if ((busy = mac_policy_list_conditional_busy_noblock()) > 0) {	\
+		for (; i <= mac_policy_list.maxindex; i++) {		\
+			mpc = mac_policy_list.entries[i].mpc;		\
+			if (mpc == NULL)                                \
+				continue;                               \
+                                                                        \
 			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
 				error = mac_error_select(      		\
 				    mpc->mpc_ops->mpo_ ## check (args),	\
 				    error);				\
 		}							\
 		mac_policy_list_unbusy();				\
-	}								\
-	else if (entrycount < 0)					\
+	} else if (busy < 0)						\
 		check_failed = 1;					\
 } while (0)
 
@@ -245,15 +274,24 @@
  */
 #define	MAC_BOOLEAN(operation, composition, args...) do {		\
 	struct mac_policy_conf *mpc;					\
-	int entrycount;							\
+	u_int i;							\
+									\
+	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
+		mpc = mac_policy_list.entries[i].mpc;			\
+		if (mpc == NULL)                                	\
+			continue;                               	\
 									\
-	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
 		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
 			result = result composition			\
-			    mpc->mpc_ops->mpo_ ## operation (args);	\
+			    mpc->mpc_ops->mpo_ ## operation		\

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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