On Thu, Jul 21, 2022 at 11:11 AM Christian Göttsche <cgzones@xxxxxxxxxxxxxx> wrote: > > Support the compile time constraint with the following syntax: > > (segregateattributes (attr1 attr2 [...])) Not a list. The vast majority of the cases are going to be that a type can be either one or another. (typesdisjoint attr1 attr2) Keep it simple. > > and reports like: > > ... > Qualifying Names > Compile post process > Building policy binary > Checking Neverallows > Checking Segregate Attributes > Segregate Attributes 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@xxxxxxxxxxxxxx> > --- > libsepol/cil/src/cil.c | 17 +++++++ > libsepol/cil/src/cil_binary.c | 75 ++++++++++++++++++++++++++++++ > libsepol/cil/src/cil_build_ast.c | 58 +++++++++++++++++++++++ > libsepol/cil/src/cil_build_ast.h | 2 + > libsepol/cil/src/cil_copy_ast.c | 18 +++++++ > libsepol/cil/src/cil_flavor.h | 1 + > libsepol/cil/src/cil_internal.h | 8 ++++ > libsepol/cil/src/cil_policy.c | 26 +++++++++++ > libsepol/cil/src/cil_reset_ast.c | 8 ++++ > libsepol/cil/src/cil_resolve_ast.c | 38 +++++++++++++++ > libsepol/cil/src/cil_resolve_ast.h | 1 + > libsepol/cil/src/cil_write_ast.c | 11 +++++ > libsepol/src/kernel_to_cil.c | 32 +++++++++++++ > secilc/docs/README.md | 1 + > secilc/docs/cil_type_statements.md | 50 ++++++++++++++++++++ > 15 files changed, 346 insertions(+) > > diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c > index 38edcf8e..cc6adb90 100644 > --- a/libsepol/cil/src/cil.c > +++ b/libsepol/cil/src/cil.c > @@ -225,6 +225,7 @@ char *CIL_KEY_SRC_CIL; > char *CIL_KEY_SRC_HLL_LMS; > char *CIL_KEY_SRC_HLL_LMX; > char *CIL_KEY_SRC_HLL_LME; > +char *CIL_KEY_SEGREGATEATTRIBUTES; > > static void cil_init_keys(void) > { > @@ -394,6 +395,7 @@ static void cil_init_keys(void) > CIL_KEY_SRC_HLL_LMS = cil_strpool_add("lms"); > CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx"); > CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme"); > + CIL_KEY_SEGREGATEATTRIBUTES = cil_strpool_add("segregateattributes"); > } > > void cil_db_init(struct cil_db **db) > @@ -426,6 +428,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)->names, CIL_LIST_ITEM); > + cil_list_init(&(*db)->segregateattributes, CIL_LIST_ITEM); > > cil_type_init(&(*db)->selftype); > (*db)->selftype->datum.name = CIL_KEY_SELF; > @@ -481,6 +484,7 @@ void cil_db_destroy(struct cil_db **db) > cil_list_destroy(&(*db)->userprefixes, CIL_FALSE); > cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE); > cil_list_destroy(&(*db)->names, CIL_TRUE); > + cil_list_destroy(&(*db)->segregateattributes, CIL_FALSE); > > cil_destroy_type((*db)->selftype); > > @@ -1005,6 +1009,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) > case CIL_SRC_INFO: > cil_destroy_src_info(*data); > break; > + case CIL_SEGREGATEATTRIBUTES: > + cil_destroy_segregateattributes(*data); > + break; > case CIL_OP: > case CIL_CONS_OPERAND: > break; > @@ -1413,6 +1420,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_SEGREGATEATTRIBUTES: > + return CIL_KEY_SEGREGATEATTRIBUTES; > > default: > break; > @@ -2904,3 +2913,11 @@ void cil_src_info_init(struct cil_src_info **info) > (*info)->hll_line = 0; > (*info)->path = NULL; > } > + > +void cil_segregateattributes_init(struct cil_segregateattributes **sattrs) > +{ > + *sattrs = cil_malloc(sizeof(**sattrs)); > + > + (*sattrs)->str_expr = NULL; > + (*sattrs)->datum_expr = NULL; > +} > diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c > index 40615db2..0301d739 100644 > --- a/libsepol/cil/src/cil_binary.c > +++ b/libsepol/cil/src/cil_binary.c > @@ -3818,6 +3818,38 @@ exit: > return SEPOL_ERR; > } > > +static int cil_segregateattributes_to_policydb(policydb_t *pdb, const struct cil_segregateattributes *sattrs) > +{ > + segregate_attributes_rule_t *sattr; > + struct cil_list_item *curr; > + type_datum_t *sepol_type; > + int rc = SEPOL_ERR; > + > + sattr = cil_malloc(sizeof(segregate_attributes_rule_t)); > + ebitmap_init(&sattr->attrs); > + > + cil_list_for_each(curr, sattrs->datum_expr) { > + rc = __cil_get_sepol_type_datum(pdb, DATUM(curr->data), &sepol_type); > + if (rc != SEPOL_OK) goto exit; > + > + if (ebitmap_set_bit(&sattr->attrs, sepol_type->s.value - 1, 1)) { > + goto exit; > + } > + } > + > + sattr->next = pdb->segregate_attributes; > + pdb->segregate_attributes = sattr; > + > + return SEPOL_OK; > + > +exit: > + if (sattr) { > + ebitmap_destroy(&sattr->attrs); > + free(sattr); > + } > + return rc; > +} > + > static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args) > { > int rc = SEPOL_OK; > @@ -3960,6 +3992,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_SEGREGATEATTRIBUTES: > + rc = cil_segregateattributes_to_policydb(pdb, node->data); > + break; > default: > break; > } > @@ -4890,6 +4925,42 @@ exit: > return rc; > } > > +static int cil_check_segregateattributes(const policydb_t *pdb, int *violation) > +{ > + const segregate_attributes_rule_t *sattr; > + > + for (sattr = pdb->segregate_attributes; sattr; sattr = sattr->next) { > + ebitmap_node_t *first_node; > + unsigned int first_bit; > + > + ebitmap_for_each_positive_bit(&sattr->attrs, first_node, first_bit) { > + ebitmap_node_t *second_node; > + unsigned int second_bit; > + > + ebitmap_for_each_positive_bit_after(&sattr->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, "Segregate Attributes 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; It needs to report the file and linenumber of the violation. This is the case for checkpolicy as well. There is a reason that we carry that information for neverallow rules. Thanks, Jim > + } > + > + 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; > @@ -5160,6 +5231,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 Segregate Attributes\n"); > + rc = cil_check_segregateattributes(pdb, &violation); > + if (rc != SEPOL_OK) goto exit; > + > cil_log(CIL_INFO, "Checking User Bounds\n"); > rc = bounds_check_users(NULL, pdb); > if (rc) { > diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c > index 4177c9f6..611aade8 100644 > --- a/libsepol/cil/src/cil_build_ast.c > +++ b/libsepol/cil/src/cil_build_ast.c > @@ -6164,6 +6164,62 @@ void cil_destroy_src_info(struct cil_src_info *info) > free(info); > } > > +int cil_gen_segregateattributes(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_segregateattributes *sattrs = 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_segregateattributes_init(&sattrs); > + > + rc = cil_gen_expr(parse_current->next, CIL_TYPEATTRIBUTE, &sattrs->str_expr); > + if (rc != SEPOL_OK) { > + goto exit; > + } > + > + /* require at least two attributes */ > + if (sattrs->str_expr->head == sattrs->str_expr->tail) { > + rc = SEPOL_ERR; > + goto exit; > + } > + > + ast_node->data = sattrs; > + ast_node->flavor = CIL_SEGREGATEATTRIBUTES; > + > + return SEPOL_OK; > + > +exit: > + cil_tree_log(parse_current, CIL_ERR, "Bad segregate attributes declaration"); > + cil_destroy_segregateattributes(sattrs); > + return rc; > +} > + > +void cil_destroy_segregateattributes(struct cil_segregateattributes *sattrs) > +{ > + if (sattrs == NULL) { > + return; > + } > + > + cil_list_destroy(&sattrs->str_expr, CIL_TRUE); > + cil_list_destroy(&sattrs->datum_expr, CIL_FALSE); > + > + free(sattrs); > +} > + > static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args) > { > if (args->tunif != NULL) { > @@ -6455,6 +6511,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_SEGREGATEATTRIBUTES) { > + rc = cil_gen_segregateattributes(db, parse_current, new_ast_node); > } else { > cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); > rc = SEPOL_ERR; > diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h > index fd9053ce..d815a22f 100644 > --- a/libsepol/cil/src/cil_build_ast.h > +++ b/libsepol/cil/src/cil_build_ast.h > @@ -225,6 +225,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_segregateattributes(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); > +void cil_destroy_segregateattributes(struct cil_segregateattributes *sattrs); > > int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats); > void cil_destroy_cats(struct cil_cats *cats); > diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c > index 17f05021..e0f3ba4f 100644 > --- a/libsepol/cil/src/cil_copy_ast.c > +++ b/libsepol/cil/src/cil_copy_ast.c > @@ -1697,6 +1697,21 @@ static int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *da > return SEPOL_OK; > } > > +static int cil_copy_segregateattributes(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) > +{ > + struct cil_segregateattributes *orig = data; > + struct cil_segregateattributes *new = NULL; > + > + cil_segregateattributes_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; > @@ -1990,6 +2005,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_SEGREGATEATTRIBUTES: > + copy_func = &cil_copy_segregateattributes; > + break; > default: > goto exit; > } > diff --git a/libsepol/cil/src/cil_flavor.h b/libsepol/cil/src/cil_flavor.h > index c2f0cee7..ffbd5877 100644 > --- a/libsepol/cil/src/cil_flavor.h > +++ b/libsepol/cil/src/cil_flavor.h > @@ -115,6 +115,7 @@ enum cil_flavor { > CIL_SRC_INFO, > CIL_IBPKEYCON, > CIL_IBENDPORTCON, > + CIL_SEGREGATEATTRIBUTES, > > /* > * boolean constraint set catset > diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h > index a7604762..e22c2f87 100644 > --- a/libsepol/cil/src/cil_internal.h > +++ b/libsepol/cil/src/cil_internal.h > @@ -242,6 +242,7 @@ extern char *CIL_KEY_SRC_CIL; > 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_SEGREGATEATTRIBUTES; > > /* > Symbol Table Array Indices > @@ -309,6 +310,7 @@ struct cil_db { > struct cil_list *userprefixes; > struct cil_list *selinuxusers; > struct cil_list *names; > + struct cil_list *segregateattributes; > int num_types_and_attrs; > int num_classes; > int num_cats; > @@ -975,6 +977,11 @@ struct cil_src_info { > char *path; > }; > > +struct cil_segregateattributes { > + 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); > > @@ -1085,5 +1092,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_segregateattributes_init(struct cil_segregateattributes **sattrs); > > #endif > diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c > index 7c543c47..36f6780d 100644 > --- a/libsepol/cil/src/cil_policy.c > +++ b/libsepol/cil/src/cil_policy.c > @@ -69,6 +69,7 @@ enum cil_statement_list { > CIL_LIST_USER, > CIL_LIST_CONSTRAINT, > CIL_LIST_VALIDATETRANS, > + CIL_LIST_SEGREGATEATTRIBUTES, > CIL_LIST_NUM_LISTS > }; > > @@ -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_SEGREGATEATTRIBUTES: > + kind = CIL_LIST_SEGREGATEATTRIBUTES; > + break; > default: > break; > } > @@ -1911,6 +1915,27 @@ static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreec > } > } > > +static void cil_segregateattributes_to_policy(FILE *out, struct cil_list *sattrs_list) > +{ > + struct cil_list_item *curr_sattrs, *curr_attr; > + struct cil_segregateattributes *sattrs; > + int first = 1; > + > + cil_list_for_each(curr_sattrs, sattrs_list) { > + sattrs = curr_sattrs->data; > + fprintf(out, "segregate_attriutes "); > + cil_list_for_each(curr_attr, sattrs->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; > @@ -1956,6 +1981,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_segregateattributes_to_policy(out, db->segregateattributes); > > cil_roles_to_policy(out, lists[CIL_LIST_ROLE]); > cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]); > diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c > index 0864d7ef..c5ac83c8 100644 > --- a/libsepol/cil/src/cil_reset_ast.c > +++ b/libsepol/cil/src/cil_reset_ast.c > @@ -475,6 +475,11 @@ static void cil_reset_booleanif(struct cil_booleanif *bif) > cil_list_destroy(&bif->datum_expr, CIL_FALSE); > } > > +static void cil_reset_segregateattributes(struct cil_segregateattributes *sattrs) > +{ > + cil_list_destroy(&sattrs->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) { > @@ -630,6 +635,9 @@ static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) > case CIL_BOOLEANIF: > cil_reset_booleanif(node->data); > break; > + case CIL_SEGREGATEATTRIBUTES: > + cil_reset_segregateattributes(node->data); > + break; > case CIL_TUNABLEIF: > case CIL_CALL: > break; /* Not effected by optional block disabling */ > diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c > index f5e22c97..36a96199 100644 > --- a/libsepol/cil/src/cil_resolve_ast.c > +++ b/libsepol/cil/src/cil_resolve_ast.c > @@ -3265,6 +3265,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc > sym_index = CIL_SYM_TUNABLES; > break; > case CIL_TYPE: > + case CIL_TYPEATTRIBUTE: > sym_index = CIL_SYM_TYPES; > break; > case CIL_ROLE: > @@ -3312,6 +3313,13 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc > } else { > if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) { > cil_type_used(res_datum, CIL_ATTR_CONSTRAINT); > + } else if (expr_type == CIL_SEGREGATEATTRIBUTES) { > + if (FLAVOR(res_datum) != CIL_TYPEATTRIBUTE) { > + cil_tree_log(parent, CIL_ERR, "Type or type alias not supported in segregate attributes declaration"); > + rc = SEPOL_ERR; > + goto exit; > + } > + cil_type_used(res_datum, CIL_ATTR_NEVERALLOW); > } > cil_list_append(*datum_expr, CIL_DATUM, res_datum); > } > @@ -3508,6 +3516,33 @@ exit: > return rc; > } > > +int cil_resolve_segregateattributes(struct cil_tree_node *current, void *extra_args) > +{ > + struct cil_segregateattributes *sattrs = current->data; > + struct cil_list_item *first, *second; > + int rc; > + > + rc = cil_resolve_expr(CIL_SEGREGATEATTRIBUTES, sattrs->str_expr, &sattrs->datum_expr, current, extra_args); > + if (rc != SEPOL_OK) { > + goto exit; > + } > + > + cil_list_for_each(first, sattrs->datum_expr) { > + for (second = first->next; second; second = second->next) { > + if (first->data == second->data) { > + cil_tree_log(current, CIL_ERR, "Repeated attribute in segregate attributes declaration"); > + rc = SEPOL_ERR; > + goto exit; > + } > + } > + } > + > + return SEPOL_OK; > + > +exit: > + return rc; > +} > + > /* > * Degenerate inheritance leads to exponential growth of the policy > * It can take many forms, but here is one example. > @@ -3888,6 +3923,9 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) > case CIL_USERATTRIBUTESET: > rc = cil_resolve_userattributeset(node, args); > break; > + case CIL_SEGREGATEATTRIBUTES: > + rc = cil_resolve_segregateattributes(node, args); > + break; > default: > break; > } > diff --git a/libsepol/cil/src/cil_resolve_ast.h b/libsepol/cil/src/cil_resolve_ast.h > index 1d971fd6..31594954 100644 > --- a/libsepol/cil/src/cil_resolve_ast.h > +++ b/libsepol/cil/src/cil_resolve_ast.h > @@ -96,6 +96,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc > int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args); > int cil_evaluate_expr(struct cil_list *datum_expr, uint16_t *result); > int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args); > +int cil_resolve_segregateattributes(struct cil_tree_node *current, void *extra_args); > > int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current); > 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); > diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c > index b75784ef..d0fb555b 100644 > --- a/libsepol/cil/src/cil_write_ast.c > +++ b/libsepol/cil/src/cil_write_ast.c > @@ -1474,7 +1474,18 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) > fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf); > break; > } > + case CIL_SEGREGATEATTRIBUTES: { > + struct cil_segregateattributes *sattrs = node->data; > + fprintf(out, "(segregateattributes "); > + if (sattrs->datum_expr) > + write_expr(out, sattrs->datum_expr); > + else > + write_expr(out, sattrs->str_expr); > + fprintf(out, ")\n"); > + break; > + } > default : > + cil_log(CIL_ERR, "Unsupported flavor: %d\n", node->flavor); > fprintf(out, "(<?RULE:%s>)\n", cil_node_to_string(node)); > break; > } > diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c > index 9128ac55..4b99208d 100644 > --- a/libsepol/src/kernel_to_cil.c > +++ b/libsepol/src/kernel_to_cil.c > @@ -1906,6 +1906,33 @@ static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) > return 0; > } > > +static int write_segregate_attributes_to_cil(FILE *out, const struct policydb *pdb) > +{ > + const segregate_attributes_rule_t *sattr; > + > + for (sattr = pdb->segregate_attributes; sattr; sattr = sattr->next) { > + struct ebitmap_node *node; > + unsigned int bit; > + int first = 1; > + > + sepol_printf(out, "(segregateattributes ("); > + > + ebitmap_for_each_positive_bit(&sattr->attrs, node, bit) { > + if (first) { > + first = 0; > + } else { > + sepol_printf(out, " "); > + } > + > + sepol_printf(out, "%s", pdb->p_type_val_to_name[bit - 1]); > + } > + > + sepol_printf(out, "))\n"); > + } > + > + return 0; > +} > + > static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb) > { > struct map_filename_trans_args args; > @@ -3329,6 +3356,11 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) > goto exit; > } > > + rc = write_segregate_attributes_to_cil(out, pdb); > + if (rc != 0) { > + goto exit; > + } > + > rc = write_filename_trans_rules_to_cil(out, pdb); > if (rc != 0) { > goto exit; > diff --git a/secilc/docs/README.md b/secilc/docs/README.md > index efab2a71..8f584019 100644 > --- a/secilc/docs/README.md > +++ b/secilc/docs/README.md > @@ -132,6 +132,7 @@ CIL (Common Intermediate Language) > * [typemember](cil_type_statements.md#typemember) > * [typetransition](cil_type_statements.md#typetransition) > * [typepermissive](cil_type_statements.md#typepermissive) > + * [segregateattributes](cil_type_statements.md#segregateattributes) > > * [User Statements](cil_user_statements.md#user-statements) > * [user](cil_user_statements.md#user) > diff --git a/secilc/docs/cil_type_statements.md b/secilc/docs/cil_type_statements.md > index 19438417..56533eea 100644 > --- a/secilc/docs/cil_type_statements.md > +++ b/secilc/docs/cil_type_statements.md > @@ -601,3 +601,53 @@ This example will allow SELinux to run the `healthd.process` domain in permissiv > (allow ...) > ) > ``` > + > +segregateattributes > +------------------- > + > +Libsepol and secilc version 3.5 introduced the segregateattributes statement > +to mark two or more type attributes mutual exclusive. This is a compiler > +enforced action that will stop compilation until the offending associations > +are modified. > + > +Note that these constraints can be over-ridden by the CIL compiler command > +line parameter `-N` or `--disable-neverallow` flags. > + > +**Statement definition:** > + > +```secil > + (segregateattributes (typeattribute_id typeattribute_id...)) > +``` > + > +**Where:** > + > +<table> > +<colgroup> > +<col width="27%" /> > +<col width="72%" /> > +</colgroup> > +<tbody> > +<tr class="odd"> > +<td align="left"><p><code>segregateattributes</code></p></td> > +<td align="left"><p>The <code>segregateattributes</code> keyword.</p></td> > +</tr> > +<tr class="even"> > +<td align="left"><p><code>typeattribute_id</code></p></td> > +<td align="left"><p>At least two previously declared <code>typeattribute</code> identifier.</p> > +<p>Note that the same <code>typeattribute</code> identifier must not be repeated.</p></td> > +</tr> > +</tbody> > +</table> > + > +**Example:** > + > +This example will not compile as `type_1` is associated with type attributes `attr_1` and `attr_2`: > + > +```secil > + (type type_1) > + (typeattribute attr_1) > + (typeattribute attr_2) > + (typeattributeset attr_1 (type_1)) > + (typeattributeset attr_2 (type_1)) > + (segregateattributes (attr_1 attr_2)) > +``` > -- > 2.36.1 >