* [PATCH 1/3] policycoreutils/hll/pp: Fix role/roletype scoping
2014-10-02 13:10 [PATCH 0/3] pp2cil fixes based on feedback Yuli Khodorkovskiy
@ 2014-10-02 13:10 ` Yuli Khodorkovskiy
2014-10-02 13:10 ` [PATCH 2/3] policycoreutils/hll/pp: fix '\n' parsing in filecon statements Yuli Khodorkovskiy
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Yuli Khodorkovskiy @ 2014-10-02 13:10 UTC (permalink / raw)
To: SELinux List
- Create role declarations no matter if the declaration is in base or
a module. Since CIL does not permit role re-declarations, this change
will break existing policies that have the same role declared in multiple
modules. To fix this, the policies will need to change the role to be
defined in a single place.
- Pass around the avrule_decl stack rather than just the most recent
decl. The full stack is needed to determine if identifiers are in
scope
- Only create roletype statements for a role and a type in two cases:
1) The role is declared/required and the type is declared/required in
the same scope or an ancestor scope of the role
2) The type is declared/required and the role is declared/required in
an ancestor scope of the type
Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
---
policycoreutils/hll/pp/pp.c | 410 +++++++++++++++++++++++++-------------------
1 file changed, 237 insertions(+), 173 deletions(-)
diff --git a/policycoreutils/hll/pp/pp.c b/policycoreutils/hll/pp/pp.c
index 1c476b7..d424f80 100644
--- a/policycoreutils/hll/pp/pp.c
+++ b/policycoreutils/hll/pp/pp.c
@@ -104,7 +104,7 @@ static void cil_println(int indent, char *fmt, ...)
struct map_args {
struct policydb *pdb;
struct avrule_block *block;
- struct avrule_decl *decl;
+ struct stack *decl_stack;
int scope;
int indent;
int sym_index;
@@ -116,6 +116,122 @@ struct stack {
int size;
};
+struct role_list_node {
+ char *role_name;
+ role_datum_t *role;
+};
+
+struct list_node {
+ void *data;
+ struct list_node *next;
+};
+
+struct list {
+ struct list_node *head;
+};
+
+/* A linked list of all roles stored in the pdb
+ * which is iterated to determine types associated
+ * with each role when printing role_type statements
+ */
+static struct list *role_list;
+
+static void list_destroy(struct list **list)
+{
+ struct list_node *curr = (*list)->head;
+ struct list_node *tmp;
+
+ while (curr != NULL) {
+ tmp = curr->next;
+ free(curr);
+ curr = tmp;
+ }
+
+ free(*list);
+ *list = NULL;
+}
+
+static void role_list_destroy(void)
+{
+ struct list_node *curr = role_list->head;
+
+ while (curr != NULL) {
+ free(curr->data);
+ curr->data = NULL;
+ curr = curr->next;
+ }
+
+ list_destroy(&role_list);
+}
+
+static int list_init(struct list **list)
+{
+ int rc = -1;
+ struct list *l = calloc(1, sizeof(*l));
+ if (l == NULL) {
+ goto exit;
+ }
+
+ *list = l;
+
+ return 0;
+
+exit:
+ list_destroy(&l);
+ return rc;
+}
+
+static int list_prepend(struct list *list, void *data)
+{
+ int rc = -1;
+ struct list_node *node = calloc(1, sizeof(*node));
+ if (node == NULL) {
+ goto exit;
+ }
+
+ node->data = data;
+ node->next = list->head;
+ list->head = node;
+
+ rc = 0;
+
+exit:
+ return rc;
+}
+
+static int roles_gather_map(char *key, void *data, void *args)
+{
+ struct role_list_node *role_node;
+ role_datum_t *role = data;
+ int rc = -1;
+
+ role_node = calloc(1, sizeof(*role_node));
+ if (role_node == NULL) {
+ return rc;
+ }
+
+ role_node->role_name = key;
+ role_node->role = role;
+
+ rc = list_prepend((struct list *)args, role_node);
+ return rc;
+}
+
+static int role_list_create(hashtab_t roles_tab)
+{
+ int rc = -1;
+
+ rc = list_init(&role_list);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ rc = hashtab_map(roles_tab, roles_gather_map, role_list);
+
+exit:
+ return rc;
+}
+
static int stack_destroy(struct stack **stack)
{
if (stack == NULL || *stack == NULL) {
@@ -195,6 +311,44 @@ static void *stack_peek(struct stack *stack)
return stack->stack[stack->pos];
}
+static int is_id_in_scope_with_start(struct policydb *pdb, struct stack *decl_stack, int start, uint32_t symbol_type, char *id)
+{
+ int i;
+ uint32_t j;
+ struct avrule_decl *decl;
+ struct scope_datum *scope;
+
+ scope = hashtab_search(pdb->scope[symbol_type].table, id);
+ if (scope == NULL) {
+ return 0;
+ }
+
+ for (i = start; i >= 0; i--) {
+ decl = decl_stack->stack[i];
+
+ for (j = 0; j < scope->decl_ids_len; j++) {
+ if (scope->decl_ids[j] == decl->decl_id) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int is_id_in_ancestor_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type)
+{
+ int start = decl_stack->pos - 1;
+
+ return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type);
+}
+
+static int is_id_in_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type)
+{
+ int start = decl_stack->pos;
+
+ return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type);
+}
static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct mls_semantic_level *level)
{
@@ -539,6 +693,39 @@ static void names_destroy(char ***names, uint32_t *num_names)
*num_names = 0;
}
+static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *decl_stack, char *type_name, int indent)
+{
+ struct list_node *curr;
+ char **tnames = NULL;
+ uint32_t num_tnames, i;
+ struct role_list_node *role_node = NULL;
+ int rc;
+
+ curr = role_list->head;
+ for (curr = role_list->head; curr != NULL; curr = curr->next) {
+ role_node = curr->data;
+ if (!is_id_in_ancestor_scope(pdb, decl_stack, role_node->role_name, SYM_ROLES)) {
+ continue;
+ }
+
+ rc = typeset_to_names(indent, pdb, &role_node->role->types, &tnames, &num_tnames);
+ if (rc != 0) {
+ goto exit;
+ }
+ for (i = 0; i < num_tnames; i++) {
+ if (!strcmp(type_name, tnames[i])) {
+ cil_println(indent, "(roletype %s %s)", role_node->role_name, type_name);
+ }
+ }
+ names_destroy(&tnames, &num_tnames);
+ }
+
+ rc = 0;
+
+exit:
+ return rc;
+}
+
static int name_list_to_string(char **names, int num_names, char **string)
{
@@ -1342,7 +1529,7 @@ exit:
return rc;
}
-static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
{
int rc = -1;
struct class_datum *class = datum;
@@ -1472,7 +1659,7 @@ static int class_order_to_cil(int indent, struct policydb *pdb, struct ebitmap o
return 0;
}
-static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope)
{
int rc = -1;
struct ebitmap_node *node;
@@ -1484,16 +1671,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
switch (role->flavor) {
case ROLE_ROLE:
if (scope == SCOPE_DECL) {
- if (pdb->policy_type == SEPOL_POLICY_MOD) {
- // roles are defined twice, once in a module and once in base.
- // CIL doesn't allow duplicate declarations, so only take the
- // roles defined in the modules
- cil_println(indent, "(role %s)", key);
-
- // the attributes of a decl role are handled elswhere
- rc = 0;
- goto exit;
- }
+ cil_println(indent, "(role %s)", key);
}
if (ebitmap_cardinality(&role->dominates) > 1) {
@@ -1506,7 +1684,9 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
}
for (i = 0; i < num_types; i++) {
- cil_println(indent, "(roletype %s %s)", key, types[i]);
+ if (is_id_in_scope(pdb, decl_stack, types[i], SYM_TYPES)) {
+ cil_println(indent, "(roletype %s %s)", key, types[i]);
+ }
}
if (role->bounds > 0) {
@@ -1556,7 +1736,7 @@ exit:
return rc;
}
-static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope)
{
int rc = -1;
struct type_datum *type = datum;
@@ -1569,6 +1749,11 @@ static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
// object_r is implicit in checkmodule, but not with CIL,
// create it as part of base
cil_println(indent, "(roletype " DEFAULT_OBJECT " %s)", key);
+
+ rc = roletype_role_in_ancestor_to_cil(pdb, decl_stack, key, indent);
+ if (rc != 0) {
+ goto exit;
+ }
} else {
cil_println(indent, "(typealias %s)", key);
cil_println(indent, "(typealiasactual %s %s)", key, pdb->p_type_val_to_name[type->s.value - 1]);
@@ -1601,13 +1786,13 @@ static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
goto exit;
}
- return 0;
+ rc = 0;
exit:
return rc;
}
-static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
{
struct user_datum *user = datum;
struct ebitmap roles = user->roles.roles;
@@ -1661,7 +1846,7 @@ static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *bl
return 0;
}
-static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
{
struct cond_bool_datum *boolean = datum;
char *type;
@@ -1679,7 +1864,7 @@ static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrul
return 0;
}
-static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
{
struct level_datum *level = datum;
@@ -1726,7 +1911,7 @@ static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap or
return 0;
}
-static int cat_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct avrule_decl *UNUSED(decl), char *key, void *datum, int scope)
+static int cat_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
{
struct cat_datum *cat = datum;
@@ -1779,7 +1964,7 @@ static int typealias_to_cil(char *key, void *data, void *arg)
struct map_args *args = arg;
if (type->primary != 1) {
- rc = type_to_cil(args->indent, args->pdb, args->block, args->decl, key, data, args->scope);
+ rc = type_to_cil(args->indent, args->pdb, args->block, args->decl_stack, key, data, args->scope);
if (rc != 0) {
goto exit;
}
@@ -2642,7 +2827,7 @@ exit:
}
-static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct avrule_decl *decl, char *key, void *datum, int scope) = {
+static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = {
NULL, // commons, only stored in the global symtab, handled elsewhere
class_to_cil,
role_to_cil,
@@ -2653,7 +2838,7 @@ static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avru
cat_to_cil
};
-static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct avrule_decl *decl)
+static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
struct ebitmap map;
@@ -2663,6 +2848,7 @@ static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrul
struct scope_datum *scope;
int sym;
void *datum;
+ struct avrule_decl *decl = stack_peek(decl_stack);
for (sym = 0; sym < SYM_NUM; sym++) {
if (func_to_cil[sym] == NULL) {
@@ -2685,7 +2871,7 @@ static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrul
rc = -1;
goto exit;
}
- rc = func_to_cil[sym](indent, pdb, block, decl, key, datum, scope->scope);
+ rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, scope->scope);
if (rc != 0) {
goto exit;
}
@@ -2718,7 +2904,7 @@ exit:
return rc;
}
-static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct avrule_decl *decl)
+static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
struct ebitmap map;
@@ -2727,6 +2913,7 @@ static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrul
char * key;
int sym;
void *datum;
+ struct avrule_decl *decl = stack_peek(decl_stack);
for (sym = 0; sym < SYM_NUM; sym++) {
if (func_to_cil[sym] == NULL) {
@@ -2744,7 +2931,7 @@ static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrul
rc = -1;
goto exit;
}
- rc = func_to_cil[sym](indent, pdb, block, decl, key, datum, SCOPE_REQ);
+ rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, SCOPE_REQ);
if (rc != 0) {
goto exit;
}
@@ -2762,7 +2949,7 @@ static int additive_scopes_to_cil_map(char *key, void *data, void *arg)
int rc = -1;
struct map_args *args = arg;
- rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl, key, data, SCOPE_REQ);
+ rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl_stack, key, data, SCOPE_REQ);
if (rc != 0) {
goto exit;
}
@@ -2773,14 +2960,15 @@ exit:
return rc;
}
-static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct avrule_decl *decl)
+static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
struct map_args args;
args.pdb = pdb;
args.block = block;
- args.decl = decl;
+ args.decl_stack = decl_stack;
args.indent = indent;
+ struct avrule_decl *decl = stack_peek(decl_stack);
for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
rc = hashtab_map(decl->symtab[args.sym_index].table, additive_scopes_to_cil_map, &args);
@@ -2842,144 +3030,14 @@ exit:
return rc;
}
-static int decl_roles_to_cil(int indent, struct policydb *pdb, struct avrule_decl *decl, struct role_datum **decl_roles, uint32_t num_decl_roles)
-{
- int rc = -1;
- uint32_t i, j, k;
- char **types = NULL;
- uint32_t num_types = 0;
- struct role_datum *role;
- struct scope_datum *scope;
-
- for (i = 0; i < num_decl_roles; i++) {
- role = decl_roles[i];
-
- rc = typeset_to_names(indent, pdb, &role->types, &types, &num_types);
- if (rc != 0) {
- goto exit;
- }
-
- for (j = 0; j < num_types; j++) {
- scope = hashtab_search(pdb->p_types_scope.table, types[j]);
- if (scope == NULL) {
- rc = -1;
- goto exit;
- }
- for (k = 0; k < scope->decl_ids_len; k++) {
- if (scope->decl_ids[k] == decl->decl_id) {
- cil_println(indent, "(roletype %s %s)", pdb->p_role_val_to_name[role->s.value - 1], types[j]);
- }
- }
- }
-
- names_destroy(&types, &num_types);
- }
-
- rc = 0;
-
-exit:
- names_destroy(&types, &num_types);
-
- return rc;
-}
-
-struct decl_roles_args {
- struct policydb *pdb;
- int count;
- struct role_datum **decl_roles;
-};
-
-static int count_decl_roles(char *key, void *UNUSED(datum), void *arg)
-{
- struct scope_datum *scope;
- struct decl_roles_args *args = arg;
-
- if (!strcmp(key, DEFAULT_OBJECT)) {
- return 0;
- }
-
- scope = hashtab_search(args->pdb->p_roles_scope.table, key);
- if (scope == NULL || scope->scope != SCOPE_DECL) {
- return 0;
- }
- args->count++;
-
- return 0;
-}
-
-static int fill_decl_roles(char *key, void *datum, void *arg)
-{
- struct scope_datum *scope;
- struct decl_roles_args *args = arg;
-
- if (!strcmp(key, DEFAULT_OBJECT)) {
- return 0;
- }
-
- scope = hashtab_search(args->pdb->p_roles_scope.table, key);
- if (scope == NULL || scope->scope != SCOPE_DECL) {
- return 0;
- }
-
- args->decl_roles[args->count++] = datum;
-
- return 0;
-}
-
-static int get_decl_roles(struct policydb *pdb, struct role_datum ***decl_roles, int *num_decl_roles)
-{
- int rc = -1;
- uint32_t num;
- struct role_datum **roles;
- struct decl_roles_args args;
- args.pdb = pdb;
-
- args.count = 0;
- rc = hashtab_map(pdb->p_roles.table, count_decl_roles, &args);
- if (rc != 0) {
- goto exit;
- }
- num = args.count;
-
- roles = malloc(sizeof(*roles) * num);
- if (roles == NULL) {
- log_err("Out of memory");
- rc = -1;
- goto exit;
- }
-
- args.count = 0;
- args.decl_roles = roles;
- rc = hashtab_map(pdb->p_roles.table, fill_decl_roles, &args);
- if (rc != 0) {
- goto exit;
- }
-
- *decl_roles = roles;
- *num_decl_roles = num;
-
- return 0;
-
-exit:
- free(roles);
- return rc;
-}
-
-
static int blocks_to_cil(struct policydb *pdb)
{
int rc = -1;
struct avrule_block *block;
struct avrule_decl *decl;
+ struct avrule_decl *decl_tmp;
int indent = 0;
struct stack *stack;
- int num_decl_roles = 0;
- struct role_datum **decl_roles = NULL;
-
- rc = get_decl_roles(pdb, &decl_roles, &num_decl_roles);
- if (rc != 0) {
- goto exit;
- }
rc = stack_init(&stack);
if (rc != 0) {
@@ -2997,7 +3055,12 @@ static int blocks_to_cil(struct policydb *pdb)
}
if (block->flags & AVRULE_OPTIONAL) {
- while (stack->pos > 0 && !is_scope_superset(&decl->required, stack_peek(stack))) {
+ while (stack->pos > 0) {
+ decl_tmp = stack_peek(stack);
+ if (is_scope_superset(&decl->required, &decl_tmp->required)) {
+ break;
+ }
+
stack_pop(stack);
indent--;
cil_println(indent, ")");
@@ -3007,7 +3070,7 @@ static int blocks_to_cil(struct policydb *pdb)
indent++;
}
- stack_push(stack, &decl->required);
+ stack_push(stack, decl);
if (stack->pos == 0) {
// type aliases and commons are only stored in the global symtab.
@@ -3016,7 +3079,7 @@ static int blocks_to_cil(struct policydb *pdb)
struct map_args args;
args.pdb = pdb;
args.block = block;
- args.decl = decl;
+ args.decl_stack = stack;
args.indent = 0;
args.scope = SCOPE_DECL;
@@ -3031,22 +3094,17 @@ static int blocks_to_cil(struct policydb *pdb)
}
}
- rc = decl_roles_to_cil(indent, pdb, decl, decl_roles, num_decl_roles);
+ rc = declared_scopes_to_cil(indent, pdb, block, stack);
if (rc != 0) {
goto exit;
}
- rc = declared_scopes_to_cil(indent, pdb, block, decl);
+ rc = required_scopes_to_cil(indent, pdb, block, stack);
if (rc != 0) {
goto exit;
}
- rc = required_scopes_to_cil(indent, pdb, block, decl);
- if (rc != 0) {
- goto exit;
- }
-
- rc = additive_scopes_to_cil(indent, pdb, block, decl);
+ rc = additive_scopes_to_cil(indent, pdb, block, stack);
if (rc != 0) {
goto exit;
}
@@ -3092,7 +3150,6 @@ static int blocks_to_cil(struct policydb *pdb)
exit:
stack_destroy(&stack);
- free(decl_roles);
return rc;
}
@@ -3240,6 +3297,11 @@ static int module_package_to_cil(struct sepol_module_package *mod_pkg)
}
}
+ rc = role_list_create(pdb->p.p_roles.table);
+ if (rc != 0) {
+ goto exit;
+ }
+
rc = polcaps_to_cil(&pdb->p);
if (rc != 0) {
goto exit;
@@ -3281,9 +3343,11 @@ static int module_package_to_cil(struct sepol_module_package *mod_pkg)
goto exit;
}
- return 0;
+ rc = 0;
exit:
+ role_list_destroy();
+
return rc;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 3/3] policycoreutils/hll/pp: change printing behavior of typeattribute/sets
2014-10-02 13:10 [PATCH 0/3] pp2cil fixes based on feedback Yuli Khodorkovskiy
2014-10-02 13:10 ` [PATCH 1/3] policycoreutils/hll/pp: Fix role/roletype scoping Yuli Khodorkovskiy
2014-10-02 13:10 ` [PATCH 2/3] policycoreutils/hll/pp: fix '\n' parsing in filecon statements Yuli Khodorkovskiy
@ 2014-10-02 13:10 ` Yuli Khodorkovskiy
2014-10-02 14:06 ` [PATCH 0/3] pp2cil fixes based on feedback Steve Lawrence
2014-10-02 14:44 ` James Carter
4 siblings, 0 replies; 12+ messages in thread
From: Yuli Khodorkovskiy @ 2014-10-02 13:10 UTC (permalink / raw)
To: SELinux List
Avrules that have the negation, star, or complement flag set for types
need typeattributes and typeattributesets that are generated. This caused
issues when these generated statements were inserted into conditionals, since
typeattributes/sets are not allowed in conditionals.
This change always prints typeattributes and typeattributesets
immediately unless the types appear inside of an avrule in conditionals or blocks.
For this special case, we print the typeattributes after the end
of each conditional/block.
Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
---
policycoreutils/hll/pp/pp.c | 351 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 290 insertions(+), 61 deletions(-)
diff --git a/policycoreutils/hll/pp/pp.c b/policycoreutils/hll/pp/pp.c
index 55cf819..3f32350 100644
--- a/policycoreutils/hll/pp/pp.c
+++ b/policycoreutils/hll/pp/pp.c
@@ -121,6 +121,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;
@@ -164,6 +173,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;
@@ -455,7 +487,54 @@ 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)
+{
+ static unsigned int num_attrs = 0;
+ int rc = -1;
+ int len, rlen;
+ char *attr_infix;
+ char *attr;
+
+ num_attrs++;
+
+ if (is_type) {
+ attr_infix = "_typeattr_";
+ } else {
+ attr_infix = "_roleattr_";
+ }
+
+ len = strlen(pdb->name) + strlen(attr_infix) + num_digits(num_attrs) + 1;
+ attr = malloc(len);
+ if (attr == NULL) {
+ log_err("Out of memory");
+ rc = -1;
+ goto exit;
+ }
+ rlen = snprintf(attr, len, "%s%s%i", pdb->name, attr_infix, num_attrs);
+ if (rlen < 0 || rlen >= len) {
+ log_err("Failed to generate attribute name");
+ rc = -1;
+ 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
@@ -464,46 +543,22 @@ static int set_to_cil_attr(int indent, struct policydb *pdb, int is_type, struct
// 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;
+ int rc = 0;
struct ebitmap_node *node;
unsigned int i;
- char *attr_infix;
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;
- attr = malloc(len);
- if (attr == NULL) {
- log_err("Out of memory");
- rc = -1;
- goto exit;
- }
- rlen = snprintf(attr, len, "%s%s%i", pdb->name, attr_infix, num_attrs);
- if (rlen < 0 || rlen >= len) {
- log_err("Failed to generate attribute name");
- rc = -1;
- goto exit;
- }
-
cil_println(indent, "(%sattribute %s)", statement, attr);
cil_indent(indent);
cil_printf("(%sattributeset %s ", statement, attr);
@@ -554,17 +609,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;
}
@@ -637,14 +681,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) {
@@ -657,14 +745,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) {
@@ -677,6 +768,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;
@@ -700,6 +854,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) {
@@ -708,7 +863,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;
}
@@ -776,7 +932,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;
@@ -786,15 +942,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;
}
@@ -971,10 +1129,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) {
@@ -985,7 +1183,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;
}
@@ -994,7 +1192,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;
}
@@ -1004,9 +1202,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;
}
@@ -1022,15 +1221,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;
}
@@ -1072,14 +1275,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;
}
@@ -1115,18 +1321,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;
}
@@ -1183,16 +1392,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;
}
@@ -1296,6 +1508,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) {
@@ -1355,7 +1568,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;
}
@@ -1667,6 +1881,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:
@@ -1678,7 +1893,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;
}
@@ -1711,7 +1927,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;
}
@@ -3040,6 +3257,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) {
@@ -3047,6 +3265,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;
@@ -3111,7 +3334,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;
}
@@ -3141,6 +3364,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) {
@@ -3152,6 +3380,7 @@ static int blocks_to_cil(struct policydb *pdb)
exit:
stack_destroy(&stack);
+ attr_list_destroy(&attr_list);
return rc;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread