In order to reduce policy size, CIL removes attributes that are not used by a policy rule in the generated binary policy. However, CIL keeps attributes used by neverallow rules (which are checked at compile time and not in the binary policy) even if the attribute is not used anywhere else in the policy. This behavior is useful to Google who pulls neverallow rules out of the original policy.conf for compatibility testing, but converts the policy.conf to CIL and uses the CIL compiler to generate policy. Without this behavior, the generated binary policy might not have an attribute referred to by one of the neverallow rules used for testing. The one exception to this behavior is for attributes generated in module_to_cil (these have an "_typeattr_" in the middle of their name). Since these attributes are only created because CIL does not allow a type expression in an AV rule, they are removed if they only appear in a neverallow rule (which is the case for most of them) or if the option to expand generated attributes (-G or --expand-generated) is specified for secilc when compiling the policy. Removing generated attributes causes a problem, however, if the type expression that the generated attribute is replacing uses an attribute that is removed. In this case, the original neverallow rule will refer to an attribute that does not exist in the generated binary policy. Now any non-generated attribute used in a typeattributeset rule for a generated attribute which is used in a neverallow rule will be treated like it was used in a neverallow rule. This does not change the behavior of an expandtypeattribute rule for the attribute. That rule, if it exists, will take precedence. Signed-off-by: James Carter <jwcart2@xxxxxxxxxxxxx> --- libsepol/cil/src/cil_post.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c index ad073e8..ee693d4 100644 --- a/libsepol/cil/src/cil_post.c +++ b/libsepol/cil/src/cil_post.c @@ -1297,6 +1297,57 @@ static int cil_typeattribute_used(struct cil_typeattribute *attr, struct cil_db return CIL_TRUE; } +static void __mark_neverallow_attrs(struct cil_list *expr_list) +{ + struct cil_list_item *curr; + + cil_list_for_each(curr, expr_list) { + if (curr->flavor == CIL_DATUM) { + if (NODE(curr->data)->flavor == CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *attr = curr->data; + if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { + __mark_neverallow_attrs(attr->expr_list); + } else { + attr->used |= CIL_ATTR_NEVERALLOW; + } + } + } else if (curr->flavor == CIL_LIST) { + __mark_neverallow_attrs(curr->data); + } + } +} + +static int __cil_post_db_neverallow_attr_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) +{ + struct cil_db *db = extra_args; + + switch (node->flavor) { + case CIL_BLOCK: { + struct cil_block *blk = node->data; + if (blk->is_abstract == CIL_TRUE) { + *finished = CIL_TREE_SKIP_HEAD; + } + break; + } + case CIL_MACRO: { + *finished = CIL_TREE_SKIP_HEAD; + break; + } + case CIL_TYPEATTRIBUTE: { + struct cil_typeattribute *attr = node->data; + if ((attr->used & CIL_ATTR_NEVERALLOW) && + strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { + __mark_neverallow_attrs(attr->expr_list); + } + break; + } + default: + break; + } + + return SEPOL_OK; +} + static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; @@ -2031,6 +2082,12 @@ static int cil_post_db(struct cil_db *db) goto exit; } + rc = cil_tree_walk(db->ast->root, __cil_post_db_neverallow_attr_helper, NULL, NULL, db); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failed to mark attributes used by generated attributes used in neverallow rules\n"); + goto exit; + } + rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to create attribute bitmaps\n"); -- 2.9.5