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 all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions checkpolicy/policy_define.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,72 @@ int expand_attrib(void)
return rc;
}

int define_disjoint_attributes(void)
{
char *id = NULL;
disjoint_attributes_rule_t *dattr = NULL;
int rc = -1;

if (pass == 1) {
while ((id = queue_remove(id_queue)))
free(id);
return 0;
}

dattr = malloc(sizeof(disjoint_attributes_rule_t));
if (!dattr) {
yyerror("Out of memory!");
goto exit;
}

ebitmap_init(&dattr->attrs);

while ((id = queue_remove(id_queue))) {
const type_datum_t *attr;

if (!is_id_in_scope(SYM_TYPES, id)) {
yyerror2("attribute %s is not within scope", id);
goto exit;
}

attr = hashtab_search(policydbp->p_types.table, id);
if (!attr) {
yyerror2("attribute %s is not declared", id);
goto exit;
}

if (attr->flavor != TYPE_ATTRIB) {
yyerror2("%s is a type, not an attribute", id);
goto exit;
}

if (ebitmap_get_bit(&dattr->attrs, attr->s.value - 1)) {
yyerror2("attribute %s used multiple times", id);
goto exit;
}

if (ebitmap_set_bit(&dattr->attrs, attr->s.value - 1, TRUE)) {
yyerror("Out of memory!");
goto exit;
}

free(id);
}

dattr->next = policydbp->disjoint_attributes;
policydbp->disjoint_attributes = dattr;

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

static int add_aliases_to_type(type_datum_t * type)
{
char *id;
Expand Down
1 change: 1 addition & 0 deletions checkpolicy/policy_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ int define_type(int alias);
int define_user(void);
int define_validatetrans(constraint_expr_t *expr);
int expand_attrib(void);
int define_disjoint_attributes(void);
int insert_id(const char *id,int push);
int insert_separator(int push);
uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2);
Expand Down
5 changes: 5 additions & 0 deletions checkpolicy/policy_parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ typedef int (* require_func_t)(int pass);
%token ALIAS
%token ATTRIBUTE
%token EXPANDATTRIBUTE
%token DISJOINTATTRIBUTES
%token BOOL
%token TUNABLE
%token IF
Expand Down Expand Up @@ -318,6 +319,7 @@ rbac_decl : attribute_role_def
;
te_decl : attribute_def
| expandattribute_def
| disjointattributes_def
| type_def
| typealias_def
| typeattribute_def
Expand All @@ -335,6 +337,9 @@ attribute_def : ATTRIBUTE identifier ';'
expandattribute_def : EXPANDATTRIBUTE names bool_val ';'
{ if (expand_attrib()) YYABORT;}
;
disjointattributes_def : DISJOINTATTRIBUTES identifier ',' id_comma_list ';'
{ if (define_disjoint_attributes()) return -1;}
;
type_def : TYPE identifier alias_def opt_attr_list ';'
{if (define_type(1)) YYABORT;}
| TYPE identifier opt_attr_list ';'
Expand Down
2 changes: 2 additions & 0 deletions checkpolicy/policy_scan.l
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ ATTRIBUTE |
attribute { return(ATTRIBUTE); }
EXPANDATTRIBUTE |
expandattribute { return(EXPANDATTRIBUTE); }
DISJOINT_ATTRIBUTES |
disjoint_attributes { return(DISJOINTATTRIBUTES); }
TYPE_TRANSITION |
type_transition { return(TYPE_TRANSITION); }
TYPE_MEMBER |
Expand Down
1 change: 1 addition & 0 deletions checkpolicy/tests/policy_allonce.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ attribute ATTR1;
attribute ATTR2;
expandattribute ATTR1 true;
expandattribute ATTR2 false;
disjoint_attributes ATTR1, ATTR2;
type TYPE1;
type TYPE2, ATTR1;
type TYPE3 alias { TYPEALIAS3A TYPEALIAS3B };
Expand Down
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
Loading
Loading