Add a new function, sepol_module_policydb_to_cil, that generates CIL from a module (not kernel) policydb. Refactor sepol_module_package_to_cil() to use the new function. Signed-off-by: James Carter <jwcart2@xxxxxxxxxxxxx> --- libsepol/include/sepol/module_to_cil.h | 2 + libsepol/src/module_to_cil.c | 367 ++++++++++++++++++++++----------- 2 files changed, 254 insertions(+), 115 deletions(-) diff --git a/libsepol/include/sepol/module_to_cil.h b/libsepol/include/sepol/module_to_cil.h index 1d0225c..18bb3bf 100644 --- a/libsepol/include/sepol/module_to_cil.h +++ b/libsepol/include/sepol/module_to_cil.h @@ -1,6 +1,8 @@ #include <stdlib.h> #include <sepol/module.h> +#include <sepol/policydb/policydb.h> +int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked); int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg); int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg); diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c index 8326826..d1d2efe 100644 --- a/libsepol/src/module_to_cil.c +++ b/libsepol/src/module_to_cil.c @@ -3407,126 +3407,177 @@ exit: return rc; } -static int blocks_to_cil(struct policydb *pdb) +static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int indent) { int rc = -1; - struct avrule_block *block; struct avrule_decl *decl; - struct avrule_decl *decl_tmp; - int indent = 0; - struct stack *stack; struct list *attr_list; - rc = stack_init(&stack); + decl = block->branch_list; + + rc = list_init(&attr_list); if (rc != 0) { goto exit; } - for (block = pdb->global; block != NULL; block = block->next) { - rc = list_init(&attr_list); - if (rc != 0) { - goto exit; - } + rc = typealiases_to_cil(indent, pdb, block, stack); + if (rc != 0) { + goto exit; + } - decl = block->branch_list; - if (decl == NULL) { - continue; - } + rc = declared_scopes_to_cil(indent, pdb, block, stack); + if (rc != 0) { + goto exit; + } - if (decl->next != NULL) { - log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); - } + rc = required_scopes_to_cil(indent, pdb, block, stack); + if (rc != 0) { + goto exit; + } - if (block->flags & AVRULE_OPTIONAL) { - while (stack->pos > 0) { - decl_tmp = stack_peek(stack); - if (is_scope_superset(&decl->required, &decl_tmp->required)) { - break; - } + rc = additive_scopes_to_cil(indent, pdb, block, stack); + if (rc != 0) { + goto exit; + } - stack_pop(stack); - indent--; - cil_println(indent, ")"); - } + rc = avrule_list_to_cil(indent, pdb, decl->avrules, attr_list); + if (rc != 0) { + goto exit; + } - cil_println(indent, "(optional %s_optional_%i", pdb->name, decl->decl_id); - indent++; - } + rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules); + if (rc != 0) { + goto exit; + } - stack_push(stack, decl); + rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules); + if (rc != 0) { + goto exit; + } - if (stack->pos == 0) { - // type aliases and commons are only stored in the global symtab. - // However, to get scoping correct, we assume they are in the - // global block - struct map_args args; - args.pdb = pdb; - args.block = block; - args.decl_stack = stack; - args.indent = 0; - args.scope = SCOPE_DECL; + rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules); + if (rc != 0) { + goto exit; + } - rc = hashtab_map(pdb->p_commons.table, common_to_cil, &args); - if (rc != 0) { - goto exit; + rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules); + if (rc != 0) { + goto exit; + } + + rc = cond_list_to_cil(indent, pdb, decl->cond_list); + if (rc != 0) { + goto exit; + } + + rc = cil_print_attr_list(indent, pdb, attr_list); + if (rc != 0) { + goto exit; + } + +exit: + attr_list_destroy(&attr_list); + return rc; +} + +static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int *indent) +{ + int rc = 0; + struct avrule_decl *decl; + struct avrule_decl *decl_tmp; + + decl = block->branch_list; + if (decl == NULL) { + goto exit; + } + + if (decl->next != NULL) { + log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); + } + + if (block->flags & AVRULE_OPTIONAL) { + while (stack->pos > 0) { + decl_tmp = stack_peek(stack); + if (is_scope_superset(&decl->required, &decl_tmp->required)) { + break; } - } - rc = typealiases_to_cil(indent, pdb, block, stack); - if (rc != 0) { - goto exit; + stack_pop(stack); + (*indent)--; + cil_println(*indent, ")"); } - rc = declared_scopes_to_cil(indent, pdb, block, stack); - if (rc != 0) { - goto exit; - } + cil_println(*indent, "(optional %s_optional_%i", pdb->name, decl->decl_id); + (*indent)++; + } - rc = required_scopes_to_cil(indent, pdb, block, stack); - if (rc != 0) { - goto exit; - } + stack_push(stack, decl); - rc = additive_scopes_to_cil(indent, pdb, block, stack); - if (rc != 0) { - goto exit; - } + rc = block_to_cil(pdb, block, stack, *indent); + if (rc != 0) { + goto exit; + } - rc = avrule_list_to_cil(indent, pdb, decl->avrules, attr_list); - if (rc != 0) { - goto exit; - } +exit: + return rc; +} - rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules); - if (rc != 0) { - goto exit; - } +static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) +{ + int rc = 0; + struct avrule_decl *decl; - rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules); - if (rc != 0) { - goto exit; - } + decl = block->branch_list; + if (decl == NULL) { + goto exit; + } - rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules); - if (rc != 0) { - goto exit; - } + if (decl->next != NULL) { + log_err("Warning: 'else' not allowed in global block. Dropping from output."); + } - rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules); - if (rc != 0) { - goto exit; - } + stack_push(stack, decl); - rc = cond_list_to_cil(indent, pdb, decl->cond_list); - if (rc != 0) { - goto exit; - } + // type aliases and commons are only stored in the global symtab. + // However, to get scoping correct, we assume they are in the + // global block + rc = hashtab_map(pdb->p_commons.table, common_to_cil, NULL); + if (rc != 0) { + goto exit; + } - rc = cil_print_attr_list(indent, pdb, attr_list); + rc = block_to_cil(pdb, block, stack, 0); + if (rc != 0) { + goto exit; + } + +exit: + return rc; +} + +static int blocks_to_cil(struct policydb *pdb) +{ + int rc = -1; + struct avrule_block *block; + int indent = 0; + struct stack *stack; + + rc = stack_init(&stack); + if (rc != 0) { + goto exit; + } + + block = pdb->global; + rc = global_block_to_cil(pdb, block, stack); + if (rc != 0) { + goto exit; + } + + for (block = block->next; block != NULL; block = block->next) { + rc = module_block_to_cil(pdb, block, stack, &indent); if (rc != 0) { goto exit; } - attr_list_destroy(&attr_list); } while (indent > 0) { @@ -3534,11 +3585,71 @@ static int blocks_to_cil(struct policydb *pdb) cil_println(indent, ")"); } - rc = 0; +exit: + stack_destroy(&stack); + + return rc; +} + +static int linked_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) +{ + int rc = 0; + struct avrule_decl *decl; + + decl = block->branch_list; + if (decl == NULL) { + goto exit; + } + + if (!decl->enabled) { + if (decl->next != NULL) { + decl = decl->next; + } else { + goto exit; + } + } + + stack_push(stack, decl); + + rc = block_to_cil(pdb, block, stack, 0); + if (rc != 0) { + goto exit; + } + + stack_pop(stack); + +exit: + return rc; +} + +static int linked_blocks_to_cil(struct policydb *pdb) +{ + // Convert base module that has been linked to CIL + // Since it is linked, all optional blocks have been resolved + int rc = -1; + struct avrule_block *block; + struct stack *stack; + + rc = stack_init(&stack); + if (rc != 0) { + goto exit; + } + + block = pdb->global; + rc = global_block_to_cil(pdb, block, stack); + if (rc != 0) { + goto exit; + } + + for (block = block->next; block != NULL; block = block->next) { + rc = linked_block_to_cil(pdb, block, stack); + if (rc != 0) { + goto exit; + } + } exit: stack_destroy(&stack); - attr_list_destroy(&attr_list); return rc; } @@ -3638,33 +3749,30 @@ exit: return rc; } -int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) +int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked) { int rc = -1; - struct sepol_policydb *pdb; out_file = fp; - pdb = sepol_module_package_get_policy(mod_pkg); if (pdb == NULL) { - log_err("Failed to get policydb"); - rc = -1; + rc = 0; goto exit; } - if (pdb->p.policy_type != SEPOL_POLICY_BASE && - pdb->p.policy_type != SEPOL_POLICY_MOD) { + if (pdb->policy_type != SEPOL_POLICY_BASE && + pdb->policy_type != SEPOL_POLICY_MOD) { log_err("Policy pakcage is not a base or module"); rc = -1; goto exit; } - rc = fix_module_name(&pdb->p); + rc = fix_module_name(pdb); if (rc != 0) { goto exit; } - if (pdb->p.policy_type == SEPOL_POLICY_BASE && !pdb->p.mls) { + if (pdb->policy_type == SEPOL_POLICY_BASE && !pdb->mls) { // If this is a base non-mls policy, we need to define a default level // range that can be used for contexts by other non-mls modules, since // CIL requires that all contexts have a range, even if they are @@ -3675,7 +3783,7 @@ int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) } } - if (pdb->p.policy_type == SEPOL_POLICY_BASE) { + if (pdb->policy_type == SEPOL_POLICY_BASE) { // object_r is implicit in checkmodule, but not with CIL, create it // as part of base rc = generate_default_object(); @@ -3690,65 +3798,97 @@ int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) } // handle_unknown is used from only the base module - rc = handle_unknown_to_cil(&pdb->p); + rc = handle_unknown_to_cil(pdb); if (rc != 0) { goto exit; } // mls is used from only the base module - rc = generate_mls(&pdb->p); + rc = generate_mls(pdb); if (rc != 0) { goto exit; } } - rc = role_list_create(pdb->p.p_roles.table); + rc = role_list_create(pdb->p_roles.table); if (rc != 0) { goto exit; } - rc = typealias_list_create(&pdb->p); + rc = typealias_list_create(pdb); if (rc != 0) { goto exit; } - rc = polcaps_to_cil(&pdb->p); + rc = polcaps_to_cil(pdb); if (rc != 0) { goto exit; } - rc = ocontexts_to_cil(&pdb->p); + rc = ocontexts_to_cil(pdb); if (rc != 0) { goto exit; } - rc = genfscon_to_cil(&pdb->p); + rc = genfscon_to_cil(pdb); if (rc != 0) { goto exit; } - rc = seusers_to_cil(mod_pkg); + // now print everything that is scoped + if (linked) { + rc = linked_blocks_to_cil(pdb); + } else { + rc = blocks_to_cil(pdb); + } if (rc != 0) { goto exit; } - rc = netfilter_contexts_to_cil(mod_pkg); + rc = 0; + +exit: + role_list_destroy(); + typealias_list_destroy(); + + return rc; +} + +int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) +{ + int rc = -1; + struct sepol_policydb *pdb; + + out_file = fp; + + pdb = sepol_module_package_get_policy(mod_pkg); + if (pdb == NULL) { + log_err("Failed to get policydb"); + rc = -1; + goto exit; + } + + rc = sepol_module_policydb_to_cil(fp, &pdb->p, 0); if (rc != 0) { goto exit; } - rc = user_extra_to_cil(mod_pkg); + rc = seusers_to_cil(mod_pkg); if (rc != 0) { goto exit; } - rc = file_contexts_to_cil(mod_pkg); + rc = netfilter_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } - // now print everything that is scoped - rc = blocks_to_cil(&pdb->p); + rc = user_extra_to_cil(mod_pkg); + if (rc != 0) { + goto exit; + } + + rc = file_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } @@ -3756,9 +3896,6 @@ int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) rc = 0; exit: - role_list_destroy(); - typealias_list_destroy(); - return rc; } -- 1.9.3 _______________________________________________ Selinux mailing list Selinux@xxxxxxxxxxxxx To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx. To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.