diff --git a/.gitignore b/.gitignore index d02d081c..7218d83c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ src/cil_lexer.c unit_tests cov secilc - docs/pdf/ - docs/html/ - docs/man8/ +docs/pdf/ +docs/html/ +docs/man8/ +policy.* +file_contexts diff --git a/docs/cil_container_statements.xml b/docs/cil_container_statements.xml index 6d7d8bf2..6bdd1ab5 100644 --- a/docs/cil_container_statements.xml +++ b/docs/cil_container_statements.xml @@ -115,7 +115,7 @@ blockinherit - Used to add common policy rules to the current namespace via a template that has been defined with the blockabstract statement. + Used to add common policy rules to the current namespace via a template that has been defined with the blockabstract statement. All blockinherit statements are resolved first and then the contents of the block are copied. This is so that inherited blocks will not be inherited. For a concrete example, please see the examples section. Statement definition: +) + +; This is an example of how blockinherits resolve inherits before copying +(block a + (type one)) + +(block b + ; Notice that block a is declared here as well + (block a + (type two))) + +; This will first copy the contents of block b, which results in type b.a.two being copied. +; Next, the contents of block a will be copied which will result in type a.one. +(block ab + (blockinherit b) + (blockinherit a))]]> diff --git a/src/cil.c b/src/cil.c index a8a989f6..0971bb37 100644 --- a/src/cil.c +++ b/src/cil.c @@ -215,6 +215,7 @@ void cil_db_init(struct cil_db **db) cil_tree_init(&(*db)->parse); cil_tree_init(&(*db)->ast); + cil_root_init((struct cil_root **)&(*db)->ast->root->data); (*db)->sidorder = NULL; (*db)->classorder = NULL; (*db)->catorder = NULL; @@ -235,6 +236,7 @@ void cil_db_init(struct cil_db **db) cil_type_init(&(*db)->selftype); (*db)->selftype->datum.name = CIL_KEY_SELF; + (*db)->selftype->datum.fqn = CIL_KEY_SELF; (*db)->num_types = 0; (*db)->num_roles = 0; @@ -256,7 +258,6 @@ void cil_db_destroy(struct cil_db **db) } cil_tree_destroy(&(*db)->parse); - cil_destroy_ast_symtabs((*db)->ast->root); cil_tree_destroy(&(*db)->ast); cil_list_destroy(&(*db)->sidorder, CIL_FALSE); cil_list_destroy(&(*db)->classorder, CIL_FALSE); @@ -1079,7 +1080,7 @@ int cil_userprefixes_to_string(struct cil_db *db, __attribute__((unused)) sepol_ cil_list_for_each(curr, db->userprefixes) { userprefix = curr->data; user = userprefix->user; - str_len += strlen("user ") + strlen(user->datum.name) + strlen(" prefix ") + strlen(userprefix->prefix_str) + 2; + str_len += strlen("user ") + strlen(user->datum.fqn) + strlen(" prefix ") + strlen(userprefix->prefix_str) + 2; } *size = str_len * sizeof(char); @@ -1091,7 +1092,7 @@ int cil_userprefixes_to_string(struct cil_db *db, __attribute__((unused)) sepol_ userprefix = curr->data; user = userprefix->user; - buf_pos = snprintf(str_tmp, str_len, "user %s prefix %s;\n", user->datum.name, + buf_pos = snprintf(str_tmp, str_len, "user %s prefix %s;\n", user->datum.fqn, userprefix->prefix_str); str_len -= buf_pos; str_tmp += buf_pos; @@ -1130,26 +1131,26 @@ static int __cil_level_strlen(struct cil_level *lvl) int first = -1; int last = -1; - str_len += strlen(lvl->sens->datum.name); + str_len += strlen(lvl->sens->datum.fqn); if (cats && cats->datum_expr != NULL) { str_len++; /* initial ":" */ cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { - str1 = cat->datum.name; + str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; - str2 = cat->datum.name; + str2 = cat->datum.fqn; } else { if (first == last) { - str_len += strlen(str1) + strlen(cat->datum.name) + 1; + str_len += strlen(str1) + strlen(cat->datum.fqn) + 1; } else if (last == first + 1) { - str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.name) + 2; + str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } else { - str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.name) + 2; + str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } first = -1; last = -1; @@ -1183,7 +1184,7 @@ static int __cil_level_to_string(struct cil_level *lvl, char *out) int first = -1; int last = -1; - buf_pos = sprintf(str_tmp, "%s", lvl->sens->datum.name); + buf_pos = sprintf(str_tmp, "%s", lvl->sens->datum.fqn); str_tmp += buf_pos; if (cats && cats->datum_expr != NULL) { @@ -1193,21 +1194,21 @@ static int __cil_level_to_string(struct cil_level *lvl, char *out) cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { - str1 = cat->datum.name; + str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; - str2 = cat->datum.name; + str2 = cat->datum.fqn; } else { if (first == last) { - buf_pos = sprintf(str_tmp, "%s,%s", str1, cat->datum.name); + buf_pos = sprintf(str_tmp, "%s,%s", str1, cat->datum.fqn); str_tmp += buf_pos; } else if (last == first + 1) { - buf_pos = sprintf(str_tmp, "%s,%s,%s", str1, str2, cat->datum.name); + buf_pos = sprintf(str_tmp, "%s,%s,%s", str1, str2, cat->datum.fqn); str_tmp += buf_pos; } else { - buf_pos = sprintf(str_tmp, "%s.%s,%s",str1, str2, cat->datum.name); + buf_pos = sprintf(str_tmp, "%s.%s,%s",str1, str2, cat->datum.fqn); str_tmp += buf_pos; } first = -1; @@ -1252,7 +1253,7 @@ int cil_selinuxusers_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, ch struct cil_selinuxuser *selinuxuser = curr->data; struct cil_user *user = selinuxuser->user; - str_len += strlen(selinuxuser->name_str) + strlen(user->datum.name) + 1; + str_len += strlen(selinuxuser->name_str) + strlen(user->datum.fqn) + 1; if (sepol_db->p.mls == CIL_TRUE) { struct cil_levelrange *range = selinuxuser->range; @@ -1270,7 +1271,7 @@ int cil_selinuxusers_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, ch struct cil_selinuxuser *selinuxuser = curr->data; struct cil_user *user = selinuxuser->user; - buf_pos = sprintf(str_tmp, "%s:%s", selinuxuser->name_str, user->datum.name); + buf_pos = sprintf(str_tmp, "%s:%s", selinuxuser->name_str, user->datum.fqn); str_tmp += buf_pos; if (sepol_db->p.mls == CIL_TRUE) { @@ -1317,7 +1318,7 @@ int cil_filecons_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, char * struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; - str_len += (strlen(user->datum.name) + strlen(role->datum.name) + strlen(type->datum.name) + 3); + str_len += (strlen(user->datum.fqn) + strlen(role->datum.fqn) + strlen(type->datum.fqn) + 3); if (sepol_db->p.mls == CIL_TRUE) { struct cil_levelrange *range = ctx->range; @@ -1380,8 +1381,8 @@ int cil_filecons_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, char * struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; - buf_pos = sprintf(str_tmp, "\t%s:%s:%s", user->datum.name, role->datum.name, - type->datum.name); + buf_pos = sprintf(str_tmp, "\t%s:%s:%s", user->datum.fqn, role->datum.fqn, + type->datum.fqn); str_tmp += buf_pos; if (sepol_db->p.mls == CIL_TRUE) { @@ -1650,12 +1651,15 @@ void cil_block_init(struct cil_block **block) cil_symtab_array_init((*block)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK]); (*block)->is_abstract = CIL_FALSE; + + (*block)->bi_nodes = NULL; } void cil_blockinherit_init(struct cil_blockinherit **inherit) { *inherit = cil_malloc(sizeof(**inherit)); (*inherit)->block_str = NULL; + (*inherit)->block = NULL; } void cil_blockabstract_init(struct cil_blockabstract **abstract) @@ -2243,6 +2247,7 @@ void cil_call_init(struct cil_call **call) void cil_optional_init(struct cil_optional **optional) { *optional = cil_malloc(sizeof(**optional)); + (*optional)->enabled = CIL_TRUE; cil_symtab_datum_init(&(*optional)->datum); } diff --git a/src/cil_binary.c b/src/cil_binary.c index e43a7cf8..99fb2dae 100644 --- a/src/cil_binary.c +++ b/src/cil_binary.c @@ -103,9 +103,9 @@ void cil_neverallows_list_destroy(struct cil_list *neverallows) static int __cil_get_sepol_user_datum(policydb_t *pdb, struct cil_symtab_datum *datum, user_datum_t **sepol_user) { - *sepol_user = hashtab_search(pdb->p_users.table, datum->name); + *sepol_user = hashtab_search(pdb->p_users.table, datum->fqn); if (*sepol_user == NULL) { - cil_log(CIL_INFO, "Failed to find user %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find user %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -114,9 +114,9 @@ static int __cil_get_sepol_user_datum(policydb_t *pdb, struct cil_symtab_datum * static int __cil_get_sepol_role_datum(policydb_t *pdb, struct cil_symtab_datum *datum, role_datum_t **sepol_role) { - *sepol_role = hashtab_search(pdb->p_roles.table, datum->name); + *sepol_role = hashtab_search(pdb->p_roles.table, datum->fqn); if (*sepol_role == NULL) { - cil_log(CIL_INFO, "Failed to find role %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find role %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -125,9 +125,9 @@ static int __cil_get_sepol_role_datum(policydb_t *pdb, struct cil_symtab_datum * static int __cil_get_sepol_type_datum(policydb_t *pdb, struct cil_symtab_datum *datum, type_datum_t **sepol_type) { - *sepol_type = hashtab_search(pdb->p_types.table, datum->name); + *sepol_type = hashtab_search(pdb->p_types.table, datum->fqn); if (*sepol_type == NULL) { - cil_log(CIL_INFO, "Failed to find type %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find type %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -136,9 +136,9 @@ static int __cil_get_sepol_type_datum(policydb_t *pdb, struct cil_symtab_datum * static int __cil_get_sepol_class_datum(policydb_t *pdb, struct cil_symtab_datum *datum, class_datum_t **sepol_class) { - *sepol_class = hashtab_search(pdb->p_classes.table, datum->name); + *sepol_class = hashtab_search(pdb->p_classes.table, datum->fqn); if (*sepol_class == NULL) { - cil_log(CIL_INFO, "Failed to find class %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find class %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -147,9 +147,9 @@ static int __cil_get_sepol_class_datum(policydb_t *pdb, struct cil_symtab_datum static int __cil_get_sepol_cat_datum(policydb_t *pdb, struct cil_symtab_datum *datum, cat_datum_t **sepol_cat) { - *sepol_cat = hashtab_search(pdb->p_cats.table, datum->name); + *sepol_cat = hashtab_search(pdb->p_cats.table, datum->fqn); if (*sepol_cat == NULL) { - cil_log(CIL_INFO, "Failed to find category %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find category %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -158,9 +158,9 @@ static int __cil_get_sepol_cat_datum(policydb_t *pdb, struct cil_symtab_datum *d static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum *datum, level_datum_t **sepol_level) { - *sepol_level = hashtab_search(pdb->p_levels.table, datum->name); + *sepol_level = hashtab_search(pdb->p_levels.table, datum->fqn); if (*sepol_level == NULL) { - cil_log(CIL_INFO, "Failed to find level %s in sepol hashtab\n", datum->name); + cil_log(CIL_INFO, "Failed to find level %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } @@ -292,7 +292,7 @@ int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common common_datum_t *sepol_common = cil_malloc(sizeof(*sepol_common)); memset(sepol_common, 0, sizeof(common_datum_t)); - key = cil_strdup(cil_common->datum.name); + key = cil_strdup(cil_common->datum.fqn); rc = symtab_insert(pdb, SYM_COMMONS, key, sepol_common, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_common); @@ -310,7 +310,7 @@ int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); - key = cil_strdup(curr->datum.name); + key = cil_strdup(curr->datum.fqn); rc = hashtab_insert(sepol_common->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); @@ -345,7 +345,7 @@ int cil_classorder_to_policydb(policydb_t *pdb, const struct cil_db *db) class_datum_t *sepol_class = cil_malloc(sizeof(*sepol_class)); memset(sepol_class, 0, sizeof(class_datum_t)); - key = cil_strdup(cil_class->datum.name); + key = cil_strdup(cil_class->datum.fqn); rc = symtab_insert(pdb, SYM_CLASSES, key, sepol_class, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_class); @@ -362,7 +362,7 @@ int cil_classorder_to_policydb(policydb_t *pdb, const struct cil_db *db) if (cil_class->common != NULL) { struct cil_class *cil_common = cil_class->common; - key = cil_class->common->datum.name; + key = cil_class->common->datum.fqn; sepol_common = hashtab_search(pdb->p_commons.table, key); if (sepol_common == NULL) { rc = cil_common_to_policydb(pdb, cil_common, &sepol_common); @@ -380,7 +380,7 @@ int cil_classorder_to_policydb(policydb_t *pdb, const struct cil_db *db) perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); - key = cil_strdup(curr_perm->datum.name); + key = cil_strdup(curr_perm->datum.fqn); rc = hashtab_insert(sepol_class->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); @@ -407,14 +407,14 @@ int cil_role_to_policydb(policydb_t *pdb, struct cil_role *cil_role) role_datum_t *sepol_role = cil_malloc(sizeof(*sepol_role)); role_datum_init(sepol_role); - if (cil_role->datum.name == CIL_KEY_OBJECT_R) { + if (cil_role->datum.fqn == CIL_KEY_OBJECT_R) { /* special case * object_r defaults to 1 in libsepol symtab */ rc = SEPOL_OK; goto exit; } - key = cil_strdup(cil_role->datum.name); + key = cil_strdup(cil_role->datum.fqn); rc = symtab_insert(pdb, SYM_ROLES, (hashtab_key_t)key, sepol_role, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -453,7 +453,7 @@ int cil_role_bounds_to_policydb(policydb_t *pdb, struct cil_role *cil_role) return SEPOL_OK; exit: - cil_log(CIL_ERR, "Failed to insert role bounds for role %s\n", cil_role->datum.name); + cil_log(CIL_ERR, "Failed to insert role bounds for role %s\n", cil_role->datum.fqn); return SEPOL_ERR; } @@ -500,7 +500,7 @@ int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type) sepol_type->flavor = TYPE_TYPE; - key = cil_strdup(cil_type->datum.name); + key = cil_strdup(cil_type->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_type, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -536,7 +536,7 @@ int cil_type_bounds_to_policydb(policydb_t *pdb, struct cil_type *cil_type) return SEPOL_OK; exit: - cil_log(CIL_ERR, "Failed to insert type bounds for type %s\n", cil_type->datum.name); + cil_log(CIL_ERR, "Failed to insert type bounds for type %s\n", cil_type->datum.fqn); return SEPOL_ERR; } @@ -553,7 +553,7 @@ int cil_typealias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) sepol_alias->flavor = TYPE_TYPE; - key = cil_strdup(cil_alias->datum.name); + key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; @@ -607,7 +607,7 @@ int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil sepol_attr->flavor = TYPE_ATTRIB; - key = cil_strdup(cil_attr->datum.name); + key = cil_strdup(cil_attr->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_attr, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -687,7 +687,7 @@ int cil_policycap_to_policydb(policydb_t *pdb, struct cil_policycap *cil_polcap) int rc = SEPOL_ERR; int capnum; - capnum = sepol_polcap_getnum(cil_polcap->datum.name); + capnum = sepol_polcap_getnum(cil_polcap->datum.fqn); if (capnum == -1) { goto exit; } @@ -710,7 +710,7 @@ int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user) user_datum_t *sepol_user = cil_malloc(sizeof(*sepol_user)); user_datum_init(sepol_user); - key = cil_strdup(cil_user->datum.name); + key = cil_strdup(cil_user->datum.fqn); rc = symtab_insert(pdb, SYM_USERS, key, sepol_user, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -745,7 +745,7 @@ int cil_user_bounds_to_policydb(policydb_t *pdb, struct cil_user *cil_user) return SEPOL_OK; exit: - cil_log(CIL_ERR, "Failed to insert user bounds for user %s\n", cil_user->datum.name); + cil_log(CIL_ERR, "Failed to insert user bounds for user %s\n", cil_user->datum.fqn); return SEPOL_ERR; } @@ -797,7 +797,7 @@ int cil_bool_to_policydb(policydb_t *pdb, struct cil_bool *cil_bool) cond_bool_datum_t *sepol_bool = cil_malloc(sizeof(*sepol_bool)); memset(sepol_bool, 0, sizeof(cond_bool_datum_t)); - key = cil_strdup(cil_bool->datum.name); + key = cil_strdup(cil_bool->datum.fqn); rc = symtab_insert(pdb, SYM_BOOLS, key, sepol_bool, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -827,7 +827,7 @@ int cil_catorder_to_policydb(policydb_t *pdb, const struct cil_db *db) sepol_cat = cil_malloc(sizeof(*sepol_cat)); cat_datum_init(sepol_cat); - key = cil_strdup(cil_cat->datum.name); + key = cil_strdup(cil_cat->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_cat, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -855,7 +855,7 @@ int cil_catalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) rc = __cil_get_sepol_cat_datum(pdb, DATUM(cil_alias->actual), &sepol_cat); if (rc != SEPOL_OK) goto exit; - key = cil_strdup(cil_alias->datum.name); + key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { free(key); @@ -890,7 +890,7 @@ int cil_sensitivityorder_to_policydb(policydb_t *pdb, const struct cil_db *db) level_datum_init(sepol_level); mls_level_init(mls_level); - key = cil_strdup(cil_sens->datum.name); + key = cil_strdup(cil_sens->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_level, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; @@ -922,7 +922,7 @@ int cil_sensalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) rc = __cil_get_sepol_level_datum(pdb, DATUM(cil_alias->actual), &sepol_level); if (rc != SEPOL_OK) goto exit; - key = cil_strdup(cil_alias->datum.name); + key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; @@ -1255,7 +1255,7 @@ int __cil_perms_to_datum(struct cil_list *perms, class_datum_t *sepol_class, uin cil_list_for_each(curr_perm, perms) { perm_datum_t *sepol_perm; cil_perm = curr_perm->data; - key = cil_perm->datum.name; + key = cil_perm->datum.fqn; sepol_perm = hashtab_search(sepol_class->permissions.table, key); if (sepol_perm == NULL) { common_datum_t *sepol_common = sepol_class->comdatum; @@ -1341,7 +1341,7 @@ static void __cil_neverallow_handle(struct cil_list *neverallows, struct cil_sym static int __cil_is_type_match(enum cil_flavor f1, struct cil_symtab_datum *t1, enum cil_flavor f2, struct cil_symtab_datum *t2) { - if (t1->name == t2->name) { + if (t1->fqn == t2->fqn) { return CIL_TRUE; } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a = (struct cil_typeattribute *)t1; @@ -1518,7 +1518,7 @@ int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_a src = cil_avrule->src; tgt = cil_avrule->tgt; - if (tgt->name == CIL_KEY_SELF) { + if (tgt->fqn == CIL_KEY_SELF) { ebitmap_t type_bitmap; ebitmap_node_t *tnode; unsigned int i; @@ -1571,7 +1571,7 @@ int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unu switch (flavor) { case CIL_NAMETYPETRANSITION: cil_typetrans = (struct cil_nametypetransition*)node->data; - if (DATUM(cil_typetrans->name)->name != CIL_KEY_STAR) { + if (DATUM(cil_typetrans->name)->fqn != CIL_KEY_STAR) { cil_log(CIL_ERR, "typetransition with file name not allowed within a booleanif block.\n"); cil_log(CIL_ERR,"Invalid typetransition statement at line %d of %s\n", node->line, node->path); @@ -1621,7 +1621,7 @@ static int __cil_cond_item_to_sepol_expr(policydb_t *pdb, struct cil_list_item * if (item == NULL) { goto exit; } else if (item->flavor == CIL_DATUM) { - char *key = DATUM(item->data)->name; + char *key = DATUM(item->data)->fqn; cond_bool_datum_t *sepol_bool = hashtab_search(pdb->p_bools.table, key); if (sepol_bool == NULL) { cil_log(CIL_INFO, "Failed to find boolean\n"); @@ -2617,10 +2617,10 @@ int cil_sidorder_to_policydb(policydb_t *pdb, const struct cil_db *db) ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_ISID], &tail); count++; new_ocon->sid[0] = count; - new_ocon->u.name = cil_strdup(cil_sid->datum.name); + new_ocon->u.name = cil_strdup(cil_sid->datum.fqn); rc = __cil_context_to_sepol_context(pdb, cil_context, &new_ocon->context[0]); if (rc != SEPOL_OK) { - cil_log(CIL_ERR,"Problem with context for SID %s\n",cil_sid->datum.name); + cil_log(CIL_ERR,"Problem with context for SID %s\n",cil_sid->datum.fqn); goto exit; } } @@ -3013,7 +3013,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def) if (!sepol_class->default_user) { sepol_class->default_user = def->object; } else if (sepol_class->default_user != (char)def->object) { - cil_log(CIL_ERR,"User default labeling for class %s already specified\n",DATUM(c->data)->name); + cil_log(CIL_ERR,"User default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; @@ -3021,7 +3021,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def) if (!sepol_class->default_role) { sepol_class->default_role = def->object; } else if (sepol_class->default_role != (char)def->object) { - cil_log(CIL_ERR,"Role default labeling for class %s already specified\n",DATUM(c->data)->name); + cil_log(CIL_ERR,"Role default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; @@ -3029,7 +3029,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def) if (!sepol_class->default_type) { sepol_class->default_type = def->object; } else if (sepol_class->default_type != (char)def->object) { - cil_log(CIL_ERR,"Type default labeling for class %s already specified\n",DATUM(c->data)->name); + cil_log(CIL_ERR,"Type default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; @@ -3066,7 +3066,7 @@ int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def) if (!sepol_class->default_range) { sepol_class->default_range = def->object_range; } else if (sepol_class->default_range != (char)def->object_range) { - cil_log(CIL_ERR,"Range default labeling for class %s already specified\n", DATUM(curr->data)->name); + cil_log(CIL_ERR,"Range default labeling for class %s already specified\n", DATUM(curr->data)->fqn); goto exit; } } @@ -3274,13 +3274,6 @@ int __cil_binary_create_helper(struct cil_tree_node *node, __attribute__((unused rc = SEPOL_OK; goto exit; } - } else if (node->flavor == CIL_OPTIONAL) { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - rc = SEPOL_OK; - goto exit; - } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; diff --git a/src/cil_build_ast.c b/src/cil_build_ast.c index 01b39794..419c20f8 100644 --- a/src/cil_build_ast.c +++ b/src/cil_build_ast.c @@ -201,6 +201,7 @@ void cil_destroy_block(struct cil_block *block) cil_symtab_datum_destroy(&block->datum); cil_symtab_array_destroy(block->symtab); + cil_list_destroy(&block->bi_nodes, CIL_FALSE); free(block); } diff --git a/src/cil_copy_ast.c b/src/cil_copy_ast.c index 0e54545e..5a245551 100644 --- a/src/cil_copy_ast.c +++ b/src/cil_copy_ast.c @@ -135,6 +135,7 @@ int cil_copy_blockinherit(__attribute__((unused)) struct cil_db *db, void *data, cil_blockinherit_init(&new); new->block_str = orig->block_str; + new->block = orig->block; *copy = new; @@ -1315,6 +1316,7 @@ int cil_copy_call(struct cil_db *db, void *data, void **copy, __attribute__((unu cil_call_init(&new); new->macro_str = orig->macro_str; + new->macro = orig->macro; if (orig->args_tree != NULL) { cil_tree_init(&new->args_tree); @@ -1345,7 +1347,9 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void * if (datum == NULL) { struct cil_macro *new; cil_macro_init(&new); - cil_copy_list(orig->params, &new->params); + if (orig->params != NULL) { + cil_copy_list(orig->params, &new->params); + } *copy = new; @@ -1575,6 +1579,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u symtab_t *symtab = NULL; void *data = NULL; int (*copy_func)(struct cil_db *db, void *data, void **copy, symtab_t *symtab) = NULL; + struct cil_blockinherit *blockinherit = NULL; if (orig == NULL || extra_args == NULL) { goto exit; @@ -1878,6 +1883,11 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u } } + if (new->flavor == CIL_BLOCKINHERIT) { + blockinherit = new->data; + cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new); + } + if (parent->cl_head == NULL) { parent->cl_head = new; parent->cl_tail = new; diff --git a/src/cil_fqn.c b/src/cil_fqn.c index d745988b..dbdd995d 100644 --- a/src/cil_fqn.c +++ b/src/cil_fqn.c @@ -33,189 +33,108 @@ #include "cil_internal.h" #include "cil_log.h" -#include "cil_mem.h" -#include "cil_tree.h" #include "cil_strpool.h" +#include "cil_symtab.h" -struct cil_args_qualify { - char fqparent[CIL_MAX_NAME_LENGTH]; +struct cil_fqn_args { + char prefix[CIL_MAX_NAME_LENGTH]; int len; + struct cil_tree_node *node; }; -int __cil_fqn_qualify_last_child_helper(struct cil_tree_node *node, void *extra_args) +static int __cil_fqn_qualify_decls(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { - struct cil_args_qualify *args = NULL; - struct cil_symtab_datum *datum = NULL; - int rc = SEPOL_ERR; + struct cil_fqn_args *fqn_args = args; + struct cil_symtab_datum *datum = (struct cil_symtab_datum *)d; + int newlen; + char prefix[CIL_MAX_NAME_LENGTH]; + int rc = SEPOL_OK; - if (node == NULL || extra_args == NULL) { + if (fqn_args->len == 0) { + goto exit; + } + + newlen = fqn_args->len + strlen(datum->name); + if (newlen >= CIL_MAX_NAME_LENGTH) { + cil_log(CIL_INFO, "Fully qualified name for %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } - - if (node->parent->flavor != CIL_BLOCK) { - rc = SEPOL_OK; - goto exit; - } - - datum = node->parent->data; - args = extra_args; - args->len -= (strlen(datum->name) + 1); - args->fqparent[args->len] = '\0'; - - return SEPOL_OK; + strcpy(prefix, fqn_args->prefix); + strcat(prefix, datum->name); + datum->fqn = cil_strpool_add(prefix); exit: return rc; } -int __cil_fqn_qualify_first_child_helper(struct cil_tree_node *node, void *extra_args) +static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { - struct cil_args_qualify *args = NULL; - struct cil_symtab_datum *datum = NULL; - int rc = SEPOL_ERR; + struct cil_fqn_args *fqn_args = args; + struct cil_fqn_args child_args; + struct cil_block *block = (struct cil_block *)d; + struct cil_symtab_datum *datum = (struct cil_symtab_datum *)block; + struct cil_tree_node *node = NODE(datum); + int i; + int rc = SEPOL_OK; - if (node == NULL || extra_args == NULL) { + if (node->flavor != CIL_BLOCK) { + goto exit; + } + + int newlen = fqn_args->len + strlen(datum->name) + 1; + if (newlen >= CIL_MAX_NAME_LENGTH) { + cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } - if (node->parent->flavor != CIL_BLOCK) { - rc = SEPOL_OK; - goto exit; - } + child_args.node = node; + child_args.len = newlen; + strcpy(child_args.prefix, fqn_args->prefix); + strcat(child_args.prefix, datum->name); + strcat(child_args.prefix, "."); - args = extra_args; - datum = node->parent->data; - - if (args->len + strlen(datum->name) + 1 >= CIL_MAX_NAME_LENGTH) { - cil_log(CIL_INFO, "Fully qualified name too long at line %d of %s\n", - node->line, node->path); - rc = SEPOL_ERR; - goto exit; - } - - strcat(args->fqparent, datum->name); - strcat(args->fqparent, "."); - args->len += (strlen(datum->name) + 1); - - return SEPOL_OK; - -exit: - return rc; -} - -int __cil_fqn_qualify_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) -{ - struct cil_args_qualify *args = NULL; - struct cil_symtab_datum *datum = NULL; - char *fqn = NULL; - int newlen = 0; - int rc = SEPOL_ERR; - - if (node == NULL || finished == NULL || extra_args == NULL) { - goto exit; - } - - if (node->flavor < CIL_MIN_DECLARATIVE || node->flavor == CIL_PERM || node->flavor == CIL_MAP_PERM) { - rc = SEPOL_OK; - goto exit; - } - - args = extra_args; - datum = node->data; - - switch (node->flavor) { - case CIL_OPTIONAL: - if (datum->state == CIL_STATE_DISABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - case CIL_MACRO: - *finished = CIL_TREE_SKIP_HEAD; - break; - case CIL_BLOCK: - if (((struct cil_block *)datum)->is_abstract == CIL_TRUE) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - case CIL_STRING: - case CIL_NAME: - /* Strings don't change */ - break; - case CIL_TYPEATTRIBUTE: - case CIL_ROLEATTRIBUTE: - case CIL_BOOL: - case CIL_CAT: - case CIL_CATALIAS: - case CIL_CATSET: - case CIL_CLASS: - case CIL_MAP_CLASS: - case CIL_CLASSPERMISSION: - case CIL_COMMON: - case CIL_CONTEXT: - case CIL_IPADDR: - case CIL_LEVEL: - case CIL_LEVELRANGE: - case CIL_POLICYCAP: - case CIL_ROLE: - case CIL_SENS: - case CIL_SENSALIAS: - case CIL_SID: - case CIL_TUNABLE: - case CIL_TYPE: - case CIL_TYPEALIAS: - case CIL_USER: - if (node != ((struct cil_symtab_datum*)node->data)->nodes->head->data) { + for (i=1; isymtab[i]), __cil_fqn_qualify_decls, &child_args); + if (rc != SEPOL_OK) { + goto exit; + } break; } - - if (args->len == 0) { - rc = SEPOL_OK; - goto exit; - } - - newlen = args->len + strlen(datum->name); - if (newlen >= CIL_MAX_NAME_LENGTH) { - cil_log(CIL_INFO, "Fully qualified name too long at line %d of %s\n", - node->line, node->path); - rc = SEPOL_ERR; - goto exit; - } - fqn = cil_malloc(newlen + 1); - strcpy(fqn, args->fqparent); - strcat(fqn, datum->name); - - datum->name = cil_strpool_add(fqn); - free(fqn); - break; - default: - rc = SEPOL_ERR; - goto exit; } - return SEPOL_OK; + rc = cil_symtab_map(&(block->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &child_args); exit: - return rc; -} - -int cil_fqn_qualify(struct cil_tree_node *root) -{ - struct cil_args_qualify extra_args; - int rc = SEPOL_ERR; - - extra_args.fqparent[0] = '\0'; - extra_args.len = 0; - - rc = cil_tree_walk(root, __cil_fqn_qualify_node_helper, __cil_fqn_qualify_first_child_helper, __cil_fqn_qualify_last_child_helper, &extra_args); if (rc != SEPOL_OK) { - goto exit; + cil_log(CIL_ERR,"Problem qualifying names in block at line %d of %s\n", child_args.node->line, child_args.node->path); } - return SEPOL_OK; - -exit: return rc; } +int cil_fqn_qualify(struct cil_tree_node *root_node) +{ + struct cil_root *root = root_node->data; + struct cil_fqn_args fqn_args; + + fqn_args.prefix[0] = '\0'; + fqn_args.len = 0; + fqn_args.node = root_node; + + return cil_symtab_map(&(root->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &fqn_args); +} + diff --git a/src/cil_fqn.h b/src/cil_fqn.h index bbd249aa..9248ca18 100644 --- a/src/cil_fqn.h +++ b/src/cil_fqn.h @@ -33,6 +33,6 @@ #include "cil_internal.h" #include "cil_tree.h" -int cil_fqn_qualify(struct cil_tree_node *root); +int cil_fqn_qualify(struct cil_tree_node *root_node); #endif /* CIL_FQN_H_ */ diff --git a/src/cil_internal.h b/src/cil_internal.h index 3c926748..f88864f3 100644 --- a/src/cil_internal.h +++ b/src/cil_internal.h @@ -53,7 +53,8 @@ enum cil_pass { CIL_PASS_TIF, CIL_PASS_IN, - CIL_PASS_BLKIN, + CIL_PASS_BLKIN_LINK, + CIL_PASS_BLKIN_COPY, CIL_PASS_BLKABS, CIL_PASS_MACRO, CIL_PASS_CALL1, @@ -303,10 +304,12 @@ struct cil_block { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; uint16_t is_abstract; + struct cil_list *bi_nodes; }; struct cil_blockinherit { char *block_str; + struct cil_block *block; }; struct cil_blockabstract { @@ -320,6 +323,7 @@ struct cil_in { struct cil_optional { struct cil_symtab_datum datum; + int enabled; }; struct cil_perm { diff --git a/src/cil_list.c b/src/cil_list.c index e1e6ec1c..766985ed 100644 --- a/src/cil_list.c +++ b/src/cil_list.c @@ -28,15 +28,19 @@ */ #include +#include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" -__attribute__((noreturn)) void cil_list_error(const char* msg) +__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_list_error(const char* msg, ...) { - cil_log(CIL_ERR, "%s\n",msg); + va_list ap; + va_start(ap, msg); + cil_vlog(CIL_ERR, msg, ap); + va_end(ap); exit(1); } @@ -216,3 +220,29 @@ void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item) last->next = list->head; list->head = item; } + +void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data) +{ + struct cil_list_item *item; + struct cil_list_item *previous = NULL; + + if (list == NULL) { + cil_list_error("Attempt to remove data from a NULL list"); + } + + cil_list_for_each(item, list) { + if (item->data == data && item->flavor == flavor) { + if (previous == NULL) { + list->head = item->next; + } else { + previous->next = item->next; + } + if (item->next == NULL) { + list->tail = previous; + } + cil_list_item_destroy(&item, destroy_data); + break; + } + previous = item; + } +} diff --git a/src/cil_list.h b/src/cil_list.h index de927fc2..16d743c5 100644 --- a/src/cil_list.h +++ b/src/cil_list.h @@ -54,6 +54,7 @@ void cil_list_item_init(struct cil_list_item **item); void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data); void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data); void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data); +void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data); struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data); void cil_list_append_item(struct cil_list *list, struct cil_list_item *item); void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item); diff --git a/src/cil_log.c b/src/cil_log.c index c2c5b6f0..b222b155 100644 --- a/src/cil_log.c +++ b/src/cil_log.c @@ -49,18 +49,23 @@ void cil_set_log_handler(void (*handler)(int lvl, char *msg)) cil_log_handler = handler; } -__attribute__ ((format (printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...) +__attribute__ ((format (printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args) { if (cil_log_level >= lvl) { char buff[MAX_LOG_SIZE]; - va_list args; - va_start(args, msg); vsnprintf(buff, MAX_LOG_SIZE, msg, args); - va_end(args); (*cil_log_handler)(cil_log_level, buff); } } +__attribute__ ((format (printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...) +{ + va_list args; + va_start(args, msg); + cil_vlog(lvl, msg, args); + va_end(args); +} + void cil_set_log_level(enum cil_log_level lvl) { cil_log_level = lvl; diff --git a/src/cil_log.h b/src/cil_log.h index 9c2ff2e8..4112aaf4 100644 --- a/src/cil_log.h +++ b/src/cil_log.h @@ -34,6 +34,7 @@ #define MAX_LOG_SIZE 512 +__attribute__ ((format(printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args); __attribute__ ((format(printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...); #endif // CIL_LOG_H_ diff --git a/src/cil_parser.c b/src/cil_parser.c index 43df1df5..d0e108cc 100644 --- a/src/cil_parser.c +++ b/src/cil_parser.c @@ -40,7 +40,7 @@ #include "cil_lexer.h" #include "cil_strpool.h" -int cil_parser(char *path, char *buffer, uint32_t size, struct cil_tree **parse_tree) +int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree) { int paren_count = 0; @@ -49,6 +49,7 @@ int cil_parser(char *path, char *buffer, uint32_t size, struct cil_tree **parse_ struct cil_tree_node *node = NULL; struct cil_tree_node *item = NULL; struct cil_tree_node *current = NULL; + char *path = cil_strpool_add(_path); struct token tok; diff --git a/src/cil_policy.c b/src/cil_policy.c index d19accbf..ec38f694 100644 --- a/src/cil_policy.c +++ b/src/cil_policy.c @@ -1137,13 +1137,6 @@ int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished, return SEPOL_OK; } - if (node->flavor == CIL_OPTIONAL) { - if (((struct cil_symtab_datum *)node->data)->state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - return SEPOL_OK; - } - if (node->flavor == CIL_BLOCK && ((struct cil_block*)node->data)->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; return SEPOL_OK; diff --git a/src/cil_post.c b/src/cil_post.c index 71f8c734..e89f16ba 100644 --- a/src/cil_post.c +++ b/src/cil_post.c @@ -325,13 +325,6 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; @@ -406,13 +399,6 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__( } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; @@ -994,13 +980,6 @@ static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__(( } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; @@ -1077,13 +1056,6 @@ static int __cil_post_db_roletype_helper(struct cil_tree_node *node, __attribute } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; @@ -1176,13 +1148,6 @@ static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finish } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; @@ -1530,13 +1495,6 @@ static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t } break; } - case CIL_OPTIONAL: { - struct cil_optional *opt = node->data; - if (opt->datum.state != CIL_STATE_ENABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - break; - } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; diff --git a/src/cil_reset_ast.c b/src/cil_reset_ast.c index aafbd948..170e612c 100644 --- a/src/cil_reset_ast.c +++ b/src/cil_reset_ast.c @@ -46,6 +46,20 @@ static inline void cil_reset_classperms(struct cil_classperms *cp) cil_list_destroy(&cp->perms, CIL_FALSE); } +static void cil_reset_classpermission(struct cil_classpermission *cp) +{ + if (cp == NULL) { + return; + } + + cil_reset_classperms_list(cp->classperms); +} + +static void cil_reset_classperms_set(struct cil_classperms_set *cp_set) +{ + cil_reset_classpermission(cp_set->set); +} + static inline void cil_reset_classperms_list(struct cil_list *cp_list) { struct cil_list_item *curr; @@ -55,17 +69,14 @@ static inline void cil_reset_classperms_list(struct cil_list *cp_list) } cil_list_for_each(curr, cp_list) { - if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP, but not SET */ + if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP */ cil_reset_classperms(curr->data); + } else if (curr->flavor == CIL_CLASSPERMS_SET) { /* SET */ + cil_reset_classperms_set(curr->data); } } } -static void cil_reset_classpermission(struct cil_classpermission *cp) -{ - cil_reset_classperms_list(cp->classperms); -} - static void cil_reset_classpermissionset(struct cil_classpermissionset *cps) { cil_reset_classperms_list(cps->classperms); diff --git a/src/cil_resolve_ast.c b/src/cil_resolve_ast.c index 2250016d..e27f9656 100644 --- a/src/cil_resolve_ast.c +++ b/src/cil_resolve_ast.c @@ -45,6 +45,7 @@ #include "cil_copy_ast.h" #include "cil_verify.h" #include "cil_strpool.h" +#include "cil_symtab.h" struct cil_args_resolve { struct cil_db *db; @@ -2035,32 +2036,69 @@ exit: return rc; } -int cil_resolve_blockinherit(struct cil_tree_node *current, void *extra_args) +int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) { struct cil_blockinherit *inherit = current->data; - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; struct cil_symtab_datum *block_datum = NULL; - struct cil_tree_node *block_node = NULL; + struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; - if (args != NULL) { - db = args->db; - } - rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); if (rc != SEPOL_OK) { goto exit; } - block_node = block_datum->nodes->head->data; + node = block_datum->nodes->head->data; - rc = cil_copy_ast(db, block_node, current); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to copy block, rc: %d\n", rc); + if (node->flavor != CIL_BLOCK) { + cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); + rc = SEPOL_ERR; goto exit; } + inherit->block = (struct cil_block *)block_datum; + + if (inherit->block->bi_nodes == NULL) { + cil_list_init(&inherit->block->bi_nodes, CIL_NODE); + } + cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); + + return SEPOL_OK; + +exit: + return rc; +} + +int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) +{ + struct cil_block *block = current->data; + struct cil_args_resolve *args = extra_args; + struct cil_db *db = NULL; + struct cil_list_item *item = NULL; + int rc = SEPOL_ERR; + + // This block is not inherited + if (block->bi_nodes == NULL) { + rc = SEPOL_OK; + goto exit; + } + + db = args->db; + + // Make sure this is the original block and not a merged block from a blockinherit + if (current != block->datum.nodes->head->data) { + rc = SEPOL_OK; + goto exit; + } + + cil_list_for_each(item, block->bi_nodes) { + rc = cil_copy_ast(db, current, item->data); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n"); + goto exit; + } + } + return SEPOL_OK; exit: @@ -2936,9 +2974,14 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) cil_list_prepend(ins, CIL_NODE, node); } break; - case CIL_PASS_BLKIN: + case CIL_PASS_BLKIN_LINK: if (node->flavor == CIL_BLOCKINHERIT) { - rc = cil_resolve_blockinherit(node, args); + rc = cil_resolve_blockinherit_link(node, args); + } + break; + case CIL_PASS_BLKIN_COPY: + if (node->flavor == CIL_BLOCK) { + rc = cil_resolve_blockinherit_copy(node, args); } break; case CIL_PASS_BLKABS: @@ -3216,13 +3259,6 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unu } } - if (node->flavor == CIL_OPTIONAL && ((struct cil_symtab_datum *)node->data)->state == CIL_STATE_DISABLED) { - /* don't try to resolve children of a disabled optional */ - *finished = CIL_TREE_SKIP_HEAD; - rc = SEPOL_OK; - goto exit; - } - if (node->flavor == CIL_BLOCK && ((((struct cil_block*)node->data)->is_abstract == CIL_TRUE) && (pass > CIL_PASS_BLKABS))) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; @@ -3234,7 +3270,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unu struct cil_optional *opt = (struct cil_optional *)optstack->data; cil_log(CIL_WARN, "Disabling optional %s at %d of %s\n", opt->datum.name, node->parent->line, node->parent->path); /* disable an optional if something failed to resolve */ - opt->datum.state = CIL_STATE_DISABLING; + opt->enabled = CIL_FALSE; rc = SEPOL_OK; } else if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve %s statement at %d of %s\n", cil_node_to_string(node), node->line, node->path); @@ -3247,42 +3283,6 @@ exit: return rc; } -int __cil_disable_children_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) -{ - int rc = SEPOL_ERR; - struct cil_args_resolve *args = extra_args; - uint32_t *changed = args->changed; - - if (node == NULL || finished == NULL) { - goto exit; - } - - if (node->flavor < CIL_MIN_DECLARATIVE) { - /* only declarative statements need to be disabled */ - rc = SEPOL_OK; - goto exit; - } - - if (node->flavor == CIL_OPTIONAL) { - if (((struct cil_symtab_datum *)node->data)->state == CIL_STATE_DISABLED) { - /* don't bother going into an optional that isn't enabled */ - *finished = CIL_TREE_SKIP_HEAD; - rc = SEPOL_OK; - goto exit; - } - } else { - /* Do we need to reset for a block? */ - *changed = 1; - } - - ((struct cil_symtab_datum *)node->data)->state = CIL_STATE_DISABLED; - - return SEPOL_OK; - -exit: - return rc; -} - int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; @@ -3369,16 +3369,9 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext } else if (parent->flavor == CIL_OPTIONAL) { struct cil_tree_node *optstack; - if (((struct cil_optional *)parent->data)->datum.state == CIL_STATE_DISABLING) { - /* go into the optional, removing everything that it added */ - if (args->pass >= CIL_PASS_CALL1) { - rc = cil_tree_walk(parent, __cil_disable_children_helper, NULL, NULL, extra_args); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to disable declarations in optional\n"); - goto exit; - } - } - ((struct cil_optional *)parent->data)->datum.state = CIL_STATE_DISABLED; + if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { + *(args->changed) = CIL_TRUE; + cil_tree_children_destroy(parent); } /* pop off the stack */ @@ -3527,255 +3520,158 @@ exit: return rc; } -static int __cil_resolve_name_helper(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) +static int __cil_resolve_name_with_root(struct cil_db *db, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { - struct cil_args_resolve *args = extra_args; - struct cil_call *call = NULL; - struct cil_tree_node *macro = NULL; - enum cil_pass pass = CIL_PASS_INIT; + symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; + return cil_symtab_get_datum(symtab, name, datum); +} + +static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) +{ int rc = SEPOL_ERR; - char* name_dup = cil_strdup(name); - char *tok_current = strtok(name_dup, "."); - char *tok_next = strtok(NULL, "."); symtab_t *symtab = NULL; - struct cil_symtab_datum *tmp_datum = NULL; - enum cil_flavor flavor = CIL_NONE; - if (args != NULL) { - if (args->callstack != NULL) { - call = args->callstack->data; - } - pass = args->pass; - macro = args->macro; - } - - if (ast_node->flavor == CIL_ROOT) { - symtab = &((struct cil_root *)ast_node->data)->symtab[CIL_SYM_BLOCKS]; - } else { - if (call != NULL) { - // check macro symtab - symtab = &call->macro->symtab[CIL_SYM_BLOCKS]; - rc = cil_symtab_get_datum(symtab, tok_current, datum); - if (rc == SEPOL_OK) { - flavor = ((struct cil_tree_node*)(*datum)->nodes->head->data)->flavor; - if (flavor != CIL_BLOCK) { - printf("Failed to get block from symtab\n"); - rc = SEPOL_ERR; - goto exit; - } - // if in macro, check call parent to verify successful copy to call - rc = cil_get_symtab(ast_node->parent->parent, &symtab, CIL_SYM_BLOCKS); - if (rc == SEPOL_OK) { - rc = cil_symtab_get_datum(symtab, tok_current, datum); - flavor = ((struct cil_tree_node*)(*datum)->nodes->head->data)->flavor; - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get datum from parent symtab of call\n"); - goto exit; - } else if (flavor != CIL_BLOCK) { - printf("Failed to get block from symtab\n"); - rc = SEPOL_ERR; - goto exit; - } - } else { - cil_log(CIL_ERR, "Failed to get symtab from call parent\n"); - goto exit; - } - } else if (rc == SEPOL_ENOENT) { - rc = cil_get_symtab(((struct cil_tree_node*)call->macro->datum.nodes->head->data)->parent, &symtab, CIL_SYM_BLOCKS); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get datum from parent symtab of macro\n"); - goto exit; - } - } else { - goto exit; - } - - } else { - if (ast_node->flavor == CIL_TUNABLEIF && macro != NULL) { - rc = cil_get_symtab(macro->parent, &symtab, CIL_SYM_BLOCKS); - } else { - rc = cil_get_symtab(ast_node->parent, &symtab, CIL_SYM_BLOCKS); - } + while (node != NULL && rc != SEPOL_OK) { + switch (node->flavor) { + case CIL_ROOT: + goto exit; + break; + case CIL_BLOCK: + symtab = &((struct cil_block*)node->data)->symtab[sym_index]; + rc = cil_symtab_get_datum(symtab, name, datum); + break; + case CIL_BLOCKINHERIT: { + struct cil_blockinherit *inherit = node->data; + rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get parent symtab, rc: %d\n", rc); + /* Continue search in original block's parent */ + rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum); goto exit; } } - } - - if (tok_next == NULL) { - /*TODO: Should this set rc to SEPOL_ERR? */ - /* Cant this be done earlier */ - goto exit; - } - - while (tok_current != NULL) { - if (tok_next != NULL) { - rc = cil_symtab_get_datum(symtab, tok_current, &tmp_datum); - if (rc == SEPOL_OK) { - flavor = ((struct cil_tree_node*)tmp_datum->nodes->head->data)->flavor; - } else { - goto exit; - } - - if ((flavor != CIL_BLOCK && ast_node->flavor != CIL_IN) || - (flavor == CIL_BLOCK && (((struct cil_block*)tmp_datum)->is_abstract == CIL_TRUE && pass > CIL_PASS_BLKABS ))) { - printf("Failed to resolve block: %s\n", tok_current); - rc = SEPOL_ERR; - goto exit; - } - symtab = &(((struct cil_block*)tmp_datum)->symtab[CIL_SYM_BLOCKS]); - } else { - //cil_log(CIL_ERR, "type key: %s\n", tok_current); - symtab = &(((struct cil_block*)tmp_datum)->symtab[sym_index]); - rc = cil_symtab_get_datum(symtab, tok_current, &tmp_datum); + break; + case CIL_MACRO: { + struct cil_macro *macro = node->data; + symtab = ¯o->symtab[sym_index]; + rc = cil_symtab_get_datum(symtab, name, datum); + } + break; + case CIL_CALL: { + struct cil_call *call = node->data; + rc = cil_resolve_name_call_args(call, name, sym_index, datum); if (rc != SEPOL_OK) { - goto exit; + /* Continue search in macro's parent */ + rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum); } } - tok_current = tok_next; - tok_next = strtok(NULL, "."); - } - *datum = tmp_datum; - free(name_dup); + break; + case CIL_IN: + /* In block symtabs only exist before resolving the AST */ + case CIL_CONDBLOCK: + /* Cond block symtabs only exist before resolving the AST */ + default: + break; + } - return SEPOL_OK; + node = node->parent; + } exit: - free(name_dup); + return rc; +} + +static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) +{ + int rc = SEPOL_ERR; + + rc = __cil_resolve_name_with_parents(node, name, sym_index, datum); + if (rc != SEPOL_OK) { + rc = __cil_resolve_name_with_root(db, name, sym_index, datum); + } return rc; } int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) { - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; - struct cil_call *call = NULL; - struct cil_tree_node *node = NULL; - struct cil_tree_node *macro = NULL; - struct cil_tree_node *namespace = NULL; int rc = SEPOL_ERR; - char *global_symtab_name = NULL; - char first; + struct cil_args_resolve *args = extra_args; + struct cil_db *db = args->db; + struct cil_tree_node *node = NULL; - if (args != NULL) { - db = args->db; - if (args->callstack != NULL) { - call = args->callstack->data; - } - macro = args->macro; - } - - if (db == NULL || ast_node == NULL || name == NULL) { + if (name == NULL) { cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n"); goto exit; } - global_symtab_name = name; - first = *name; + *datum = NULL; - if (first != '.') { - if (strrchr(name, '.') == NULL) { - symtab_t *symtab = NULL; - if (call != NULL) { - namespace = ast_node; - while (namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_CALL) { - namespace = namespace->parent; - } - if (namespace->flavor == CIL_BLOCK) { - rc = cil_get_symtab(namespace, &symtab, sym_index); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get parent symtab\n"); - goto exit; - } - } else { - symtab = &call->macro->symtab[sym_index]; - rc = cil_symtab_get_datum(symtab, name, datum); - if (rc == SEPOL_OK) { - rc = cil_get_symtab(namespace, &symtab, sym_index); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get parent symtab from call\n"); - goto exit; - } - } - } - - rc = cil_symtab_get_datum(symtab, name, datum); - if (rc != SEPOL_OK) { - rc = cil_resolve_name_call_args(call, name, sym_index, datum); - if (rc == SEPOL_OK) { - goto exit; - } - - rc = cil_get_symtab(((struct cil_tree_node*)call->macro->datum.nodes->head->data)->parent, &symtab, sym_index); - if (rc != SEPOL_OK) { - goto exit; - } - - rc = cil_symtab_get_datum(symtab, name, datum); - if (rc == SEPOL_OK) { - goto exit; - } - - global_symtab_name = cil_malloc(strlen(name)+2); - strcpy(global_symtab_name, "."); - strncat(global_symtab_name, name, strlen(name)); - } + if (strchr(name,'.') == NULL) { + /* No '.' in name */ + rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum); + if (rc != SEPOL_OK) { + goto exit; + } + } else { + char *sp = NULL; + char *name_dup = cil_strdup(name); + char *current = strtok_r(name_dup, ".", &sp); + char *next = strtok_r(NULL, ".", &sp); + symtab_t *symtab = NULL; + + node = ast_node; + if (*name == '.') { + /* Leading '.' */ + symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_BLOCKS]; + } else { + rc = __cil_resolve_name_helper(db, node->parent, current, CIL_SYM_BLOCKS, datum); + if (rc != SEPOL_OK) { + free(name_dup); + goto exit; + } + symtab = (*datum)->symtab; + } + /* Keep looking up blocks by name until only last part of name remains */ + while (next != NULL) { + rc = cil_symtab_get_datum(symtab, current, datum); + if (rc != SEPOL_OK) { + free(name_dup); + goto exit; + } + node = NODE(*datum); + if (node->flavor == CIL_BLOCK) { + symtab = &((struct cil_block*)node->data)->symtab[CIL_SYM_BLOCKS]; } else { - if (ast_node->flavor == CIL_TUNABLEIF && macro != NULL) { - rc = cil_get_symtab(macro->parent, &symtab, sym_index); - } else { - rc = cil_get_symtab(ast_node->parent, &symtab, sym_index); - } - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to get parent symtab, rc: %d\n", rc); + if (ast_node->flavor != CIL_IN) { + cil_log(CIL_WARN, "Can only use %s name for name resolution in \"in\" blocks\n", cil_node_to_string(node)); + free(name_dup); + rc = SEPOL_ERR; goto exit; } - rc = cil_symtab_get_datum(symtab, name, datum); - if (rc != SEPOL_OK) { - global_symtab_name = cil_malloc(strlen(name)+2); - strcpy(global_symtab_name, "."); - strncat(global_symtab_name, name, strlen(name)); + if (node->flavor == CIL_MACRO) { + struct cil_macro *macro = node->data; + symtab = ¯o->symtab[sym_index]; + } else { + /* optional */ + symtab = (*datum)->symtab; } } - } else { - rc = __cil_resolve_name_helper(ast_node, name, sym_index, args, datum); - if (rc != SEPOL_OK) { - global_symtab_name = cil_malloc(strlen(name)+2); - strcpy(global_symtab_name, "."); - strncat(global_symtab_name, name, strlen(name)); - } + current = next; + next = strtok_r(NULL, ".", &sp); + } + symtab = &(symtab[sym_index]); + rc = cil_symtab_get_datum(symtab, current, datum); + free(name_dup); + if (rc != SEPOL_OK) { + goto exit; } } - first = *global_symtab_name; - - if (first == '.') { - if (strrchr(global_symtab_name, '.') == global_symtab_name) { //Only one dot in name, check global symtabs - symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; - rc = cil_symtab_get_datum(symtab, global_symtab_name+1, datum); - if (rc != SEPOL_OK) { - free(global_symtab_name); - goto exit; - } - } else { - rc = __cil_resolve_name_helper(db->ast->root, global_symtab_name, sym_index, args, datum); - if (rc != SEPOL_OK) { - free(global_symtab_name); - goto exit; - } - } - } - - if (global_symtab_name != name) { - free(global_symtab_name); - } - rc = SEPOL_OK; exit: if (rc != SEPOL_OK) { + *datum = NULL; cil_log(CIL_WARN, "Failed to resolve %s in %s statement on line %d of %s\n", name, cil_node_to_string(ast_node), ast_node->line, ast_node->path); } @@ -3784,7 +3680,7 @@ exit: /* If this datum is an alias, then return the actual node * This depends on aliases already being processed */ - node = (*datum)->nodes->head->data; + node = NODE(*datum); if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS || node->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)(*datum); diff --git a/src/cil_symtab.c b/src/cil_symtab.c index f9093575..3769979b 100644 --- a/src/cil_symtab.c +++ b/src/cil_symtab.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -39,10 +40,14 @@ #include "cil_symtab.h" #include "cil_mem.h" #include "cil_strpool.h" +#include "cil_log.h" -__attribute__((noreturn)) void cil_symtab_error(const char* msg) +__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_symtab_error(const char* msg, ...) { - cil_log(CIL_ERR, "%s\n",msg); + va_list ap; + va_start(ap, msg); + cil_vlog(CIL_ERR, msg, ap); + va_end(ap); exit(1); } @@ -57,13 +62,25 @@ void cil_symtab_init(symtab_t *symtab, unsigned int size) void cil_symtab_datum_init(struct cil_symtab_datum *datum) { datum->name = NULL; + datum->fqn = NULL; + datum->symtab = NULL; cil_list_init(&datum->nodes, CIL_LIST_ITEM); - datum->state = CIL_STATE_ENABLED; } void cil_symtab_datum_destroy(struct cil_symtab_datum *datum) { cil_list_destroy(&datum->nodes, 0); + cil_symtab_remove_datum(datum); +} + +void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node) +{ + if (datum && datum->nodes != NULL) { + cil_list_remove(datum->nodes, CIL_NODE, node, 0); + if (datum->nodes->head == NULL) { + cil_symtab_datum_destroy(datum); + } + } } /* This both initializes the datum and inserts it into the symtab. @@ -73,6 +90,8 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat int rc = hashtab_insert(symtab->table, key, (hashtab_datum_t)datum); if (rc == SEPOL_OK) { datum->name = key; + datum->fqn = key; + datum->symtab = symtab; cil_list_append(datum->nodes, CIL_NODE, node); } else if (rc == SEPOL_EEXIST) { cil_list_append(datum->nodes, CIL_NODE, node); @@ -83,36 +102,22 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat return rc; } -void cil_symtab_remove_datum_destroy(__attribute__((unused))hashtab_key_t key, hashtab_datum_t datum, __attribute__((unused))void *args) +void cil_symtab_remove_datum(struct cil_symtab_datum *datum) { - cil_symtab_datum_destroy((struct cil_symtab_datum *)datum); - free(datum); -} + symtab_t *symtab = datum->symtab; -void cil_symtab_datum_remove(struct cil_symtab_datum *datum, struct cil_tree_node *node) -{ - if (datum->nodes != NULL) { - struct cil_list_item *item; - struct cil_list_item *previous = NULL; - cil_list_for_each(item, datum->nodes) { - if (item->data == node) { - if (previous == NULL) { - datum->nodes->head = item->next; - } else { - previous->next = item->next; - } - cil_list_item_destroy(&item, 0); - break; - } - previous = item; - } + if (symtab == NULL) { + return; } + + hashtab_remove(symtab->table, datum->name, NULL, NULL); + datum->symtab = NULL; } int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum) { *datum = (struct cil_symtab_datum*)hashtab_search(symtab->table, (hashtab_key_t)key); - if (*datum == NULL || (*datum)->state != CIL_STATE_ENABLED) { + if (*datum == NULL) { return SEPOL_ENOENT; } @@ -126,9 +131,17 @@ int cil_symtab_map(symtab_t *symtab, return hashtab_map(symtab->table, apply, args); } +static int __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, __attribute__((unused)) void *args) +{ + struct cil_symtab_datum *datum = d; + datum->symtab = NULL; + return SEPOL_OK; +} + void cil_symtab_destroy(symtab_t *symtab) { if (symtab->table != NULL){ + cil_symtab_map(symtab, __cil_symtab_destroy_helper, NULL); hashtab_destroy(symtab->table); symtab->table = NULL; } diff --git a/src/cil_symtab.h b/src/cil_symtab.h index 25b0f8b7..efb63e7b 100644 --- a/src/cil_symtab.h +++ b/src/cil_symtab.h @@ -35,13 +35,11 @@ #include "cil_tree.h" -#define CIL_STATE_ENABLED 1 -#define CIL_STATE_DISABLED 2 -#define CIL_STATE_DISABLING 3 struct cil_symtab_datum { struct cil_list *nodes; char *name; - int state; + char *fqn; + symtab_t *symtab; }; #define DATUM(d) ((struct cil_symtab_datum *)(d)) @@ -75,8 +73,9 @@ struct cil_complex_symtab { void cil_symtab_init(symtab_t *symtab, unsigned int size); void cil_symtab_datum_init(struct cil_symtab_datum *datum); void cil_symtab_datum_destroy(struct cil_symtab_datum *datum); +void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node); int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node); -void cil_symtab_datum_remove(struct cil_symtab_datum *datum, struct cil_tree_node *node); +void cil_symtab_remove_datum(struct cil_symtab_datum *datum); int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum); int cil_symtab_map(symtab_t *symtab, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), diff --git a/src/cil_tree.c b/src/cil_tree.c index 7777bb98..4f9f480b 100644 --- a/src/cil_tree.c +++ b/src/cil_tree.c @@ -28,6 +28,7 @@ */ #include +#include #include @@ -48,12 +49,20 @@ void cil_tree_print_expr_tree(struct cil_tree_node *expr_root); void cil_tree_print_constrain(struct cil_constrain *cons); void cil_tree_print_node(struct cil_tree_node *node); +__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...) +{ + va_list ap; + va_start(ap, msg); + cil_vlog(CIL_ERR, msg, ap); + va_end(ap); + exit(1); +} + int cil_tree_init(struct cil_tree **tree) { struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); cil_tree_node_init(&new_tree->root); - cil_root_init((struct cil_root **)&new_tree->root->data); *tree = new_tree; @@ -126,14 +135,16 @@ void cil_tree_node_init(struct cil_tree_node **node) void cil_tree_node_destroy(struct cil_tree_node **node) { + struct cil_symtab_datum *datum; + if (node == NULL || *node == NULL) { return; } if ((*node)->flavor >= CIL_MIN_DECLARATIVE) { - cil_symtab_datum_remove((*node)->data, *node); - struct cil_symtab_datum *datum = (*node)->data; - if (datum->nodes != NULL && datum->nodes->head == NULL) { + datum = (*node)->data; + cil_symtab_datum_remove_node(datum, *node); + if (datum->nodes == NULL) { cil_destroy_data(&(*node)->data, (*node)->flavor); } } else { diff --git a/src/cil_verify.c b/src/cil_verify.c index a1576e76..03e0fd19 100644 --- a/src/cil_verify.c +++ b/src/cil_verify.c @@ -1263,7 +1263,6 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex int *handleunknown; int *mls; int *nseuserdflt = 0; - int state = 0; int *pass = 0; struct cil_args_verify *args = extra_args; struct cil_complex_symtab *csymtab = NULL; @@ -1281,14 +1280,7 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex csymtab = args->csymtab; pass = args->pass; - if (node->flavor == CIL_OPTIONAL) { - state = ((struct cil_symtab_datum *)node->data)->state; - if (state == CIL_STATE_DISABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - rc = SEPOL_OK; - goto exit; - } else if (node->flavor == CIL_MACRO) { + if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; @@ -1519,14 +1511,7 @@ static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, ui { int rc = SEPOL_ERR; - if (node->flavor == CIL_OPTIONAL) { - int state = ((struct cil_symtab_datum *)node->data)->state; - if (state == CIL_STATE_DISABLED) { - *finished = CIL_TREE_SKIP_HEAD; - } - rc = SEPOL_OK; - goto exit; - } else if (node->flavor == CIL_MACRO) { + if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; diff --git a/test/block_test.cil b/test/block_test.cil new file mode 100644 index 00000000..2dfcb899 --- /dev/null +++ b/test/block_test.cil @@ -0,0 +1,126 @@ +;; Minimum stuff +(class CLASS (PERM)) +(classorder (CLASS)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) +;; Extra stuff +(common COMMON (PERM1 PERM2 PERM3 PERM4)) +(classcommon CLASS COMMON) + + +;; Tests 1 and 2 show that the order of inheritance matters +;; +(block b1 + (type ta)) + +(block b1a + (block b1 + (type tb))) + +(block b1b + (blockinherit b1) ;; Results in b1b.ta + (blockinherit b1a)) + + +(block b2 + (type ta)) + +(block b2a + (block b2 + (type tb))) + +(block b2b + (blockinherit b2a) + (blockinherit b2)) + + +;; All of these work +(block b3a + (type t3a) + (block b + (type t) + (allow t3a t (CLASS (PERM))) + ) +) + +(block b3b + (blockinherit b3a) +) + +(block b3c + (blockinherit b3a.b) +) + +(block b3d + (type t3a) + (blockinherit b3a) +) + +(block b3e + (type t3a) + (blockinherit b3a.b) +) + + +;; Since block is abstract, allow rule will not be in policy +(type t4) +(block b4 + (blockabstract b4) + (allow t4 self (CLASS (PERM))) +) + + +;; Inherting the abstract block causes the allow rule to be in the policy +(type t5) +(block b5 + (blockabstract b5) + (allow t5 self (CLASS (PERM))) +) +(blockinherit b5) + + +;; A sub-block can be inherited out of an abstract block +(type t6) +(block b6 + (blockabstract b6) + (allow t6 self (CLASS (PERM1))) + (block b + (blockabstract b) + (allow t6 self (CLASS (PERM))) + ) +) +(blockinherit b6.b) + +;; +;; Expected: +;; +;; Types: +;; b1.ta, b1a.b1.tb, b1b.b1.tb, b1b.ta +;; b2.ta, b2a.b2.tb, b2b.b2.tb, b2b.ta +;; b3a.b.t, b3a.t3a, b3b.b.t, b3b.t3a, b3c.t, b3d.b.t, b3d.t3a, b3e.t, b3e.t3a +;; t4 +;; t5 +;; t6 +;; +;; Allow rules: +;; allow b3a.t3a b3a.b.t : CLASS { PERM }; +;; allow b3a.t3a b3c.t : CLASS { PERM }; +;; allow b3b.t3a b3b.b.t : CLASS { PERM }; +;; allow b3d.t3a b3d.b.t : CLASS { PERM }; +;; allow b3e.t3a b3e.t : CLASS { PERM }; +;; allow t5 t5 : CLASS { PERM }; +;; allow t6 t6 : CLASS { PERM }; \ No newline at end of file diff --git a/test/in_test.cil b/test/in_test.cil new file mode 100644 index 00000000..62cc733a --- /dev/null +++ b/test/in_test.cil @@ -0,0 +1,142 @@ +;; Minimum stuff +(class CLASS (PERM)) +(classorder (CLASS)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) +;; Extra stuff +(common COMMON (PERM1 PERM2 PERM3 PERM4)) +(classcommon CLASS COMMON) + + +;; Check that "in" statements work in blocks +(block b1 + (type t1a) + (allow t1b self (CLASS (PERM1))) +) + +(in b1 + (type t1b) + (allow t1a self (CLASS (PERM1))) +) + +(in b1 + (allow t1a self (CLASS (PERM2))) + (allow b1.t1a self (CLASS (PERM3))) + (allow .b1.t1a self (CLASS (PERM4))) + + (allow t1b self (CLASS (PERM2))) + (allow b1.t1b self (CLASS (PERM3))) + (allow .b1.t1b self (CLASS (PERM4))) +) + + +;; Check that "in" statements work in optionals +(optional option2 + (type t2a) + (allow t2b self (CLASS (PERM1))) +) + +(in option2 + (type t2b) + (allow t2a self (CLASS (PERM1))) +) + +(in option2 + (allow t2a self (CLASS (PERM2))) + (allow t2b self (CLASS (PERM2))) +) + +(allow t2a self (CLASS (PERM3))) +(allow t2b self (CLASS (PERM3))) + + +;; Check that "in" statements work in macros +(type t3a) +(type t3b) +(macro m3 ((type t)) + (allow t3a self (CLASS (PERM1))) + (allow t self (CLASS (PERM1))) +) + +(call m3 (t3b)) + +(in m3 + (allow t3a self (CLASS (PERM2))) +) + +(in m3 + (allow t self (CLASS (PERM3))) +) + + +;; Check "in" statements work for nested optionals +(optional o4a + (optional o4b + (type t4b) + (allow t4b self (CLASS (PERM1))) + ) +) + +(in o4a.o4b + (allow t4b self (CLASS (PERM2))) +) + + +;; Check "in: statements work for nested optionals and macros +(macro m5 () + (type t5a) + (type t5b) + (optional o5a + (allow t5a self (CLASS (PERM1))) + (optional o5b + (allow t5b self (CLASS (PERM1))) + ) + ) +) + +(call m5) + +(in m5.o5a + (allow t5a self (CLASS (PERM2))) +) + +(in m5.o5a.o5b + (allow t5b self (CLASS (PERM2))) +) + + +;; +;; Expected: +;; +;; Types: +;; b1.t1a, b1.t1b +;; t2a, t2b +;; t3a, t3b +;; t4b +;; t5a, t5b +;; +;; Allow rules: +;; allow b1.t1a b1.t1a : CLASS { PERM1 PERM2 PERM3 PERM4 }; +;; allow b1.t1b b1.t1b : CLASS { PERM1 PERM2 PERM3 PERM4 }; +;; allow t2a t2a : CLASS { PERM1 PERM2 PERM3 }; +;; allow t2b t2b : CLASS { PERM1 PERM2 PERM3 }; +;; allow t3a t3a : CLASS { PERM1 PERM2 }; +;; allow t3b t3b : CLASS { PERM1 PERM3 }; +;; allow t4b t4b : CLASS { PERM1 PERM2 }; +;; allow t5a t5a : CLASS { PERM1 PERM2 }; +;; allow t5b t5b : CLASS { PERM1 PERM2 }; + diff --git a/test/minimum.cil b/test/minimum.cil new file mode 100644 index 00000000..9bd752e0 --- /dev/null +++ b/test/minimum.cil @@ -0,0 +1,18 @@ +(class CLASS (PERM)) +(classorder (CLASS)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) \ No newline at end of file diff --git a/test/name_resolution_test.cil b/test/name_resolution_test.cil new file mode 100644 index 00000000..8d0664fe --- /dev/null +++ b/test/name_resolution_test.cil @@ -0,0 +1,172 @@ +;; Minimum stuff +(class CLASS (PERM)) +(classorder (CLASS)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) +;; Extra stuff +(common COMMON (PERM1 PERM2 PERM3 PERM4)) +(classcommon CLASS COMMON) + + +;; Check global resolution +(type t0) +(allow t0 self (CLASS (PERM1))) +(allow .t0 self (CLASS (PERM2))) + + +;; Check block and sub-block resolution +(block b1a + (type t1a) + (allow t1a self (CLASS (PERM))) + (allow b1b.t1b self (CLASS (PERM))) + (block b1b + (type t1b) + (allow t1a self (CLASS (PERM1))) + (allow t1b self (CLASS (PERM1))) + (allow .b1a.t1a self (CLASS (PERM2))) + (allow .b1a.b1b.t1b self (CLASS (PERM2))) + ) +) +(allow b1a.t1a self (CLASS (PERM3))) +(allow b1a.b1b.t1b self (CLASS (PERM3))) +(allow .b1a.t1a self (CLASS (PERM4))) +(allow .b1a.b1b.t1b self (CLASS (PERM4))) + + +;; Check macro arg resolution +(type t2) +(macro m2 ((type t)) + (allow t self (CLASS (PERM))) +) +(call m2 (t2)) + + +;; Check resolution for a macro with a parent decl +(block b3 + (type t3) + (macro m3 () + (allow t3 self (CLASS (PERM))) + ) +) +(call b3.m3) + + +;; Check resolution for a macro with a caller decl +(block b4 + (block b4a + (macro m4 () + (allow t4 self (CLASS (PERM))) + ) + ) + (block b4b + (type t4) + (call .b4.b4a.m4) + ) +) + + +;; Check resolution for blockinherits with type in inheriting block +(block b5a + (type t5a) + (block b5b + (allow t5a self (CLASS (PERM1))) + ) +) + +(block b5c + (type t5a) + (blockinherit b5a.b5b) + (allow t5a self (CLASS (PERM2))) +) + +;; Check resolution for blockinherits with no type in inheriting block +(block b6a + (type t6a) + (block b6b + (allow t6a self (CLASS (PERM1))) + ) +) + +(block b6c + (blockinherit b6a.b6b) ;; This does not cause an error. + ;;(allow t6a self (CLASS (PERM2))) ;; This causes an error +) + + +;; Check for proper resolution of t +(block b7 + (type t) + (macro m7 ((type t)) + (allow t self (CLASS (PERM))) + ) + (allow t self (CLASS (PERM1))) + (block b7a + (type t) + (allow t self (CLASS (PERM2))) + (block b7b + (type t) + (allow t self (CLASS (PERM3))) + (call m7 (t)) + ) + ) +) + + +;; Check that improper name causes an error +(block b8 + (optional o8a + (type t8a) + ) + (in o8a + (allow t8a self (CLASS (PERM1))) + ) + ;;(allow o8a.t8a self (CLASS (PERM))) ;; Bad name + (macro m8 ((type t)) + (allow t self (CLASS (PERM1))) + ) + ;;(allow m8.t self (CLASS (PERM))) ;; Bad name +) + + +;; +;; Expected: +;; +;; Types: +;; t0 +;; b1a.t1a, b1a.b1b.t1b +;; t2 +;; b3.t3 +;; b4.b4b.t4 +;; b5a.t5a, b5c.t5a +;; b6a.t6a +;; b7.t, b7.b7a.t, b7.b7a.b7b.t +;; b8.t8a +;; +;; Allow rules: +;; allow t0 t0 : CLASS { PERM1 PERM2 }; +;; allow b1a.b1b.t1b b1a.b1b.t1b : CLASS { PERM PERM1 PERM2 PERM3 PERM4 }; +;; allow b1a.t1a b1a.t1a : CLASS { PERM PERM1 PERM2 PERM3 PERM4 }; +;; allow t2 t2 : CLASS { PERM }; +;; allow b3.t3 b3.t3 : CLASS { PERM }; +;; allow b4.b4b.t4 b4.b4b.t4 : CLASS { PERM }; +;; allow b5a.t5a b5a.t5a : CLASS { PERM1 }; +;; allow b5c.t5a b5c.t5a : CLASS { PERM1 PERM2 }; +;; allow b6a.t6a b6a.t6a : CLASS { PERM1 }; +;; allow b7.b7a.b7b.t b7.b7a.b7b.t : CLASS { PERM PERM3 }; +;; allow b7.b7a.t b7.b7a.t : CLASS { PERM2 }; +;; allow b7.t b7.t : CLASS { PERM1 }; +;; allow b8.t8a b8.t8a : CLASS { PERM1 }; diff --git a/test/optional_test.cil b/test/optional_test.cil new file mode 100644 index 00000000..64d7930c --- /dev/null +++ b/test/optional_test.cil @@ -0,0 +1,78 @@ +;; Minimum stuff +(class CLASS (PERM)) +(classorder (CLASS)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) +;; Extra stuff +(common COMMON (PERM1 PERM2 PERM3 PERM4)) +(classcommon CLASS COMMON) + + +;; Check resolution failure handling for optionals +(type t1) +(optional o1 + (allow t1 self (CLASS (PERM))) ;; Should not appear in policy + (allow UNKNOWN self (CLASS (PERM))) +) + + +;; These should not cause an error +(block b2a + (type t2) + (allow t2 self (CLASS (PERM1))) +) + +(block b2b + (optional o2b + (type t2) + (allow t2 DNE (CLASS (PERM))) + ) + (blockinherit b2a) +) + +(block b2c + (optional o2c + (type t2) + (allow t2 self (CLASS (PERM))) + ) + (blockinherit b2a) +) + + +;; This is not allowed +;;(block b3 +;; (optional o3 +;; (type t3) +;; (allow t3 DNE (CLASS (PERM))) +;; ) +;; (type t3) +;; (allow t3 self (CLASS (PERM1))) +;;) + + +;; +;; Expected: +;; +;; Types: +;; t1 +;; b2a.t2, b2b.t2, b2c.t2 +;; +;; Allow rules: +;; allow b2a.t2 b2a.t2 : CLASS { PERM1 }; +;; allow b2b.t2 b2b.t2 : CLASS { PERM1 }; +;; allow b2c.t2 b2c.t2 : CLASS { PERM PERM1 }; +