Skip to content

Commit

Permalink
libsepol/cil: add support for segregate attributes
Browse files Browse the repository at this point in the history
Support the compile time constraint with the following syntax:

    (disjointattributes (attr1 attr2 [...]))

and reports like:

    ...
    Qualifying Names
    Compile post process
    Building policy binary
    Checking Neverallows
    Checking Segregate Attributes
    Disjoint Attributes Rule violation, type test_type associated with attributes attr1 attr2
    Checking User Bounds
    Checking Role Bounds
    Checking Type Bounds
    Failed to generate binary
    Failed to build policydb

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v4:
   rename to disjointattributes
  • Loading branch information
cgzones committed Apr 29, 2024
1 parent fbf66c0 commit d9a1b82
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 0 deletions.
17 changes: 17 additions & 0 deletions libsepol/cil/src/cil.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ char *CIL_KEY_SRC_HLL_LMS;
char *CIL_KEY_SRC_HLL_LMX;
char *CIL_KEY_SRC_HLL_LME;
char *CIL_KEY_DENY_RULE;
char *CIL_KEY_DISJOINTATTRIBUTES;

static void cil_init_keys(void)
{
Expand Down Expand Up @@ -400,6 +401,7 @@ static void cil_init_keys(void)
CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx");
CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme");
CIL_KEY_DENY_RULE = cil_strpool_add("deny");
CIL_KEY_DISJOINTATTRIBUTES = cil_strpool_add("disjointattributes");
}

void cil_db_init(struct cil_db **db)
Expand Down Expand Up @@ -432,6 +434,7 @@ void cil_db_init(struct cil_db **db)
cil_list_init(&(*db)->userprefixes, CIL_LIST_ITEM);
cil_list_init(&(*db)->selinuxusers, CIL_LIST_ITEM);
cil_list_init(&(*db)->declared_strings, CIL_LIST_ITEM);
cil_list_init(&(*db)->disjointattributes, CIL_LIST_ITEM);

cil_type_init(&(*db)->selftype);
(*db)->selftype->datum.name = CIL_KEY_SELF;
Expand Down Expand Up @@ -504,6 +507,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->fsuse);
cil_list_destroy(&(*db)->userprefixes, CIL_FALSE);
cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE);
cil_list_destroy(&(*db)->disjointattributes, CIL_FALSE);

cil_declared_strings_list_destroy(&(*db)->declared_strings);

Expand Down Expand Up @@ -1084,6 +1088,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_SRC_INFO:
cil_destroy_src_info(*data);
break;
case CIL_DISJOINTATTRIBUTES:
cil_destroy_disjointattributes(*data);
break;
case CIL_OP:
case CIL_CONS_OPERAND:
break;
Expand Down Expand Up @@ -1492,6 +1499,8 @@ const char * cil_node_to_string(struct cil_tree_node *node)
return CIL_KEY_CONS_H1;
case CIL_CONS_H2:
return CIL_KEY_CONS_H2;
case CIL_DISJOINTATTRIBUTES:
return CIL_KEY_DISJOINTATTRIBUTES;

default:
break;
Expand Down Expand Up @@ -2984,3 +2993,11 @@ void cil_src_info_init(struct cil_src_info **info)
(*info)->hll_line = 0;
(*info)->path = NULL;
}

void cil_disjointattributes_init(struct cil_disjointattributes **dattrs)
{
*dattrs = cil_malloc(sizeof(**dattrs));

(*dattrs)->str_expr = NULL;
(*dattrs)->datum_expr = NULL;
}
75 changes: 75 additions & 0 deletions libsepol/cil/src/cil_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -3896,6 +3896,38 @@ static int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange
return SEPOL_ERR;
}

static int cil_disjointattributes_to_policydb(policydb_t *pdb, const struct cil_disjointattributes *dattrs)
{
disjoint_attributes_rule_t *dattr;
struct cil_list_item *curr;
type_datum_t *sepol_type;
int rc = SEPOL_ERR;

dattr = cil_malloc(sizeof(disjoint_attributes_rule_t));
ebitmap_init(&dattr->attrs);

cil_list_for_each(curr, dattrs->datum_expr) {
rc = __cil_get_sepol_type_datum(pdb, DATUM(curr->data), &sepol_type);
if (rc != SEPOL_OK) goto exit;

if (ebitmap_set_bit(&dattr->attrs, sepol_type->s.value - 1, 1)) {
goto exit;
}
}

dattr->next = pdb->disjoint_attributes;
pdb->disjoint_attributes = dattr;

return SEPOL_OK;

exit:
if (dattr) {
ebitmap_destroy(&dattr->attrs);
free(dattr);
}
return rc;
}

