Skip to content

Commit

Permalink
libsepol/cil: add support for xperms in conditional policies
Browse files Browse the repository at this point in the history
Add support for extended permission rules in conditional policies.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
  • Loading branch information
cgzones committed Apr 5, 2024
1 parent 22fcfa7 commit 1b26e7e
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 21 deletions.
99 changes: 84 additions & 15 deletions libsepol/cil/src/cil_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,14 @@ struct cil_args_booleanif {
policydb_t *pdb;
cond_node_t *cond_node;
enum cil_flavor cond_flavor;
hashtab_t avrulex_ioctl_table;
};

static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hashtab_key_t key);
static int avrulex_compare(hashtab_t h
__attribute__ ((unused)), const_hashtab_key_t key1,
const_hashtab_key_t key2);

static int __cil_get_sepol_user_datum(policydb_t *pdb, struct cil_symtab_datum *datum, user_datum_t **sepol_user)
{
*sepol_user = hashtab_search(pdb->p_users.table, datum->fqn);
Expand Down Expand Up @@ -1742,7 +1748,10 @@ static int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil
static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args)
{
int rc = SEPOL_OK;
struct policydb *pdb;
struct cil_args_booleanif *booleanif_args = args;
struct policydb *pdb = booleanif_args->pdb;
cond_node_t *cond_node = booleanif_args->cond_node;
enum cil_flavor cond_flavor = booleanif_args->cond_flavor;
avtab_key_t *avtab_key;
avtab_datum_t avtab_datum;
struct cil_list *xperms_list = NULL;
Expand All @@ -1751,7 +1760,6 @@ static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datu
uint32_t data = 0;

avtab_key = (avtab_key_t *)k;
pdb = args;

sepol_obj = pdb->class_val_to_struct[avtab_key->target_class - 1];

Expand All @@ -1771,7 +1779,12 @@ static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datu

cil_list_for_each(item, xperms_list) {
avtab_datum.xperms = item->data;
rc = avtab_insert(&pdb->te_avtab, avtab_key, &avtab_datum);

if (cond_node) {
rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, avtab_key, &avtab_datum, cond_node, cond_flavor);
} else {
rc = avtab_insert(&pdb->te_avtab, avtab_key, &avtab_datum);
}
if (rc != SEPOL_OK) {
goto exit;
}
Expand Down Expand Up @@ -1846,7 +1859,7 @@ static int __cil_avrulex_ioctl_to_hashtable(hashtab_t h, uint16_t kind, uint32_t
return rc;
}

static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_permissionx *permx, struct cil_args_binary *args)
static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_permissionx *permx, hashtab_t h)
{
int rc = SEPOL_ERR;
type_datum_t *sepol_src = NULL;
Expand All @@ -1869,7 +1882,7 @@ static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, str

switch (permx->kind) {
case CIL_PERMX_KIND_IOCTL:
rc = __cil_avrulex_ioctl_to_hashtable(args->avrulex_ioctl_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms);
rc = __cil_avrulex_ioctl_to_hashtable(h, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms);
if (rc != SEPOL_OK) goto exit;
break;
default:
Expand All @@ -1886,7 +1899,7 @@ static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, str
return rc;
}

static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrulex, struct cil_args_binary *args)
static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrulex, hashtab_t h)
{
int rc = SEPOL_ERR;
uint16_t kind;
Expand All @@ -1912,7 +1925,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st

ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
src = DATUM(db->val_to_type[s]);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&src_bitmap);
goto exit;
Expand All @@ -1930,7 +1943,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
for (t = 0; t < (unsigned int)db->num_types; t++) {
if (s != t) {
tgt = DATUM(db->val_to_type[t]);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&src_bitmap);
goto exit;
Expand All @@ -1950,7 +1963,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
if (s != t) {
tgt = DATUM(db->val_to_type[t]);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&src_bitmap);
goto exit;
Expand All @@ -1964,7 +1977,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
int expand_tgt = __cil_should_expand_attribute(db, tgt);

if (!expand_src && !expand_tgt) {
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
goto exit;
}
Expand All @@ -1985,7 +1998,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) {
tgt = DATUM(db->val_to_type[t]);

rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&src_bitmap);
ebitmap_destroy(&tgt_bitmap);
Expand All @@ -2004,7 +2017,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
src = DATUM(db->val_to_type[s]);

rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&src_bitmap);
goto exit;
Expand All @@ -2020,7 +2033,7 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) {
tgt = DATUM(db->val_to_type[t]);

rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, h);
if (rc != SEPOL_OK) {
ebitmap_destroy(&tgt_bitmap);
goto exit;
Expand Down Expand Up @@ -2089,6 +2102,21 @@ static int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute
goto exit;
}
break;
case CIL_AVRULEX:
if (db->policy_version < POLICYDB_VERSION_COND_XPERMS) {
cil_tree_log(node, CIL_ERR, "Extended permission rules are not supported in policy version %d\n",
db->policy_version);
rc = SEPOL_ERR;
goto exit;
}
cil_avrule = node->data;
rc = cil_avrulex_to_hashtable(pdb, db, cil_avrule, args->avrulex_ioctl_table);
if (rc != SEPOL_OK) {
cil_tree_log(node, CIL_ERR, "Failed to insert avrulex into avtab");
goto exit;
}
break;

case CIL_CALL:
case CIL_TUNABLEIF:
break;
Expand Down Expand Up @@ -2395,6 +2423,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
int was_created;
int swapped = CIL_FALSE;
cond_av_list_t tmp_cl;
hashtab_t avrulex_ioctl_table = NULL;

