Skip to content

Commit 70a62d4

Browse files
committed
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
1 parent fbf66c0 commit 70a62d4

15 files changed

+346
-0
lines changed

libsepol/cil/src/cil.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ char *CIL_KEY_SRC_HLL_LMS;
228228
char *CIL_KEY_SRC_HLL_LMX;
229229
char *CIL_KEY_SRC_HLL_LME;
230230
char *CIL_KEY_DENY_RULE;
231+
char *CIL_KEY_DISJOINTATTRIBUTES;
231232

232233
static void cil_init_keys(void)
233234
{
@@ -400,6 +401,7 @@ static void cil_init_keys(void)
400401
CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx");
401402
CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme");
402403
CIL_KEY_DENY_RULE = cil_strpool_add("deny");
404+
CIL_KEY_DISJOINTATTRIBUTES = cil_strpool_add("disjointattributes");
403405
}
404406

405407
void cil_db_init(struct cil_db **db)
@@ -432,6 +434,7 @@ void cil_db_init(struct cil_db **db)
432434
cil_list_init(&(*db)->userprefixes, CIL_LIST_ITEM);
433435
cil_list_init(&(*db)->selinuxusers, CIL_LIST_ITEM);
434436
cil_list_init(&(*db)->declared_strings, CIL_LIST_ITEM);
437+
cil_list_init(&(*db)->disjointattributes, CIL_LIST_ITEM);
435438

436439
cil_type_init(&(*db)->selftype);
437440
(*db)->selftype->datum.name = CIL_KEY_SELF;
@@ -504,6 +507,7 @@ void cil_db_destroy(struct cil_db **db)
504507
cil_sort_destroy(&(*db)->fsuse);
505508
cil_list_destroy(&(*db)->userprefixes, CIL_FALSE);
506509
cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE);
510+
cil_list_destroy(&(*db)->disjointattributes, CIL_FALSE);
507511

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

@@ -1084,6 +1088,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
10841088
case CIL_SRC_INFO:
10851089
cil_destroy_src_info(*data);
10861090
break;
1091+
case CIL_DISJOINTATTRIBUTES:
1092+
cil_destroy_disjointattributes(*data);
1093+
break;
10871094
case CIL_OP:
10881095
case CIL_CONS_OPERAND:
10891096
break;
@@ -1492,6 +1499,8 @@ const char * cil_node_to_string(struct cil_tree_node *node)
14921499
return CIL_KEY_CONS_H1;
14931500
case CIL_CONS_H2:
14941501
return CIL_KEY_CONS_H2;
1502+
case CIL_DISJOINTATTRIBUTES:
1503+
return CIL_KEY_DISJOINTATTRIBUTES;
14951504

14961505
default:
14971506
break;
@@ -2984,3 +2993,11 @@ void cil_src_info_init(struct cil_src_info **info)
29842993
(*info)->hll_line = 0;
29852994
(*info)->path = NULL;
29862995
}
2996+
2997+
void cil_disjointattributes_init(struct cil_disjointattributes **dattrs)
2998+
{
2999+
*dattrs = cil_malloc(sizeof(**dattrs));
3000+
3001+
(*dattrs)->str_expr = NULL;
3002+
(*dattrs)->datum_expr = NULL;
3003+
}

libsepol/cil/src/cil_binary.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3896,6 +3896,38 @@ static int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange
38963896
return SEPOL_ERR;
38973897
}
38983898