static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
{
int rc = SEPOL_OK;
Expand Down Expand Up @@ -4038,6 +4070,9 @@ static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
case CIL_DEFAULTRANGE:
rc = cil_defaultrange_to_policydb(pdb, node->data);
break;
case CIL_DISJOINTATTRIBUTES:
rc = cil_disjointattributes_to_policydb(pdb, node->data);
break;
default:
break;
}
Expand Down Expand Up @@ -4976,6 +5011,42 @@ static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struc
return rc;
}

static int cil_check_disjointattributes(const policydb_t *pdb, int *violation)
{
const disjoint_attributes_rule_t *dattr;

for (dattr = pdb->disjoint_attributes; dattr; dattr = dattr->next) {
ebitmap_node_t *first_node;
unsigned int first_bit;

ebitmap_for_each_positive_bit(&dattr->attrs, first_node, first_bit) {
ebitmap_node_t *second_node;
unsigned int second_bit;

ebitmap_for_each_positive_bit_after(&dattr->attrs, second_node, second_bit, first_node, first_bit) {
ebitmap_t attr_union;
ebitmap_node_t *type_node;
unsigned int type_bit;

if (ebitmap_and(&attr_union, &pdb->attr_type_map[first_bit], &pdb->attr_type_map[second_bit]))
return SEPOL_ERR;

ebitmap_for_each_positive_bit(&attr_union, type_node, type_bit) {
cil_log(CIL_ERR, "Disjoint Attributes Rule violation, type %s associated with attributes %s and %s\n",
pdb->p_type_val_to_name[type_bit],
pdb->p_type_val_to_name[first_bit],
pdb->p_type_val_to_name[second_bit]);
*violation = CIL_TRUE;
}

ebitmap_destroy(&attr_union);
}
}
}

return SEPOL_OK;
}

static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[])
{
struct cil_classperms *cp;
Expand Down Expand Up @@ -5246,6 +5317,10 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
rc = cil_check_neverallows(db, pdb, neverallows, &violation);
if (rc != SEPOL_OK) goto exit;

cil_log(CIL_INFO, "Checking Disjoint Attributes Rules\n");
rc = cil_check_disjointattributes(pdb, &violation);
if (rc != SEPOL_OK) goto exit;

cil_log(CIL_INFO, "Checking User Bounds\n");
rc = bounds_check_users(NULL, pdb);
if (rc) {
Expand Down
58 changes: 58 additions & 0 deletions libsepol/cil/src/cil_build_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -6108,6 +6108,62 @@ void cil_destroy_src_info(struct cil_src_info *info)
free(info);
}

int cil_gen_disjointattributes(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_LIST,
CIL_SYN_END
};
size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_disjointattributes *dattrs = NULL;
int rc = SEPOL_ERR;

if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
}

rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}

cil_disjointattributes_init(&dattrs);

rc = cil_gen_expr(parse_current->next, CIL_TYPEATTRIBUTE, &dattrs->str_expr);
if (rc != SEPOL_OK) {
goto exit;
}

/* require at least two attributes */
if (dattrs->str_expr->head == dattrs->str_expr->tail) {
rc = SEPOL_ERR;
goto exit;
}

ast_node->data = dattrs;
ast_node->flavor = CIL_DISJOINTATTRIBUTES;

return SEPOL_OK;

exit:
cil_tree_log(parse_current, CIL_ERR, "Bad disjoint attributes rule declaration");
cil_destroy_disjointattributes(dattrs);
return rc;
}

void cil_destroy_disjointattributes(struct cil_disjointattributes *dattrs)
{
if (dattrs == NULL) {
return;
}

cil_list_destroy(&dattrs->str_expr, CIL_TRUE);
cil_list_destroy(&dattrs->datum_expr, CIL_FALSE);

free(dattrs);
}

