@@ -129,6 +129,7 @@ typedef struct {
avtab_key_t *key;
policydb_t *p;
FILE *fp;
+ name_trans_match_t match;
} render_name_trans_args_t;
static int render_name_trans_helper(hashtab_key_t k, hashtab_datum_t d, void *a)
@@ -140,7 +141,22 @@ static int render_name_trans_helper(hashtab_key_t k, hashtab_datum_t d, void *a)
fprintf(args->fp, "type_transition ");
render_key(args->key, args->p, args->fp);
render_type(*otype, args->p, args->fp);
- fprintf(args->fp, " \"%s\";\n", name);
+ const char *match_str = "";
+ switch (args->match) {
+ case NAME_TRANS_MATCH_EXACT:
+ match_str = "";
+ break;
+ case NAME_TRANS_MATCH_PREFIX:
+ match_str = " PREFIX";
+ break;
+ case NAME_TRANS_MATCH_SUFFIX:
+ match_str = " SUFFIX";
+ break;
+ default:
+ fprintf(args->fp, " ERROR: no valid name match type specified\n");
+ return -1;
+ }
+ fprintf(args->fp, " \"%s\"%s;\n", name, match_str);
return 0;
}
@@ -207,9 +223,16 @@ static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t wha
.key = key,
.p = p,
.fp = fp,
+ .match = NAME_TRANS_MATCH_EXACT,
};
hashtab_map(datum->trans->name_trans.table,
render_name_trans_helper, &args);
+ args.match = NAME_TRANS_MATCH_PREFIX;
+ hashtab_map(datum->trans->prefix_trans.table,
+ render_name_trans_helper, &args);
+ args.match = NAME_TRANS_MATCH_SUFFIX;
+ hashtab_map(datum->trans->suffix_trans.table,
+ render_name_trans_helper, &args);
}
if (key->specified & AVTAB_MEMBER) {
fprintf(fp, "type_member ");
@@ -74,6 +74,8 @@ typedef struct avtab_key {
typedef struct avtab_trans {
uint32_t otype; /* resulting type of the new object */
symtab_t name_trans; /* filename transitions */
+ symtab_t prefix_trans; /* prefix filename transitions */
+ symtab_t suffix_trans; /* prefix filename transitions */
} avtab_trans_t;
typedef struct avtab_extended_perms {
@@ -252,6 +252,12 @@ 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 */
@@ -723,10 +729,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_GLBLUB 32
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
#define POLICYDB_VERSION_AVTAB_FTRANS 34 /* filename transitions moved to avtab */
+#define POLICYDB_VERSION_PREFIX_SUFFIX 35 /* prefix/suffix support for filename transitions */
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB_FTRANS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PREFIX_SUFFIX
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
@@ -327,6 +327,10 @@ void avtab_trans_destroy(avtab_trans_t *trans)
{
hashtab_map(trans->name_trans.table, avtab_trans_destroy_helper, NULL);
symtab_destroy(&trans->name_trans);
+ hashtab_map(trans->prefix_trans.table, avtab_trans_destroy_helper, NULL);
+ symtab_destroy(&trans->prefix_trans);
+ hashtab_map(trans->suffix_trans.table, avtab_trans_destroy_helper, NULL);
+ symtab_destroy(&trans->suffix_trans);
}
void avtab_destroy(avtab_t * h)
@@ -520,6 +524,15 @@ static int avtab_trans_read(policy_file_t *fp, uint32_t vers,
if (rc < 0)
goto bad;
+ if (vers >= POLICYDB_VERSION_PREFIX_SUFFIX) {
+ rc = avtab_read_name_trans(fp, &trans->prefix_trans);
+ if (rc < 0)
+ goto bad;
+ rc = avtab_read_name_trans(fp, &trans->suffix_trans);
+ if (rc < 0)
+ goto bad;
+ }
+
return SEPOL_OK;
bad:
@@ -1707,9 +1707,24 @@ static int name_trans_to_strs_helper(hashtab_key_t k, hashtab_datum_t d, void *a
char *name = k;
uint32_t *otype = d;
name_trans_to_strs_args_t *args = a;
- return strs_create_and_add(args->strs, "(%s %s %s %s \"%s\" %s)", 6,
+ const char *match_str = "";
+ switch (args->match) {
+ case NAME_TRANS_MATCH_EXACT:
+ match_str = "";
+ break;
+ case NAME_TRANS_MATCH_PREFIX:
+ match_str = " prefix";
+ break;
+ case NAME_TRANS_MATCH_SUFFIX:
+ match_str = " suffix";
+ break;
+ default:
+ ERR(NULL, "Unknown name match type: %" PRIu8, args->match);
+ return SEPOL_ERR;
+ }
+ return strs_create_and_add(args->strs, "(%s %s %s %s \"%s\"%s %s)", 7,
args->flavor, args->src, args->tgt,
- args->class, name,
+ args->class, name, match_str,
args->pdb->p_type_val_to_name[*otype - 1]);
}
@@ -1797,9 +1812,20 @@ static int avtab_node_to_strs(struct policydb *pdb, avtab_key_t *key, avtab_datu
.src = src,
.tgt = tgt,
.class = class,
+ .match = NAME_TRANS_MATCH_EXACT,
};
rc = hashtab_map(datum->trans->name_trans.table,
name_trans_to_strs_helper, &args);
+ if (rc < 0)
+ return rc;
+ args.match = NAME_TRANS_MATCH_PREFIX;
+ rc = hashtab_map(datum->trans->prefix_trans.table,
+ name_trans_to_strs_helper, &args);
+ if (rc < 0)
+ return rc;
+ args.match = NAME_TRANS_MATCH_SUFFIX;
+ rc = hashtab_map(datum->trans->suffix_trans.table,
+ name_trans_to_strs_helper, &args);
} else {
new = pdb->p_type_val_to_name[data - 1];
@@ -90,6 +90,7 @@ typedef struct {
const char *src;
const char *tgt;
const char *class;
+ name_trans_match_t match;
} name_trans_to_strs_args_t;
void sepol_indent(FILE *out, int indent);
@@ -1685,11 +1685,26 @@ static int name_trans_to_strs_helper(hashtab_key_t k, hashtab_datum_t d, void *a
char *name = k;
uint32_t *otype = d;
name_trans_to_strs_args_t *args = a;
- return strs_create_and_add(args->strs, "%s %s %s:%s %s \"%s\";", 6,
+ const char *match_str = "";
+ switch (args->match) {
+ case NAME_TRANS_MATCH_EXACT:
+ match_str = "";
+ break;
+ case NAME_TRANS_MATCH_PREFIX:
+ match_str = " PREFIX";
+ break;
+ case NAME_TRANS_MATCH_SUFFIX:
+ match_str = " SUFFIX";
+ break;
+ default:
+ ERR(NULL, "Unknown name match type: %" PRIu8, args->match);
+ return SEPOL_ERR;
+ }
+ return strs_create_and_add(args->strs, "%s %s %s:%s %s \"%s\"%s;", 7,
args->flavor, args->src, args->tgt,
args->class,
args->pdb->p_type_val_to_name[*otype - 1],
- name);
+ name, match_str);
}
static int avtab_node_to_strs(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum, struct strs *strs)
@@ -1773,9 +1788,20 @@ static int avtab_node_to_strs(struct policydb *pdb, avtab_key_t *key, avtab_datu
.src = src,
.tgt = tgt,
.class = class,
+ .match = NAME_TRANS_MATCH_EXACT,
};
rc = hashtab_map(datum->trans->name_trans.table,
name_trans_to_strs_helper, &args);
+ if (rc < 0)
+ return rc;
+ args.match = NAME_TRANS_MATCH_PREFIX;
+ rc = hashtab_map(datum->trans->prefix_trans.table,
+ name_trans_to_strs_helper, &args);
+ if (rc < 0)
+ return rc;
+ args.match = NAME_TRANS_MATCH_SUFFIX;
+ rc = hashtab_map(datum->trans->suffix_trans.table,
+ name_trans_to_strs_helper, &args);
} else {
new = pdb->p_type_val_to_name[data - 1];
@@ -215,6 +215,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_PREFIX_SUFFIX,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_IBENDPORT + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
{
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
@@ -855,11 +855,18 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *
/* also each transition must be non empty */
if (!d->trans->otype &&
- !hashtab_nel(d->trans->name_trans.table))
+ !hashtab_nel(d->trans->name_trans.table) &&
+ !hashtab_nel(d->trans->name_trans.table) &&
+ !hashtab_nel(d->trans->prefix_trans.table) &&
+ !hashtab_nel(d->trans->suffix_trans.table))
return -1;
- /* and each filename transition must be also valid */
+ /* and each name transition must be also valid */
if (hashtab_map(d->trans->name_trans.table,
+ validate_name_trans_helper, margs) ||
+ hashtab_map(d->trans->prefix_trans.table,
+ validate_name_trans_helper, margs) ||
+ hashtab_map(d->trans->suffix_trans.table,
validate_name_trans_helper, margs))
return -1;
} else if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) {
@@ -133,16 +133,43 @@ static int avtab_trans_write(policydb_t *p, const avtab_trans_t *cur,
uint32_t buf32[2];
if (p->policyvers >= POLICYDB_VERSION_AVTAB_FTRANS) {
- /* write otype and number of filename transitions */
+ /* write otype and number of name transitions */
buf32[0] = cpu_to_le32(cur->otype);
buf32[1] = cpu_to_le32(hashtab_nel(cur->name_trans.table));
items = put_entry(buf32, sizeof(uint32_t), 2, fp);
if (items != 2)
return -1;
- /* write filename transitions */
- return hashtab_map(cur->name_trans.table,
- avtab_trans_write_helper, fp);
+ /* write name transitions */
+ if (hashtab_map(cur->name_trans.table,
+ avtab_trans_write_helper, fp))
+ return -1;
+
+ if (p->policyvers >= POLICYDB_VERSION_PREFIX_SUFFIX) {
+ /* write number of prefix transitions */
+ buf32[0] = cpu_to_le32(hashtab_nel(
+ cur->prefix_trans.table));
+ items = put_entry(buf32, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+
+ /* write prefix transitions */
+ if (hashtab_map(cur->prefix_trans.table,
+ avtab_trans_write_helper, fp))
+ return -1;
+
+ /* write number of suffix transitions */
+ buf32[0] = cpu_to_le32(hashtab_nel(
+ cur->suffix_trans.table));
+ items = put_entry(buf32, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+
+ /* write suffix transitions */
+ if (hashtab_map(cur->suffix_trans.table,
+ avtab_trans_write_helper, fp))
+ return -1;
+ }
} else if (cur->otype) {
buf32[0] = cpu_to_le32(cur->otype);
items = put_entry(buf32, sizeof(uint32_t), 1, fp);
@@ -168,14 +195,26 @@ static int avtab_write_item(policydb_t * p,
/*
* skip entries which only contain filename transitions in versions
- * before filename transitions were moved to avtab
+ * before filename transitions were moved to avtab,
+ * skip entries which only contain prefix/suffix transitions in versions
+ * before prefix/suffix filename transitions
*/
- if (p->policyvers < POLICYDB_VERSION_AVTAB_FTRANS &&
- cur->key.specified & AVTAB_TRANSITION && !cur->datum.trans->otype) {
- /* if oldvers, reduce nel, because this node will be skipped */
- if (oldvers && nel)
- (*nel)--;
- return 0;
+ if (cur->key.specified & AVTAB_TRANSITION) {
+ if (p->policyvers < POLICYDB_VERSION_AVTAB_FTRANS &&
+ cur->key.specified & AVTAB_TRANSITION &&
+ !cur->datum.trans->otype) {
+ /*
+ * if oldvers, reduce nel, because this node will be
+ * skipped
+ */
+ if (oldvers && nel)
+ (*nel)--;
+ return 0;
+ }
+ if (p->policyvers < POLICYDB_VERSION_PREFIX_SUFFIX &&
+ !cur->datum.trans->otype &&
+ !hashtab_nel(cur->datum.trans->name_trans.table))
+ return 0;
}
if (oldvers) {
@@ -378,17 +417,27 @@ static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
* filename transitions.
*/
nel = a->nel;
- if (p->policyvers < POLICYDB_VERSION_AVTAB_FTRANS) {
- /*
- * entries containing only filename transitions are
- * skipped and written out later
- */
- for (i = 0; i < a->nslot; i++) {
- for (cur = a->htable[i]; cur; cur = cur->next) {
- if ((cur->key.specified
- & AVTAB_TRANSITION) &&
- !cur->datum.trans->otype)
- nel--;
+ for (i = 0; i < a->nslot; i++) {
+ for (cur = a->htable[i]; cur; cur = cur->next) {
+ if (!(cur->key.specified & AVTAB_TRANSITION))
+ continue;
+ if (p->policyvers < POLICYDB_VERSION_AVTAB_FTRANS &&
+ !cur->datum.trans->otype) {
+ /*
+ * entries containing only filename
+ * transitions are skipped and written
+ * out later
+ */
+ nel--;
+ } else if (p->policyvers < POLICYDB_VERSION_PREFIX_SUFFIX &&
+ !cur->datum.trans->otype &&
+ !hashtab_nel(cur->datum.trans->name_trans.table)) {
+ /*
+ * entries containing only prefix/suffix
+ * transitions are not supported in
+ * previous versions
+ */
+ nel--;
}
}
}
@@ -2520,6 +2569,22 @@ static int avtab_has_filename_transitions(avtab_t *a)
return 0;
}
+static int avtab_has_prefix_suffix_filename_transitions(avtab_t *a)
+{
+ uint32_t i;
+ struct avtab_node *cur;
+ for (i = 0; i < a->nslot; i++) {
+ for (cur = a->htable[i]; cur; cur = cur->next) {
+ if (cur->key.specified & AVTAB_TRANSITION) {
+ if (hashtab_nel(cur->datum.trans->prefix_trans.table)
+ || hashtab_nel(cur->datum.trans->suffix_trans.table))
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
/*
* Write the configuration data in a policy database
* structure to a policy database binary representation
@@ -2686,6 +2751,10 @@ 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)) {
+ WARN(fp->handle,
+ "Discarding filename prefix/suffix type transition rules");
+ }
if (p->policyvers < POLICYDB_VERSION_BOOL) {
if (p->p_bools.nprim)
WARN(fp->handle, "Discarding "