[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