static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
{
if (args->tunif != NULL) {
Expand Down Expand Up @@ -6401,6 +6457,8 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree
rc = cil_gen_mls(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SRC_INFO) {
rc = cil_gen_src_info(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_DISJOINTATTRIBUTES) {
rc = cil_gen_disjointattributes(db, parse_current, new_ast_node);
} else {
cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
rc = SEPOL_ERR;
Expand Down
2 changes: 2 additions & 0 deletions libsepol/cil/src/cil_build_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
void cil_destroy_defaultrange(struct cil_defaultrange *def);
int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_src_info(struct cil_src_info *info);
int cil_gen_disjointattributes(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_disjointattributes(struct cil_disjointattributes *dattrs);

int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats);
void cil_destroy_cats(struct cil_cats *cats);
Expand Down
18 changes: 18 additions & 0 deletions libsepol/cil/src/cil_copy_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,21 @@ static int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *da
return SEPOL_OK;
}

static int cil_copy_disjointattributes(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_disjointattributes *orig = data;
struct cil_disjointattributes *new = NULL;

cil_disjointattributes_init(&new);

cil_copy_expr(db, orig->str_expr, &new->str_expr);
cil_copy_expr(db, orig->datum_expr, &new->datum_expr);

*copy = new;

return SEPOL_OK;
}

static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args)
{
int rc = SEPOL_ERR;
Expand Down Expand Up @@ -1977,6 +1992,9 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished
case CIL_SRC_INFO:
copy_func = &cil_copy_src_info;
break;
case CIL_DISJOINTATTRIBUTES:
copy_func = &cil_copy_disjointattributes;
break;
default:
goto exit;
}
Expand Down
1 change: 1 addition & 0 deletions libsepol/cil/src/cil_flavor.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ enum cil_flavor {
CIL_SRC_INFO,
CIL_IBPKEYCON,
CIL_IBENDPORTCON,
CIL_DISJOINTATTRIBUTES,

/*
* boolean constraint set catset
Expand Down
8 changes: 8 additions & 0 deletions libsepol/cil/src/cil_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ extern char *CIL_KEY_SRC_HLL_LMS;
extern char *CIL_KEY_SRC_HLL_LMX;
extern char *CIL_KEY_SRC_HLL_LME;
extern char *CIL_KEY_DENY_RULE;
extern char *CIL_KEY_DISJOINTATTRIBUTES;

/*
Symbol Table Array Indices
Expand Down Expand Up @@ -314,6 +315,7 @@ struct cil_db {
struct cil_list *userprefixes;
struct cil_list *selinuxusers;
struct cil_list *declared_strings;
struct cil_list *disjointattributes;
int num_types_and_attrs;
int num_classes;
int num_cats;
Expand Down Expand Up @@ -992,6 +994,11 @@ struct cil_src_info {
char *path;
};

struct cil_disjointattributes {
struct cil_list *str_expr;
struct cil_list *datum_expr;
};

void cil_db_init(struct cil_db **db);
void cil_db_destroy(struct cil_db **db);

Expand Down Expand Up @@ -1099,5 +1106,6 @@ void cil_mls_init(struct cil_mls **mls);
void cil_src_info_init(struct cil_src_info **info);
void cil_userattribute_init(struct cil_userattribute **attribute);
void cil_userattributeset_init(struct cil_userattributeset **attrset);
void cil_disjointattributes_init(struct cil_disjointattributes **dattrs);

#endif
26 changes: 26 additions & 0 deletions libsepol/cil/src/cil_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ enum cil_statement_list {
CIL_LIST_USER,
CIL_LIST_CONSTRAINT,
CIL_LIST_VALIDATETRANS,
CIL_LIST_DISJOINTATTRIBUTES,
CIL_LIST_NUM_LISTS
};

Expand Down Expand Up @@ -168,6 +169,9 @@ static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *
case CIL_VALIDATETRANS:
kind = CIL_LIST_VALIDATETRANS;
break;
case CIL_DISJOINTATTRIBUTES:
kind = CIL_LIST_DISJOINTATTRIBUTES;
break;
default:
break;
}
Expand Down Expand Up @@ -1910,6 +1914,27 @@ static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreec
}
}

static void cil_disjointattributes_to_policy(FILE *out, struct cil_list *dattrs_list)
{
struct cil_list_item *curr_dattrs, *curr_attr;
struct cil_disjointattributes *dattrs;
int first = 1;

cil_list_for_each(curr_dattrs, dattrs_list) {
dattrs = curr_dattrs->data;
fprintf(out, "disjoint_attributes ");
cil_list_for_each(curr_attr, dattrs->datum_expr) {
if (!first) {
first = 0;
} else {
fprintf(out, ", ");
}
fprintf(out, "%s", DATUM(curr_attr->data)->fqn);
}
fprintf(out, ";\n");
}
}

void cil_gen_policy(FILE *out, struct cil_db *db)
{
unsigned i;
Expand Down Expand Up @@ -1955,6 +1980,7 @@ void cil_gen_policy(FILE *out, struct cil_db *db)
cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
cil_te_rules_to_policy(out, head, db->mls);
cil_disjointattributes_to_policy(out, db->disjointattributes);

cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
Expand Down
8 changes: 8 additions & 0 deletions libsepol/cil/src/cil_reset_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,11 @@ static void cil_reset_booleanif(struct cil_booleanif *bif)
cil_list_destroy(&bif->datum_expr, CIL_FALSE);
}

static void cil_reset_disjointattributes(struct cil_disjointattributes *dattrs)
{
cil_list_destroy(&dattrs->datum_expr, CIL_FALSE);
}

static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
{
switch (node->flavor) {
Expand Down Expand Up @@ -644,6 +649,9 @@ static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused))
case CIL_BOOLEANIF:
cil_reset_booleanif(node->data);
break;
case CIL_DISJOINTATTRIBUTES:
cil_reset_disjointattributes(node->data);
break;
case CIL_SIDORDER:
case CIL_CLASSORDER:
case CIL_CATORDER:
Expand Down
Loading

0 comments on commit d9a1b82

Please sign in to comment.