libsepol/cil: Add userattribute{set} functionality

This adds a userattribute statement that may be used in userroles and
constraints. The syntax is the same as typeattributset.

Also, disallow roleattributes where roles are accepted in contexts.

Specify a userattribute

    (userattribute foo)

Add users to the set foo

    (userattributeset foo (u1 u2))

Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
This commit is contained in:
Yuli Khodorkovskiy 2015-09-10 12:56:05 -04:00 committed by James Carter
parent 8e74de5f8d
commit 77779d2ca5
19 changed files with 787 additions and 67 deletions

View File

@ -122,6 +122,8 @@ static void cil_init_keys(void)
CIL_KEY_TYPE = cil_strpool_add("type"); CIL_KEY_TYPE = cil_strpool_add("type");
CIL_KEY_ROLE = cil_strpool_add("role"); CIL_KEY_ROLE = cil_strpool_add("role");
CIL_KEY_USER = cil_strpool_add("user"); CIL_KEY_USER = cil_strpool_add("user");
CIL_KEY_USERATTRIBUTE = cil_strpool_add("userattribute");
CIL_KEY_USERATTRIBUTESET = cil_strpool_add("userattributeset");
CIL_KEY_SENSITIVITY = cil_strpool_add("sensitivity"); CIL_KEY_SENSITIVITY = cil_strpool_add("sensitivity");
CIL_KEY_CATEGORY = cil_strpool_add("category"); CIL_KEY_CATEGORY = cil_strpool_add("category");
CIL_KEY_CATSET = cil_strpool_add("categoryset"); CIL_KEY_CATSET = cil_strpool_add("categoryset");
@ -266,9 +268,11 @@ void cil_db_init(struct cil_db **db)
(*db)->num_classes = 0; (*db)->num_classes = 0;
(*db)->num_types = 0; (*db)->num_types = 0;
(*db)->num_roles = 0; (*db)->num_roles = 0;
(*db)->num_users = 0;
(*db)->num_cats = 0; (*db)->num_cats = 0;
(*db)->val_to_type = NULL; (*db)->val_to_type = NULL;
(*db)->val_to_role = NULL; (*db)->val_to_role = NULL;
(*db)->val_to_user = NULL;
(*db)->disable_dontaudit = CIL_FALSE; (*db)->disable_dontaudit = CIL_FALSE;
(*db)->disable_neverallow = CIL_FALSE; (*db)->disable_neverallow = CIL_FALSE;
@ -311,6 +315,7 @@ void cil_db_destroy(struct cil_db **db)
cil_strpool_destroy(); cil_strpool_destroy();
free((*db)->val_to_type); free((*db)->val_to_type);
free((*db)->val_to_role); free((*db)->val_to_role);
free((*db)->val_to_user);
free(*db); free(*db);
*db = NULL; *db = NULL;
@ -552,6 +557,12 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_USER: case CIL_USER:
cil_destroy_user(*data); cil_destroy_user(*data);
break; break;
case CIL_USERATTRIBUTE:
cil_destroy_userattribute(*data);
break;
case CIL_USERATTRIBUTESET:
cil_destroy_userattributeset(*data);
break;
case CIL_USERPREFIX: case CIL_USERPREFIX:
cil_destroy_userprefix(*data); cil_destroy_userprefix(*data);
break; break;
@ -794,6 +805,7 @@ int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_i
*sym_index = CIL_SYM_CLASSPERMSETS; *sym_index = CIL_SYM_CLASSPERMSETS;
break; break;
case CIL_USER: case CIL_USER:
case CIL_USERATTRIBUTE:
*sym_index = CIL_SYM_USERS; *sym_index = CIL_SYM_USERS;
break; break;
case CIL_ROLE: case CIL_ROLE:
@ -924,6 +936,10 @@ const char * cil_node_to_string(struct cil_tree_node *node)
return CIL_KEY_CLASSPERMISSIONSET; return CIL_KEY_CLASSPERMISSIONSET;
case CIL_USER: case CIL_USER:
return CIL_KEY_USER; return CIL_KEY_USER;
case CIL_USERATTRIBUTE:
return CIL_KEY_USERATTRIBUTE;
case CIL_USERATTRIBUTESET:
return CIL_KEY_USERATTRIBUTESET;
case CIL_USERPREFIX: case CIL_USERPREFIX:
return CIL_KEY_USERPREFIX; return CIL_KEY_USERPREFIX;
case CIL_USERROLE: case CIL_USERROLE:
@ -2379,6 +2395,26 @@ void cil_user_init(struct cil_user **user)
(*user)->roles = NULL; (*user)->roles = NULL;
(*user)->dftlevel = NULL; (*user)->dftlevel = NULL;
(*user)->range = NULL; (*user)->range = NULL;
(*user)->value = 0;
}
void cil_userattribute_init(struct cil_userattribute **attr)
{
*attr = cil_malloc(sizeof(**attr));
cil_symtab_datum_init(&(*attr)->datum);
(*attr)->expr_list = NULL;
(*attr)->users = NULL;
}
void cil_userattributeset_init(struct cil_userattributeset **attrset)
{
*attrset = cil_malloc(sizeof(**attrset));
(*attrset)->attr_str = NULL;
(*attrset)->str_expr = NULL;
(*attrset)->datum_expr = NULL;
} }
void cil_userlevel_init(struct cil_userlevel **usrlvl) void cil_userlevel_init(struct cil_userlevel **usrlvl)

View File