tmp_cond = cond_node_create(pdb, NULL);
if (tmp_cond == NULL) {
Expand Down Expand Up @@ -2463,26 +2492,60 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
bool_args.cond_node = cond_node;

if (true_node != NULL) {
avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE);
if (!avrulex_ioctl_table) {
cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n");
goto exit;
}

bool_args.cond_flavor = CIL_CONDTRUE;
bool_args.avrulex_ioctl_table = avrulex_ioctl_table;
rc = cil_tree_walk(true_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args);
if (rc != SEPOL_OK) {
cil_tree_log(true_node, CIL_ERR, "Failure while walking true conditional block");
goto exit;
}

rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &bool_args);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failure creating avrulex rules\n");
goto exit;
}
hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
avrulex_ioctl_table = NULL;
}

if (false_node != NULL) {
avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE);
if (!avrulex_ioctl_table) {
cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n");
goto exit;
}

bool_args.cond_flavor = CIL_CONDFALSE;
bool_args.avrulex_ioctl_table = avrulex_ioctl_table;
rc = cil_tree_walk(false_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args);
if (rc != SEPOL_OK) {
cil_tree_log(false_node, CIL_ERR, "Failure while walking false conditional block");
goto exit;
}

rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &bool_args);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failure creating avrulex rules\n");
goto exit;
}
hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
avrulex_ioctl_table = NULL;
}

return SEPOL_OK;

exit:
hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
if (tmp_cond) {
if (tmp_cond->expr)
cond_expr_destroy(tmp_cond->expr);
Expand Down Expand Up @@ -4057,7 +4120,7 @@ static int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
case CIL_AVRULEX: {
struct cil_avrule *rule = node->data;
if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) {
rc = cil_avrulex_to_hashtable(pdb, db, node->data, args);
rc = cil_avrulex_to_hashtable(pdb, db, node->data, args->avrulex_ioctl_table);
}
}
break;
Expand Down Expand Up @@ -5132,6 +5195,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
int rc = SEPOL_ERR;
int i;
struct cil_args_binary extra_args;
struct cil_args_booleanif booleanif_args;
policydb_t *pdb = &policydb->p;
struct cil_list *neverallows = NULL;
hashtab_t role_trans_table = NULL;
Expand Down Expand Up @@ -5192,6 +5256,11 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
extra_args.avrulex_ioctl_table = avrulex_ioctl_table;
extra_args.type_value_to_cil = type_value_to_cil;

booleanif_args.db = db;
booleanif_args.pdb = pdb;
booleanif_args.cond_node = NULL;
booleanif_args.cond_flavor = CIL_NONE;

for (i = 1; i <= 3; i++) {
extra_args.pass = i;

Expand All @@ -5210,7 +5279,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
}

if (i == 3) {
rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, pdb);
rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &booleanif_args);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failure creating avrulex rules\n");
goto exit;
Expand Down
8 changes: 6 additions & 2 deletions libsepol/cil/src/cil_build_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -6166,11 +6166,15 @@ static int check_for_illegal_statement(struct cil_tree_node *parse_current, stru
parse_current->data != CIL_KEY_AUDITALLOW &&
parse_current->data != CIL_KEY_TYPETRANSITION &&
parse_current->data != CIL_KEY_TYPECHANGE &&
parse_current->data != CIL_KEY_TYPEMEMBER) {
parse_current->data != CIL_KEY_TYPEMEMBER &&
((args->db->policy_version < POLICYDB_VERSION_COND_XPERMS) ||
(parse_current->data != CIL_KEY_ALLOWX &&
parse_current->data != CIL_KEY_DONTAUDITX &&
parse_current->data != CIL_KEY_AUDITALLOWX))) {
if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
} else {
cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif1", (char *)parse_current->data);
}
return SEPOL_ERR;
}
Expand Down
8 changes: 5 additions & 3 deletions libsepol/cil/src/cil_resolve_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -3848,9 +3848,11 @@ static int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *f
node->flavor != CIL_CONDBLOCK &&
node->flavor != CIL_AVRULE &&
node->flavor != CIL_TYPE_RULE &&
node->flavor != CIL_NAMETYPETRANSITION) {
node->flavor != CIL_NAMETYPETRANSITION &&
((args->db->policy_version < POLICYDB_VERSION_COND_XPERMS) ||
(node->flavor != CIL_AVRULEX))) {
rc = SEPOL_ERR;
} else if (node->flavor == CIL_AVRULE) {
} else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) {
struct cil_avrule *rule = node->data;
if (rule->rule_kind == CIL_AVRULE_NEVERALLOW) {
rc = SEPOL_ERR;
Expand All @@ -3860,7 +3862,7 @@ static int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *f
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node));
} else {
cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node));
cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif2", cil_node_to_string(node));
}
goto exit;
}
Expand Down
3 changes: 2 additions & 1 deletion libsepol/cil/src/cil_verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,8 @@ static int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute
struct cil_booleanif *bif = node->parent->parent->data;

switch (rule_node->flavor) {
case CIL_AVRULE: {
case CIL_AVRULE:
case CIL_AVRULEX: {
struct cil_avrule *avrule = NULL;
avrule = rule_node->data;
if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
Expand Down
2 changes: 2 additions & 0 deletions secilc/test/policy.cil
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,11 @@
(true
(typechange auditadm_t console_device_t file user_tty_device_t)
(allow getty_t console_device_t (file (getattr open read write append)))
(auditallowx getty_t console_device_t (ioctl file (range 0x2000 0x21FF)))
)
(false
(dontaudit getty_t console_device_t (file (getattr open read write append)))
(dontauditx getty_t console_device_t (ioctl file (range 0x3000 0x31FF)))
)
)

Expand Down

0 comments on commit 1b26e7e

Please sign in to comment.