3899+
static int cil_disjointattributes_to_policydb(policydb_t *pdb, const struct cil_disjointattributes *dattrs)
3900+
{
3901+
disjoint_attributes_rule_t *dattr;
3902+
struct cil_list_item *curr;
3903+
type_datum_t *sepol_type;
3904+
int rc = SEPOL_ERR;
3905+
3906+
dattr = cil_malloc(sizeof(disjoint_attributes_rule_t));
3907+
ebitmap_init(&dattr->attrs);
3908+
3909+
cil_list_for_each(curr, dattrs->datum_expr) {
3910+
rc = __cil_get_sepol_type_datum(pdb, DATUM(curr->data), &sepol_type);
3911+
if (rc != SEPOL_OK) goto exit;
3912+
3913+
if (ebitmap_set_bit(&dattr->attrs, sepol_type->s.value - 1, 1)) {
3914+
goto exit;
3915+
}
3916+
}
3917+
3918+
dattr->next = pdb->disjoint_attributes;
3919+
pdb->disjoint_attributes = dattr;
3920+
3921+
return SEPOL_OK;
3922+
3923+
exit:
3924+
if (dattr) {
3925+
ebitmap_destroy(&dattr->attrs);
3926+
free(dattr);
3927+
}
3928+
return rc;
3929+
}
3930+
38993931
static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
39003932
{
39013933
int rc = SEPOL_OK;
@@ -4038,6 +4070,9 @@ static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
40384070
case CIL_DEFAULTRANGE:
40394071
rc = cil_defaultrange_to_policydb(pdb, node->data);
40404072
break;
4073+
case CIL_DISJOINTATTRIBUTES:
4074+
rc = cil_disjointattributes_to_policydb(pdb, node->data);
4075+
break;
40414076
default:
40424077
break;
40434078
}
@@ -4976,6 +5011,42 @@ static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struc
49765011
return rc;
49775012
}
49785013