@ -144,6 +144,34 @@ static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum
return SEPOL_OK; return SEPOL_OK;
} }
static int __cil_expand_user(struct cil_symtab_datum *datum, ebitmap_t *new)
{
struct cil_tree_node *node = datum->nodes->head->data;
struct cil_user *user = NULL;
struct cil_userattribute *attr = NULL;
if (node->flavor == CIL_USERATTRIBUTE) {
attr = (struct cil_userattribute *)datum;
if (ebitmap_cpy(new, attr->users)) {
cil_log(CIL_ERR, "Failed to copy user bits\n");
goto exit;
}
} else {
user = (struct cil_user *)datum;
ebitmap_init(new);
if (ebitmap_set_bit(new, user->value, 1)) {
cil_log(CIL_ERR, "Failed to set user bit\n");
ebitmap_destroy(new);
goto exit;
}
}
return SEPOL_OK;
exit:
return SEPOL_ERR;
}
static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new) static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new)
{ {
struct cil_tree_node *node = datum->nodes->head->data; struct cil_tree_node *node = datum->nodes->head->data;
@ -746,43 +774,41 @@ exit:
return SEPOL_ERR; return SEPOL_ERR;
} }
int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_userrole *userrole) int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user)
{ {
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
user_datum_t *sepol_user = NULL; user_datum_t *sepol_user = NULL;
role_datum_t *sepol_role = NULL; role_datum_t *sepol_role = NULL;
ebitmap_t role_bitmap; ebitmap_node_t *rnode = NULL;
ebitmap_node_t *rnode;
unsigned int i; unsigned int i;
rc = __cil_get_sepol_user_datum(pdb, DATUM(userrole->user), &sepol_user); if (user->roles) {
if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_user_datum(pdb, DATUM(user), &sepol_user);
if (rc != SEPOL_OK) {
rc = __cil_expand_role(userrole->role, &role_bitmap); goto exit;
if (rc != SEPOL_OK) goto exit;
ebitmap_for_each_bit(&role_bitmap, rnode, i) {
if (!ebitmap_get_bit(&role_bitmap, i)) continue;
rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role);
if (rc != SEPOL_OK) goto exit;
if (sepol_role->s.value == 1) {
// role is object_r, ignore it since it is implicitly associated
// with all users
continue;
} }
if (ebitmap_set_bit(&sepol_user->roles.roles, sepol_role->s.value - 1, 1)) { ebitmap_for_each_bit(user->roles, rnode, i) {
cil_log(CIL_INFO, "Failed to set role bit for user\n"); if (!ebitmap_get_bit(user->roles, i)) {
goto exit; continue;
}
rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role);
if (rc != SEPOL_OK) {
goto exit;
}
if (ebitmap_set_bit(&sepol_user->roles.roles, sepol_role->s.value - 1, 1)) {
cil_log(CIL_INFO, "Failed to set role bit for user\n");
rc = SEPOL_ERR;
goto exit;
}
} }
} }
rc = SEPOL_OK; rc = SEPOL_OK;
exit: exit:
ebitmap_destroy(&role_bitmap);
return rc; return rc;
} }
@ -2183,12 +2209,30 @@ int __cil_constrain_expr_datum_to_sepol_expr(policydb_t *pdb, const struct cil_d
if (expr_flavor == CIL_USER) { if (expr_flavor == CIL_USER) {
user_datum_t *sepol_user = NULL; user_datum_t *sepol_user = NULL;
rc = __cil_get_sepol_user_datum(pdb, item->data, &sepol_user); ebitmap_t user_bitmap;
ebitmap_node_t *unode;
unsigned int i;
rc = __cil_expand_user(item->data, &user_bitmap);
if (rc != SEPOL_OK) goto exit; if (rc != SEPOL_OK) goto exit;
if (ebitmap_set_bit(&expr->names, sepol_user->s.value - 1, 1)) { ebitmap_for_each_bit(&user_bitmap, unode, i) {
goto exit; if (!ebitmap_get_bit(&user_bitmap, i)) {
continue;
}
rc = __cil_get_sepol_user_datum(pdb, DATUM(db->val_to_user[i]), &sepol_user);
if (rc != SEPOL_OK) {
ebitmap_destroy(&user_bitmap);
goto exit;
}
if (ebitmap_set_bit(&expr->names, sepol_user->s.value - 1, 1)) {
ebitmap_destroy(&user_bitmap);
goto exit;
}
} }
ebitmap_destroy(&user_bitmap);
} else if (expr_flavor == CIL_ROLE) { } else if (expr_flavor == CIL_ROLE) {
role_datum_t *sepol_role = NULL; role_datum_t *sepol_role = NULL;
ebitmap_t role_bitmap; ebitmap_t role_bitmap;
@ -3374,9 +3418,10 @@ int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
if (rc != SEPOL_OK) goto exit; if (rc != SEPOL_OK) goto exit;
if (pdb->mls == CIL_TRUE) { if (pdb->mls == CIL_TRUE) {
rc = cil_userlevel_userrange_to_policydb(pdb, node->data); rc = cil_userlevel_userrange_to_policydb(pdb, node->data);
if (rc != SEPOL_OK) {
goto exit;
}
} }
break;
case CIL_USERROLE:
rc = cil_userrole_to_policydb(pdb, db, node->data); rc = cil_userrole_to_policydb(pdb, db, node->data);
break; break;
case CIL_TYPE_RULE: case CIL_TYPE_RULE:

View File

@ -184,12 +184,13 @@ int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user);
/** /**
* Insert cil userrole structure into sepol policydb. * Insert cil userrole structure into sepol policydb.
* *
* @param[in] pdb THe policy database to insert the userrole into. * @param[in] pdb The policy database to insert the userrole into.
* @param[in] datum The cil_userrole datum. * @param[in] db The cil database
* @param[in] datum The cil_user
* *
* @return SEPOL_OK upon success or SEPOL_ERR otherwise. * @return SEPOL_OK upon success or SEPOL_ERR otherwise.
*/ */
int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_userrole *userrole); int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user);
/** /**
* Insert cil bool structure into sepol policydb. * Insert cil bool structure into sepol policydb.

View File

@ -1196,10 +1196,132 @@ void cil_destroy_user(struct cil_user *user)
} }
cil_symtab_datum_destroy(&user->datum); cil_symtab_datum_destroy(&user->datum);
cil_list_destroy(&user->roles, CIL_FALSE); ebitmap_destroy(user->roles);
free(user->roles);
free(user); free(user);
} }
int cil_gen_userattribute(__attribute__((unused)) 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_STRING,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_userattribute *attr = NULL;
int rc = SEPOL_ERR;
if (parse_current == NULL || ast_node == NULL) {
goto exit;
}
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
cil_userattribute_init(&attr);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
if (rc != SEPOL_OK) {
goto exit;
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad userattribute declaration at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_userattribute(attr);
cil_clear_node(ast_node);
return rc;
}
void cil_destroy_userattribute(struct cil_userattribute *attr)
{
struct cil_list_item *expr = NULL;
struct cil_list_item *next = NULL;
if (attr == NULL) {
return;
}
if (attr->expr_list != NULL) {
/* we don't want to destroy the expression stacks (cil_list) inside
* this list cil_list_destroy destroys sublists, so we need to do it
* manually */
expr = attr->expr_list->head;
while (expr != NULL) {
next = expr->next;
cil_list_item_destroy(&expr, CIL_FALSE);
expr = next;
}
free(attr->expr_list);
attr->expr_list = NULL;
}
cil_symtab_datum_destroy(&attr->datum);
ebitmap_destroy(attr->users);
free(attr->users);
free(attr);
}
int cil_gen_userattributeset(__attribute__((unused)) 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_STRING,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userattributeset *attrset = 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_userattributeset_init(&attrset);
attrset->attr_str = parse_current->next->data;
rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr);
if (rc != SEPOL_OK) {
goto exit;
}
ast_node->data = attrset;
ast_node->flavor = CIL_USERATTRIBUTESET;
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad userattributeset declaration at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_userattributeset(attrset);
return rc;
}
void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
{
if (attrset == NULL) {
return;
}
cil_list_destroy(&attrset->str_expr, CIL_TRUE);
cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
free(attrset);
}
int cil_gen_userlevel(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) int cil_gen_userlevel(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{ {
enum cil_syntax syntax[] = { enum cil_syntax syntax[] = {
@ -5855,6 +5977,11 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
*finished = CIL_TREE_SKIP_NEXT; *finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_USER) { } else if (parse_current->data == CIL_KEY_USER) {
rc = cil_gen_user(db, parse_current, ast_node); rc = cil_gen_user(db, parse_current, ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
rc = cil_gen_userattribute(db, parse_current, ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
rc = cil_gen_userattributeset(db, parse_current, ast_node);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_USERLEVEL) { } else if (parse_current->data == CIL_KEY_USERLEVEL) {
rc = cil_gen_userlevel(db, parse_current, ast_node); rc = cil_gen_userlevel(db, parse_current, ast_node);
*finished = CIL_TREE_SKIP_NEXT; *finished = CIL_TREE_SKIP_NEXT;

View File

@ -80,6 +80,10 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str
void cil_destroy_sidorder(struct cil_sidorder *sidorder); void cil_destroy_sidorder(struct cil_sidorder *sidorder);
int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_user(struct cil_user *user); void cil_destroy_user(struct cil_user *user);
int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userattribute(struct cil_userattribute *attr);
int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userattributeset(struct cil_userattributeset *attrset);
int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userlevel(struct cil_userlevel *usrlvl); void cil_destroy_userlevel(struct cil_userlevel *usrlvl);
int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);

View File

@ -392,6 +392,41 @@ int cil_copy_user(__attribute__((unused)) struct cil_db *db, void *data, void **
return SEPOL_OK; return SEPOL_OK;
} }
int cil_copy_userattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
{
struct cil_userattribute *orig = data;
struct cil_userattribute *new = NULL;
char *key = orig->datum.name;
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
if (datum == NULL) {
cil_userattribute_init(&new);
*copy = new;
} else {
*copy = datum;
}
return SEPOL_OK;
}
int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_userattributeset *orig = data;
struct cil_userattributeset *new = NULL;
cil_userattributeset_init(&new);
new->attr_str = orig->attr_str;
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;
}
int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{ {
struct cil_userrole *orig = data; struct cil_userrole *orig = data;
@ -1717,6 +1752,12 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
case CIL_USER: case CIL_USER:
copy_func = &cil_copy_user; copy_func = &cil_copy_user;
break; break;
case CIL_USERATTRIBUTE:
copy_func = &cil_copy_userattribute;
break;
case CIL_USERATTRIBUTESET:
copy_func = &cil_copy_userattributeset;
break;
case CIL_USERROLE: case CIL_USERROLE:
copy_func = &cil_copy_userrole; copy_func = &cil_copy_userrole;
break; break;

View File

@ -57,6 +57,8 @@ int cil_copy_sid(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_sidorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sidorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userrole(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrole(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab);

View File

@ -63,6 +63,7 @@ enum cil_flavor {
CIL_CLASSPERMISSIONSET, CIL_CLASSPERMISSIONSET,
CIL_USERPREFIX, CIL_USERPREFIX,
CIL_USERROLE, CIL_USERROLE,
CIL_USERATTRIBUTESET,
CIL_USERLEVEL, CIL_USERLEVEL,
CIL_USERRANGE, CIL_USERRANGE,
CIL_USERBOUNDS, CIL_USERBOUNDS,
@ -164,6 +165,7 @@ enum cil_flavor {
CIL_MAP_CLASS, CIL_MAP_CLASS,
CIL_CLASSPERMISSION, CIL_CLASSPERMISSION,
CIL_USER, CIL_USER,
CIL_USERATTRIBUTE,
CIL_ROLE, CIL_ROLE,
CIL_ROLEATTRIBUTE, CIL_ROLEATTRIBUTE,
CIL_TYPE, CIL_TYPE,

View File

@ -127,6 +127,8 @@ char *CIL_KEY_TRANS;
char *CIL_KEY_TYPE; char *CIL_KEY_TYPE;
char *CIL_KEY_ROLE; char *CIL_KEY_ROLE;
char *CIL_KEY_USER; char *CIL_KEY_USER;
char *CIL_KEY_USERATTRIBUTE;
char *CIL_KEY_USERATTRIBUTESET;
char *CIL_KEY_SENSITIVITY; char *CIL_KEY_SENSITIVITY;
char *CIL_KEY_CATEGORY; char *CIL_KEY_CATEGORY;
char *CIL_KEY_CATSET; char *CIL_KEY_CATSET;
@ -290,8 +292,10 @@ struct cil_db {
int num_cats; int num_cats;
int num_types; int num_types;
int num_roles; int num_roles;
int num_users;
struct cil_type **val_to_type; struct cil_type **val_to_type;
struct cil_role **val_to_role; struct cil_role **val_to_role;
struct cil_user **val_to_user;
int disable_dontaudit; int disable_dontaudit;
int disable_neverallow; int disable_neverallow;
int preserve_tunables; int preserve_tunables;
@ -418,14 +422,27 @@ struct cil_sidorder {
struct cil_user { struct cil_user {
struct cil_symtab_datum datum; struct cil_symtab_datum datum;
struct cil_user *bounds; struct cil_user *bounds;
struct cil_list *roles; ebitmap_t *roles;
struct cil_level *dftlevel; struct cil_level *dftlevel;
struct cil_levelrange *range; struct cil_levelrange *range;
int value;
};
struct cil_userattribute {
struct cil_symtab_datum datum;
struct cil_list *expr_list;
ebitmap_t *users;
};
struct cil_userattributeset {
char *attr_str;
struct cil_list *str_expr;
struct cil_list *datum_expr;
}; };
struct cil_userrole { struct cil_userrole {
char *user_str; char *user_str;
struct cil_user *user; void *user;
char *role_str; char *role_str;
void *role; void *role;
}; };
@ -1002,5 +1019,7 @@ void cil_default_init(struct cil_default **def);
void cil_defaultrange_init(struct cil_defaultrange **def); void cil_defaultrange_init(struct cil_defaultrange **def);
void cil_handleunknown_init(struct cil_handleunknown **unk); void cil_handleunknown_init(struct cil_handleunknown **unk);
void cil_mls_init(struct cil_mls **mls); void cil_mls_init(struct cil_mls **mls);
void cil_userattribute_init(struct cil_userattribute **attribute);
void cil_userattributeset_init(struct cil_userattributeset **attrset);
#endif #endif

View File

@ -1155,11 +1155,6 @@ int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished,
case CIL_USER: case CIL_USER:
cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE); cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE);
break; break;
case CIL_USERROLE: {
struct cil_userrole *userrole = node->data;
cil_multimap_insert(users, &userrole->user->datum, (struct cil_symtab_datum *)userrole->role, CIL_USERROLE, CIL_ROLE);
}
break;
case CIL_CATALIAS: { case CIL_CATALIAS: {
struct cil_alias *alias = node->data; struct cil_alias *alias = node->data;
struct cil_symtab_datum *datum = alias->actual; struct cil_symtab_datum *datum = alias->actual;

View File

@ -375,6 +375,17 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini
} }
break; break;
} }
case CIL_USER: {
struct cil_user *user = node->data;
if (user->datum.nodes->head->data == node) {
// multiple AST nodes can point to the same cil_user data (like if
// copied from a macro). This check ensures we only count the
// duplicates once
user->value = db->num_users;
db->num_users++;
}
break;
}
case CIL_NETIFCON: case CIL_NETIFCON:
db->netifcon->count++; db->netifcon->count++;
break; break;
@ -446,6 +457,14 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__(
db->val_to_role[role->value] = role; db->val_to_role[role->value] = role;
break; break;
} }
case CIL_USER: {
struct cil_user *user= node->data;
if (db->val_to_user == NULL) {
db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users);
}
db->val_to_user[user->value] = user;
break;
}
case CIL_USERPREFIX: { case CIL_USERPREFIX: {
cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data); cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
break; break;
@ -638,6 +657,54 @@ exit:
return rc; return rc;
} }
static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db)
{
int rc;
attr->users = cil_malloc(sizeof(*attr->users));
rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n");
ebitmap_destroy(attr->users);
free(attr->users);
attr->users = NULL;
}
return rc;
}
static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
{
int rc = SEPOL_ERR;
struct cil_tree_node *node = datum->nodes->head->data;
struct cil_userattribute *attr = NULL;
struct cil_user *user = NULL;
ebitmap_init(bitmap);
if (node->flavor == CIL_USERATTRIBUTE) {
attr = (struct cil_userattribute *)datum;
if (attr->users == NULL) {
rc = __evaluate_user_expression(attr, db);
if (rc != SEPOL_OK) {
goto exit;
}
}
ebitmap_union(bitmap, attr->users);
} else {
user = (struct cil_user *)datum;
if (ebitmap_set_bit(bitmap, user->value, 1)) {
cil_log(CIL_ERR, "Failed to set user bit\n");
ebitmap_destroy(bitmap);
goto exit;
}
}
return SEPOL_OK;
exit:
return rc;
}
static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db) static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
{ {
int rc; int rc;
@ -941,6 +1008,9 @@ static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flav
case CIL_ROLE: case CIL_ROLE:
rc = __cil_role_to_bitmap(curr->data, bitmap, db); rc = __cil_role_to_bitmap(curr->data, bitmap, db);
break; break;
case CIL_USER:
rc = __cil_user_to_bitmap(curr->data, bitmap, db);
break;
case CIL_PERM: case CIL_PERM:
rc = __cil_perm_to_bitmap(curr->data, bitmap, db); rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
break; break;
@ -1163,6 +1233,16 @@ static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__((
if (rc != SEPOL_OK) goto exit; if (rc != SEPOL_OK) goto exit;
break; break;
} }
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = node->data;
if (attr->users == NULL) {
rc = __evaluate_user_expression(attr, db);
if (rc != SEPOL_OK) {
goto exit;
}
}
break;
}
default: default:
break; break;
} }
@ -1268,6 +1348,102 @@ exit:
return rc; return rc;
} }
static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum)
{
struct cil_tree_node *node = datum->nodes->head->data;
struct cil_role *role = NULL;
struct cil_roleattribute *attr = NULL;
if (user->roles == NULL) {
user->roles = cil_malloc(sizeof(*user->roles));
ebitmap_init(user->roles);
}
if (node->flavor == CIL_ROLE) {
role = (struct cil_role *)datum;
if (ebitmap_set_bit(user->roles, role->value, 1)) {
cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n");
goto exit;
}
} else if (node->flavor == CIL_ROLEATTRIBUTE) {
attr = (struct cil_roleattribute *)datum;
ebitmap_union(user->roles, attr->roles);
}
return SEPOL_OK;
exit:
return SEPOL_ERR;
}
static int __cil_post_db_userrole_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_db *db = extra_args;
struct cil_block *blk = NULL;
struct cil_userrole *userrole = NULL;
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *role_datum = NULL;
struct cil_tree_node *user_node = NULL;
struct cil_userattribute *u_attr = NULL;
unsigned int i;
struct cil_user *user = NULL;
ebitmap_node_t *unode = NULL;
switch (node->flavor) {
case CIL_BLOCK: {
blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
}
break;
}
case CIL_MACRO: {
*finished = CIL_TREE_SKIP_HEAD;
break;
}
case CIL_USERROLE: {
userrole = node->data;
user_datum = userrole->user;
role_datum = userrole->role;
user_node = user_datum->nodes->head->data;
if (user_node->flavor == CIL_USERATTRIBUTE) {
u_attr = userrole->user;
ebitmap_for_each_bit(u_attr->users, unode, i) {
if (!ebitmap_get_bit(u_attr->users, i)) {
continue;
}
user = db->val_to_user[i];
rc = __cil_user_assign_roles(user, role_datum);
if (rc != SEPOL_OK) {
goto exit;
}
}
} else {
user = userrole->user;
rc = __cil_user_assign_roles(user, role_datum);
if (rc != SEPOL_OK) {
goto exit;
}
}
break;
}
default:
break;
}
return SEPOL_OK;
exit:
cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n");
return rc;
}
static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db) static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
{ {
if (level->cats != NULL) { if (level->cats != NULL) {
@ -1739,6 +1915,12 @@ static int cil_post_db(struct cil_db *db)
goto exit; goto exit;
} }
rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed during userrole association\n");
goto exit;
}
rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db); rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n"); cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");

