From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <450EDC2E.50009@trustedcs.com> Date: Mon, 18 Sep 2006 12:49:34 -0500 From: Darrel Goeddel MIME-Version: 1.0 To: SELinux List , Serge Hallyn , Christopher PeBenito , Joshua Brindle , Stephen Smalley , Karl MacMillan Subject: [RFC PATCH] allow range_transitions and MLS users in modules Content-Type: text/plain; charset=ISO-8859-1; format=flowed Sender: owner-selinux@tycho.nsa.gov List-Id: selinux@tycho.nsa.gov - Add the ability to require MLS sensitivities and categories in policy modules. - Remove the restrictions on defining users in MLS-enabled modules. - Handle range_trans_rules in modules. This all allows range_transition statements to be used in policy modules and allows definition of users in MLS policy modules. I haven't tested this as much as I would like, but it is working nicely for me. I have built several policies (MLS, non-MLS, strict, targeted, etc.) and have built several modules exercising the new functionality. I'd appreciate any feedback you may have at this point. --- checkpolicy/module_compiler.c | 110 ++++++++++++++++++++++++ checkpolicy/module_compiler.h | 2 checkpolicy/policy_parse.y | 7 - libsepol/src/link.c | 189 ++++++++++++++++++++++++++++++++++++------ libsepol/src/policydb.c | 6 + 5 files changed, 283 insertions(+), 31 deletions(-) diff --exclude=.svn -ruNp selinux/checkpolicy/module_compiler.c selinux-modular-mls/checkpolicy/module_compiler.c --- selinux/checkpolicy/module_compiler.c 2006-09-05 06:44:56.000000000 -0500 +++ selinux-modular-mls/checkpolicy/module_compiler.c 2006-09-08 16:12:22.000000000 -0500 @@ -937,6 +937,116 @@ int require_bool(int pass) } } +int require_sens(int pass) +{ + char *id = queue_remove(id_queue); + level_datum_t *level = NULL; + int retval; + if (pass == 2) { + free(id); + return 0; + } + if (!id) { + yyerror("no sensitivity name"); + return -1; + } + level = calloc(1, sizeof(level_datum_t)); + if (!level) { + free(id); + yyerror("Out of memory!"); + return -1; + } + level->level = malloc(sizeof(mls_level_t)); + if (!level->level) { + free(id); + free(level); + yyerror("Out of memory!"); + return -1; + } + mls_level_init(level->level); + retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, + &level->level->sens, &level->level->sens); + if (retval != 0) { + free(id); + mls_level_destroy(level->level); + free(level->level); + free(level); + } + switch (retval) { + case -3:{ + yyerror("Out of memory!"); + return -1; + } + case -2:{ + yyerror("duplicate declaration of sensitivity"); + return -1; + } + case -1:{ + yyerror("could not require sensitivity here"); + return -1; + } + case 0:{ + return 0; + } + case 1:{ + return 0; /* sensitivity already required */ + } + default:{ + assert(0); /* should never get here */ + } + } +} + +int require_cat(int pass) +{ + char *id = queue_remove(id_queue); + cat_datum_t *cat = NULL; + int retval; + if (pass == 2) { + free(id); + return 0; + } + if (!id) { + yyerror("no category name"); + return -1; + } + cat = calloc(1, sizeof(cat_datum_t)); + if (!cat) { + free(id); + yyerror("Out of memory!"); + return -1; + } + retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, + &cat->s.value, &cat->s.value); + if (retval != 0) { + free(id); + free(cat); + } + switch (retval) { + case -3:{ + yyerror("Out of memory!"); + return -1; + } + case -2:{ + yyerror("duplicate declaration of category"); + return -1; + } + case -1:{ + yyerror("could not require category here"); + return -1; + } + case 0:{ + return 0; + } + case 1:{ + return 0; /* category already required */ + } + default:{ + assert(0); /* should never get here */ + } + } +} + static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) { int i; diff --exclude=.svn -ruNp selinux/checkpolicy/module_compiler.h selinux-modular-mls/checkpolicy/module_compiler.h --- selinux/checkpolicy/module_compiler.h 2006-09-05 06:44:56.000000000 -0500 +++ selinux-modular-mls/checkpolicy/module_compiler.h 2006-09-08 16:12:22.000000000 -0500 @@ -56,6 +56,8 @@ int require_type(int pass); int require_attribute(int pass); int require_user(int pass); int require_bool(int pass); +int require_sens(int pass); +int require_cat(int pass); /* Check if an identifier is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. diff --exclude=.svn -ruNp selinux/checkpolicy/policy_parse.y selinux-modular-mls/checkpolicy/policy_parse.y --- selinux/checkpolicy/policy_parse.y 2006-09-05 06:17:18.000000000 -0500 +++ selinux-modular-mls/checkpolicy/policy_parse.y 2006-09-08 12:09:35.000000000 -0500 @@ -834,10 +834,8 @@ require_decl_def : ROLE { | ATTRIBUTE { $$ = require_attribute; } | USER { $$ = require_user; } | BOOL { $$ = require_bool; } -/* MLS-enabled modules are not implemented at this time. | SENSITIVITY { $$ = require_sens; } | CATEGORY { $$ = require_cat; } -*/ ; require_id_list : identifier { if ($0 (pass)) return -1; } @@ -3682,11 +3680,6 @@ static int define_user(void) level_datum_t *levdatum; int l; - if (policydbp->policy_type == POLICY_MOD && mlspol) { - yyerror("Users cannot be declared in MLS modules"); - return -1; - } - if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); diff --exclude=.svn -ruNp selinux/libsepol/src/link.c selinux-modular-mls/libsepol/src/link.c --- selinux/libsepol/src/link.c 2006-09-05 06:44:54.000000000 -0500 +++ selinux-modular-mls/libsepol/src/link.c 2006-09-08 16:12:21.000000000 -0500 @@ -468,25 +468,8 @@ static int user_copy_callback(hashtab_ke char *id = key, *new_id = NULL; user_datum_t *user, *base_user, *new_user = NULL; link_state_t *state = (link_state_t *) data; - scope_datum_t *scope; user = (user_datum_t *) datum; - if (state->base->mls) { - scope = - hashtab_search(state->cur->policy->p_users_scope.table, id); - if (!scope) { - ERR(state->handle, - "No scope information for user %s in module %s\n", - id, state->cur_mod_name); - return -1; - } - if (scope->scope == SCOPE_DECL) { - ERR(state->handle, - "Users cannot be declared in MLS modules"); - return -1; - } - /* required users fall through */ - } base_user = hashtab_search(state->base->p_users.table, id); if (base_user == NULL) { @@ -502,9 +485,8 @@ static int user_copy_callback(hashtab_ke goto cleanup; } user_datum_init(new_user); - /* new_users's roles field will be copied during - fix_user_callback(). the MLS fields are currently - unimplemented */ + /* new_users's roles and MLS fields will be copied during + user_fix_callback(). */ new_user->s.value = state->base->p_users.nprim + 1; @@ -592,10 +574,72 @@ static int bool_copy_callback(hashtab_ke return -1; } +static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, + void *data) +{ + char *id = key; + level_datum_t *level, *base_level; + link_state_t *state = (link_state_t *) data; + scope_datum_t *scope; + + level = (level_datum_t *) datum; + + base_level = hashtab_search(state->base->p_levels.table, id); + if (!base_level) { + scope = + hashtab_search(state->cur->policy->p_sens_scope.table, id); + if (!scope) + return -SEPOL_LINK_ERROR; + if (scope->scope == SCOPE_DECL) { + /* disallow declarations in modules */ + ERR(state->handle, + "%s: Modules may not declare new sensitivities.", + state->cur_mod_name); + return -SEPOL_LINK_NOTSUP; + } + } + + state->cur->map[SYM_LEVELS][level->level->sens - 1] = + base_level->level->sens; + + return 0; +} + +static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum, + void *data) +{ + char *id = key; + cat_datum_t *cat, *base_cat; + link_state_t *state = (link_state_t *) data; + scope_datum_t *scope; + + cat = (cat_datum_t *) datum; + + base_cat = hashtab_search(state->base->p_cats.table, id); + if (!base_cat) { + scope = + hashtab_search(state->cur->policy->p_cat_scope.table, id); + if (!scope) + return -SEPOL_LINK_ERROR; + if (scope->scope == SCOPE_DECL) { + /* disallow declarations in modules */ + ERR(state->handle, + "%s: Modules may not declare new categories.", + state->cur_mod_name); + return -SEPOL_LINK_NOTSUP; + } + } + + state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value; + + return 0; +} + static int (*copy_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, class_copy_callback, role_copy_callback, type_copy_callback, - user_copy_callback, bool_copy_callback, NULL, NULL}; + user_copy_callback, bool_copy_callback, sens_copy_callback, + cat_copy_callback}; /* The aliases have to be copied after the types and attributes to be * certain that the base symbol table will have the type that the @@ -783,6 +827,43 @@ static int role_set_or_convert(role_set_ return -1; } +static int mls_level_convert(mls_semantic_level_t * src, + mls_semantic_level_t * dst, policy_module_t * mod) +{ + mls_semantic_cat_t *src_cat, *new_cat; + + assert(mod->map[SYM_LEVELS][src->sens - 1]); + dst->sens = mod->map[SYM_LEVELS][src->sens - 1]; + + for (src_cat = src->cat; src_cat; src_cat = src_cat->next) { + new_cat = + (mls_semantic_cat_t *) calloc(1, + sizeof(mls_semantic_cat_t)); + if (!new_cat) + return -1; + + new_cat->next = dst->cat; + dst->cat = new_cat; + + assert(mod->map[SYM_CATS][src_cat->low - 1]); + dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1]; + assert(mod->map[SYM_CATS][src_cat->high - 1]); + dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1]; + } + + return 0; +} + +static int mls_range_convert(mls_semantic_range_t * src, + mls_semantic_range_t * dst, policy_module_t * mod) +{ + if (mls_level_convert(&src->level[0], &dst->level[0], mod)) + return -1; + if (mls_level_convert(&src->level[1], &dst->level[1], mod)) + return -1; + return 0; +} + static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { @@ -893,13 +974,16 @@ static int user_fix_callback(hashtab_key user_datum_t *user, *new_user = NULL; link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; + symtab_t *usertab; user = (user_datum_t *) datum; if (state->dest_decl == NULL) - return 0; + usertab = &state->base->p_users; + else + usertab = &state->dest_decl->p_users; - new_user = hashtab_search(state->dest_decl->p_users.table, id); + new_user = hashtab_search(usertab->table, id); assert(new_user != NULL); if (state->verbose) { @@ -910,6 +994,12 @@ static int user_fix_callback(hashtab_key goto cleanup; } + if (mls_range_convert(&user->range, &new_user->range, mod)) + goto cleanup; + + if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod)) + goto cleanup; + return 0; cleanup: @@ -1096,6 +1186,55 @@ static int copy_role_allow_list(role_all return -1; } +static int copy_range_trans_list(range_trans_rule_t * rules, + range_trans_rule_t ** dst, + policy_module_t * mod, link_state_t * state) +{ + range_trans_rule_t *rule, *new_rule = NULL; + unsigned int i; + ebitmap_node_t *cnode; + + for (rule = rules; rule; rule = rule->next) { + new_rule = + (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t)); + if (!new_rule) + goto cleanup; + + range_trans_rule_init(new_rule); + + new_rule->next = *dst; + *dst = new_rule; + + if (type_set_convert(&rule->stypes, &new_rule->stypes, + mod, state)) + goto cleanup; + + if (type_set_convert(&rule->ttypes, &new_rule->ttypes, + mod, state)) + goto cleanup; + + ebitmap_for_each_bit(&rule->tclasses, cnode, i) { + if (ebitmap_node_get_bit(cnode, i)) { + assert(mod->map[SYM_CLASSES][i]); + if (ebitmap_set_bit + (&new_rule->tclasses, + mod->map[SYM_CLASSES][i] - 1, 1)) { + goto cleanup; + } + } + } + + if (mls_range_convert(&rule->trange, &new_rule->trange, mod)) + goto cleanup; + } + return 0; + + cleanup: + ERR(state->handle, "Out of memory!"); + range_trans_rule_list_destroy(new_rule); + return -1; +} + static int copy_cond_list(cond_node_t * list, cond_node_t ** dst, policy_module_t * module, link_state_t * state) { @@ -1278,6 +1417,10 @@ static int copy_avrule_decl(link_state_t return -1; } + if (copy_range_trans_list(src_decl->range_tr_rules, + &dest_decl->range_tr_rules, module, state)) + return -1; + /* finally copy any identifiers local to this declaration */ ret = copy_identifiers(state, src_decl->symtab, dest_decl); if (ret < 0) { diff --exclude=.svn -ruNp selinux/libsepol/src/policydb.c selinux-modular-mls/libsepol/src/policydb.c --- selinux/libsepol/src/policydb.c 2006-09-05 06:44:54.000000000 -0500 +++ selinux-modular-mls/libsepol/src/policydb.c 2006-09-08 16:12:21.000000000 -0500 @@ -502,7 +502,11 @@ int policydb_user_cache(hashtab_key_t ke return -1; } - if (p->policy_type != POLICY_KERN) { + /* we do not expand user's MLS info in kernel policies because the + * semantic representation is not present and we do not expand user's + * MLS info in module policies because all of the necessary mls + * information is not present */ + if (p->policy_type != POLICY_KERN && p->policy_type != POLICY_MOD) { mls_range_destroy(&user->exp_range); if (mls_semantic_range_expand(&user->range, &user->exp_range, p, NULL)) { -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.