[PATCH 1/2] libsepol: Copy a chain of type alias references

James Carter <[email protected]>
Newsgroups org.kernel.vger.selinux
Message-ID <[email protected]>
For a policy with multiple modules it is possible for there to be
a chain of type alias references where an alias in one module refers
to an alias in another module which refers an alias in a third
module and so on. When expanding a policy with this sort of chain,
a situation can arise where an alias being copied references an
alias that has yet to be copied. Since the value of an alias is set
to the typemap of its primary and the typemap of its primary has not
been set yet, this alias will end up with an invalid value of 0 and
return an error.

When copying aliases, skip over aliases that refer to an alias that
has yet to be copied and keep repeating the copying of aliases until
none have been skipped or the maximum number of repeats has been
exceeded.

Signed-off-by: James Carter <[email protected]>
---
 libsepol/src/expand.c | 47 ++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 466d5bc1..96d7b332 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -39,6 +39,8 @@
 #include "debug.h"
 #include "private.h"
 
+#define MAX_ALIAS_REPEATS 32
+
 typedef struct expand_state {
 	int verbose;
 	uint32_t *typemap;
@@ -49,6 +51,7 @@ typedef struct expand_state {
 	policydb_t *out;
 	sepol_handle_t *handle;
 	int expand_neverallow;
+	int aliases_skipped;
 } expand_state_t;
 
 static void expand_state_init(expand_state_t *state)
@@ -771,6 +774,19 @@ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 		return 0;
 	}
 
+	if (state->typemap[prival - 1] == 0) {
+		/* The primary is another alias that has yet to be copied.
+		 * Skip this alias for now and come back to it later. */
+		state->aliases_skipped++;
+		return 0;
+	}
+
+	new_alias = hashtab_search(state->out->p_types.table, key);
+	if (new_alias) {
+		/* This alias has already been copied */
+		return 0;
+	}
+
 	if (state->verbose)
 		INFO(state->handle, "copying alias %s", id);
 
@@ -787,20 +803,7 @@ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 		return SEPOL_ENOMEM;
 	}
 	memset(new_alias, 0, sizeof(type_datum_t));
-	if (alias->flavor == TYPE_TYPE)
-		new_alias->s.value = state->typemap[alias->s.value - 1];
-	else if (alias->flavor == TYPE_ALIAS)
-		new_alias->s.value = state->typemap[alias->primary - 1];
-	else
-		assert(0); /* unreachable */
-
-	if (!new_alias->s.value) {
-		ERR(state->handle, "No type mapping for %s", new_id);
-		free(new_alias);
-		free(new_id);
-		return -1;
-	}
-
+	new_alias->s.value = state->typemap[prival - 1];
 	new_alias->flags = alias->flags;
 
 	ret = hashtab_insert(state->out->p_types.table, (hashtab_key_t)new_id,
@@ -3266,6 +3269,7 @@ int expand_module(sepol_handle_t *handle, policydb_t *base, policydb_t *out,
 	unsigned int i;
 	expand_state_t state;
 	avrule_block_t *curblock;
+	int repeats = 0;
 
 	/* Append tunable's avtrue_list or avfalse_list to the avrules list
 	 * of its home decl depending on its state value, so that the effect
@@ -3348,8 +3352,19 @@ int expand_module(sepol_handle_t *handle, policydb_t *base, policydb_t *out,
 	/* Needed for processing aliases */
 	if (policydb_index_others(handle, out, verbose))
 		goto cleanup;
-	if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state))
-		goto cleanup;
+
+	do {
+		if (repeats >= MAX_ALIAS_REPEATS) {
+			ERR(handle, "Failed to resolve alias references");
+			goto cleanup;
+		}
+		state.aliases_skipped = 0;
+		if (hashtab_map(state.base->p_types.table, alias_copy_callback,
+				&state))
+			goto cleanup;
+		repeats++;
+	} while (state.aliases_skipped > 0);
+
 	if (hashtab_map(state.base->p_types.table, type_bounds_copy_callback,
 			&state))
 		goto cleanup;
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.