View File

@ -99,7 +99,32 @@ static void cil_reset_user(struct cil_user *user)
user->bounds = NULL; user->bounds = NULL;
user->dftlevel = NULL; user->dftlevel = NULL;
user->range = NULL; user->range = NULL;
cil_list_destroy(&user->roles, CIL_FALSE); }
static void cil_reset_userattr(struct cil_userattribute *attr)
{
struct cil_list_item *expr = NULL;
struct cil_list_item *next = NULL;
/* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a userattribute statement */
if (attr->expr_list != NULL) {
/* we don't want to destroy the expression stacks (cil_list) inside
* this list cil_list_destroy destroys sublists, so we need to do it
* manually */
expr = attr->expr_list->head;
while (expr != NULL) {
next = expr->next;
cil_list_item_destroy(&expr, CIL_FALSE);
expr = next;
}
free(attr->expr_list);
attr->expr_list = NULL;
}
}
static void cil_reset_userattributeset(struct cil_userattributeset *uas)
{
cil_list_destroy(&uas->datum_expr, CIL_FALSE);
} }
static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser) static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
@ -403,6 +428,12 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_USER: case CIL_USER:
cil_reset_user(node->data); cil_reset_user(node->data);
break; break;
case CIL_USERATTRIBUTE:
cil_reset_userattr(node->data);
break;
case CIL_USERATTRIBUTESET:
cil_reset_userattributeset(node->data);
break;
case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSERDEFAULT:
case CIL_SELINUXUSER: case CIL_SELINUXUSER:
cil_reset_selinuxuser(node->data); cil_reset_selinuxuser(node->data);

