/* Return a role_datum_t for the local avrule_decl with the given ID. * If it does not exist, create one with the same value as 'value'. * This function assumes that the ID is within scope. c.f., * is_id_in_scope(). * * NOTE: this function usurps ownership of id afterwards. The caller * shall not reference it nor free() it afterwards. */ role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr) { role_datum_t *dest_roledatum; hashtab_t roles_tab; assert(stack_top->type == 1); if (stack_top->parent == NULL) { /* in global, so use global symbol table */ roles_tab = policydbp->p_roles.table; } else { roles_tab = stack_top->decl->p_roles.table; } dest_roledatum = hashtab_search(roles_tab, id); if (!dest_roledatum) { dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t)); if (dest_roledatum == NULL) { free(id); return NULL; } role_datum_init(dest_roledatum); dest_roledatum->s.value = value; dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; if (hashtab_insert(roles_tab, id, dest_roledatum)) { free(id); role_datum_destroy(dest_roledatum); free(dest_roledatum); return NULL; } } else { free(id); if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE) return NULL; } return dest_roledatum; }
role_datum_t *declare_role(void) { char *id = queue_remove(id_queue), *dest_id = NULL; role_datum_t *role = NULL, *dest_role = NULL; int retval; uint32_t value; if (id == NULL) { yyerror("no role name"); return NULL; } if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) { yyerror("Out of memory!"); free(id); return NULL; } role_datum_init(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; } } else { /* this role was already declared in this module, or error */ dest_id = id; role_datum_destroy(role); free(role); } 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; 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:{ yyerror("Out of memory!"); return NULL; } case -2:{ yyerror("duplicate declaration of role"); return NULL; } 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:{ assert(0); /* should never get here */ } } }