diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index f8a10154e8..3c5def9ea3 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -1859,6 +1859,8 @@ int define_bool_tunable(int is_tunable) avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl) { + avrule_t *last; + if (pass == 1) { /* return something so we get through pass 1 */ return (avrule_t *) 1; @@ -1869,8 +1871,12 @@ avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl) return avlist; } - /* prepend the new avlist to the pre-existing one */ - sl->next = avlist; + /* Prepend the new avlist to the pre-existing one. + * An extended permission statement might consist of multiple av + * rules. */ + for (last = sl; last->next; last = last->next) + ; + last->next = avlist; return sl; } @@ -1972,7 +1978,7 @@ static int avrule_read_xperm_ranges(struct av_xperm_range_list **rangehead) id = queue_remove(id_queue); r->range.high = (uint16_t) strtoul(id,NULL,0); if (r->range.high < r->range.low) { - yyerror2("Ioctl range %d-%d must be in ascending order.", + yyerror2("extended permission range %#x-%#x must be in ascending order.", r->range.low, r->range.high); return -1; } @@ -2454,9 +2460,9 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src) return 0; } -static int define_te_avtab_ioctl(const avrule_t *avrule_template) +static int define_te_avtab_ioctl(const avrule_t *avrule_template, avrule_t **ret_avrules) { - avrule_t *avrule; + avrule_t *avrule, *ret = NULL, **last = &ret; struct av_xperm_range_list *rangelist, *r; av_extended_perms_t *complete_driver, *partial_driver, *xperms; unsigned int i; @@ -2478,7 +2484,13 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template) if (avrule_cpy(avrule, avrule_template)) return -1; avrule->xperms = complete_driver; - append_avrule(avrule); + + if (ret_avrules) { + *last = avrule; + last = &(avrule->next); + } else { + append_avrule(avrule); + } } /* flag ioctl driver codes that are partially enabled */ @@ -2507,7 +2519,13 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template) if (avrule_cpy(avrule, avrule_template)) return -1; avrule->xperms = xperms; - append_avrule(avrule); + + if (ret_avrules) { + *last = avrule; + last = &(avrule->next); + } else { + append_avrule(avrule); + } } } @@ -2521,12 +2539,15 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template) free(r); } + if (ret_avrules) + *ret_avrules = ret; + return 0; } -static int define_te_avtab_netlink(const avrule_t *avrule_template) +static int define_te_avtab_netlink(const avrule_t *avrule_template, avrule_t **ret_avrules) { - avrule_t *avrule; + avrule_t *avrule, *ret = NULL, **last = &ret; struct av_xperm_range_list *rangelist, *r; av_extended_perms_t *partial_driver, *xperms; unsigned int i; @@ -2561,7 +2582,13 @@ static int define_te_avtab_netlink(const avrule_t *avrule_template) if (avrule_cpy(avrule, avrule_template)) return -1; avrule->xperms = xperms; - append_avrule(avrule); + + if (ret_avrules) { + *last = avrule; + last = &(avrule->next); + } else { + append_avrule(avrule); + } } } @@ -2575,9 +2602,64 @@ static int define_te_avtab_netlink(const avrule_t *avrule_template) free(r); } + if (ret_avrules) + *ret_avrules = ret; + return 0; } +avrule_t *define_cond_te_avtab_extended_perms(int which) +{ + char *id; + unsigned int i; + avrule_t *avrule_template, *rules = NULL; + int rc = 0; + + if (policydbp->policy_type == POLICY_KERN && policydbp->policyvers < POLICYDB_VERSION_COND_XPERMS) { + yyerror2("extended permissions in conditional policies are only supported since policy version %d, found policy version %d", + POLICYDB_VERSION_COND_XPERMS, policydbp->policyvers); + return COND_ERR; + } + if (policydbp->policy_type != POLICY_KERN && policydbp->policyvers < MOD_POLICYDB_VERSION_COND_XPERMS) { + yyerror2("extended permissions in conditional policies are only supported since module policy version %d, found module policy version %d", + MOD_POLICYDB_VERSION_COND_XPERMS, policydbp->policyvers); + return COND_ERR; + } + + if (pass == 1) { + for (i = 0; i < 4; i++) { + while ((id = queue_remove(id_queue))) + free(id); + } + return (avrule_t *) 1; /* any non-NULL value */ + } + + /* populate avrule template with source/target/tclass */ + if (define_te_avtab_xperms_helper(which, &avrule_template)) + return COND_ERR; + + id = queue_remove(id_queue); + if (strcmp(id, "ioctl") == 0) { + rc = define_te_avtab_ioctl(avrule_template, &rules); + } else if (strcmp(id, "nlmsg") == 0) { + rc = define_te_avtab_netlink(avrule_template, &rules); + } else { + yyerror2("only ioctl and nlmsg extended permissions are supported, found %s", id); + rc = -1; + } + + free(id); + avrule_destroy(avrule_template); + free(avrule_template); + + if (rc) { + avrule_destroy(rules); + return NULL; + } + + return rules; +} + int define_te_avtab_extended_perms(int which) { char *id; @@ -2599,11 +2681,11 @@ int define_te_avtab_extended_perms(int which) id = queue_remove(id_queue); if (strcmp(id,"ioctl") == 0) { - rc = define_te_avtab_ioctl(avrule_template); + rc = define_te_avtab_ioctl(avrule_template, NULL); } else if (strcmp(id,"nlmsg") == 0) { - rc = define_te_avtab_netlink(avrule_template); + rc = define_te_avtab_netlink(avrule_template, NULL); } else { - yyerror2("only ioctl extended permissions are supported, found %s", id); + yyerror2("only ioctl and nlmsg extended permissions are supported, found %s", id); rc = -1; } diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h index ef74f6169a..216da3ad68 100644 --- a/checkpolicy/policy_define.h +++ b/checkpolicy/policy_define.h @@ -15,6 +15,7 @@ avrule_t *define_cond_compute_type(int which); avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *sl); avrule_t *define_cond_te_avtab(int which); +avrule_t *define_cond_te_avtab_extended_perms(int which); avrule_t *define_cond_filename_trans(void); cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2); int define_attrib(void); diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y index ed1786d809..7e11722261 100644 --- a/checkpolicy/policy_parse.y +++ b/checkpolicy/policy_parse.y @@ -74,6 +74,7 @@ typedef int (* require_func_t)(int pass); %type cond_expr cond_expr_prim cond_pol_list cond_else %type cond_allow_def cond_auditallow_def cond_auditdeny_def cond_dontaudit_def +%type cond_xperm_allow_def cond_xperm_auditallow_def cond_xperm_dontaudit_def %type cond_transition_def cond_te_avtab_def cond_rule_def %type cexpr cexpr_prim op role_mls_op %type ipv4_addr_def number @@ -432,6 +433,12 @@ cond_te_avtab_def : cond_allow_def { $$ = $1; } | cond_dontaudit_def { $$ = $1; } + | cond_xperm_allow_def + { $$ = $1; } + | cond_xperm_auditallow_def + { $$ = $1; } + | cond_xperm_dontaudit_def + { $$ = $1; } ; cond_allow_def : ALLOW names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_ALLOWED) ; @@ -449,7 +456,18 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_DONTAUDIT); if ($$ == COND_ERR) YYABORT; } ; - ; +cond_xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';' + { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED) ; + if ($$ == COND_ERR) YYABORT; } + ; +cond_xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';' + { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW) ; + if ($$ == COND_ERR) YYABORT; } + ; +cond_xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';' + { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT) ; + if ($$ == COND_ERR) YYABORT; } + ; transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' {if (define_filename_trans()) YYABORT; } | TYPE_TRANSITION names names ':' names identifier ';' diff --git a/checkpolicy/tests/policy_allonce.conf b/checkpolicy/tests/policy_allonce.conf index 2cfbb7723e..51a8c40aa3 100644 --- a/checkpolicy/tests/policy_allonce.conf +++ b/checkpolicy/tests/policy_allonce.conf @@ -2,6 +2,7 @@ class CLASS1 class CLASS2 class CLASS3 +class CLASS4 class dir class file class process @@ -10,6 +11,7 @@ common COMMON1 { CPERM1 } class CLASS1 { PERM1 ioctl } class CLASS2 inherits COMMON1 class CLASS3 inherits COMMON1 { PERM1 } +class CLASS4 { nlmsg } default_user { CLASS1 } source; default_role { CLASS2 } target; default_type { CLASS3 } source; @@ -26,6 +28,7 @@ typealias TYPE1 alias TYPEALIAS1; typeattribute TYPE1 ATTR1; typebounds TYPE4 TYPE3; bool BOOL1 true; +bool BOOL2 false; tunable TUNABLE1 false; tunable TUNABLE2 true; type_transition TYPE1 TYPE2 : CLASS1 TYPE3; @@ -37,6 +40,7 @@ auditallow { TYPE1 TYPE2 } TYPE3 : CLASS1 { PERM1 }; dontaudit TYPE1 { TYPE2 TYPE3 } : CLASS3 { PERM1 CPERM1 }; neverallow TYPE1 TYPE2 : { CLASS2 CLASS3 } { CPERM1 }; allowxperm TYPE1 TYPE2 : CLASS1 ioctl { 0x456-0x5678 }; +allowxperm TYPE2 TYPE1 : CLASS4 nlmsg { 0x1 0x12 }; auditallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x2; dontauditxperm TYPE1 TYPE2 : CLASS1 ioctl 0x3; neverallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x4; @@ -50,7 +54,8 @@ role_transition ROLE1 TYPE1 : CLASS1 ROLE2; allow ROLE1 ROLE2; roleattribute ROLE3 ROLE_ATTR1; role ROLE1 types { TYPE1 }; -if ! BOOL1 { allow TYPE1 self: CLASS1 *; } +if ! BOOL1 { allow TYPE1 self: CLASS1 *; dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789 - 0x9876 }; } +if BOOL2 { allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x2 }; } if TUNABLE1 xor TUNABLE2 { allow TYPE1 self: CLASS2 *; } else { allow TYPE1 self: CLASS3 *; } optional { require { class CLASS2 { CPERM1 }; } allow TYPE1 self: CLASS2 *; } user USER1 roles ROLE1; diff --git a/checkpolicy/tests/policy_allonce.expected.conf b/checkpolicy/tests/policy_allonce.expected.conf index 26d564382c..355d999132 100644 --- a/checkpolicy/tests/policy_allonce.expected.conf +++ b/checkpolicy/tests/policy_allonce.expected.conf @@ -2,6 +2,7 @@ class CLASS1 class CLASS2 class CLASS3 +class CLASS4 class dir class file class process @@ -10,6 +11,7 @@ common COMMON1 { CPERM1 } class CLASS1 { PERM1 ioctl } class CLASS2 inherits COMMON1 class CLASS3 inherits COMMON1 { PERM1 } +class CLASS4 { nlmsg } default_user { CLASS1 } source; default_role { CLASS2 } target; default_type { CLASS3 } source; @@ -17,6 +19,7 @@ policycap open_perms; attribute ATTR1; attribute ATTR2; bool BOOL1 true; +bool BOOL2 false; type TYPE1; type TYPE2; type TYPE3; @@ -37,6 +40,7 @@ dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 }; +allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x12 }; auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; type_transition TYPE1 TYPE2:CLASS1 TYPE3; @@ -49,6 +53,12 @@ type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; if (BOOL1) { } else { allow TYPE1 self:CLASS1 { PERM1 ioctl }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789-0x67ff }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6800-0x97ff }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x9800-0x9876 }; +} +if (BOOL2) { + allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1-0x2 }; } role ROLE1; role ROLE2; diff --git a/checkpolicy/tests/policy_allonce.expected_opt.conf b/checkpolicy/tests/policy_allonce.expected_opt.conf index 769be2b3a9..74eec4ba6e 100644 --- a/checkpolicy/tests/policy_allonce.expected_opt.conf +++ b/checkpolicy/tests/policy_allonce.expected_opt.conf @@ -2,6 +2,7 @@ class CLASS1 class CLASS2 class CLASS3 +class CLASS4 class dir class file class process @@ -10,6 +11,7 @@ common COMMON1 { CPERM1 } class CLASS1 { PERM1 ioctl } class CLASS2 inherits COMMON1 class CLASS3 inherits COMMON1 { PERM1 } +class CLASS4 { nlmsg } default_user { CLASS1 } source; default_role { CLASS2 } target; default_type { CLASS3 } source; @@ -17,6 +19,7 @@ policycap open_perms; attribute ATTR1; attribute ATTR2; bool BOOL1 true; +bool BOOL2 false; type TYPE1; type TYPE2; type TYPE3; @@ -37,6 +40,7 @@ dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff }; allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 }; +allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x12 }; auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; type_transition TYPE1 TYPE2:CLASS1 TYPE3; @@ -49,6 +53,12 @@ type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; if (BOOL1) { } else { allow TYPE1 self:CLASS1 { ioctl }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789-0x67ff }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6800-0x97ff }; + dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x9800-0x9876 }; +} +if (BOOL2) { + allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x2 }; } role ROLE1; role ROLE2; diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c index 3d92018220..070bf52534 100644 --- a/libsepol/cil/src/cil_binary.c +++ b/libsepol/cil/src/cil_binary.c @@ -59,14 +59,18 @@ #define AVRULEX_TABLE_SIZE (1 << 10) #define PERMS_PER_CLASS 32 +struct cil_args_xperm_tables { + hashtab_t ioctl; + hashtab_t nlmsg; +}; + struct cil_args_binary { const struct cil_db *db; policydb_t *pdb; struct cil_list *neverallows; int pass; hashtab_t role_trans_table; - hashtab_t avrulex_ioctl_table; - hashtab_t avrulex_nlmsg_table; + struct cil_args_xperm_tables avrulex_xperm_tables; void **type_value_to_cil; }; @@ -75,8 +79,14 @@ struct cil_args_booleanif { policydb_t *pdb; cond_node_t *cond_node; enum cil_flavor cond_flavor; + struct cil_args_xperm_tables avrulex_xperm_tables; }; +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); @@ -1758,7 +1768,10 @@ static int __cil_permx_bitmap_to_sepol_xperms_list(uint32_t kind, ebitmap_t *xpe static int __cil_avrulex_xperm_to_policydb(hashtab_key_t k, hashtab_datum_t datum, uint32_t xperm_kind, 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; @@ -1768,7 +1781,6 @@ static int __cil_avrulex_xperm_to_policydb(hashtab_key_t k, hashtab_datum_t datu char *kind = NULL; avtab_key = (avtab_key_t *)k; - pdb = args; sepol_obj = pdb->class_val_to_struct[avtab_key->target_class - 1]; @@ -1789,7 +1801,12 @@ static int __cil_avrulex_xperm_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; } @@ -1872,7 +1889,7 @@ static int __cil_avrulex_xperm_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, struct cil_args_xperm_tables *xt) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; @@ -1895,11 +1912,11 @@ 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_xperm_to_hashtable(args->avrulex_ioctl_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); + rc = __cil_avrulex_xperm_to_hashtable(xt->ioctl, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); if (rc != SEPOL_OK) goto exit; break; case CIL_PERMX_KIND_NLMSG: - rc = __cil_avrulex_xperm_to_hashtable(args->avrulex_nlmsg_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); + rc = __cil_avrulex_xperm_to_hashtable(xt->nlmsg, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); if (rc != SEPOL_OK) goto exit; break; default: @@ -1916,7 +1933,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, struct cil_args_xperm_tables *xt) { int rc = SEPOL_ERR; uint16_t kind; @@ -1942,7 +1959,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; @@ -1960,7 +1977,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; @@ -1980,7 +1997,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; @@ -1994,7 +2011,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, xt); if (rc != SEPOL_OK) { goto exit; } @@ -2015,7 +2032,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); @@ -2034,7 +2051,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; @@ -2050,7 +2067,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, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&tgt_bitmap); goto exit; @@ -2119,6 +2136,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_xperm_tables); + 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; @@ -2425,6 +2457,8 @@ 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; + hashtab_t avrulex_nlmsg_table = NULL; tmp_cond = cond_node_create(pdb, NULL); if (tmp_cond == NULL) { @@ -2493,26 +2527,97 @@ 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; + } + + avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); + if (!avrulex_nlmsg_table) { + cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); + goto exit; + } + bool_args.cond_flavor = CIL_CONDTRUE; + bool_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; + bool_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_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; + } + + rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &bool_args); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failure creating avrulex rules\n"); + goto exit; + } + + hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); + hashtab_destroy(avrulex_nlmsg_table); + avrulex_nlmsg_table = NULL; + + hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_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; + } + + avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); + if (!avrulex_nlmsg_table) { + cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); + goto exit; + } + bool_args.cond_flavor = CIL_CONDFALSE; + bool_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; + bool_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_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; + } + + rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &bool_args); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failure creating avrulex rules\n"); + goto exit; + } + + hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); + hashtab_destroy(avrulex_nlmsg_table); + avrulex_nlmsg_table = NULL; + + + hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); + hashtab_destroy(avrulex_ioctl_table); + avrulex_ioctl_table = NULL; } return SEPOL_OK; exit: + hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); + hashtab_destroy(avrulex_ioctl_table); if (tmp_cond) { if (tmp_cond->expr) cond_expr_destroy(tmp_cond->expr); @@ -4087,7 +4192,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_xperm_tables); } } break; @@ -5158,6 +5263,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; @@ -5222,10 +5328,15 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p extra_args.pdb = pdb; extra_args.neverallows = neverallows; extra_args.role_trans_table = role_trans_table; - extra_args.avrulex_ioctl_table = avrulex_ioctl_table; - extra_args.avrulex_nlmsg_table = avrulex_nlmsg_table; + extra_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; + extra_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_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; @@ -5244,12 +5355,12 @@ 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; } - rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, pdb); + rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &booleanif_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c index 19fbb04e0b..8cc3f9b263 100644 --- a/libsepol/cil/src/cil_build_ast.c +++ b/libsepol/cil/src/cil_build_ast.c @@ -6158,7 +6158,11 @@ 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 { diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c index da8863c4c2..a8fa89df33 100644 --- a/libsepol/cil/src/cil_resolve_ast.c +++ b/libsepol/cil/src/cil_resolve_ast.c @@ -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; diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c index 9621a24780..550b4542f1 100644 --- a/libsepol/cil/src/cil_verify.c +++ b/libsepol/cil/src/cil_verify.c @@ -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) { diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index f73e21fc50..f833354be6 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -698,9 +698,9 @@ extern void level_datum_init(level_datum_t * x); extern void level_datum_destroy(level_datum_t * x); extern void cat_datum_init(cat_datum_t * x); extern void cat_datum_destroy(cat_datum_t * x); -extern int check_assertion(policydb_t *p, avrule_t *avrule); +extern int check_assertion(policydb_t *p, const avrule_t *avrule); extern int check_assertions(sepol_handle_t * handle, - policydb_t * p, avrule_t * avrules); + policydb_t * p, const avrule_t * avrules); extern int symtab_insert(policydb_t * x, uint32_t sym, hashtab_key_t key, hashtab_datum_t datum, @@ -759,10 +759,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); #define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */ #define POLICYDB_VERSION_GLBLUB 32 #define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */ +#define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */ /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS /* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4 @@ -785,9 +786,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); #define MOD_POLICYDB_VERSION_INFINIBAND 19 #define MOD_POLICYDB_VERSION_GLBLUB 20 #define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21 +#define MOD_POLICYDB_VERSION_COND_XPERMS 22 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SELF_TYPETRANS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_COND_XPERMS #define POLICYDB_CONFIG_MLS 1 @@ -801,6 +803,12 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); ((p)->policy_type != POLICY_KERN \ && (p)->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) +#define policydb_has_cond_xperms_feature(p) \ + (((p)->policy_type == POLICY_KERN \ + && (p)->policyvers >= POLICYDB_VERSION_COND_XPERMS) || \ + ((p)->policy_type != POLICY_KERN \ + && (p)->policyvers >= MOD_POLICYDB_VERSION_COND_XPERMS)) + /* the config flags related to unknown classes/perms are bits 2 and 3 */ #define DENY_UNKNOWN SEPOL_DENY_UNKNOWN #define REJECT_UNKNOWN SEPOL_REJECT_UNKNOWN diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c index 5e12988388..ca4cae25a4 100644 --- a/libsepol/src/assertion.c +++ b/libsepol/src/assertion.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -31,35 +32,31 @@ struct avtab_match_args { sepol_handle_t *handle; policydb_t *p; - avrule_t *avrule; - avtab_t *avtab; + const avrule_t *narule; unsigned long errors; + bool conditional; }; -static const char* policy_name(policydb_t *p) { - const char *policy_file = "policy.conf"; - if (p->name) { - policy_file = p->name; - } - return policy_file; +static const char* policy_name(const policydb_t *p) { + return p->name ?: "policy.conf"; } -static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule, +static void report_failure(sepol_handle_t *handle, const policydb_t *p, const avrule_t *narule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms) { char *permstr = sepol_av_to_string(p, curperm->tclass, perms); - if (avrule->source_filename) { + if (narule->source_filename) { ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };", - avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), + narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); - } else if (avrule->line) { + } else if (narule->line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", - avrule->line, p->p_type_val_to_name[stype], + narule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); @@ -74,29 +71,29 @@ static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t free(permstr); } -static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data) +static bool match_any_class_permissions(const class_perm_node_t *cp, uint32_t class, uint32_t data) { for (; cp; cp = cp->next) { if ((cp->tclass == class) && (cp->data & data)) - return 1; + return true; } - return 0; + return false; } -static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) { +static bool extended_permissions_and(const uint32_t *perms1, const uint32_t *perms2) { size_t i; for (i = 0; i < EXTENDED_PERMS_LEN; i++) { if (perms1[i] & perms2[i]) - return 1; + return true; } - return 0; + return false; } -static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow) +static bool check_extended_permissions(const av_extended_perms_t *neverallow, const avtab_extended_perms_t *allow) { - int rc = 0; + bool rc = false; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { if (neverallow->driver == allow->driver) @@ -121,8 +118,8 @@ static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_ext /* Compute which allowed extended permissions violate the neverallow rule */ static void extended_permissions_violated(avtab_extended_perms_t *result, - av_extended_perms_t *neverallow, - avtab_extended_perms_t *allow) + const av_extended_perms_t *neverallow, + const avtab_extended_perms_t *allow) { size_t i; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) @@ -155,23 +152,29 @@ static void extended_permissions_violated(avtab_extended_perms_t *result, } } +static bool match_node_key(const struct avtab_node *node, const avtab_key_t *key) +{ + return node->key.source_type == key->source_type + && node->key.target_type == key->target_type + && node->key.target_class == key->target_class; +} + /* Same scenarios of interest as check_assertion_extended_permissions */ static int report_assertion_extended_permissions(sepol_handle_t *handle, - policydb_t *p, const avrule_t *avrule, + policydb_t *p, const avrule_t *narule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms, - avtab_key_t *k, avtab_t *avtab) + const avtab_key_t *k, bool conditional) { avtab_ptr_t node; avtab_key_t tmp_key; avtab_extended_perms_t *xperms; avtab_extended_perms_t error; - ebitmap_t *sattr = &p->type_attr_map[stype]; - ebitmap_t *tattr = &p->type_attr_map[ttype]; + const ebitmap_t *sattr = &p->type_attr_map[stype]; + const ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; - int rc; - int found_xperm = 0; + bool found_xperm = false, found_cond_conflict = false; int errors = 0; memcpy(&tmp_key, k, sizeof(avtab_key_t)); @@ -181,7 +184,7 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, tmp_key.source_type = i + 1; ebitmap_for_each_positive_bit(tattr, tnode, j) { tmp_key.target_type = j + 1; - for (node = avtab_search_node(avtab, &tmp_key); + for (node = avtab_search_node(&p->te_avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; @@ -189,18 +192,17 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; - found_xperm = 1; - rc = check_extended_permissions(avrule->xperms, xperms); + found_xperm = true; /* failure on the extended permission check_extended_permissions */ - if (rc) { + if (check_extended_permissions(narule->xperms, xperms)) { char *permstring; - extended_permissions_violated(&error, avrule->xperms, xperms); + extended_permissions_violated(&error, narule->xperms, xperms); permstring = sepol_extended_perms_to_string(&error); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" - "allowxperm %s %s:%s %s;", - avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), + " allowxperm %s %s:%s %s;", + narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], @@ -210,16 +212,110 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, errors++; } } + + for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) { + bool found_true_base = false, found_true_xperm = false; + bool found_false_base = false, found_false_xperm = false; + + for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) { + node = cal->node; /* node->next is not from the same condition */ + if (!node) + continue; + + if (!match_node_key(node, &tmp_key)) + continue; + + if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { + found_true_base = true; + continue; + } + + if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) + continue; + + xperms = node->datum.xperms; + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) + && (xperms->specified != AVTAB_XPERMS_NLMSG)) + continue; + found_true_xperm = true; + /* failure on the extended permission check_extended_permissions */ + if (check_extended_permissions(narule->xperms, xperms)) { + char *permstring; + + extended_permissions_violated(&error, narule->xperms, xperms); + permstring = sepol_extended_perms_to_string(&error); + + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" + " allowxperm %s %s:%s %s;", + narule->source_line, narule->source_filename, narule->line, policy_name(p), + p->p_type_val_to_name[i], + p->p_type_val_to_name[j], + p->p_class_val_to_name[curperm->tclass - 1], + permstring ?: ""); + + free(permstring); + errors++; + } + } + + for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) { + node = cal->node; /* node->next is not from the same condition */ + if (!node) + continue; + + if (!match_node_key(node, &tmp_key)) + continue; + + if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { + found_false_base = true; + continue; + } + + if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) + continue; + + xperms = node->datum.xperms; + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) + && (xperms->specified != AVTAB_XPERMS_NLMSG)) + continue; + found_false_xperm = true; + /* failure on the extended permission check_extended_permissions */ + if (check_extended_permissions(narule->xperms, xperms)) { + char *permstring; + + extended_permissions_violated(&error, narule->xperms, xperms); + permstring = sepol_extended_perms_to_string(&error); + + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" + " allowxperm %s %s:%s %s;", + narule->source_line, narule->source_filename, narule->line, policy_name(p), + p->p_type_val_to_name[i], + p->p_type_val_to_name[j], + p->p_class_val_to_name[curperm->tclass - 1], + permstring ?: ""); + + free(permstring); + errors++; + } + } + + if (found_true_xperm && found_false_xperm) + found_xperm = true; + else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm))) + found_cond_conflict = true; + } } } - /* failure on the regular permissions */ - if (!found_xperm) { + if ((!found_xperm && !conditional) || found_cond_conflict) { + /* failure on the regular permissions */ char *permstr = sepol_av_to_string(p, curperm->tclass, perms); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" - "allow %s %s:%s {%s };", - avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), + " allow %s %s:%s {%s };", + narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], @@ -227,7 +323,6 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, free(permstr); errors++; - } return errors; @@ -239,27 +334,26 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void struct avtab_match_args *a = (struct avtab_match_args *)args; sepol_handle_t *handle = a->handle; policydb_t *p = a->p; - avtab_t *avtab = a->avtab; - avrule_t *avrule = a->avrule; - class_perm_node_t *cp; + const avrule_t *narule = a->narule; + const class_perm_node_t *cp; uint32_t perms; ebitmap_t src_matches, tgt_matches, self_matches; ebitmap_node_t *snode, *tnode; unsigned int i, j; - const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; - const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; + const bool is_narule_self = (narule->flags & RULE_SELF) != 0; + const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0; if ((k->specified & AVTAB_ALLOWED) == 0) return 0; - if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) + if (!match_any_class_permissions(narule->perms, k->target_class, d->data)) return 0; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); - rc = ebitmap_and(&src_matches, &avrule->stypes.types, + rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; @@ -267,22 +361,22 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void if (ebitmap_is_empty(&src_matches)) goto exit; - if (is_avrule_notself) { - if (ebitmap_is_empty(&avrule->ttypes.types)) { + if (is_narule_notself) { + if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); } else { /* avrule tgt is of the form {ATTR -self} */ - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc) goto oom; } else { - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); + rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (is_avrule_self) { + if (is_narule_self) { rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; @@ -298,7 +392,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void if (ebitmap_is_empty(&tgt_matches)) goto exit; - for (cp = avrule->perms; cp; cp = cp->next) { + for (cp = narule->perms; cp; cp = cp->next) { perms = cp->data & d->data; if ((cp->tclass != k->target_class) || !perms) { @@ -307,16 +401,17 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_for_each_positive_bit(&src_matches, snode, i) { ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { - if (is_avrule_self && i != j) + if (is_narule_self && i != j) continue; - if (is_avrule_notself && i == j) + if (is_narule_notself && i == j) continue; - if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { - a->errors += report_assertion_extended_permissions(handle,p, avrule, - i, j, cp, perms, k, avtab); + if (narule->specified == AVRULE_XPERMS_NEVERALLOW) { + a->errors += report_assertion_extended_permissions(handle,p, narule, + i, j, cp, perms, k, + a->conditional); } else { a->errors++; - report_failure(handle, p, avrule, i, j, cp, perms); + report_failure(handle, p, narule, i, j, cp, perms); } } } @@ -330,22 +425,22 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void return rc; } -static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule) +static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, const avrule_t *narule) { int rc; - struct avtab_match_args args; - - args.handle = handle; - args.p = p; - args.avrule = avrule; - args.errors = 0; - - args.avtab = &p->te_avtab; + struct avtab_match_args args = { + .handle = handle, + .p = p, + .narule = narule, + .errors = 0, + }; + + args.conditional = false; rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args); if (rc < 0) goto oom; - args.avtab = &p->te_cond_avtab; + args.conditional = true; rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args); if (rc < 0) goto oom; @@ -360,19 +455,20 @@ static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avru * Look up the extended permissions in avtab and verify that neverallowed * permissions are not granted. */ -static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab, +static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, unsigned int stype, unsigned int ttype, - avtab_key_t *k, policydb_t *p) + const avtab_key_t *k, policydb_t *p, + bool conditional) { avtab_ptr_t node; avtab_key_t tmp_key; - avtab_extended_perms_t *xperms; - av_extended_perms_t *neverallow_xperms = avrule->xperms; - ebitmap_t *sattr = &p->type_attr_map[stype]; - ebitmap_t *tattr = &p->type_attr_map[ttype]; + const avtab_extended_perms_t *xperms; + const av_extended_perms_t *neverallow_xperms = narule->xperms; + const ebitmap_t *sattr = &p->type_attr_map[stype]; + const ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; - int rc = 1; + bool found_xperm = false, found_cond_conflict = false; memcpy(&tmp_key, k, sizeof(avtab_key_t)); tmp_key.specified = AVTAB_XPERMS_ALLOWED; @@ -381,7 +477,7 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t tmp_key.source_type = i + 1; ebitmap_for_each_positive_bit(tattr, tnode, j) { tmp_key.target_type = j + 1; - for (node = avtab_search_node(avtab, &tmp_key); + for (node = avtab_search_node(&p->te_avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; @@ -390,14 +486,78 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; - rc = check_extended_permissions(neverallow_xperms, xperms); - if (rc) - return rc; + found_xperm = true; + if (check_extended_permissions(neverallow_xperms, xperms)) + return true; + } + + for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) { + bool found_true_base = false, found_true_xperm = false; + bool found_false_base = false, found_false_xperm = false; + + for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) { + node = cal->node; /* node->next is not from the same condition */ + if (!node) + continue; + + if (!match_node_key(node, &tmp_key)) + continue; + + if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { + found_true_base = true; + continue; + } + + if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) + continue; + + xperms = node->datum.xperms; + + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) + && (xperms->specified != AVTAB_XPERMS_NLMSG)) + continue; + found_true_xperm = true; + if (check_extended_permissions(neverallow_xperms, xperms)) + return true; + } + + for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) { + node = cal->node; /* node->next is not from the same condition */ + if (!node) + continue; + + if (!match_node_key(node, &tmp_key)) + continue; + + if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { + found_false_base = true; + continue; + } + + if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) + continue; + + xperms = node->datum.xperms; + + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) + && (xperms->specified != AVTAB_XPERMS_NLMSG)) + continue; + found_false_xperm = true; + if (check_extended_permissions(neverallow_xperms, xperms)) + return true; + } + + if (found_true_xperm && found_false_xperm) + found_xperm = true; + else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm))) + found_cond_conflict = true; } } } - return rc; + return (!conditional && !found_xperm) || found_cond_conflict; } /* @@ -416,21 +576,22 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t * 4. FAIL - The ioctl permission is granted AND the extended permission is * granted */ -static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab, - avtab_key_t *k, policydb_t *p) +static int check_assertion_extended_permissions(const avrule_t *narule, + const avtab_key_t *k, policydb_t *p, + bool conditional) { ebitmap_t src_matches, tgt_matches, self_matches; unsigned int i, j; ebitmap_node_t *snode, *tnode; - const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; - const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; + const bool is_narule_self = (narule->flags & RULE_SELF) != 0; + const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0; int rc; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); - rc = ebitmap_and(&src_matches, &avrule->stypes.types, + rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; @@ -440,22 +601,22 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab goto exit; } - if (is_avrule_notself) { - if (ebitmap_is_empty(&avrule->ttypes.types)) { + if (is_narule_notself) { + if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); } else { /* avrule tgt is of the form {ATTR -self} */ - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc < 0) goto oom; } else { - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); + rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (is_avrule_self) { + if (is_narule_self) { rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; @@ -475,11 +636,11 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab ebitmap_for_each_positive_bit(&src_matches, snode, i) { ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { - if (is_avrule_self && i != j) + if (is_narule_self && i != j) continue; - if (is_avrule_notself && i == j) + if (is_narule_notself && i == j) continue; - if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) { + if (check_assertion_extended_permissions_avtab(narule, i, j, k, p, conditional)) { rc = 1; goto exit; } @@ -496,7 +657,7 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab return rc; } -static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) +static int check_assertion_notself_match(const avtab_key_t *k, const avrule_t *narule, policydb_t *p) { ebitmap_t src_matches, tgt_matches; unsigned int num_src_matches, num_tgt_matches; @@ -505,16 +666,16 @@ static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, polic ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); - rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); + rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; - if (ebitmap_is_empty(&avrule->ttypes.types)) { + if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type - 1]); } else { /* avrule tgt is of the form {ATTR -self} */ - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc < 0) goto oom; @@ -551,7 +712,7 @@ static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, polic return rc; } -static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) +static int check_assertion_self_match(const avtab_key_t *k, const avrule_t *narule, policydb_t *p) { ebitmap_t src_matches; int rc; @@ -560,7 +721,7 @@ static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb * and the key's source. */ - rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); + rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; @@ -582,29 +743,28 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a int rc; struct avtab_match_args *a = (struct avtab_match_args *)args; policydb_t *p = a->p; - avrule_t *avrule = a->avrule; - avtab_t *avtab = a->avtab; + const avrule_t *narule = a->narule; if ((k->specified & AVTAB_ALLOWED) == 0) goto nomatch; - if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) + if (!match_any_class_permissions(narule->perms, k->target_class, d->data)) goto nomatch; - if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1])) + if (!ebitmap_match_any(&narule->stypes.types, &p->attr_type_map[k->source_type - 1])) goto nomatch; - if (avrule->flags & RULE_NOTSELF) { - rc = check_assertion_notself_match(k, avrule, p); + if (narule->flags & RULE_NOTSELF) { + rc = check_assertion_notself_match(k, narule, p); if (rc < 0) goto oom; if (rc == 0) goto nomatch; } else { /* neverallow may have tgts even if it uses SELF */ - if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { - if (avrule->flags == RULE_SELF) { - rc = check_assertion_self_match(k, avrule, p); + if (!ebitmap_match_any(&narule->ttypes.types, &p->attr_type_map[k->target_type -1])) { + if (narule->flags == RULE_SELF) { + rc = check_assertion_self_match(k, narule, p); if (rc < 0) goto oom; if (rc == 0) @@ -615,8 +775,8 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a } } - if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { - rc = check_assertion_extended_permissions(avrule, avtab, k, p); + if (narule->specified == AVRULE_XPERMS_NEVERALLOW) { + rc = check_assertion_extended_permissions(narule, k, p, a->conditional); if (rc < 0) goto oom; if (rc == 0) @@ -631,21 +791,21 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a return rc; } -int check_assertion(policydb_t *p, avrule_t *avrule) +int check_assertion(policydb_t *p, const avrule_t *narule) { int rc; - struct avtab_match_args args; - - args.handle = NULL; - args.p = p; - args.avrule = avrule; - args.errors = 0; - args.avtab = &p->te_avtab; - + struct avtab_match_args args = { + .handle = NULL, + .p = p, + .narule = narule, + .errors = 0, + }; + + args.conditional = false; rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args); if (rc == 0) { - args.avtab = &p->te_cond_avtab; + args.conditional = true; rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args); } @@ -653,20 +813,13 @@ int check_assertion(policydb_t *p, avrule_t *avrule) } int check_assertions(sepol_handle_t * handle, policydb_t * p, - avrule_t * avrules) + const avrule_t * narules) { int rc; - avrule_t *a; + const avrule_t *a; unsigned long errors = 0; - if (!avrules) { - /* Since assertions are stored in avrules, if it is NULL - there won't be any to check. This also prevents an invalid - free if the avtabs are never initialized */ - return 0; - } - - for (a = avrules; a != NULL; a = a->next) { + for (a = narules; a != NULL; a = a->next) { if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))) continue; rc = check_assertion(p, a); diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index e90ccca1fc..0747e7891d 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -208,6 +208,13 @@ static const struct policydb_compat_info policydb_compat[] = { .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, + { + .type = POLICY_KERN, + .version = POLICYDB_VERSION_COND_XPERMS, + .sym_num = SYM_NUM, + .ocon_num = OCON_IBENDPORT + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, @@ -334,6 +341,13 @@ static const struct policydb_compat_info policydb_compat[] = { .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, + { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_COND_XPERMS, + .sym_num = SYM_NUM, + .ocon_num = OCON_IBENDPORT + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, @@ -460,6 +474,13 @@ static const struct policydb_compat_info policydb_compat[] = { .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_COND_XPERMS, + .sym_num = SYM_NUM, + .ocon_num = 0, + .target_platform = SEPOL_TARGET_SELINUX, + }, }; #if 0 diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c index 5035313bac..9ee4b948a9 100644 --- a/libsepol/src/policydb_validate.c +++ b/libsepol/src/policydb_validate.c @@ -22,6 +22,7 @@ typedef struct map_arg { validate_t *flavors; sepol_handle_t *handle; const policydb_t *policy; + int conditional; } map_arg_t; typedef struct perm_arg { @@ -837,7 +838,7 @@ static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - map_arg_t margs = { flavors, handle, p }; + map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs)) goto bad; @@ -903,7 +904,7 @@ static int validate_avtab_key(const avtab_key_t *key, int conditional, const pol case AVTAB_XPERMS_DONTAUDIT: if (p->target_platform != SEPOL_TARGET_SELINUX) goto bad; - if (conditional) + if (conditional && !policydb_has_cond_xperms_feature(p)) goto bad; break; default: @@ -956,7 +957,7 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void * { map_arg_t *margs = args; - if (validate_avtab_key(k, 0, margs->policy, margs->flavors)) + if (validate_avtab_key(k, margs->conditional, margs->policy, margs->flavors)) return -1; if (k->specified & AVTAB_AV) { @@ -972,15 +973,23 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void * if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) return -1; - if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms)) - return -1; + if (k->specified & AVTAB_XPERMS) { + uint32_t data = d->data; + + /* checkpolicy does not touch data for xperms, CIL sets it. */ + if (data != 0 && validate_access_vector(margs->handle, margs->policy, k->target_class, data)) + return -1; + + if (validate_xperms(d->xperms)) + return -1; + } return 0; } static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[]) { - map_arg_t margs = { flavors, handle, p }; + map_arg_t margs = { flavors, handle, p, 0 }; if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) { ERR(handle, "Invalid avtab"); @@ -992,28 +1001,13 @@ static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const po static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[]) { - const struct avtab_node *avtab_ptr; - - for (; cond_av; cond_av = cond_av->next) { - for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) { - const avtab_key_t *key = &avtab_ptr->key; - const avtab_datum_t *datum = &avtab_ptr->datum; + struct avtab_node *avtab_ptr; + map_arg_t margs = { flavors, handle, p, 1 }; - if (validate_avtab_key(key, 1, p, flavors)) + for (; cond_av; cond_av = cond_av->next) + for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) + if (validate_avtab_key_and_datum(&avtab_ptr->key, &avtab_ptr->datum, &margs)) goto bad; - if (key->specified & AVTAB_AV) { - uint32_t data = datum->data; - - if ((0xFFF & key->specified) == AVTAB_AUDITDENY) - data = ~data; - - if (validate_access_vector(handle, p, key->target_class, data)) - goto bad; - } - if ((key->specified & AVTAB_TYPE) && validate_simpletype(datum->data, p, flavors)) - goto bad; - } - } return 0; @@ -1046,7 +1040,7 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int case AVRULE_XPERMS_AUDITALLOW: case AVRULE_XPERMS_DONTAUDIT: case AVRULE_XPERMS_NEVERALLOW: - if (conditional) + if (conditional && !policydb_has_cond_xperms_feature(p)) goto bad; break; default: @@ -1278,7 +1272,7 @@ static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *arg static int validate_filename_trans_hashtab(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - map_arg_t margs = { flavors, handle, p }; + map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->filename_trans, validate_filename_trans, &margs)) { ERR(handle, "Invalid filename trans"); @@ -1631,7 +1625,7 @@ static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, vo static int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - map_arg_t margs = { flavors, handle, p }; + map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->range_tr, validate_range_transition, &margs)) { ERR(handle, "Invalid range transition"); diff --git a/libsepol/src/write.c b/libsepol/src/write.c index a52e2e8292..4ef9844993 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -56,7 +56,8 @@ struct policy_data { }; static int avrule_write_list(policydb_t *p, - avrule_t * avrules, struct policy_file *fp); + avrule_t * avrules, struct policy_file *fp, + unsigned conditional); static int ebitmap_write(ebitmap_t * e, struct policy_file *fp) { @@ -104,7 +105,8 @@ static uint16_t spec_order[] = { static int avtab_write_item(policydb_t * p, avtab_ptr_t cur, struct policy_file *fp, - unsigned merge, unsigned commit, uint32_t * nel) + unsigned merge, unsigned commit, unsigned conditional, + uint32_t * nel) { avtab_ptr_t node; uint8_t buf8; @@ -229,14 +231,20 @@ static int avtab_write_item(policydb_t * p, return POLICYDB_ERROR; if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) && (cur->key.specified & AVTAB_XPERMS)) { - ERR(fp->handle, "policy version %u does not support ioctl extended" + ERR(fp->handle, "policy version %u does not support extended" "permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } + if (!policydb_has_cond_xperms_feature(p) && (cur->key.specified & AVTAB_XPERMS) && conditional) { + ERR(fp->handle, "policy version %u does not support extended" + "permissions rules in conditional policies and one was specified", p->policyvers); + return POLICYDB_ERROR; + } + if (p->target_platform != SEPOL_TARGET_SELINUX && (cur->key.specified & AVTAB_XPERMS)) { - ERR(fp->handle, "Target platform %s does not support ioctl " + ERR(fp->handle, "Target platform %s does not support " "extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; @@ -313,7 +321,7 @@ static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp) for (cur = a->htable[i]; cur; cur = cur->next) { /* If old format, compute final nel. If new format, write out the items. */ - if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) { + if (avtab_write_item(p, cur, fp, 1, !oldvers, 0, &nel)) { rc = -1; goto out; } @@ -332,7 +340,7 @@ static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp) avtab_reset_merged(a); for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { - if (avtab_write_item(p, cur, fp, 1, 1, NULL)) { + if (avtab_write_item(p, cur, fp, 1, 1, 0, NULL)) { rc = -1; goto out; } @@ -795,7 +803,7 @@ static int cond_write_av_list(policydb_t * p, for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { if (cur_list->node->parse_context) - if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL)) + if (avtab_write_item(p, cur_list->node, fp, 0, 1, 1, NULL)) goto out; } @@ -846,9 +854,9 @@ static int cond_write_node(policydb_t * p, if (cond_write_av_list(p, node->false_list, fp) != 0) return POLICYDB_ERROR; } else { - if (avrule_write_list(p, node->avtrue_list, fp)) + if (avrule_write_list(p, node->avtrue_list, fp, 1)) return POLICYDB_ERROR; - if (avrule_write_list(p, node->avfalse_list, fp)) + if (avrule_write_list(p, node->avfalse_list, fp, 1)) return POLICYDB_ERROR; } @@ -1743,7 +1751,7 @@ static int range_write(policydb_t * p, struct policy_file *fp) /************** module writing functions below **************/ static int avrule_write(policydb_t *p, avrule_t * avrule, - struct policy_file *fp) + struct policy_file *fp, unsigned conditional) { size_t items, items2; uint32_t buf[32], len; @@ -1801,15 +1809,23 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ERR(fp->handle, - "module policy version %u does not support ioctl" + "module policy version %u does not support" " extended permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } + if (conditional && !policydb_has_cond_xperms_feature(p)) { + ERR(fp->handle, + "module policy version %u does not support" + " extended permissions rules in conditional policies and one was specified", + p->policyvers); + return POLICYDB_ERROR; + } + if (p->target_platform != SEPOL_TARGET_SELINUX) { ERR(fp->handle, - "Target platform %s does not support ioctl" + "Target platform %s does not support" " extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; @@ -1834,7 +1850,7 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, } static int avrule_write_list(policydb_t *p, avrule_t * avrules, - struct policy_file *fp) + struct policy_file *fp, unsigned conditional) { uint32_t buf[32], len; avrule_t *avrule; @@ -1852,7 +1868,7 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules, avrule = avrules; while (avrule) { - if (avrule_write(p, avrule, fp)) + if (avrule_write(p, avrule, fp, conditional)) return POLICYDB_ERROR; avrule = avrule->next; } @@ -2056,7 +2072,7 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, return POLICYDB_ERROR; } if (cond_write_list(p, decl->cond_list, fp) == -1 || - avrule_write_list(p, decl->avrules, fp) == -1 || + avrule_write_list(p, decl->avrules, fp, 0) == -1 || role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || role_allow_rule_write(decl->role_allow_rules, fp) == -1) { return POLICYDB_ERROR; diff --git a/libsepol/tests/helpers.c b/libsepol/tests/helpers.c index 1192734b97..97ddfe8e73 100644 --- a/libsepol/tests/helpers.c +++ b/libsepol/tests/helpers.c @@ -53,6 +53,7 @@ int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_ p->policy_type = policy_type; p->mls = mls; + p->policyvers = MOD_POLICYDB_VERSION_MAX; if (read_source_policy(p, filename, test_name)) { fprintf(stderr, "failed to read policy %s\n", filename); diff --git a/libsepol/tests/policies/test-neverallow/policy_cond.conf b/libsepol/tests/policies/test-neverallow/policy_cond.conf new file mode 100644 index 0000000000..c81fc01d6c --- /dev/null +++ b/libsepol/tests/policies/test-neverallow/policy_cond.conf @@ -0,0 +1,251 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file + +sid kernel +sid security +sid unlabeled +sid file +sid port +sid netif +sid netmsg +sid node +sid devnull + +class process { dyntransition transition } +class file { getattr ioctl open read write } + +bool boolean1 false; +bool boolean2 true; + +ifdef(`enable_mls',` +sensitivity s0; +dominance { s0 } +category c0; category c1; category c2; category c3; +category c4; category c5; category c6; category c7; +category c8; category c9; category c10; category c11; +category c12; category c13; category c14; category c15; +category c16; category c17; category c18; category c19; +category c20; category c21; category c22; category c23; + +level s0:c0.c23; + +mlsconstrain file { write } ( h1 dom h2 ); +') + + +######################################## +# +# Test start +# +######################################## + + +## Test 1 (basic - fail) + +type test1_t; +if boolean1 { + allow test1_t self : file read; +} +neverallow test1_t * : file *; + + +## Test 2 (basic - fail) + +attribute test2_a; +type test2_1_t, test2_a; +type test2_2_t; +if !boolean1 { + allow test2_1_t test2_1_t : file write; + allow test2_2_t test2_2_t : file write; +} +neverallow test2_a * : file *; + + +## Test 3 (xperm - no xperm in one branch - fail) + +type test3_t; +if boolean1 { + allow test3_t self : file ioctl; +} else { + allowxperm test3_t self : file ioctl 0x1; +} +neverallowxperm test3_t self : file ioctl 0x4; + + +## Test 4 (xperm - xperm in neither branch - fail) + +type test4_t; +allow test4_t self : file ioctl; +if boolean1 { + allow test4_t self : file read; +} else { + allow test4_t self : file write; +} +neverallowxperm test4_t self : file ioctl 0x4; + + +## Test 5 (xperm - xperm in both branches - no failure) + +type test5_t; +allow test5_t self : file ioctl; +if boolean1 { + allowxperm test5_t self : file ioctl 0x1; +} else { + allowxperm test5_t self : file ioctl 0x2; +} +neverallowxperm test5_t self : file ioctl 0x4; # nofail + + +## Test 6 (xperm - failure in one branch - fail) + +type test6_t; +if boolean1 { + allow test6_t self : file ioctl; + allowxperm test6_t self : file ioctl 0x1; +} else { + allow test6_t self : file write; +} +neverallowxperm test6_t self : file ioctl 0x1; + + +## Test 7 (xperm - failure in both branches - fail) + +type test7_t; +if boolean1 { + allow test7_t self : file ioctl; + allowxperm test7_t self : file ioctl 0x1; +} else { + allow test7_t self : file ioctl; + allowxperm test7_t self : file ioctl 0x2; +} +neverallowxperm test7_t self : file ioctl { 0x1-0x2 }; + + +## Test 8 (xperm - different xperm in both branches - no failure) + +type test8_t; +allow test8_t self : file ioctl; +if boolean1 { + allowxperm test8_t self : file ioctl 0x1; +} else { + allowxperm test8_t self : file ioctl 0x2; +} +neverallowxperm test8_t self : file ioctl 0x3; # nofail + + +## Test 9 (xperm - rules split into two booleans - no failure) + +type test9_t; +allow test9_t self : file ioctl; +if boolean1 { + allowxperm test9_t self : file ioctl 0x1; +} +if !boolean2 { + allowxperm test9_t self : file ioctl 0x1; +} +neverallowxperm test9_t self : file ioctl 0x4; + + +## Test 10 (xperm - valid usage in one branch - no failure) + +type test10_t; +if boolean1 { + allow test10_t self : file ioctl; + allowxperm test10_t self : file ioctl 0x1; +} else { + allow test10_t self : file write; +} +neverallowxperm test10_t self : file ioctl 0x2; # nofail + + +## Test 11 (xperm - valid usage in both branches - no failure) + +type test11_t; +if boolean1 { + allow test11_t self : file ioctl; + allowxperm test11_t self : file ioctl 0x1; +} else { + allow test11_t self : file ioctl; + allowxperm test11_t self : file ioctl 0x2; +} +neverallowxperm test11_t self : file ioctl 0x3; # nofail + + +## Test 12 (xperm - base allow in one branch - fail) + +type test12_t; +if boolean1 { + allow test12_t self : file ioctl; +} else { + allow test12_t self : file write; +} +neverallowxperm test12_t self : file ioctl 0x1; + + +## Test 13 (xperm - invalid second branch - fail) + +type test13_t; +allow test13_t self : file ioctl; +if boolean1 { + allow test13_t self : file ioctl; + allowxperm test13_t self : file ioctl 0x1; +} else { + allow test13_t self : file write; +} +neverallowxperm test13_t self : file ioctl 0x1; + + +## Test 14 (xperm - invalid second branch - fail) + +type test14_t; +allow test14_t self : file ioctl; +if boolean1 { + allow test14_t self : file ioctl; + allowxperm test14_t self : file ioctl 0x1; +} else { + allow test14_t self : file write; +} +neverallowxperm test14_t self : file ioctl 0x2; + + +## Test 15 (xperm - base uncond in one branch - fail) + +type test15_t; +allow test15_t self : file ioctl; +allowxperm test15_t self : file ioctl 0x1; +if boolean1 { + allow test15_t self : file ioctl; +} else { + allow test15_t self : file write; +} +neverallowxperm test15_t self : file ioctl 0x2; + + +######################################## +# +# Test End +# +######################################## + + +type sys_isid; +role sys_role; +role sys_role types sys_isid; +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) +sid kernel gen_context(sys_user:sys_role:sys_isid, s0) +sid security gen_context(sys_user:sys_role:sys_isid, s0) +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) +sid file gen_context(sys_user:sys_role:sys_isid, s0) +sid port gen_context(sys_user:sys_role:sys_isid, s0) +sid netif gen_context(sys_user:sys_role:sys_isid, s0) +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) +sid node gen_context(sys_user:sys_role:sys_isid, s0) +sid devnull gen_context(sys_user:sys_role:sys_isid, s0) +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c index 7d6ad00e27..9c3001c4ff 100644 --- a/libsepol/tests/test-neverallow.c +++ b/libsepol/tests/test-neverallow.c @@ -112,18 +112,18 @@ static void test_neverallow_basic(void) "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { open };", "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_2_t test12_1_t:file { open };", "neverallow on line 156 of policies/test-neverallow/policy.conf.std (or line 156 of policies/test-neverallow/policy.conf.std) violated by allow test13_1_t test13_1_t:file { read };", - "neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\nallow test15_t test15_t:file { ioctl };", - "neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test16_t test16_t:file ioctl { 0x1111 };", - "neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test18_t test18_t:file ioctl { 0x1111 };", - "neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test19_t test19_t:file ioctl { 0x1111 };", - "neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test20_a test20_a:file ioctl { 0x1111 };", - "neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };", - "neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test22_t test22_t:file ioctl { 0x1111 };", - "neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test23_t test23_t:file ioctl { 0x1111 };", - "neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test24_t test24_a:file ioctl { 0x1111 };", - "neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test25_t test25_t:file ioctl { 0x1111 };", - "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };", - "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };", + "neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\n allow test15_t test15_t:file { ioctl };", + "neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test16_t test16_t:file ioctl { 0x1111 };", + "neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test18_t test18_t:file ioctl { 0x1111 };", + "neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test19_t test19_t:file ioctl { 0x1111 };", + "neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test20_a test20_a:file ioctl { 0x1111 };", + "neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };", + "neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test22_t test22_t:file ioctl { 0x1111 };", + "neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test23_t test23_t:file ioctl { 0x1111 };", + "neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test24_t test24_a:file ioctl { 0x1111 };", + "neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test25_t test25_t:file ioctl { 0x1111 };", + "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test26_a test26_a:file ioctl { 0x1111 };", + "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test26_a test26_a:file ioctl { 0x1111 };", }; if (policydb_init(&base_expanded)) @@ -174,25 +174,25 @@ static void test_neverallow_minus_self(void) "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };", "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", - "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };", - "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", - "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", - "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", - "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", - "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };", - "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };", - "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };", - "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", - "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };", - "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };", - "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", - "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", - "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", - "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test17_1_t test17_2_t:class17 { ioctl };", + "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", + "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", + "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", + "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", + "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test24_1_t test24_a:file ioctl { 0x9511 };", + "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test25_a test25_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test28_2_t test28_1_t:file { ioctl };", + "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", + "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test29_2_t test29_1_t:file { ioctl };", + "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test29_1_t test29_a:file ioctl { 0x9521 };", + "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", }; if (policydb_init(&base_expanded)) @@ -244,25 +244,25 @@ static void test_neverallow_not_self(void) "neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", - "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };", - "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", - "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", - "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", - "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", - "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };", - "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };", - "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", - "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };", - "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", - "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };", - "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };", - "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", - "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", - "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", - "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test17_1_t test17_2_t:class17 { ioctl };", + "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", + "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", + "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", + "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", + "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test24_1_t test24_a:file ioctl { 0x9511 };", + "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test25_a test25_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test28_2_t test28_1_t:file { ioctl };", + "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", + "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test29_2_t test29_1_t:file { ioctl };", + "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test29_1_t test29_a:file ioctl { 0x9521 };", + "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", }; if (policydb_init(&base_expanded)) @@ -293,6 +293,58 @@ static void test_neverallow_not_self(void) policydb_destroy(&base_expanded); } +static void test_neverallow_cond(void) +{ + policydb_t basemod, base_expanded; + sepol_handle_t *handle; + static const char *const expected_messages[] = { + "16 neverallow failures occurred", + "neverallow on line 58 of policies/test-neverallow/policy_cond.conf.std (or line 58 of policies/test-neverallow/policy_cond.conf.std) violated by allow test1_t test1_t:file { read };", + "neverallow on line 70 of policies/test-neverallow/policy_cond.conf.std (or line 70 of policies/test-neverallow/policy_cond.conf.std) violated by allow test2_1_t test2_1_t:file { write };", + "neverallowxperm on line 81 of policies/test-neverallow/policy_cond.conf.std (or line 81 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test3_t test3_t:file { ioctl };", + "neverallowxperm on line 93 of policies/test-neverallow/policy_cond.conf.std (or line 93 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test4_t test4_t:file { ioctl };", + "neverallowxperm on line 117 of policies/test-neverallow/policy_cond.conf.std (or line 117 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test6_t test6_t:file ioctl { 0x1 };", + "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x2 };", + "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x1 };", + "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x2 };", + "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x1 };", + "neverallowxperm on line 155 of policies/test-neverallow/policy_cond.conf.std (or line 155 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test9_t test9_t:file { ioctl };", + "neverallowxperm on line 191 of policies/test-neverallow/policy_cond.conf.std (or line 191 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test12_t test12_t:file { ioctl };", + "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test13_t test13_t:file ioctl { 0x1 };", + "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test13_t test13_t:file { ioctl };", + "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test13_t test13_t:file ioctl { 0x1 };", + "neverallowxperm on line 217 of policies/test-neverallow/policy_cond.conf.std (or line 217 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test14_t test14_t:file { ioctl };", + "neverallowxperm on line 230 of policies/test-neverallow/policy_cond.conf.std (or line 230 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test15_t test15_t:file { ioctl };", + }; + + if (policydb_init(&base_expanded)) + CU_FAIL_FATAL("Failed to initialize policy"); + + if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_cond.conf")) + CU_FAIL_FATAL("Failed to load policy"); + + if (link_modules(NULL, &basemod, NULL, 0, 0)) + CU_FAIL_FATAL("Failed to link base module"); + + if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) + CU_FAIL_FATAL("Failed to expand policy"); + + if ((handle = sepol_handle_create()) == NULL) + CU_FAIL_FATAL("Failed to initialize handle"); + + sepol_msg_set_callback(handle, msg_handler, NULL); + + if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) + CU_FAIL("Assertions did not trigger"); + + messages_check(ARRAY_SIZE(expected_messages), expected_messages); + + sepol_handle_destroy(handle); + messages_clean(); + policydb_destroy(&basemod); + policydb_destroy(&base_expanded); +} + int neverallow_add_tests(CU_pSuite suite) { /* @@ -317,5 +369,10 @@ int neverallow_add_tests(CU_pSuite suite) return CU_get_error(); } + if (NULL == CU_add_test(suite, "neverallow_cond", test_neverallow_cond)) { + CU_cleanup_registry(); + return CU_get_error(); + } + return 0; } diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil index e6b78618fa..d0d52d0de9 100644 --- a/secilc/test/policy.cil +++ b/secilc/test/policy.cil @@ -47,8 +47,9 @@ (block policy (class file (execute_no_trans entrypoint execmod open audit_access a b c d e)) - ; order should be: file char b c a dir d e f - (classorder (file char)) + (class socket (nlmsg)) + ; order should be: file socket char b c a dir d e f + (classorder (file socket char)) (classorder (unordered dir)) (classorder (unordered c a b d e f)) (classorder (char b c a)) @@ -161,7 +162,10 @@ ;;(allow bad_t not_bad_type (file (execute))) ;;(allow bad_t exec_t (file (execute))) (neverallow bad_t not_bad_type (file (execute))) - + + (auditallowx getty_t console_device_t (ioctl file (range 0x1000 0x10FF))) + (auditallowx getty_t kernel_t (nlmsg socket (range 0x1000 0x10FF))) + (booleanif secure_mode (true (auditallow device_t exec_t (file (read write))) @@ -172,9 +176,12 @@ (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))) + (auditallowx getty_t kernel_t (nlmsg socket (0x1))) ) (false (dontaudit getty_t console_device_t (file (getattr open read write append))) + (dontauditx getty_t console_device_t (ioctl file (range 0x3000 0x31FF))) ) )