View File

@ -820,12 +820,6 @@ int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args)
} }
userrole->role = role_datum; userrole->role = role_datum;
if (userrole->user->roles == NULL) {
cil_list_init(&userrole->user->roles, CIL_LIST_ITEM);
}
cil_list_append(userrole->user->roles, CIL_ROLE, userrole->role);
return SEPOL_OK; return SEPOL_OK;
exit: exit:
@ -838,12 +832,22 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args)
struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *lvl_datum = NULL; struct cil_symtab_datum *lvl_datum = NULL;
struct cil_user *user = NULL; struct cil_user *user = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum); rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userlevel must be a user\n");
rc = SEPOL_ERR;
goto exit;
}
user = (struct cil_user*)user_datum; user = (struct cil_user*)user_datum;
if (usrlvl->level_str != NULL) { if (usrlvl->level_str != NULL) {
@ -881,12 +885,22 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args)
struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *range_datum = NULL; struct cil_symtab_datum *range_datum = NULL;
struct cil_user *user = NULL; struct cil_user *user = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum); rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
user = (struct cil_user*)user_datum; user = (struct cil_user*)user_datum;
if (userrange->range_str != NULL) { if (userrange->range_str != NULL) {
@ -922,12 +936,22 @@ int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args)
{ {
struct cil_userprefix *userprefix = current->data; struct cil_userprefix *userprefix = current->data;
struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *user_datum = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum); rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
userprefix->user = (struct cil_user*)user_datum; userprefix->user = (struct cil_user*)user_datum;
exit: exit:
@ -939,12 +963,22 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args)
struct cil_selinuxuser *selinuxuser = current->data; struct cil_selinuxuser *selinuxuser = current->data;
struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *lvlrange_datum = NULL; struct cil_symtab_datum *lvlrange_datum = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum); rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
selinuxuser->user = (struct cil_user*)user_datum; selinuxuser->user = (struct cil_user*)user_datum;
if (selinuxuser->range_str != NULL) { if (selinuxuser->range_str != NULL) {
@ -1715,7 +1749,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *role_datum = NULL; struct cil_symtab_datum *role_datum = NULL;
struct cil_symtab_datum *type_datum = NULL; struct cil_symtab_datum *type_datum = NULL;
struct cil_tree_node *type_node = NULL; struct cil_tree_node *node = NULL;
struct cil_symtab_datum *lvlrange_datum = NULL; struct cil_symtab_datum *lvlrange_datum = NULL;
int rc = SEPOL_ERR; int rc = SEPOL_ERR;
@ -1724,12 +1758,29 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
node = user_datum->nodes->head->data;
if (node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
context->user = (struct cil_user*)user_datum; context->user = (struct cil_user*)user_datum;
rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum); rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
if (rc != SEPOL_OK) { if (rc != SEPOL_OK) {
goto exit; goto exit;
} }
node = role_datum->nodes->head->data;
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
goto exit;
}
context->role = (struct cil_role*)role_datum; context->role = (struct cil_role*)role_datum;
rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum); rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
@ -1737,9 +1788,9 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
goto exit; goto exit;
} }
type_node = type_datum->nodes->head->data; node = type_datum->nodes->head->data;
if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) { if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
rc = SEPOL_ERR; rc = SEPOL_ERR;
cil_log(CIL_ERR, "Type not a type or type alias\n"); cil_log(CIL_ERR, "Type not a type or type alias\n");
goto exit; goto exit;
@ -3036,6 +3087,48 @@ exit:
return rc; return rc;
} }
int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_userattributeset *attrusers = current->data;
struct cil_symtab_datum *attr_datum = NULL;
struct cil_tree_node *attr_node = NULL;
struct cil_userattribute *attr = NULL;
rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, extra_args, &attr_datum);
if (rc != SEPOL_OK) {
goto exit;
}
attr_node = attr_datum->nodes->head->data;
if (attr_node->flavor != CIL_USERATTRIBUTE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Attribute user not an attribute\n");
goto exit;
}
attr = (struct cil_userattribute*)attr_datum;
rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
if (rc != SEPOL_OK) {
goto exit;
}
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
}
cil_list_append(attr->expr_list, CIL_LIST, attrusers->datum_expr);
return SEPOL_OK;
exit:
return rc;
}
int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
{ {
@ -3296,6 +3389,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
case CIL_DEFAULTRANGE: case CIL_DEFAULTRANGE:
rc = cil_resolve_defaultrange(node, args); rc = cil_resolve_defaultrange(node, args);
break; break;
case CIL_USERATTRIBUTESET:
rc = cil_resolve_userattributeset(node, args);
break;
default: default:
break; break;
} }

