Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disjoint Attributes Rule #359

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
libsepol/cil: add support for segregate attributes
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 <[email protected]>
---
v4:
   rename to disjointattributes
  • Loading branch information
cgzones committed Apr 29, 2024
commit d9a1b8200535387e5fb26619650a6adb06b858f6
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