libsepol/cil: Keep attributes used by generated attributes in neverallow rules

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@tycho.nsa.gov>
This commit is contained in:
James Carter 2017-08-30 14:22:28 -04:00
parent fafe4c212b
commit 67b410e80f
1 changed files with 57 additions and 0 deletions

View File

@ -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");