View File

@ -54,6 +54,7 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args); int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userbounds(struct cil_tree_node *current, void *extra_args); int cil_resolve_userbounds(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args); int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args);
int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args); int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args);
int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args); int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args);
int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args); int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args);

View File

@ -640,15 +640,18 @@ void cil_tree_print_node(struct cil_tree_node *node)
case CIL_USERROLE: { case CIL_USERROLE: {
struct cil_userrole *userrole = node->data; struct cil_userrole *userrole = node->data;
cil_log(CIL_INFO, "USERROLE:"); cil_log(CIL_INFO, "USERROLE:");
struct cil_symtab_datum *datum = NULL;
if (userrole->user != NULL) { if (userrole->user != NULL) {
cil_log(CIL_INFO, " %s", userrole->user->datum.name); datum = userrole->user;
cil_log(CIL_INFO, " %s", datum->name);
} else if (userrole->user_str != NULL) { } else if (userrole->user_str != NULL) {
cil_log(CIL_INFO, " %s", userrole->user_str); cil_log(CIL_INFO, " %s", userrole->user_str);
} }
if (userrole->role != NULL) { if (userrole->role != NULL) {
cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)userrole->role)->name); datum = userrole->role;
cil_log(CIL_INFO, " %s", datum->name);
} else if (userrole->role_str != NULL) { } else if (userrole->role_str != NULL) {
cil_log(CIL_INFO, " %s", userrole->role_str); cil_log(CIL_INFO, " %s", userrole->role_str);
} }
@ -785,6 +788,21 @@ void cil_tree_print_node(struct cil_tree_node *node)
cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name); cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
return; return;
} }
case CIL_USERATTRIBUTESET: {
struct cil_userattributeset *attr = node->data;
cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
cil_tree_print_expr(attr->datum_expr, attr->str_expr);
cil_log(CIL_INFO, "\n");
return;
}
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = node->data;
cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
return;
}
case CIL_ROLEBOUNDS: { case CIL_ROLEBOUNDS: {
struct cil_bounds *bnds = node->data; struct cil_bounds *bnds = node->data;
cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);

View File

@ -737,16 +737,8 @@ int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
int found = CIL_FALSE; int found = CIL_FALSE;
if (user->roles != NULL) { if (user->roles != NULL) {
cil_list_for_each(curr, user->roles) { if (!ebitmap_get_bit(user->roles, role->value)) {
struct cil_role *userrole = curr->data; cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
if (userrole == role) {
break;
}
}
if (curr == NULL) {
cil_log(CIL_ERR, "Role %s is invalid for user %s\n",
ctx->role_str, ctx->user_str);
rc = SEPOL_ERR; rc = SEPOL_ERR;
goto exit; goto exit;
} }

View File

@ -51,7 +51,7 @@
<simpara>and:</simpara> <simpara>and:</simpara>
<simpara><literal> op : eq neq</literal></simpara> <simpara><literal> op : eq neq</literal></simpara>
<simpara><literal> role_op : eq neq dom domby incomp</literal></simpara> <simpara><literal> role_op : eq neq dom domby incomp</literal></simpara>
<simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara> <simpara><literal> user_id : A single <link linkend="user">user</link> or <link linkend="userattribute">userattribute</link> identifier.</literal></simpara>
<simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara> <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
<simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara> <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
</entry> </entry>
@ -154,7 +154,7 @@
<simpara>and:</simpara> <simpara>and:</simpara>
<simpara><literal> op : eq neq</literal></simpara> <simpara><literal> op : eq neq</literal></simpara>
<simpara><literal> role_op : eq neq dom domby incomp</literal></simpara> <simpara><literal> role_op : eq neq dom domby incomp</literal></simpara>
<simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara> <simpara><literal> user_id : A single <link linkend="user">user</link> or <link linkend="userattribute">userattribute</link> identifier.</literal></simpara>
<simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara> <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
<simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara> <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
</entry> </entry>
@ -236,7 +236,7 @@
<simpara>and:</simpara> <simpara>and:</simpara>
<simpara><literal> op : eq neq</literal></simpara> <simpara><literal> op : eq neq</literal></simpara>
<simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara> <simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara>
<simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara> <simpara><literal> user_id : A single <link linkend="user">user</link> or <link linkend="userattribute">userattribute</link> identifier.</literal></simpara>
<simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara> <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
<simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara> <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
</entry> </entry>
@ -332,7 +332,7 @@
<simpara>and:</simpara> <simpara>and:</simpara>
<simpara><literal> op : eq neq</literal></simpara> <simpara><literal> op : eq neq</literal></simpara>
<simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara> <simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara>
<simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara> <simpara><literal> user_id : A single <link linkend="user">user</link> or <link linkend="userattribute">userattribute</link> identifier.</literal></simpara>
<simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara> <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
<simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara> <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
</entry> </entry>

View File

@ -66,7 +66,7 @@
<para><literal>user_id</literal></para> <para><literal>user_id</literal></para>
</entry> </entry>
<entry> <entry>
<para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para> <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> or <literal><link linkend="userattribute">userattribute</link></literal> identifier.</para>
</entry> </entry>
</row> </row>
<row> <row>
@ -91,6 +91,114 @@
</programlisting> </programlisting>
</sect2> </sect2>
<sect2 id="userattribute">
<title>userattribute</title>
<para>Declares a user attribute identifier in the current namespace. The identifier may have zero or more <literal><link linkend="user">user</link></literal> and <literal><link linkend="userattribute">userattribute</link></literal> identifiers associated to it via the <literal><link linkend="userattributeset">userattributeset</link></literal> statement.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(userattribute userattribute_id)]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal>userattribute</literal></para>
</entry>
<entry>
<para>The <literal>userattribute</literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>userattribute_id</literal></para>
</entry>
<entry>
<para>The <literal>userattribute</literal> identifier.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>This example will declare a user attribute <literal>users.user_holder</literal> that will have an empty set:</para>
<programlisting><![CDATA[
(block users
(userattribute user_holder)
)]]>
</programlisting>
</sect2>
<sect2 id="userattributeset">
<title>userattributeset</title>
<para>Allows the association of one or more previously declared <literal><link linkend="user">user</link></literal> or <literal><link linkend="userattribute">userattribute</link></literal> identifiers to a <literal><link linkend="userattribute">userattribute</link></literal> identifier. Expressions may be used to refine the associations as shown in the examples.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(userattributeset userattribute_id (user_id ... | expr ...))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal>userattributeset</literal></para>
</entry>
<entry>
<para>The <literal>userattributeset</literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>userattribute_id</literal></para>
</entry>
<entry>
<para>A single previously declared <literal><link linkend="roleattribute">userattribute</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>user_id</literal></para>
</entry>
<entry>
<para>Zero or more previously declared <literal><link linkend="role">user</link></literal> or <literal><link linkend="userattribute">userattribute</link></literal> identifiers.</para>
<para>Note that there must be at least one <literal>user_id</literal> or <literal>expr</literal> parameter declared.</para>
</entry>
</row>
<row>
<entry>
<para><literal>expr</literal></para>
</entry>
<entry>
<para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
<simpara><literal> (and (user_id ...) (user_id ...))</literal></simpara>
<simpara><literal> (or (user_id ...) (user_id ...))</literal></simpara>
<simpara><literal> (xor (user_id ...) (user_id ...))</literal></simpara>
<simpara><literal> (not (user_id ...))</literal></simpara>
<simpara><literal> (all)</literal></simpara>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>This example will declare three users and two user attributes, then associate all the users to them as shown:</para>
<programlisting><![CDATA[
(block users
(user user_1)
(user user_2)
(user user_3)
(userattribute user_holder)
(userattributeset user_holder (user_1 user_2 user_3))
(userattribute user_holder_all)
(userattributeset user_holder_all (all))
)]]>
</programlisting>
</sect2>
<sect2 id="userlevel"> <sect2 id="userlevel">
<title>userlevel</title> <title>userlevel</title>
<para>Associates a previously declared <literal><link linkend="user">user</link></literal> identifier with a previously declared <literal><link linkend="level">level</link></literal> identifier. The <literal><link linkend="level">level</link></literal> may be named or anonymous.</para> <para>Associates a previously declared <literal><link linkend="user">user</link></literal> identifier with a previously declared <literal><link linkend="level">level</link></literal> identifier. The <literal><link linkend="level">level</link></literal> may be named or anonymous.</para>

View File

@ -124,7 +124,9 @@
(roleattribute foo_role) (roleattribute foo_role)
(roleattribute bar_role) (roleattribute bar_role)
(roleattribute baz_role) (roleattribute baz_role)
(roleattribute foo_role_a)
(roleattributeset exec_role (or user_r system_r)) (roleattributeset exec_role (or user_r system_r))
(roleattributeset foo_role_a (baz_r user_r system_r))
(roleattributeset foo_role (and exec_role system_r)) (roleattributeset foo_role (and exec_role system_r))
(roleattributeset bar_role (xor exec_role foo_role)) (roleattributeset bar_role (xor exec_role foo_role))
(roleattributeset baz_role (not user_r)) (roleattributeset baz_role (not user_r))
@ -194,6 +196,7 @@
(role system_r) (role system_r)
(role user_r) (role user_r)
(role baz_r)
(roletype system_r bin_t) (roletype system_r bin_t)
(roletype system_r kernel_t) (roletype system_r kernel_t)
@ -207,6 +210,23 @@
(userrole foo_u foo_role) (userrole foo_u foo_role)
(userlevel foo_u low) (userlevel foo_u low)
(userattribute ua1)
(userattribute ua2)
(userattribute ua3)
(userattribute ua4)
(userattributeset ua1 (user_u system_u))
(userattributeset ua2 (foo_u system_u))
(userattributeset ua3 (and ua1 ua2))
(user u5)
(user u6)
(userlevel u5 low)
(userlevel u6 low)
(userrange u5 low_high)
(userrange u6 low_high)
(userattributeset ua4 (u5 u6))
(userrole ua4 foo_role_a)
(userrange foo_u low_high) (userrange foo_u low_high)
(userrole system_u system_r) (userrole system_u system_r)
@ -253,7 +273,7 @@
(constrain (files (read)) (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2)))) (constrain (files (read)) (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
(constrain char_w (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2)))) (constrain char_w (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
(constrain (file (read)) (or (and (eq t1 exec_t) (neq t2 bin_t) ) (eq u1 u2) ) ) (constrain (file (read)) (or (and (eq t1 exec_t) (neq t2 bin_t) ) (eq u1 ua4) ) )
(constrain (file (open)) (dom r1 r2)) (constrain (file (open)) (dom r1 r2))
(constrain (file (open)) (domby r1 r2)) (constrain (file (open)) (domby r1 r2))
(constrain (file (open)) (incomp r1 r2)) (constrain (file (open)) (incomp r1 r2))