diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c index beea879b..9d48740d 100644 --- a/checkpolicy/module_compiler.c +++ b/checkpolicy/module_compiler.c @@ -201,108 +201,143 @@ static int role_implicit_bounds(hashtab_t roles_tab, return 0; } -role_datum_t *declare_role(unsigned char isattr) +static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role, char **key) { - char *id = queue_remove(id_queue), *dest_id = NULL; - role_datum_t *role = NULL, *dest_role = NULL; - int retval; + char *id = queue_remove(id_queue); + role_datum_t *datum = NULL; + int ret; uint32_t value; + *role = NULL; + *key = NULL; + isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE; + if (id == NULL) { yyerror("no role name"); - return NULL; + return -1; } - if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) { + + datum = malloc(sizeof(*datum)); + if (datum == NULL) { yyerror("Out of memory!"); free(id); - return NULL; + return -1; } - role_datum_init(role); - role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; - retval = - declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value, - &value); - if (retval == 0) { - role->s.value = value; - if ((dest_id = strdup(id)) == NULL) { - yyerror("Out of memory!"); - return NULL; - } + + role_datum_init(datum); + datum->flavor = isattr; + + if (scope == SCOPE_DECL) { + ret = declare_symbol(SYM_ROLES, id, datum, &value, &value); } else { - /* this role was already declared in this module, or error */ - dest_id = id; - role_datum_destroy(role); - free(role); + ret = require_symbol(SYM_ROLES, id, datum, &value, &value); } - if (retval == 0 || retval == 1) { - /* create a new role_datum_t for this decl, if necessary */ - hashtab_t roles_tab; - assert(stack_top->type == 1); - if (stack_top->parent == NULL) { - /* in parent, so use global symbol table */ - roles_tab = policydbp->p_roles.table; - } else { - roles_tab = stack_top->decl->p_roles.table; - } - dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id); - if (dest_role == NULL) { - if ((dest_role = - (role_datum_t *) malloc(sizeof(*dest_role))) == - NULL) { - yyerror("Out of memory!"); - free(dest_id); - return NULL; - } - role_datum_init(dest_role); - dest_role->s.value = value; - dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; - if (role_implicit_bounds(roles_tab, dest_id, dest_role)) { - free(dest_id); - role_datum_destroy(dest_role); - free(dest_role); - return NULL; - } - if (hashtab_insert(roles_tab, dest_id, dest_role)) { - yyerror("Out of memory!"); - free(dest_id); - role_datum_destroy(dest_role); - free(dest_role); - return NULL; - } - } else { - free(dest_id); - } - } else { - free(dest_id); - } - switch (retval) { - case -3:{ + + datum->s.value = value; + + if (ret == 0) { + *role = datum; + *key = strdup(id); + if (*key == NULL) { yyerror("Out of memory!"); - return NULL; + return -1; } - case -2:{ + } else if (ret == 1) { + *role = datum; + *key = id; + } else { + free(id); + role_datum_destroy(datum); + free(datum); + + switch (ret) { + case -3: + yyerror("Out of memory!"); + break; + case -2: yyerror("duplicate declaration of role"); - return NULL; - } - case -1:{ + break; + case -1: yyerror("could not declare role here"); - return NULL; - } - case 0:{ - if (ebitmap_set_bit - (&dest_role->dominates, role->s.value - 1, 1)) { - yyerror("out of memory"); - return NULL; - } - return dest_role; - } - case 1:{ - return dest_role; /* role already declared for this block */ - } - default:{ + break; + default: abort(); /* should never get here */ } } + + return ret; +} + +role_datum_t *declare_role(unsigned char isattr) +{ + char *key = NULL; + role_datum_t *role = NULL; + role_datum_t *dest_role = NULL; + hashtab_t roles_tab; + int ret, ret2; + + ret = create_role(SCOPE_DECL, isattr, &role, &key); + if (ret < 0) { + return NULL; + } + + /* create a new role_datum_t for this decl, if necessary */ + assert(stack_top->type == 1); + + if (stack_top->parent == NULL) { + /* in parent, so use global symbol table */ + roles_tab = policydbp->p_roles.table; + } else { + roles_tab = stack_top->decl->p_roles.table; + } + + dest_role = hashtab_search(roles_tab, key); + if (dest_role == NULL) { + if (ret == 0) { + dest_role = malloc(sizeof(*dest_role)); + if (dest_role == NULL) { + yyerror("Out of memory!"); + free(key); + return NULL; + } + role_datum_init(dest_role); + dest_role->s.value = role->s.value; + dest_role->flavor = role->flavor; + } else { + dest_role = role; + } + ret2 = role_implicit_bounds(roles_tab, key, dest_role); + if (ret2 != 0) { + free(key); + role_datum_destroy(dest_role); + free(dest_role); + return NULL; + } + ret2 = hashtab_insert(roles_tab, key, dest_role); + if (ret2 != 0) { + yyerror("Out of memory!"); + free(key); + role_datum_destroy(dest_role); + free(dest_role); + return NULL; + } + } else { + free(key); + if (ret == 1) { + role_datum_destroy(role); + free(role); + } + } + + if (ret == 0) { + ret2 = ebitmap_set_bit(&dest_role->dominates, dest_role->s.value - 1, 1); + if (ret2 != 0) { + yyerror("out of memory"); + return NULL; + } + } + + return dest_role; } static int create_type(uint32_t scope, unsigned char isattr, type_datum_t **type) @@ -881,61 +916,34 @@ int require_class(int pass) static int require_role_or_attribute(int pass, unsigned char isattr) { - char *id = queue_remove(id_queue); + char *key = NULL; role_datum_t *role = NULL; - int retval; + int ret; + if (pass == 2) { - free(id); + free(queue_remove(id_queue)); return 0; } - if (id == NULL) { - yyerror("no role name"); + + ret = create_role(SCOPE_REQ, isattr, &role, &key); + if (ret < 0) { return -1; } - if ((role = malloc(sizeof(*role))) == NULL) { - free(id); - yyerror("Out of memory!"); - return -1; - } - role_datum_init(role); - role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; - retval = - require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, - &role->s.value, &role->s.value); - if (retval != 0) { - free(id); + + free(key); + + if (ret == 0) { + ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1); + if (ret != 0) { + yyerror("Out of memory"); + return -1; + } + } else { role_datum_destroy(role); free(role); } - switch (retval) { - case -3:{ - yyerror("Out of memory!"); - return -1; - } - case -2:{ - yyerror("duplicate declaration of role"); - return -1; - } - case -1:{ - yyerror("could not require role here"); - return -1; - } - case 0:{ - /* all roles dominate themselves */ - if (ebitmap_set_bit - (&role->dominates, role->s.value - 1, 1)) { - yyerror("Out of memory"); - return -1; - } - return 0; - } - case 1:{ - return 0; /* role already required */ - } - default:{ - abort(); /* should never get here */ - } - } + + return 0; } int require_role(int pass)