5014+
static int cil_check_disjointattributes(const policydb_t *pdb, int *violation)
5015+
{
5016+
const disjoint_attributes_rule_t *dattr;
5017+
5018+
for (dattr = pdb->disjoint_attributes; dattr; dattr = dattr->next) {
5019+
ebitmap_node_t *first_node;
5020+
unsigned int first_bit;
5021+
5022+
ebitmap_for_each_positive_bit(&dattr->attrs, first_node, first_bit) {
5023+
ebitmap_node_t *second_node;
5024+
unsigned int second_bit;
5025+
5026+
ebitmap_for_each_positive_bit_after(&dattr->attrs, second_node, second_bit, first_node, first_bit) {
5027+
ebitmap_t attr_union;
5028+
ebitmap_node_t *type_node;
5029+
unsigned int type_bit;
5030+
5031+
if (ebitmap_and(&attr_union, &pdb->attr_type_map[first_bit], &pdb->attr_type_map[second_bit]))
5032+
return SEPOL_ERR;
5033+
5034+
ebitmap_for_each_positive_bit(&attr_union, type_node, type_bit) {
5035+
cil_log(CIL_ERR, "Disjoint Attributes Rule violation, type %s associated with attributes %s and %s\n",
5036+
pdb->p_type_val_to_name[type_bit],
5037+
pdb->p_type_val_to_name[first_bit],
5038+
pdb->p_type_val_to_name[second_bit]);
5039+
*violation = CIL_TRUE;
5040+
}
5041+
5042+
ebitmap_destroy(&attr_union);
5043+
}
5044+
}
5045+
}
5046+
5047+
return SEPOL_OK;
5048+
}
5049+
49795050
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[])
49805051
{
49815052
struct cil_classperms *cp;
@@ -5246,6 +5317,10 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
52465317
rc = cil_check_neverallows(db, pdb, neverallows, &violation);
52475318
if (rc != SEPOL_OK) goto exit;
52485319

5320+
cil_log(CIL_INFO, "Checking Disjoint Attributes Rules\n");
5321+
rc = cil_check_disjointattributes(pdb, &violation);
5322+
if (rc != SEPOL_OK) goto exit;
5323+
52495324
cil_log(CIL_INFO, "Checking User Bounds\n");
52505325
rc = bounds_check_users(NULL, pdb);
52515326
if (rc) {

libsepol/cil/src/cil_build_ast.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6108,6 +6108,62 @@ void cil_destroy_src_info(struct cil_src_info *info)
61086108
free(info);
61096109
}
61106110

6111+
int cil_gen_disjointattributes(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6112+
{
6113+
enum cil_syntax syntax[] = {
6114+
CIL_SYN_STRING,
6115+
CIL_SYN_LIST,
6116+
CIL_SYN_END
6117+
};
6118+
size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6119+
struct cil_disjointattributes *dattrs = NULL;
6120+
int rc = SEPOL_ERR;
6121+
6122+
if (db == NULL || parse_current == NULL || ast_node == NULL) {
6123+
goto exit;
6124+
}
6125+
6126+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6127+
if (rc != SEPOL_OK) {
6128+
goto exit;
6129+
}
6130+
6131+
cil_disjointattributes_init(&dattrs);
6132+
6133+
rc = cil_gen_expr(parse_current->next, CIL_TYPEATTRIBUTE, &dattrs->str_expr);
6134+
if (rc != SEPOL_OK) {
6135+
goto exit;
6136+
}
6137+
6138+
/* require at least two attributes */
6139+
if (dattrs->str_expr->head == dattrs->str_expr->tail) {
6140+
rc = SEPOL_ERR;
6141+
goto exit;
6142+
}
6143+
6144+
ast_node->data = dattrs;
6145+
ast_node->flavor = CIL_DISJOINTATTRIBUTES;
6146+
6147+
return SEPOL_OK;
6148+
6149+
exit:
6150+
cil_tree_log(parse_current, CIL_ERR, "Bad disjoint attributes rule declaration");
6151+
cil_destroy_disjointattributes(dattrs);
6152+
return rc;
6153+
}
6154+
6155+
void cil_destroy_disjointattributes(struct cil_disjointattributes *dattrs)
6156+
{
6157+
if (dattrs == NULL) {
6158+
return;
6159+
}
6160+
6161+
cil_list_destroy(&dattrs->str_expr, CIL_TRUE);
6162+
cil_list_destroy(&dattrs->datum_expr, CIL_FALSE);
6163+
6164+
free(dattrs);
6165+
}
6166+
61116167
static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
61126168
{
61136169
if (args->tunif != NULL) {
@@ -6401,6 +6457,8 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree
64016457
rc = cil_gen_mls(parse_current, new_ast_node);
64026458
} else if (parse_current->data == CIL_KEY_SRC_INFO) {
64036459
rc = cil_gen_src_info(parse_current, new_ast_node);
6460+
} else if (parse_current->data == CIL_KEY_DISJOINTATTRIBUTES) {
6461+
rc = cil_gen_disjointattributes(db, parse_current, new_ast_node);
64046462
} else {
64056463
cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
64066464
rc = SEPOL_ERR;

libsepol/cil/src/cil_build_ast.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
222222
void cil_destroy_defaultrange(struct cil_defaultrange *def);
223223
int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
224224
void cil_destroy_src_info(struct cil_src_info *info);
225+
int cil_gen_disjointattributes(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
226+
void cil_destroy_disjointattributes(struct cil_disjointattributes *dattrs);
225227

226228
int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats);
227229
void cil_destroy_cats(struct cil_cats *cats);

libsepol/cil/src/cil_copy_ast.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,21 @@ static int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *da
16811681
return SEPOL_OK;
16821682
}
16831683

1684+
static int cil_copy_disjointattributes(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
1685+
{
1686+
struct cil_disjointattributes *orig = data;
1687+
struct cil_disjointattributes *new = NULL;
1688+
1689+
cil_disjointattributes_init(&new);
1690+
1691+
cil_copy_expr(db, orig->str_expr, &new->str_expr);
1692+
cil_copy_expr(db, orig->datum_expr, &new->datum_expr);
1693+
1694+
*copy = new;
1695+
1696+
return SEPOL_OK;
1697+
}
1698+
16841699
static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args)
16851700
{
16861701
int rc = SEPOL_ERR;
@@ -1977,6 +1992,9 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished
19771992
case CIL_SRC_INFO:
19781993
copy_func = &cil_copy_src_info;
19791994
break;
1995+
case CIL_DISJOINTATTRIBUTES:
1996+
copy_func = &cil_copy_disjointattributes;
1997+
break;
19801998
default:
19811999
goto exit;
19822000
}

libsepol/cil/src/cil_flavor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ enum cil_flavor {
116116
CIL_SRC_INFO,
117117
CIL_IBPKEYCON,
118118
CIL_IBENDPORTCON,
119+
CIL_DISJOINTATTRIBUTES,
119120

120121
/*
121122
* boolean constraint set catset

libsepol/cil/src/cil_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ extern char *CIL_KEY_SRC_HLL_LMS;
245245
extern char *CIL_KEY_SRC_HLL_LMX;
246246
extern char *CIL_KEY_SRC_HLL_LME;
247247
extern char *CIL_KEY_DENY_RULE;
248+
extern char *CIL_KEY_DISJOINTATTRIBUTES;
248249

249250
/*
250251
Symbol Table Array Indices
@@ -314,6 +315,7 @@ struct cil_db {
314315
struct cil_list *userprefixes;
315316
struct cil_list *selinuxusers;
316317
struct cil_list *declared_strings;
318+
struct cil_list *disjointattributes;
317319
int num_types_and_attrs;
318320
int num_classes;
319321
int num_cats;
@@ -992,6 +994,11 @@ struct cil_src_info {
992994
char *path;
993995
};
994996

997+
struct cil_disjointattributes {
998+
struct cil_list *str_expr;
999+
struct cil_list *datum_expr;
1000+
};
1001+
9951002
void cil_db_init(struct cil_db **db);
9961003
void cil_db_destroy(struct cil_db **db);
9971004

@@ -1099,5 +1106,6 @@ void cil_mls_init(struct cil_mls **mls);
10991106
void cil_src_info_init(struct cil_src_info **info);
11001107
void cil_userattribute_init(struct cil_userattribute **attribute);
11011108
void cil_userattributeset_init(struct cil_userattributeset **attrset);
1109+
void cil_disjointattributes_init(struct cil_disjointattributes **dattrs);
11021110

11031111
#endif

libsepol/cil/src/cil_policy.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ enum cil_statement_list {
6969
CIL_LIST_USER,
7070
CIL_LIST_CONSTRAINT,
7171
CIL_LIST_VALIDATETRANS,
72+
CIL_LIST_DISJOINTATTRIBUTES,
7273
CIL_LIST_NUM_LISTS
7374
};
7475

@@ -168,6 +169,9 @@ static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *
168169
case CIL_VALIDATETRANS:
169170
kind = CIL_LIST_VALIDATETRANS;
170171
break;
172+
case CIL_DISJOINTATTRIBUTES:
173+
kind = CIL_LIST_DISJOINTATTRIBUTES;
174+
break;
171175
default:
172176
break;
173177
}
@@ -1910,6 +1914,27 @@ static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreec
19101914
}
19111915
}
19121916

1917+
static void cil_disjointattributes_to_policy(FILE *out, struct cil_list *dattrs_list)
1918+
{
1919+
struct cil_list_item *curr_dattrs, *curr_attr;
1920+
struct cil_disjointattributes *dattrs;
1921+
int first = 1;
1922+
1923+
cil_list_for_each(curr_dattrs, dattrs_list) {
1924+
dattrs = curr_dattrs->data;
1925+
fprintf(out, "disjoint_attributes ");
1926+
cil_list_for_each(curr_attr, dattrs->datum_expr) {
1927+
if (!first) {
1928+
first = 0;
1929+
} else {
1930+
fprintf(out, ", ");
1931+
}
1932+
fprintf(out, "%s", DATUM(curr_attr->data)->fqn);
1933+
}
1934+
fprintf(out, ";\n");
1935+
}
1936+
}
1937+
19131938
void cil_gen_policy(FILE *out, struct cil_db *db)
19141939
{
19151940
unsigned i;
@@ -1955,6 +1980,7 @@ void cil_gen_policy(FILE *out, struct cil_db *db)
19551980
cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
19561981
cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
19571982
cil_te_rules_to_policy(out, head, db->mls);
1983+
cil_disjointattributes_to_policy(out, db->disjointattributes);
19581984

19591985
cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
19601986
cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);

libsepol/cil/src/cil_reset_ast.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,11 @@ static void cil_reset_booleanif(struct cil_booleanif *bif)
486486
cil_list_destroy(&bif->datum_expr, CIL_FALSE);
487487
}
488488

489+
static void cil_reset_disjointattributes(struct cil_disjointattributes *dattrs)
490+
{
491+
cil_list_destroy(&dattrs->datum_expr, CIL_FALSE);
492+
}
493+
489494
static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
490495
{
491496
switch (node->flavor) {
@@ -644,6 +649,9 @@ static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused))
644649
case CIL_BOOLEANIF:
645650
cil_reset_booleanif(node->data);
646651
break;
652+
case CIL_DISJOINTATTRIBUTES:
653+
cil_reset_disjointattributes(node->data);
654+
break;
647655
case CIL_SIDORDER:
648656
case CIL_CLASSORDER:
649657
case CIL_CATORDER:

0 commit comments

Comments
 (0)