Message ID | 20230531114914.2237609-8-juraj@jurajmarcin.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Petr Lautrbach |
Headers | show |
Series | checkpolicy, libsepol: add prefix/suffix matching to filename type transitions | expand |
On Wed, May 31, 2023 at 7:51 AM Juraj Marcin <juraj@jurajmarcin.com> wrote: > > This patch extends the structures for module and base policy (avrule_t) > to support prefix/suffix transitions. In addition to this, it implements > the necessary changes to functions for reading and writing the binary > policy as well as parsing the policy conf. > I would like to see an example of the new syntax. Something like: type_transition ta tb : CLASS03 tc "file03" match_exact; type_transition ta tb : CLASS04 tc "file04" match_prefix; type_transition ta tb : CLASS05 tc "file05" match_suffix; > Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com> > Signed-off-by: Juraj Marcin <juraj@jurajmarcin.com> > --- > checkpolicy/policy_define.c | 13 ++++--- > checkpolicy/policy_define.h | 2 +- > checkpolicy/policy_parse.y | 15 +++++--- > checkpolicy/policy_scan.l | 6 ++++ > checkpolicy/test/dismod.c | 14 ++++++++ > checkpolicy/test/dispol.c | 2 +- > libsepol/cil/src/cil_binary.c | 4 ++- > libsepol/include/sepol/policydb/avtab.h | 1 + > libsepol/include/sepol/policydb/policydb.h | 13 ++++--- > libsepol/src/avtab.c | 30 ++++++++++++---- > libsepol/src/expand.c | 6 +++- > libsepol/src/kernel_to_common.h | 2 +- > libsepol/src/link.c | 1 + > libsepol/src/module_to_cil.c | 25 +++++++++++--- > libsepol/src/policydb.c | 23 ++++++++++++- > libsepol/src/write.c | 40 ++++++++++++++++------ > 16 files changed, 154 insertions(+), 43 deletions(-) > > diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c > index 455255ba..c3c6af72 100644 > --- a/checkpolicy/policy_define.c > +++ b/checkpolicy/policy_define.c > @@ -1601,7 +1601,8 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed) > return -1; > } > > -static int define_compute_type_helper(int which, avrule_t ** rule, int has_filename) > +static int define_compute_type_helper(int which, avrule_t ** rule, > + int has_filename, uint8_t name_match) > { > char *id; > type_datum_t *datum; > @@ -1676,6 +1677,7 @@ static int define_compute_type_helper(int which, avrule_t ** rule, int has_filen > goto bad; > } > } > + avrule->name_match = name_match; > > ebitmap_for_each_positive_bit(&tclasses, node, i) { > perm = malloc(sizeof(class_perm_node_t)); > @@ -1700,7 +1702,7 @@ static int define_compute_type_helper(int which, avrule_t ** rule, int has_filen > return -1; > } > > -int define_compute_type(int which, int has_filename) > +int define_compute_type(int which, int has_filename, uint8_t name_match) > { > char *id; > avrule_t *avrule; > @@ -1721,7 +1723,8 @@ int define_compute_type(int which, int has_filename) > return 0; > } > > - if (define_compute_type_helper(which, &avrule, has_filename)) > + if (define_compute_type_helper(which, &avrule, has_filename, > + name_match)) > return -1; > > append_avrule(avrule); > @@ -1745,7 +1748,8 @@ avrule_t *define_cond_compute_type(int which) > return (avrule_t *) 1; > } > > - if (define_compute_type_helper(which, &avrule, 0)) > + if (define_compute_type_helper(which, &avrule, 0, > + NAME_TRANS_MATCH_EXACT)) > return COND_ERR; > > return avrule; > @@ -2394,6 +2398,7 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src) > return -1; > } > } > + dest->name_match = src->name_match; > dest->line = src->line; > dest->source_filename = strdup(source_file); > if (!dest->source_filename) { > diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h > index 5d0f70e4..c1314871 100644 > --- a/checkpolicy/policy_define.h > +++ b/checkpolicy/policy_define.h > @@ -28,7 +28,7 @@ int define_default_role(int which); > int define_default_type(int which); > int define_default_range(int which); > int define_common_perms(void); > -int define_compute_type(int which, int has_filename); > +int define_compute_type(int which, int has_filename, uint8_t name_match); > int define_conditional(cond_expr_t *expr, avrule_t *t_list, avrule_t *f_list ); > int define_constraint(constraint_expr_t *expr); > int define_dominance(void); > diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y > index fccbc052..12dff7af 100644 > --- a/checkpolicy/policy_parse.y > +++ b/checkpolicy/policy_parse.y > @@ -109,6 +109,7 @@ typedef int (* require_func_t)(int pass); > %token IF > %token ELSE > %token TYPE_TRANSITION > +%token MATCH_EXACT MATCH_PREFIX MATCH_SUFFIX > %token TYPE_MEMBER > %token TYPE_CHANGE > %token ROLE_TRANSITION > @@ -452,13 +453,19 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';' > ; > ; > transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' > - {if (define_compute_type(AVRULE_TRANSITION, 1)) return -1; } > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_EXACT ';' > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_PREFIX ';' > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_PREFIX)) return -1;} > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_SUFFIX ';' > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_SUFFIX)) return -1;} > | TYPE_TRANSITION names names ':' names identifier ';' > - {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;} > + {if (define_compute_type(AVRULE_TRANSITION, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > | TYPE_MEMBER names names ':' names identifier ';' > - {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;} > + {if (define_compute_type(AVRULE_MEMBER, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > | TYPE_CHANGE names names ':' names identifier ';' > - {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;} > + {if (define_compute_type(AVRULE_CHANGE, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > ; > range_trans_def : RANGE_TRANSITION names names mls_range_def ';' > { if (define_range_trans(0)) return -1; } > diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l > index 9fefea7b..3f568701 100644 > --- a/checkpolicy/policy_scan.l > +++ b/checkpolicy/policy_scan.l > @@ -125,6 +125,12 @@ EXPANDATTRIBUTE | > expandattribute { return(EXPANDATTRIBUTE); } > TYPE_TRANSITION | > type_transition { return(TYPE_TRANSITION); } > +MATCH_EXACT | > +match_exact { return(MATCH_EXACT); } > +MATCH_PREFIX | > +match_prefix { return(MATCH_PREFIX); } > +MATCH_SUFFIX | > +match_suffix { return(MATCH_SUFFIX); } I would prefer just "exact", "prefix", and "suffix" without the "match_" prefix, but I can live with it if others think that the shorter keywords will cause problems. Thanks, Jim > TYPE_MEMBER | > type_member { return(TYPE_MEMBER); } > TYPE_CHANGE | > diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c > index f26f360c..53edecee 100644 > --- a/checkpolicy/test/dismod.c > +++ b/checkpolicy/test/dismod.c > @@ -293,6 +293,20 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, > display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); > if (avrule->object_name) > fprintf(fp, " \"%s\"", avrule->object_name); > + switch (avrule->name_match) { > + case NAME_TRANS_MATCH_EXACT: > + /* do nothing */ > + break; > + case NAME_TRANS_MATCH_PREFIX: > + fprintf(fp, " MATCH_PREFIX"); > + break; > + case NAME_TRANS_MATCH_SUFFIX: > + fprintf(fp, " MATCH_SUFFIX"); > + break; > + default: > + fprintf(fp, " ERROR: no valid name match type specified\n"); > + return -1; > + } > } else if (avrule->specified & AVRULE_XPERMS) { > avtab_extended_perms_t xperms; > int i; > diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c > index 064cbd4e..87cd6a32 100644 > --- a/checkpolicy/test/dispol.c > +++ b/checkpolicy/test/dispol.c > @@ -82,7 +82,7 @@ typedef struct { > avtab_key_t *key; > policydb_t *p; > FILE *fp; > - name_trans_match_t match; > + uint8_t match; > } render_name_trans_args_t; > > static int render_name_trans_helper(hashtab_key_t k, hashtab_datum_t d, void *a) > diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c > index 996bad70..ffa44be7 100644 > --- a/libsepol/cil/src/cil_binary.c > +++ b/libsepol/cil/src/cil_binary.c > @@ -1211,7 +1211,8 @@ static int __cil_typetransition_to_avtab_helper(policydb_t *pdb, > avt_key.target_type = sepol_tgt->s.value; > avt_key.target_class = sepol_obj->s.value; > rc = avtab_insert_filename_trans(&pdb->te_avtab, &avt_key, > - sepol_result->s.value, name, &otype); > + sepol_result->s.value, name, NAME_TRANS_MATCH_EXACT, > + &otype); > if (rc != SEPOL_OK) { > if (rc == SEPOL_EEXIST) { > if (sepol_result->s.value!= otype) { > @@ -4651,6 +4652,7 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no > __cil_init_sepol_type_set(&avrule->ttypes); > avrule->perms = NULL; > avrule->object_name = NULL; > + avrule->name_match = NAME_TRANS_MATCH_EXACT; > avrule->line = node->line; > > avrule->source_filename = NULL; > diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h > index 870fb08a..7d892879 100644 > --- a/libsepol/include/sepol/policydb/avtab.h > +++ b/libsepol/include/sepol/policydb/avtab.h > @@ -156,6 +156,7 @@ extern avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified); > > extern int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, > uint32_t otype, const char *name, > + uint8_t name_match, > uint32_t *present_otype); > extern int avtab_filename_trans_read(void *fp, uint32_t vers, avtab_t *a); > > diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h > index a2df4a62..48b7b8bb 100644 > --- a/libsepol/include/sepol/policydb/policydb.h > +++ b/libsepol/include/sepol/policydb/policydb.h > @@ -252,12 +252,6 @@ typedef struct av_extended_perms { > uint32_t perms[EXTENDED_PERMS_LEN]; > } av_extended_perms_t; > > -typedef enum name_trans_match { > - NAME_TRANS_MATCH_EXACT, > - NAME_TRANS_MATCH_PREFIX, > - NAME_TRANS_MATCH_SUFFIX, > -} name_trans_match_t; > - > typedef struct avrule { > /* these typedefs are almost exactly the same as those in avtab.h - they are > * here because of the need to include neverallow and dontaudit messages */ > @@ -285,6 +279,10 @@ typedef struct avrule { > type_set_t ttypes; > class_perm_node_t *perms; > char *object_name; /* optional object name */ > +#define NAME_TRANS_MATCH_EXACT 0 > +#define NAME_TRANS_MATCH_PREFIX 1 > +#define NAME_TRANS_MATCH_SUFFIX 2 > + uint8_t name_match; > av_extended_perms_t *xperms; > unsigned long line; /* line number from policy.conf where > * this rule originated */ > @@ -757,9 +755,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); > #define MOD_POLICYDB_VERSION_GLBLUB 20 > #define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21 > #define MOD_POLICYDB_VERSION_AVRULE_FTRANS 22 > +#define MOD_POLICYDB_VERSION_PREFIX_SUFFIX 23 /* preffix/suffix support for filename transitions */ > > #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE > -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_AVRULE_FTRANS > +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_PREFIX_SUFFIX > > #define POLICYDB_CONFIG_MLS 1 > > diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c > index 45cbb3a1..5dc7cc59 100644 > --- a/libsepol/src/avtab.c > +++ b/libsepol/src/avtab.c > @@ -771,7 +771,7 @@ int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) > > int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, > uint32_t otype, const char *name, > - uint32_t *present_otype) > + uint8_t name_match, uint32_t *present_otype) > { > int rc = SEPOL_ENOMEM; > avtab_trans_t new_trans = {0}; > @@ -780,6 +780,7 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, > avtab_ptr_t node; > char *name_key = NULL; > uint32_t *otype_datum = NULL; > + symtab_t *target_symtab; > > datum = avtab_search(a, key); > if (!datum) { > @@ -793,8 +794,22 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, > datum = &node->datum; > } > > - if (hashtab_is_empty(datum->trans->name_trans.table)) { > - rc = symtab_init(&datum->trans->name_trans, 1 << 8); > + switch (name_match) { > + case NAME_TRANS_MATCH_EXACT: > + target_symtab = &datum->trans->name_trans; > + break; > + case NAME_TRANS_MATCH_PREFIX: > + target_symtab = &datum->trans->prefix_trans; > + break; > + case NAME_TRANS_MATCH_SUFFIX: > + target_symtab = &datum->trans->suffix_trans; > + break; > + default: > + return SEPOL_ERR; > + } > + > + if (hashtab_is_empty(target_symtab->table)) { > + rc = symtab_init(target_symtab, 1 << 8); > if (rc < 0) > return rc; > } > @@ -808,8 +823,7 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, > goto bad; > *otype_datum = otype; > > - rc = hashtab_insert(datum->trans->name_trans.table, name_key, > - otype_datum); > + rc = hashtab_insert(target_symtab->table, name_key, otype_datum); > if (rc < 0) > goto bad; > > @@ -854,7 +868,8 @@ static int filename_trans_read_one(avtab_t *a, void *fp) > key.target_class = le32_to_cpu(buf[2]); > otype = le32_to_cpu(buf[3]); > > - rc = avtab_insert_filename_trans(a, &key, otype, name, NULL); > + rc = avtab_insert_filename_trans(a, &key, otype, name, > + NAME_TRANS_MATCH_EXACT, NULL); > if (rc) > goto err; > > @@ -907,7 +922,8 @@ static int filename_trans_comp_read_one(avtab_t *a, void *fp) > key.source_type = bit + 1; > > rc = avtab_insert_filename_trans(a, &key, otype, name, > - NULL); > + NAME_TRANS_MATCH_EXACT, > + NULL); > if (rc < 0) > goto err_ebitmap; > } > diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c > index f3417547..43f8ab3f 100644 > --- a/libsepol/src/expand.c > +++ b/libsepol/src/expand.c > @@ -1620,7 +1620,8 @@ static int expand_terule_helper(sepol_handle_t * handle, > uint32_t specified, cond_av_list_t ** cond, > cond_av_list_t ** other, uint32_t stype, > uint32_t ttype, class_perm_node_t * perms, > - char *object_name, avtab_t * avtab, int enabled) > + char *object_name, uint8_t name_match, > + avtab_t * avtab, int enabled) > { > avtab_key_t avkey; > avtab_datum_t *avdatump; > @@ -1652,6 +1653,7 @@ static int expand_terule_helper(sepol_handle_t * handle, > int rc = avtab_insert_filename_trans(avtab, &avkey, > remapped_data, > object_name, > + name_match, > &oldtype); > if (rc == SEPOL_EEXIST) { > ERR(handle, "conflicting filename transition %s %s:%s \"%s\": %s vs %s", > @@ -1881,6 +1883,7 @@ static int expand_rule_helper(sepol_handle_t * handle, > source_rule->specified, cond, > other, i, i, source_rule->perms, > source_rule->object_name, > + source_rule->name_match, > dest_avtab, enabled); > if (retval != EXPAND_RULE_SUCCESS) > return retval; > @@ -1898,6 +1901,7 @@ static int expand_rule_helper(sepol_handle_t * handle, > source_rule->specified, cond, > other, i, j, source_rule->perms, > source_rule->object_name, > + source_rule->name_match, > dest_avtab, enabled); > if (retval != EXPAND_RULE_SUCCESS) > return retval; > diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h > index 2a1cae85..c0a72107 100644 > --- a/libsepol/src/kernel_to_common.h > +++ b/libsepol/src/kernel_to_common.h > @@ -90,7 +90,7 @@ typedef struct { > const char *src; > const char *tgt; > const char *class; > - name_trans_match_t match; > + uint8_t match; > } name_trans_to_strs_args_t; > > __attribute__ ((format(printf, 1, 2))) > diff --git a/libsepol/src/link.c b/libsepol/src/link.c > index 88b23594..332d62b2 100644 > --- a/libsepol/src/link.c > +++ b/libsepol/src/link.c > @@ -1254,6 +1254,7 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, > if (!new_rule->object_name) > goto cleanup; > } > + new_rule->name_match = cur->name_match; > > cur_perm = cur->perms; > tail_perm = NULL; > diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c > index 653b4b33..4b15bca1 100644 > --- a/libsepol/src/module_to_cil.c > +++ b/libsepol/src/module_to_cil.c > @@ -560,12 +560,13 @@ static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct m > return 0; > } > > -static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const char *object_name, const struct class_perm_node *classperms) > +static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const char *object_name, uint8_t name_match, const struct class_perm_node *classperms) > { > int rc = -1; > const char *rule; > const struct class_perm_node *classperm; > char *perms; > + const char *match_str = ""; > > switch (type) { > case AVRULE_ALLOWED: > @@ -611,10 +612,24 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const > pdb->p_class_val_to_name[classperm->tclass - 1], > perms + 1); > } else if (object_name) { > - cil_println(indent, "(%s %s %s %s \"%s\" %s)", > + switch (name_match) { > + case NAME_TRANS_MATCH_EXACT: > + match_str = ""; > + break; > + case NAME_TRANS_MATCH_PREFIX: > + match_str = " match_prefix"; > + break; > + case NAME_TRANS_MATCH_SUFFIX: > + match_str = " match_suffix"; > + break; > + default: > + log_err("Unknown name match type: %" PRIu8, > + name_match); > + } > + cil_println(indent, "(%s %s %s %s \"%s\"%s %s)", > rule, src, tgt, > pdb->p_class_val_to_name[classperm->tclass - 1], > - object_name, > + object_name, match_str, > pdb->p_type_val_to_name[classperm->data - 1]); > } else { > cil_println(indent, "(%s %s %s %s %s)", > @@ -1218,7 +1233,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a > if (avrule->specified & AVRULE_XPERMS) { > rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms); > } else { > - rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->object_name, avrule->perms); > + rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->object_name, avrule->name_match, avrule->perms); > } > if (rc != 0) { > goto exit; > @@ -1229,7 +1244,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a > if (avrule->specified & AVRULE_XPERMS) { > rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms); > } else { > - rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->object_name, avrule->perms); > + rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->object_name, avrule->name_match, avrule->perms); > } > if (rc != 0) { > goto exit; > diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c > index bd1a151d..594b875e 100644 > --- a/libsepol/src/policydb.c > +++ b/libsepol/src/policydb.c > @@ -355,6 +355,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_PREFIX_SUFFIX, > + .sym_num = SYM_NUM, > + .ocon_num = OCON_IBENDPORT + 1, > + .target_platform = SEPOL_TARGET_SELINUX, > + }, > { > .type = POLICY_MOD, > .version = MOD_POLICYDB_VERSION_BASE, > @@ -488,6 +495,13 @@ static const struct policydb_compat_info policydb_compat[] = { > .ocon_num = 0, > .target_platform = SEPOL_TARGET_SELINUX, > }, > + { > + .type = POLICY_MOD, > + .version = MOD_POLICYDB_VERSION_PREFIX_SUFFIX, > + .sym_num = SYM_NUM, > + .ocon_num = 0, > + .target_platform = SEPOL_TARGET_SELINUX, > + }, > }; > > #if 0 > @@ -3171,6 +3185,7 @@ common_read, class_read, role_read, type_read, user_read, > static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) > { > unsigned int i; > + uint8_t buf8; > uint32_t buf[2], len; > class_perm_node_t *cur, *tail = NULL; > avrule_t *avrule; > @@ -3234,10 +3249,15 @@ static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) > if (rc < 0) > goto bad; > } > + if (p->policyvers >= MOD_POLICYDB_VERSION_PREFIX_SUFFIX) { > + rc = next_entry(&buf8, fp, sizeof(uint8_t)); > + if (rc < 0) > + goto bad; > + avrule->name_match = buf8; > + } > } > > if (avrule->specified & AVRULE_XPERMS) { > - uint8_t buf8; > size_t nel = ARRAY_SIZE(avrule->xperms->perms); > uint32_t buf32[nel]; > > @@ -3546,6 +3566,7 @@ static int filename_trans_rule_read(policydb_t *p, avrule_t **r, > rc = str_read(&cur->object_name, fp, len); > if (rc) > return -1; > + cur->name_match = NAME_TRANS_MATCH_EXACT; > > if (type_set_read(&cur->stypes, fp)) > return -1; > diff --git a/libsepol/src/write.c b/libsepol/src/write.c > index 92a7b6cf..da83257d 100644 > --- a/libsepol/src/write.c > +++ b/libsepol/src/write.c > @@ -2048,6 +2048,7 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, > struct policy_file *fp) > { > size_t items, items2; > + uint8_t buf8; > uint32_t buf[32], len; > class_perm_node_t *cur; > > @@ -2055,6 +2056,11 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, > if (p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS && > avrule->specified & AVRULE_TRANSITION && avrule->object_name) > return POLICYDB_SUCCESS; > + /* skip prefix/suffix name transition if writing older version */ > + if (p->policyvers < MOD_POLICYDB_VERSION_PREFIX_SUFFIX && > + avrule->specified & AVRULE_TRANSITION && > + avrule->object_name && avrule->name_match != NAME_TRANS_MATCH_EXACT) > + return POLICYDB_SUCCESS; > > if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && > (avrule->specified & AVRULE_TYPE) && > @@ -2113,12 +2119,17 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, > if (items != len) > return POLICYDB_ERROR; > } > + if (p->policyvers >= MOD_POLICYDB_VERSION_PREFIX_SUFFIX) { > + buf8 = avrule->name_match; > + items = put_entry(&buf8, sizeof(uint8_t), 1, fp); > + if (items != 1) > + return POLICYDB_ERROR; > + } > } > > if (avrule->specified & AVRULE_XPERMS) { > size_t nel = ARRAY_SIZE(avrule->xperms->perms); > uint32_t buf32[nel]; > - uint8_t buf8; > unsigned int i; > > if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { > @@ -2163,12 +2174,17 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules, > > avrule = avrules; > len = 0; > - while (avrule) { > - if (p->policyvers >= MOD_POLICYDB_VERSION_AVRULE_FTRANS || > - !(avrule->specified & AVRULE_TRANSITION && > - avrule->object_name)) > - len++; > - avrule = avrule->next; > + for (avrule = avrules; avrule; avrule = avrule->next) { > + if (p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS && > + (avrule->specified & AVTAB_TRANSITION) && > + avrule->object_name) > + continue; > + if (p->policyvers < MOD_POLICYDB_VERSION_PREFIX_SUFFIX && > + (avrule->specified & AVTAB_TRANSITION) && > + avrule->object_name && > + avrule->name_match != NAME_TRANS_MATCH_EXACT) > + continue; > + len++; > } > > buf[0] = cpu_to_le32(len); > @@ -2276,7 +2292,8 @@ static int filename_trans_rule_write(policydb_t *p, avrule_t *rules, > class_perm_node_t *perm; > > for (rule = rules; rule; rule = rule->next) { > - if (rule->specified & AVRULE_TRANSITION && rule->object_name) { > + if (rule->specified & AVRULE_TRANSITION && rule->object_name && > + rule->name_match == NAME_TRANS_MATCH_EXACT) { > for (perm = rule->perms; perm; perm = perm->next) { > nel++; > } > @@ -2289,7 +2306,9 @@ static int filename_trans_rule_write(policydb_t *p, avrule_t *rules, > return POLICYDB_ERROR; > > for (rule = rules; rule; rule = rule->next) { > - if (!(rule->specified & AVRULE_TRANSITION && rule->object_name)) > + if (!(rule->specified & AVRULE_TRANSITION && > + rule->object_name && > + rule->name_match == NAME_TRANS_MATCH_EXACT)) > continue; > len = strlen(rule->object_name); > for (perm = rule->perms; perm; perm = perm->next) { > @@ -2728,7 +2747,8 @@ int policydb_write(policydb_t * p, struct policy_file *fp) > if (p->policy_type == POLICY_KERN) { > if (avtab_write(p, &p->te_avtab, fp)) > return POLICYDB_ERROR; > - if (avtab_has_prefix_suffix_filename_transitions(&p->te_avtab)) { > + if (p->policyvers < POLICYDB_VERSION_PREFIX_SUFFIX && > + avtab_has_prefix_suffix_filename_transitions(&p->te_avtab)) { > WARN(fp->handle, > "Discarding filename prefix/suffix type transition rules"); > } > -- > 2.40.0 >
On Thu, Jun 1, 2023 at 10:59 PM James Carter <jwcart2@gmail.com> wrote: > > On Wed, May 31, 2023 at 7:51 AM Juraj Marcin <juraj@jurajmarcin.com> wrote: > > > > This patch extends the structures for module and base policy (avrule_t) > > to support prefix/suffix transitions. In addition to this, it implements > > the necessary changes to functions for reading and writing the binary > > policy as well as parsing the policy conf. > > > > I would like to see an example of the new syntax. > Something like: > type_transition ta tb : CLASS03 tc "file03" match_exact; > type_transition ta tb : CLASS04 tc "file04" match_prefix; > type_transition ta tb : CLASS05 tc "file05" match_suffix; > > > Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com> > > Signed-off-by: Juraj Marcin <juraj@jurajmarcin.com> > > --- > > checkpolicy/policy_define.c | 13 ++++--- > > checkpolicy/policy_define.h | 2 +- > > checkpolicy/policy_parse.y | 15 +++++--- > > checkpolicy/policy_scan.l | 6 ++++ > > checkpolicy/test/dismod.c | 14 ++++++++ > > checkpolicy/test/dispol.c | 2 +- > > libsepol/cil/src/cil_binary.c | 4 ++- > > libsepol/include/sepol/policydb/avtab.h | 1 + > > libsepol/include/sepol/policydb/policydb.h | 13 ++++--- > > libsepol/src/avtab.c | 30 ++++++++++++---- > > libsepol/src/expand.c | 6 +++- > > libsepol/src/kernel_to_common.h | 2 +- > > libsepol/src/link.c | 1 + > > libsepol/src/module_to_cil.c | 25 +++++++++++--- > > libsepol/src/policydb.c | 23 ++++++++++++- > > libsepol/src/write.c | 40 ++++++++++++++++------ > > 16 files changed, 154 insertions(+), 43 deletions(-) <snip> > > @@ -452,13 +453,19 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';' > > ; > > ; > > transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' > > - {if (define_compute_type(AVRULE_TRANSITION, 1)) return -1; } > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_EXACT ';' > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_PREFIX ';' > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_PREFIX)) return -1;} > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_SUFFIX ';' > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_SUFFIX)) return -1;} > > | TYPE_TRANSITION names names ':' names identifier ';' > > - {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;} > > + {if (define_compute_type(AVRULE_TRANSITION, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > | TYPE_MEMBER names names ':' names identifier ';' > > - {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;} > > + {if (define_compute_type(AVRULE_MEMBER, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > | TYPE_CHANGE names names ':' names identifier ';' > > - {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;} > > + {if (define_compute_type(AVRULE_CHANGE, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > ; > > range_trans_def : RANGE_TRANSITION names names mls_range_def ';' > > { if (define_range_trans(0)) return -1; } > > diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l > > index 9fefea7b..3f568701 100644 > > --- a/checkpolicy/policy_scan.l > > +++ b/checkpolicy/policy_scan.l > > @@ -125,6 +125,12 @@ EXPANDATTRIBUTE | > > expandattribute { return(EXPANDATTRIBUTE); } > > TYPE_TRANSITION | > > type_transition { return(TYPE_TRANSITION); } > > +MATCH_EXACT | > > +match_exact { return(MATCH_EXACT); } > > +MATCH_PREFIX | > > +match_prefix { return(MATCH_PREFIX); } > > +MATCH_SUFFIX | > > +match_suffix { return(MATCH_SUFFIX); } > > I would prefer just "exact", "prefix", and "suffix" without the > "match_" prefix, but I can live with it if others think that the > shorter keywords will cause problems. I slightly prefer the "match_" in the keyword, since it makes the semantic more clear when reading the policy (especially for people that are only learning SELinux). But I guess in the case of "prefix" and "suffix" it doesn't make as much difference as in the case of "exact". Which leads me to the question whether we want to even add the redundant "exact"/"match_exact" keyword as opposed to just leaving the current syntax (which we need to keep either way for compatibility). IIRC, when we discussed this with Juraj, we were not sure which way to go, so we are open to dropping it if that's preferred by others. -- Ondrej Mosnacek Senior Software Engineer, Linux Security - SELinux kernel Red Hat, Inc.
On Wed, Jun 7, 2023 at 4:31 AM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > On Thu, Jun 1, 2023 at 10:59 PM James Carter <jwcart2@gmail.com> wrote: > > > > On Wed, May 31, 2023 at 7:51 AM Juraj Marcin <juraj@jurajmarcin.com> wrote: > > > > > > This patch extends the structures for module and base policy (avrule_t) > > > to support prefix/suffix transitions. In addition to this, it implements > > > the necessary changes to functions for reading and writing the binary > > > policy as well as parsing the policy conf. > > > > > > > I would like to see an example of the new syntax. > > Something like: > > type_transition ta tb : CLASS03 tc "file03" match_exact; > > type_transition ta tb : CLASS04 tc "file04" match_prefix; > > type_transition ta tb : CLASS05 tc "file05" match_suffix; > > > > > Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com> > > > Signed-off-by: Juraj Marcin <juraj@jurajmarcin.com> > > > --- > > > checkpolicy/policy_define.c | 13 ++++--- > > > checkpolicy/policy_define.h | 2 +- > > > checkpolicy/policy_parse.y | 15 +++++--- > > > checkpolicy/policy_scan.l | 6 ++++ > > > checkpolicy/test/dismod.c | 14 ++++++++ > > > checkpolicy/test/dispol.c | 2 +- > > > libsepol/cil/src/cil_binary.c | 4 ++- > > > libsepol/include/sepol/policydb/avtab.h | 1 + > > > libsepol/include/sepol/policydb/policydb.h | 13 ++++--- > > > libsepol/src/avtab.c | 30 ++++++++++++---- > > > libsepol/src/expand.c | 6 +++- > > > libsepol/src/kernel_to_common.h | 2 +- > > > libsepol/src/link.c | 1 + > > > libsepol/src/module_to_cil.c | 25 +++++++++++--- > > > libsepol/src/policydb.c | 23 ++++++++++++- > > > libsepol/src/write.c | 40 ++++++++++++++++------ > > > 16 files changed, 154 insertions(+), 43 deletions(-) > > <snip> > > > > @@ -452,13 +453,19 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';' > > > ; > > > ; > > > transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' > > > - {if (define_compute_type(AVRULE_TRANSITION, 1)) return -1; } > > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_EXACT ';' > > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} > > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_PREFIX ';' > > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_PREFIX)) return -1;} > > > + | TYPE_TRANSITION names names ':' names identifier filename MATCH_SUFFIX ';' > > > + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_SUFFIX)) return -1;} > > > | TYPE_TRANSITION names names ':' names identifier ';' > > > - {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;} > > > + {if (define_compute_type(AVRULE_TRANSITION, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > > | TYPE_MEMBER names names ':' names identifier ';' > > > - {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;} > > > + {if (define_compute_type(AVRULE_MEMBER, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > > | TYPE_CHANGE names names ':' names identifier ';' > > > - {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;} > > > + {if (define_compute_type(AVRULE_CHANGE, 0, NAME_TRANS_MATCH_EXACT)) return -1;} > > > ; > > > range_trans_def : RANGE_TRANSITION names names mls_range_def ';' > > > { if (define_range_trans(0)) return -1; } > > > diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l > > > index 9fefea7b..3f568701 100644 > > > --- a/checkpolicy/policy_scan.l > > > +++ b/checkpolicy/policy_scan.l > > > @@ -125,6 +125,12 @@ EXPANDATTRIBUTE | > > > expandattribute { return(EXPANDATTRIBUTE); } > > > TYPE_TRANSITION | > > > type_transition { return(TYPE_TRANSITION); } > > > +MATCH_EXACT | > > > +match_exact { return(MATCH_EXACT); } > > > +MATCH_PREFIX | > > > +match_prefix { return(MATCH_PREFIX); } > > > +MATCH_SUFFIX | > > > +match_suffix { return(MATCH_SUFFIX); } > > > > I would prefer just "exact", "prefix", and "suffix" without the > > "match_" prefix, but I can live with it if others think that the > > shorter keywords will cause problems. > > I slightly prefer the "match_" in the keyword, since it makes the > semantic more clear when reading the policy (especially for people > that are only learning SELinux). But I guess in the case of "prefix" > and "suffix" it doesn't make as much difference as in the case of > "exact". Which leads me to the question whether we want to even add > the redundant "exact"/"match_exact" keyword as opposed to just leaving > the current syntax (which we need to keep either way for > compatibility). IIRC, when we discussed this with Juraj, we were not > sure which way to go, so we are open to dropping it if that's > preferred by others. > I think that I would prefer just "prefix" and "suffix" and using the current syntax for the exact match. That seems like it would make it very clear when something other than an exact match is being used. But if others want to keep "match_" and use "exact", I can live with it. Jim > -- > Ondrej Mosnacek > Senior Software Engineer, Linux Security - SELinux kernel > Red Hat, Inc. >
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index 455255ba..c3c6af72 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -1601,7 +1601,8 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed) return -1; } -static int define_compute_type_helper(int which, avrule_t ** rule, int has_filename) +static int define_compute_type_helper(int which, avrule_t ** rule, + int has_filename, uint8_t name_match) { char *id; type_datum_t *datum; @@ -1676,6 +1677,7 @@ static int define_compute_type_helper(int which, avrule_t ** rule, int has_filen goto bad; } } + avrule->name_match = name_match; ebitmap_for_each_positive_bit(&tclasses, node, i) { perm = malloc(sizeof(class_perm_node_t)); @@ -1700,7 +1702,7 @@ static int define_compute_type_helper(int which, avrule_t ** rule, int has_filen return -1; } -int define_compute_type(int which, int has_filename) +int define_compute_type(int which, int has_filename, uint8_t name_match) { char *id; avrule_t *avrule; @@ -1721,7 +1723,8 @@ int define_compute_type(int which, int has_filename) return 0; } - if (define_compute_type_helper(which, &avrule, has_filename)) + if (define_compute_type_helper(which, &avrule, has_filename, + name_match)) return -1; append_avrule(avrule); @@ -1745,7 +1748,8 @@ avrule_t *define_cond_compute_type(int which) return (avrule_t *) 1; } - if (define_compute_type_helper(which, &avrule, 0)) + if (define_compute_type_helper(which, &avrule, 0, + NAME_TRANS_MATCH_EXACT)) return COND_ERR; return avrule; @@ -2394,6 +2398,7 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src) return -1; } } + dest->name_match = src->name_match; dest->line = src->line; dest->source_filename = strdup(source_file); if (!dest->source_filename) { diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h index 5d0f70e4..c1314871 100644 --- a/checkpolicy/policy_define.h +++ b/checkpolicy/policy_define.h @@ -28,7 +28,7 @@ int define_default_role(int which); int define_default_type(int which); int define_default_range(int which); int define_common_perms(void); -int define_compute_type(int which, int has_filename); +int define_compute_type(int which, int has_filename, uint8_t name_match); int define_conditional(cond_expr_t *expr, avrule_t *t_list, avrule_t *f_list ); int define_constraint(constraint_expr_t *expr); int define_dominance(void); diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y index fccbc052..12dff7af 100644 --- a/checkpolicy/policy_parse.y +++ b/checkpolicy/policy_parse.y @@ -109,6 +109,7 @@ typedef int (* require_func_t)(int pass); %token IF %token ELSE %token TYPE_TRANSITION +%token MATCH_EXACT MATCH_PREFIX MATCH_SUFFIX %token TYPE_MEMBER %token TYPE_CHANGE %token ROLE_TRANSITION @@ -452,13 +453,19 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';' ; ; transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' - {if (define_compute_type(AVRULE_TRANSITION, 1)) return -1; } + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} + | TYPE_TRANSITION names names ':' names identifier filename MATCH_EXACT ';' + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_EXACT)) return -1;} + | TYPE_TRANSITION names names ':' names identifier filename MATCH_PREFIX ';' + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_PREFIX)) return -1;} + | TYPE_TRANSITION names names ':' names identifier filename MATCH_SUFFIX ';' + {if (define_compute_type(AVRULE_TRANSITION, 1, NAME_TRANS_MATCH_SUFFIX)) return -1;} | TYPE_TRANSITION names names ':' names identifier ';' - {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;} + {if (define_compute_type(AVRULE_TRANSITION, 0, NAME_TRANS_MATCH_EXACT)) return -1;} | TYPE_MEMBER names names ':' names identifier ';' - {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;} + {if (define_compute_type(AVRULE_MEMBER, 0, NAME_TRANS_MATCH_EXACT)) return -1;} | TYPE_CHANGE names names ':' names identifier ';' - {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;} + {if (define_compute_type(AVRULE_CHANGE, 0, NAME_TRANS_MATCH_EXACT)) return -1;} ; range_trans_def : RANGE_TRANSITION names names mls_range_def ';' { if (define_range_trans(0)) return -1; } diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l index 9fefea7b..3f568701 100644 --- a/checkpolicy/policy_scan.l +++ b/checkpolicy/policy_scan.l @@ -125,6 +125,12 @@ EXPANDATTRIBUTE | expandattribute { return(EXPANDATTRIBUTE); } TYPE_TRANSITION | type_transition { return(TYPE_TRANSITION); } +MATCH_EXACT | +match_exact { return(MATCH_EXACT); } +MATCH_PREFIX | +match_prefix { return(MATCH_PREFIX); } +MATCH_SUFFIX | +match_suffix { return(MATCH_SUFFIX); } TYPE_MEMBER | type_member { return(TYPE_MEMBER); } TYPE_CHANGE | diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c index f26f360c..53edecee 100644 --- a/checkpolicy/test/dismod.c +++ b/checkpolicy/test/dismod.c @@ -293,6 +293,20 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); if (avrule->object_name) fprintf(fp, " \"%s\"", avrule->object_name); + switch (avrule->name_match) { + case NAME_TRANS_MATCH_EXACT: + /* do nothing */ + break; + case NAME_TRANS_MATCH_PREFIX: + fprintf(fp, " MATCH_PREFIX"); + break; + case NAME_TRANS_MATCH_SUFFIX: + fprintf(fp, " MATCH_SUFFIX"); + break; + default: + fprintf(fp, " ERROR: no valid name match type specified\n"); + return -1; + } } else if (avrule->specified & AVRULE_XPERMS) { avtab_extended_perms_t xperms; int i; diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c index 064cbd4e..87cd6a32 100644 --- a/checkpolicy/test/dispol.c +++ b/checkpolicy/test/dispol.c @@ -82,7 +82,7 @@ typedef struct { avtab_key_t *key; policydb_t *p; FILE *fp; - name_trans_match_t match; + uint8_t match; } render_name_trans_args_t; static int render_name_trans_helper(hashtab_key_t k, hashtab_datum_t d, void *a) diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c index 996bad70..ffa44be7 100644 --- a/libsepol/cil/src/cil_binary.c +++ b/libsepol/cil/src/cil_binary.c @@ -1211,7 +1211,8 @@ static int __cil_typetransition_to_avtab_helper(policydb_t *pdb, avt_key.target_type = sepol_tgt->s.value; avt_key.target_class = sepol_obj->s.value; rc = avtab_insert_filename_trans(&pdb->te_avtab, &avt_key, - sepol_result->s.value, name, &otype); + sepol_result->s.value, name, NAME_TRANS_MATCH_EXACT, + &otype); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { if (sepol_result->s.value!= otype) { @@ -4651,6 +4652,7 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no __cil_init_sepol_type_set(&avrule->ttypes); avrule->perms = NULL; avrule->object_name = NULL; + avrule->name_match = NAME_TRANS_MATCH_EXACT; avrule->line = node->line; avrule->source_filename = NULL; diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h index 870fb08a..7d892879 100644 --- a/libsepol/include/sepol/policydb/avtab.h +++ b/libsepol/include/sepol/policydb/avtab.h @@ -156,6 +156,7 @@ extern avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified); extern int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, uint32_t otype, const char *name, + uint8_t name_match, uint32_t *present_otype); extern int avtab_filename_trans_read(void *fp, uint32_t vers, avtab_t *a); diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index a2df4a62..48b7b8bb 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -252,12 +252,6 @@ typedef struct av_extended_perms { uint32_t perms[EXTENDED_PERMS_LEN]; } av_extended_perms_t; -typedef enum name_trans_match { - NAME_TRANS_MATCH_EXACT, - NAME_TRANS_MATCH_PREFIX, - NAME_TRANS_MATCH_SUFFIX, -} name_trans_match_t; - typedef struct avrule { /* these typedefs are almost exactly the same as those in avtab.h - they are * here because of the need to include neverallow and dontaudit messages */ @@ -285,6 +279,10 @@ typedef struct avrule { type_set_t ttypes; class_perm_node_t *perms; char *object_name; /* optional object name */ +#define NAME_TRANS_MATCH_EXACT 0 +#define NAME_TRANS_MATCH_PREFIX 1 +#define NAME_TRANS_MATCH_SUFFIX 2 + uint8_t name_match; av_extended_perms_t *xperms; unsigned long line; /* line number from policy.conf where * this rule originated */ @@ -757,9 +755,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); #define MOD_POLICYDB_VERSION_GLBLUB 20 #define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21 #define MOD_POLICYDB_VERSION_AVRULE_FTRANS 22 +#define MOD_POLICYDB_VERSION_PREFIX_SUFFIX 23 /* preffix/suffix support for filename transitions */ #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_AVRULE_FTRANS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_PREFIX_SUFFIX #define POLICYDB_CONFIG_MLS 1 diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c index 45cbb3a1..5dc7cc59 100644 --- a/libsepol/src/avtab.c +++ b/libsepol/src/avtab.c @@ -771,7 +771,7 @@ int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, uint32_t otype, const char *name, - uint32_t *present_otype) + uint8_t name_match, uint32_t *present_otype) { int rc = SEPOL_ENOMEM; avtab_trans_t new_trans = {0}; @@ -780,6 +780,7 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, avtab_ptr_t node; char *name_key = NULL; uint32_t *otype_datum = NULL; + symtab_t *target_symtab; datum = avtab_search(a, key); if (!datum) { @@ -793,8 +794,22 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, datum = &node->datum; } - if (hashtab_is_empty(datum->trans->name_trans.table)) { - rc = symtab_init(&datum->trans->name_trans, 1 << 8); + switch (name_match) { + case NAME_TRANS_MATCH_EXACT: + target_symtab = &datum->trans->name_trans; + break; + case NAME_TRANS_MATCH_PREFIX: + target_symtab = &datum->trans->prefix_trans; + break; + case NAME_TRANS_MATCH_SUFFIX: + target_symtab = &datum->trans->suffix_trans; + break; + default: + return SEPOL_ERR; + } + + if (hashtab_is_empty(target_symtab->table)) { + rc = symtab_init(target_symtab, 1 << 8); if (rc < 0) return rc; } @@ -808,8 +823,7 @@ int avtab_insert_filename_trans(avtab_t *a, avtab_key_t *key, goto bad; *otype_datum = otype; - rc = hashtab_insert(datum->trans->name_trans.table, name_key, - otype_datum); + rc = hashtab_insert(target_symtab->table, name_key, otype_datum); if (rc < 0) goto bad; @@ -854,7 +868,8 @@ static int filename_trans_read_one(avtab_t *a, void *fp) key.target_class = le32_to_cpu(buf[2]); otype = le32_to_cpu(buf[3]); - rc = avtab_insert_filename_trans(a, &key, otype, name, NULL); + rc = avtab_insert_filename_trans(a, &key, otype, name, + NAME_TRANS_MATCH_EXACT, NULL); if (rc) goto err; @@ -907,7 +922,8 @@ static int filename_trans_comp_read_one(avtab_t *a, void *fp) key.source_type = bit + 1; rc = avtab_insert_filename_trans(a, &key, otype, name, - NULL); + NAME_TRANS_MATCH_EXACT, + NULL); if (rc < 0) goto err_ebitmap; } diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c index f3417547..43f8ab3f 100644 --- a/libsepol/src/expand.c +++ b/libsepol/src/expand.c @@ -1620,7 +1620,8 @@ static int expand_terule_helper(sepol_handle_t * handle, uint32_t specified, cond_av_list_t ** cond, cond_av_list_t ** other, uint32_t stype, uint32_t ttype, class_perm_node_t * perms, - char *object_name, avtab_t * avtab, int enabled) + char *object_name, uint8_t name_match, + avtab_t * avtab, int enabled) { avtab_key_t avkey; avtab_datum_t *avdatump; @@ -1652,6 +1653,7 @@ static int expand_terule_helper(sepol_handle_t * handle, int rc = avtab_insert_filename_trans(avtab, &avkey, remapped_data, object_name, + name_match, &oldtype); if (rc == SEPOL_EEXIST) { ERR(handle, "conflicting filename transition %s %s:%s \"%s\": %s vs %s", @@ -1881,6 +1883,7 @@ static int expand_rule_helper(sepol_handle_t * handle, source_rule->specified, cond, other, i, i, source_rule->perms, source_rule->object_name, + source_rule->name_match, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; @@ -1898,6 +1901,7 @@ static int expand_rule_helper(sepol_handle_t * handle, source_rule->specified, cond, other, i, j, source_rule->perms, source_rule->object_name, + source_rule->name_match, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h index 2a1cae85..c0a72107 100644 --- a/libsepol/src/kernel_to_common.h +++ b/libsepol/src/kernel_to_common.h @@ -90,7 +90,7 @@ typedef struct { const char *src; const char *tgt; const char *class; - name_trans_match_t match; + uint8_t match; } name_trans_to_strs_args_t; __attribute__ ((format(printf, 1, 2))) diff --git a/libsepol/src/link.c b/libsepol/src/link.c index 88b23594..332d62b2 100644 --- a/libsepol/src/link.c +++ b/libsepol/src/link.c @@ -1254,6 +1254,7 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, if (!new_rule->object_name) goto cleanup; } + new_rule->name_match = cur->name_match; cur_perm = cur->perms; tail_perm = NULL; diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c index 653b4b33..4b15bca1 100644 --- a/libsepol/src/module_to_cil.c +++ b/libsepol/src/module_to_cil.c @@ -560,12 +560,13 @@ static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct m return 0; } -static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const char *object_name, const struct class_perm_node *classperms) +static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const char *object_name, uint8_t name_match, const struct class_perm_node *classperms) { int rc = -1; const char *rule; const struct class_perm_node *classperm; char *perms; + const char *match_str = ""; switch (type) { case AVRULE_ALLOWED: @@ -611,10 +612,24 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const pdb->p_class_val_to_name[classperm->tclass - 1], perms + 1); } else if (object_name) { - cil_println(indent, "(%s %s %s %s \"%s\" %s)", + switch (name_match) { + case NAME_TRANS_MATCH_EXACT: + match_str = ""; + break; + case NAME_TRANS_MATCH_PREFIX: + match_str = " match_prefix"; + break; + case NAME_TRANS_MATCH_SUFFIX: + match_str = " match_suffix"; + break; + default: + log_err("Unknown name match type: %" PRIu8, + name_match); + } + cil_println(indent, "(%s %s %s %s \"%s\"%s %s)", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], - object_name, + object_name, match_str, pdb->p_type_val_to_name[classperm->data - 1]); } else { cil_println(indent, "(%s %s %s %s %s)", @@ -1218,7 +1233,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms); } else { - rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->object_name, avrule->perms); + rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->object_name, avrule->name_match, avrule->perms); } if (rc != 0) { goto exit; @@ -1229,7 +1244,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms); } else { - rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->object_name, avrule->perms); + rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->object_name, avrule->name_match, avrule->perms); } if (rc != 0) { goto exit; diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index bd1a151d..594b875e 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -355,6 +355,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_PREFIX_SUFFIX, + .sym_num = SYM_NUM, + .ocon_num = OCON_IBENDPORT + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, @@ -488,6 +495,13 @@ static const struct policydb_compat_info policydb_compat[] = { .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_PREFIX_SUFFIX, + .sym_num = SYM_NUM, + .ocon_num = 0, + .target_platform = SEPOL_TARGET_SELINUX, + }, }; #if 0 @@ -3171,6 +3185,7 @@ common_read, class_read, role_read, type_read, user_read, static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) { unsigned int i; + uint8_t buf8; uint32_t buf[2], len; class_perm_node_t *cur, *tail = NULL; avrule_t *avrule; @@ -3234,10 +3249,15 @@ static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) if (rc < 0) goto bad; } + if (p->policyvers >= MOD_POLICYDB_VERSION_PREFIX_SUFFIX) { + rc = next_entry(&buf8, fp, sizeof(uint8_t)); + if (rc < 0) + goto bad; + avrule->name_match = buf8; + } } if (avrule->specified & AVRULE_XPERMS) { - uint8_t buf8; size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; @@ -3546,6 +3566,7 @@ static int filename_trans_rule_read(policydb_t *p, avrule_t **r, rc = str_read(&cur->object_name, fp, len); if (rc) return -1; + cur->name_match = NAME_TRANS_MATCH_EXACT; if (type_set_read(&cur->stypes, fp)) return -1; diff --git a/libsepol/src/write.c b/libsepol/src/write.c index 92a7b6cf..da83257d 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -2048,6 +2048,7 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, struct policy_file *fp) { size_t items, items2; + uint8_t buf8; uint32_t buf[32], len; class_perm_node_t *cur; @@ -2055,6 +2056,11 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, if (p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS && avrule->specified & AVRULE_TRANSITION && avrule->object_name) return POLICYDB_SUCCESS; + /* skip prefix/suffix name transition if writing older version */ + if (p->policyvers < MOD_POLICYDB_VERSION_PREFIX_SUFFIX && + avrule->specified & AVRULE_TRANSITION && + avrule->object_name && avrule->name_match != NAME_TRANS_MATCH_EXACT) + return POLICYDB_SUCCESS; if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && (avrule->specified & AVRULE_TYPE) && @@ -2113,12 +2119,17 @@ static int avrule_write(policydb_t *p, avrule_t * avrule, if (items != len) return POLICYDB_ERROR; } + if (p->policyvers >= MOD_POLICYDB_VERSION_PREFIX_SUFFIX) { + buf8 = avrule->name_match; + items = put_entry(&buf8, sizeof(uint8_t), 1, fp); + if (items != 1) + return POLICYDB_ERROR; + } } if (avrule->specified & AVRULE_XPERMS) { size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; - uint8_t buf8; unsigned int i; if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { @@ -2163,12 +2174,17 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules, avrule = avrules; len = 0; - while (avrule) { - if (p->policyvers >= MOD_POLICYDB_VERSION_AVRULE_FTRANS || - !(avrule->specified & AVRULE_TRANSITION && - avrule->object_name)) - len++; - avrule = avrule->next; + for (avrule = avrules; avrule; avrule = avrule->next) { + if (p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS && + (avrule->specified & AVTAB_TRANSITION) && + avrule->object_name) + continue; + if (p->policyvers < MOD_POLICYDB_VERSION_PREFIX_SUFFIX && + (avrule->specified & AVTAB_TRANSITION) && + avrule->object_name && + avrule->name_match != NAME_TRANS_MATCH_EXACT) + continue; + len++; } buf[0] = cpu_to_le32(len); @@ -2276,7 +2292,8 @@ static int filename_trans_rule_write(policydb_t *p, avrule_t *rules, class_perm_node_t *perm; for (rule = rules; rule; rule = rule->next) { - if (rule->specified & AVRULE_TRANSITION && rule->object_name) { + if (rule->specified & AVRULE_TRANSITION && rule->object_name && + rule->name_match == NAME_TRANS_MATCH_EXACT) { for (perm = rule->perms; perm; perm = perm->next) { nel++; } @@ -2289,7 +2306,9 @@ static int filename_trans_rule_write(policydb_t *p, avrule_t *rules, return POLICYDB_ERROR; for (rule = rules; rule; rule = rule->next) { - if (!(rule->specified & AVRULE_TRANSITION && rule->object_name)) + if (!(rule->specified & AVRULE_TRANSITION && + rule->object_name && + rule->name_match == NAME_TRANS_MATCH_EXACT)) continue; len = strlen(rule->object_name); for (perm = rule->perms; perm; perm = perm->next) { @@ -2728,7 +2747,8 @@ int policydb_write(policydb_t * p, struct policy_file *fp) if (p->policy_type == POLICY_KERN) { if (avtab_write(p, &p->te_avtab, fp)) return POLICYDB_ERROR; - if (avtab_has_prefix_suffix_filename_transitions(&p->te_avtab)) { + if (p->policyvers < POLICYDB_VERSION_PREFIX_SUFFIX && + avtab_has_prefix_suffix_filename_transitions(&p->te_avtab)) { WARN(fp->handle, "Discarding filename prefix/suffix type transition rules"); }