diff --git a/policycoreutils/hll/pp/pp.c b/policycoreutils/hll/pp/pp.c index 2016b43b..ee6a12c8 100644 --- a/policycoreutils/hll/pp/pp.c +++ b/policycoreutils/hll/pp/pp.c @@ -124,6 +124,15 @@ struct role_list_node { role_datum_t *role; }; +struct attr_list_node { + char *attribute; + int is_type; + union { + struct type_set *ts; + struct role_set *rs; + } set; +}; + struct list_node { void *data; struct list_node *next; @@ -167,6 +176,29 @@ static void role_list_destroy(void) list_destroy(&role_list); } +static void attr_list_destroy(struct list **attr_list) +{ + if (attr_list == NULL || *attr_list == NULL) { + return; + } + + struct list_node *curr = (*attr_list)->head; + struct attr_list_node *attr; + + while (curr != NULL) { + attr = curr->data; + if (attr != NULL) { + free(attr->attribute); + } + + free(curr->data); + curr->data = NULL; + curr = curr->next; + } + + list_destroy(attr_list); +} + static int list_init(struct list **list) { int rc = -1; @@ -458,39 +490,20 @@ static int num_digits(int n) return num; } -static int set_to_cil_attr(int indent, struct policydb *pdb, int is_type, struct ebitmap *pos, struct ebitmap *neg, uint32_t flags, char ***names, uint32_t *num_names) +static int set_to_cil_attr(struct policydb *pdb, int is_type, char ***names, uint32_t *num_names) { - // CIL doesn't support anonymous positive/negative/complemented sets. So - // instead we create a CIL type/roleattributeset that matches the set. If - // the set has a negative set, then convert it to is (P & !N), where P is - // the list of members in the positive set , and N is the list of members - // in the negative set. Additonally, if the set is complemented, then wrap - // the whole thing with a negation. - static unsigned int num_attrs = 0; - int rc = -1; - struct ebitmap_node *node; - unsigned int i; + int len, rlen; const char *attr_infix; - const char *statement; char *attr; - int len; - int rlen; - int has_positive = pos && (ebitmap_cardinality(pos) > 0); - int has_negative = neg && (ebitmap_cardinality(neg) > 0); - char **val_to_name; num_attrs++; if (is_type) { attr_infix = "_typeattr_"; - statement = "type"; - val_to_name = pdb->p_type_val_to_name; } else { attr_infix = "_roleattr_"; - statement = "role"; - val_to_name = pdb->p_role_val_to_name; } len = strlen(pdb->name) + strlen(attr_infix) + num_digits(num_attrs) + 1; @@ -507,6 +520,48 @@ static int set_to_cil_attr(int indent, struct policydb *pdb, int is_type, struct goto exit; } + *names = malloc(sizeof(**names)); + if (*names == NULL) { + log_err("Out of memory"); + rc = -1; + goto exit; + } + + + *names[0] = attr; + *num_names = 1; + + rc = 0; + +exit: + return rc; +} + +static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, struct ebitmap *pos, struct ebitmap *neg, uint32_t flags, char *attr) +{ + // CIL doesn't support anonymous positive/negative/complemented sets. So + // instead we create a CIL type/roleattributeset that matches the set. If + // the set has a negative set, then convert it to is (P & !N), where P is + // the list of members in the positive set , and N is the list of members + // in the negative set. Additonally, if the set is complemented, then wrap + // the whole thing with a negation. + + int rc = 0; + struct ebitmap_node *node; + unsigned int i; + char *statement; + int has_positive = pos && (ebitmap_cardinality(pos) > 0); + int has_negative = neg && (ebitmap_cardinality(neg) > 0); + char **val_to_name; + + if (is_type) { + statement = "type"; + val_to_name = pdb->p_type_val_to_name; + } else { + statement = "role"; + val_to_name = pdb->p_role_val_to_name; + } + cil_println(indent, "(%sattribute %s)", statement, attr); cil_indent(indent); cil_printf("(%sattributeset %s ", statement, attr); @@ -557,17 +612,6 @@ static int set_to_cil_attr(int indent, struct policydb *pdb, int is_type, struct cil_printf(")\n"); - *names = malloc(sizeof(**names)); - if (*names == NULL) { - log_err("Out of memory"); - rc = -1; - goto exit; - } - *names[0] = attr; - *num_names = 1; - - return 0; -exit: return rc; } @@ -640,14 +684,58 @@ exit: return rc; } -static int typeset_to_names(int indent, struct policydb *pdb, struct type_set *ts, char ***names, uint32_t *num_names) +static int cil_add_attr_to_list(struct list *attr_list, char *attribute, int is_type, void *set) +{ + struct attr_list_node *attr_list_node = NULL; + int rc = -1; + + attr_list_node = calloc(1, sizeof(*attr_list_node)); + if (attr_list_node == NULL) { + log_err("Out of memory"); + rc = -1; + goto exit; + } + + rc = list_prepend(attr_list, attr_list_node); + if (rc != 0) { + goto exit; + } + + attr_list_node->attribute = strdup(attribute); + if (attr_list_node->attribute == NULL) { + log_err("Out of memory"); + rc = -1; + goto exit; + } + + attr_list_node->is_type = is_type; + if (is_type) { + attr_list_node->set.ts = set; + } else { + attr_list_node->set.rs = set; + } + + return rc; + +exit: + if (attr_list_node != NULL) { + free(attr_list_node->attribute); + } + free(attr_list_node); + return rc; +} + +/* generated_attribute is only set if a new attribute was generated in set_to_cil_attr */ +static int typeset_to_names(struct policydb *pdb, struct type_set *ts, char ***names, uint32_t *num_names, char **generated_attribute) { int rc = -1; if (ebitmap_cardinality(&ts->negset) > 0 || ts->flags != 0) { - rc = set_to_cil_attr(indent, pdb, 1, &ts->types, &ts->negset, ts->flags, names, num_names); + rc = set_to_cil_attr(pdb, 1, names, num_names); if (rc != 0) { goto exit; } + + *generated_attribute = *names[0]; } else { rc = ebitmap_to_names(pdb->p_type_val_to_name, ts->types, names, num_names); if (rc != 0) { @@ -660,14 +748,17 @@ exit: return rc; } -static int roleset_to_names(int indent, struct policydb *pdb, struct role_set *rs, char ***names, uint32_t *num_names) +/* generated_attribute is only set if a new attribute was generated in set_to_cil_attr */ +static int roleset_to_names(struct policydb *pdb, struct role_set *rs, char ***names, uint32_t *num_names, char **generated_attribute) { int rc = -1; if (rs->flags != 0) { - rc = set_to_cil_attr(indent, pdb, 0, &rs->roles, NULL, rs->flags, names, num_names); + rc = set_to_cil_attr(pdb, 0, names, num_names); if (rc != 0) { goto exit; } + + *generated_attribute = *names[0]; } else { rc = ebitmap_to_names(pdb->p_role_val_to_name, rs->roles, names, num_names); if (rc != 0) { @@ -680,6 +771,69 @@ exit: return rc; } +static int process_roleset(int indent, struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***type_names, uint32_t *num_type_names) +{ + int rc = -1; + char *generated_attribute = NULL; + *num_type_names = 0; + + rc = roleset_to_names(pdb, rs, type_names, num_type_names, &generated_attribute); + if (rc != 0) { + goto exit; + } + + if (generated_attribute == NULL) { + goto exit; + } + + if (attr_list == NULL) { + rc = cil_print_attr_strs(indent, pdb, 0, &rs->roles, NULL, rs->flags, generated_attribute); + if (rc != 0) { + goto exit; + } + } else { + rc = cil_add_attr_to_list(attr_list, generated_attribute, 0, rs); + if (rc != 0) { + goto exit; + } + } + +exit: + return rc; +} + +static int process_typeset(int indent, struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***type_names, uint32_t *num_type_names) +{ + int rc = -1; + char *generated_attribute = NULL; + *num_type_names = 0; + + rc = typeset_to_names(pdb, ts, type_names, num_type_names, &generated_attribute); + if (rc != 0) { + goto exit; + } + + if (generated_attribute == NULL) { + rc = 0; + goto exit; + } + + if (attr_list == NULL) { + rc = cil_print_attr_strs(indent, pdb, 1, &ts->types, &ts->negset, ts->flags, generated_attribute); + if (rc != 0) { + goto exit; + } + } else { + rc = cil_add_attr_to_list(attr_list, generated_attribute, 1, ts); + if (rc != 0) { + goto exit; + } + } + +exit: + return rc; +} + static void names_destroy(char ***names, uint32_t *num_names) { char **arr = *names; @@ -703,6 +857,7 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack * uint32_t num_tnames, i; struct role_list_node *role_node = NULL; int rc; + struct type_set *ts; curr = role_list->head; for (curr = role_list->head; curr != NULL; curr = curr->next) { @@ -711,7 +866,8 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack * continue; } - rc = typeset_to_names(indent, pdb, &role_node->role->types, &tnames, &num_tnames); + ts = &role_node->role->types; + rc = process_typeset(indent, pdb, ts, NULL, &tnames, &num_tnames); if (rc != 0) { goto exit; } @@ -779,7 +935,7 @@ exit: return rc; } -static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *avrule_list) +static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *avrule_list, struct list *attr_list) { int rc = -1; struct avrule *avrule; @@ -789,15 +945,17 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a uint32_t num_tnames; uint32_t s; uint32_t t; + struct type_set *ts; for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) { - - rc = typeset_to_names(indent, pdb, &avrule->stypes, &snames, &num_snames); + ts = &avrule->stypes; + rc = process_typeset(indent, pdb, ts, attr_list, &snames, &num_snames); if (rc != 0) { goto exit; } - rc = typeset_to_names(indent, pdb, &avrule->ttypes, &tnames, &num_tnames); + ts = &avrule->ttypes; + rc = process_typeset(indent, pdb, ts, attr_list, &tnames, &num_tnames); if (rc != 0) { goto exit; } @@ -974,10 +1132,50 @@ exit: return rc; } +static int cil_print_attr_list(int indent, struct policydb *pdb, struct list *attr_list) +{ + struct list_node *curr; + struct attr_list_node *attr_list_node; + int rc = 0; + struct type_set *ts; + struct role_set *rs; + char *generated_attribute; + + for (curr = attr_list->head; curr != NULL; curr = curr->next) { + attr_list_node = curr->data; + generated_attribute = attr_list_node->attribute; + if (generated_attribute == NULL) { + return -1; + } + + if (attr_list_node->is_type) { + ts = attr_list_node->set.ts; + rc = cil_print_attr_strs(indent, pdb, 1, &ts->types, &ts->negset, ts->flags, generated_attribute); + if (rc != 0) { + return rc; + } + } else { + rs = attr_list_node->set.rs; + rc = cil_print_attr_strs(indent, pdb, 0, &rs->roles, NULL, rs->flags, generated_attribute); + if (rc != 0) { + return rc; + } + } + } + + return rc; +} + static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node *cond_list) { int rc = -1; struct cond_node *cond; + struct list *attr_list; + + rc = list_init(&attr_list); + if (rc != 0) { + goto exit; + } for (cond = cond_list; cond != NULL; cond = cond->next) { @@ -988,7 +1186,7 @@ static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node * if (cond->avtrue_list != NULL) { cil_println(indent + 1, "(true"); - rc = avrule_list_to_cil(indent + 2, pdb, cond->avtrue_list); + rc = avrule_list_to_cil(indent + 2, pdb, cond->avtrue_list, attr_list); if (rc != 0) { goto exit; } @@ -997,7 +1195,7 @@ static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node * if (cond->avfalse_list != NULL) { cil_println(indent + 1, "(false"); - rc = avrule_list_to_cil(indent + 2, pdb, cond->avfalse_list); + rc = avrule_list_to_cil(indent + 2, pdb, cond->avfalse_list, attr_list); if (rc != 0) { goto exit; } @@ -1007,9 +1205,10 @@ static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node * cil_println(indent, ")"); } - return 0; + rc = cil_print_attr_list(indent, pdb, attr_list); exit: + attr_list_destroy(&attr_list); return rc; } @@ -1025,15 +1224,19 @@ static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans uint32_t role; uint32_t i; struct ebitmap_node *node; + struct type_set *ts; + struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { - rc = roleset_to_names(indent, pdb, &rule->roles, &role_names, &num_role_names); + rs = &rule->roles; + rc = process_roleset(indent, pdb, rs, NULL, &role_names, &num_role_names); if (rc != 0) { goto exit; } - rc = typeset_to_names(indent, pdb, &rule->types, &type_names, &num_type_names); + ts = &rule->types; + rc = process_typeset(indent, pdb, ts, NULL, &type_names, &num_type_names); if (rc != 0) { goto exit; } @@ -1075,14 +1278,17 @@ static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allo uint32_t num_new_roles = 0; uint32_t i; uint32_t j; + struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { - rc = roleset_to_names(indent, pdb, &rule->roles, &roles, &num_roles); + rs = &rule->roles; + rc = process_roleset(indent, pdb, rs, NULL, &roles, &num_roles); if (rc != 0) { goto exit; } - rc = roleset_to_names(indent, pdb, &rule->new_roles, &new_roles, &num_new_roles); + rs = &rule->new_roles; + rc = process_roleset(indent, pdb, rs, NULL, &new_roles, &num_new_roles); if (rc != 0) { goto exit; } @@ -1118,18 +1324,21 @@ static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_tra uint32_t i; uint32_t stype; uint32_t ttype; + struct type_set *ts; if (!pdb->mls) { return 0; } for (rule = rules; rule != NULL; rule = rule->next) { - rc = typeset_to_names(indent, pdb, &rule->stypes, &stypes, &num_stypes); + ts = &rule->stypes; + rc = process_typeset(indent, pdb, ts, NULL, &stypes, &num_stypes); if (rc != 0) { goto exit; } - rc = typeset_to_names(indent, pdb, &rule->ttypes, &ttypes, &num_ttypes); + ts = &rule->ttypes; + rc = process_typeset(indent, pdb, ts, NULL, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } @@ -1186,16 +1395,19 @@ static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filena uint32_t num_ttypes = 0; uint32_t stype; uint32_t ttype; + struct type_set *ts; struct filename_trans_rule *rule; for (rule = rules; rule != NULL; rule = rule->next) { - rc = typeset_to_names(indent, pdb, &rule->stypes, &stypes, &num_stypes); + ts = &rule->stypes; + rc = process_typeset(indent, pdb, ts, NULL, &stypes, &num_stypes); if (rc != 0) { goto exit; } - rc = typeset_to_names(indent, pdb, &rule->ttypes, &ttypes, &num_ttypes); + ts = &rule->ttypes; + rc = process_typeset(indent, pdb, ts, NULL, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } @@ -1299,6 +1511,7 @@ static int constraint_expr_to_string(int indent, struct policydb *pdb, struct co char *names; char **name_list = NULL; uint32_t num_names = 0; + struct type_set *ts; rc = stack_init(&stack); if (rc != 0) { @@ -1358,7 +1571,8 @@ static int constraint_expr_to_string(int indent, struct policydb *pdb, struct co } } else { if (expr->attr & CEXPR_TYPE) { - rc = typeset_to_names(indent, pdb, expr->type_names, &name_list, &num_names); + ts = expr->type_names; + rc = process_typeset(indent, pdb, ts, NULL, &name_list, &num_names); if (rc != 0) { goto exit; } @@ -1670,6 +1884,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN char **types = NULL; uint32_t num_types = 0; struct role_datum *role = datum; + struct type_set *ts; switch (role->flavor) { case ROLE_ROLE: @@ -1681,7 +1896,8 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN log_err("Warning: role 'dominance' statment unsupported in CIL. Dropping from output."); } - rc = typeset_to_names(indent, pdb, &role->types, &types, &num_types); + ts = &role->types; + rc = process_typeset(indent, pdb, ts, NULL, &types, &num_types); if (rc != 0) { goto exit; } @@ -1714,7 +1930,8 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN cil_printf("))\n"); } - rc = typeset_to_names(indent, pdb, &role->types, &types, &num_types); + ts = &role->types; + rc = process_typeset(indent, pdb, ts, NULL, &types, &num_types); if (rc != 0) { goto exit; } @@ -3047,6 +3264,7 @@ static int blocks_to_cil(struct policydb *pdb) struct avrule_decl *decl_tmp; int indent = 0; struct stack *stack; + struct list *attr_list; rc = stack_init(&stack); if (rc != 0) { @@ -3054,6 +3272,11 @@ static int blocks_to_cil(struct policydb *pdb) } for (block = pdb->global; block != NULL; block = block->next) { + rc = list_init(&attr_list); + if (rc != 0) { + goto exit; + } + decl = block->branch_list; if (decl == NULL) { continue; @@ -3118,7 +3341,7 @@ static int blocks_to_cil(struct policydb *pdb) goto exit; } - rc = avrule_list_to_cil(indent, pdb, decl->avrules); + rc = avrule_list_to_cil(indent, pdb, decl->avrules, attr_list); if (rc != 0) { goto exit; } @@ -3148,6 +3371,11 @@ static int blocks_to_cil(struct policydb *pdb) goto exit; } + rc = cil_print_attr_list(indent, pdb, attr_list); + if (rc != 0) { + goto exit; + } + attr_list_destroy(&attr_list); } while (indent > 0) { @@ -3159,6 +3387,7 @@ static int blocks_to_cil(struct policydb *pdb) exit: stack_destroy(&stack); + attr_list_destroy(&attr_list); return rc; }