diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c index 9d48740d..1ee331b1 100644 --- a/checkpolicy/module_compiler.c +++ b/checkpolicy/module_compiler.c @@ -456,103 +456,132 @@ static int user_implicit_bounds(hashtab_t users_tab, return 0; } -user_datum_t *declare_user(void) +static int create_user(uint32_t scope, user_datum_t **user, char **key) { - char *id = queue_remove(id_queue), *dest_id = NULL; - user_datum_t *user = NULL, *dest_user = NULL; - int retval; - uint32_t value = 0; + char *id = queue_remove(id_queue); + user_datum_t *datum = NULL; + int ret; + uint32_t value; + + *user = NULL; + *key = NULL; if (id == NULL) { yyerror("no user name"); - return NULL; + return -1; } - if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) { + + datum = malloc(sizeof(*datum)); + if (datum == NULL) { yyerror("Out of memory!"); free(id); - return NULL; + return -1; } - user_datum_init(user); - retval = - declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value, - &value); + user_datum_init(datum); - if (retval == 0) { - user->s.value = value; - if ((dest_id = strdup(id)) == NULL) { - yyerror("Out of memory!"); - return NULL; - } + if (scope == SCOPE_DECL) { + ret = declare_symbol(SYM_USERS, id, datum, &value, &value); } else { - /* this user was already declared in this module, or error */ - dest_id = id; - user_datum_destroy(user); - free(user); + ret = require_symbol(SYM_USERS, id, datum, &value, &value); } - if (retval == 0 || retval == 1) { - /* create a new user_datum_t for this decl, if necessary */ - hashtab_t users_tab; - assert(stack_top->type == 1); - if (stack_top->parent == NULL) { - /* in parent, so use global symbol table */ - users_tab = policydbp->p_users.table; - } else { - users_tab = stack_top->decl->p_users.table; - } - dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id); - if (dest_user == NULL) { - if ((dest_user = - (user_datum_t *) malloc(sizeof(*dest_user))) == - NULL) { - yyerror("Out of memory!"); - free(dest_id); - return NULL; - } - user_datum_init(dest_user); - dest_user->s.value = value; - if (user_implicit_bounds(users_tab, dest_id, dest_user)) { - free(dest_id); - user_datum_destroy(dest_user); - free(dest_user); - return NULL; - } - if (hashtab_insert(users_tab, dest_id, dest_user)) { - yyerror("Out of memory!"); - free(dest_id); - user_datum_destroy(dest_user); - free(dest_user); - return NULL; - } - } else { - free(dest_id); - } - } else { - free(dest_id); - } - switch (retval) { - case -3:{ + + datum->s.value = value; + + if (ret == 0) { + *user = datum; + *key = strdup(id); + if (*key == NULL) { yyerror("Out of memory!"); - return NULL; + return -1; } - case -2:{ + } else if (ret == 1) { + *user = datum; + *key = id; + } else { + free(id); + user_datum_destroy(datum); + free(datum); + + switch (ret) { + case -3: + yyerror("Out of memory!"); + break; + case -2: yyerror("duplicate declaration of user"); - return NULL; - } - case -1:{ + break; + case -1: yyerror("could not declare user here"); - return NULL; - } - case 0:{ - return dest_user; - } - case 1:{ - return dest_user; /* user already declared for this block */ - } - default:{ + break; + default: abort(); /* should never get here */ } } + + return ret; +} + +user_datum_t *declare_user(void) +{ + char *key = NULL; + user_datum_t *user = NULL; + user_datum_t *dest_user = NULL; + hashtab_t users_tab; + int ret, ret2; + + ret = create_user(SCOPE_DECL, &user, &key); + if (ret < 0) { + return NULL; + } + + /* create a new user_datum_t for this decl, if necessary */ + assert(stack_top->type == 1); + + if (stack_top->parent == NULL) { + /* in parent, so use global symbol table */ + users_tab = policydbp->p_users.table; + } else { + users_tab = stack_top->decl->p_users.table; + } + + dest_user = hashtab_search(users_tab, key); + if (dest_user == NULL) { + if (ret == 0) { + dest_user = malloc(sizeof(*dest_user)); + if (dest_user == NULL) { + yyerror("Out of memory!"); + free(key); + return NULL; + } + user_datum_init(dest_user); + dest_user->s.value = user->s.value; + } else { + dest_user = user; + } + ret2 = user_implicit_bounds(users_tab, key, dest_user); + if (ret2 != 0) { + free(key); + user_datum_destroy(dest_user); + free(dest_user); + return NULL; + } + ret2 = hashtab_insert(users_tab, key, dest_user); + if (ret2 != 0) { + yyerror("Out of memory!"); + free(key); + user_datum_destroy(dest_user); + free(dest_user); + return NULL; + } + } else { + free(key); + if (ret == 1) { + user_datum_destroy(user); + free(user); + } + } + + return dest_user; } /* Return a type_datum_t for the local avrule_decl with the given ID. @@ -987,53 +1016,28 @@ int require_attribute(int pass) int require_user(int pass) { - char *id = queue_remove(id_queue); + char *key = NULL; user_datum_t *user = NULL; - int retval; + int ret; + if (pass == 1) { - free(id); + free(queue_remove(id_queue)); return 0; } - if (id == NULL) { - yyerror("no user name"); + + ret = create_user(SCOPE_REQ, &user, &key); + if (ret < 0) { return -1; } - if ((user = malloc(sizeof(*user))) == NULL) { - free(id); - yyerror("Out of memory!"); - return -1; - } - user_datum_init(user); - retval = - require_symbol(SYM_USERS, id, (hashtab_datum_t *) user, - &user->s.value, &user->s.value); - if (retval != 0) { - free(id); + + free(key); + + if (ret == 1) { user_datum_destroy(user); + free(user); } - switch (retval) { - case -3:{ - yyerror("Out of memory!"); - return -1; - } - case -2:{ - yyerror("duplicate declaration of user"); - return -1; - } - case -1:{ - yyerror("could not require user here"); - return -1; - } - case 0:{ - return 0; - } - case 1:{ - return 0; /* user already required */ - } - default:{ - abort(); /* should never get here */ - } - } + + return 0; } static int require_bool_tunable(int pass, int is_tunable)