@@ -615,6 +615,15 @@ int main(int argc, char **argv)
parse_policy.mls = mlspol;
parse_policy.handle_unknown = handle_unknown;
+ /*
+ * Init and alloc te_avtab for filename transition duplicate
+ * checking
+ */
+ if (avtab_init(&parse_policy.te_avtab))
+ exit(1);
+ if (avtab_alloc(&parse_policy.te_avtab, 1 << 11))
+ exit(1);
+
policydbp = &parse_policy;
if (read_source_policy(policydbp, file, "checkpolicy") < 0)
@@ -1278,6 +1278,18 @@ void append_role_allow(role_allow_rule_t * role_allow_rules)
decl->role_allow_rules = role_allow_rules;
}
+/* this doesn't actually append, but really prepends it */
+void append_filename_trans(filename_trans_rule_t * filename_trans_rules)
+{
+ avrule_decl_t *decl = stack_top->decl;
+
+ /* filename transitions are not allowed within conditionals */
+ assert(stack_top->type == 1);
+
+ filename_trans_rules->next = decl->filename_trans_rules;
+ decl->filename_trans_rules = filename_trans_rules;
+}
+
/* this doesn't actually append, but really prepends it */
void append_range_trans(range_trans_rule_t * range_tr_rules)
{
@@ -83,6 +83,7 @@ void append_avrule(avrule_t * avrule);
void append_role_trans(role_trans_rule_t * role_tr_rules);
void append_role_allow(role_allow_rule_t * role_allow_rules);
void append_range_trans(range_trans_rule_t * range_tr_rules);
+void append_filename_trans(filename_trans_rule_t * filename_trans_rules);
/* Create a new optional block and add it to the global policy.
* During the second pass resolve the block's requirements. Return 0
@@ -1601,7 +1601,7 @@ 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)
{
char *id;
type_datum_t *datum;
@@ -1669,14 +1669,6 @@ static int define_compute_type_helper(int which, avrule_t ** rule, int has_filen
}
free(id);
- if (has_filename) {
- avrule->object_name = queue_remove(id_queue);
- if (!avrule->object_name) {
- yyerror("no object_name?");
- goto bad;
- }
- }
-
ebitmap_for_each_positive_bit(&tclasses, node, i) {
perm = malloc(sizeof(class_perm_node_t));
if (!perm) {
@@ -1700,7 +1692,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)
{
char *id;
avrule_t *avrule;
@@ -1714,14 +1706,10 @@ int define_compute_type(int which, int has_filename)
free(id);
id = queue_remove(id_queue);
free(id);
- if (has_filename) {
- id = queue_remove(id_queue);
- free(id);
- }
return 0;
}
- if (define_compute_type_helper(which, &avrule, has_filename))
+ if (define_compute_type_helper(which, &avrule))
return -1;
append_avrule(avrule);
@@ -1745,7 +1733,7 @@ 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))
return COND_ERR;
return avrule;
@@ -2387,13 +2375,6 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src)
yyerror("out of memory");
return -1;
}
- if (src->object_name) {
- dest->object_name = strdup(src->object_name);
- if (!dest->object_name) {
- yyerror("out of memory");
- return -1;
- }
- }
dest->line = src->line;
dest->source_filename = strdup(source_file);
if (!dest->source_filename) {
@@ -3362,6 +3343,194 @@ avrule_t *define_cond_filename_trans(void)
return COND_ERR;
}
+int define_filename_trans(void)
+{
+ char *id, *name = NULL;
+ type_set_t stypes, ttypes;
+ ebitmap_t e_stypes, e_ttypes;
+ ebitmap_t e_tclasses;
+ ebitmap_node_t *snode, *tnode, *cnode;
+ filename_trans_rule_t *ftr;
+ type_datum_t *typdatum;
+ avtab_key_t avt_key;
+ uint32_t otype;
+ unsigned int c, s, t;
+ int add, self, rc;
+
+ if (pass == 1) {
+ /* stype */
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ /* ttype */
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ /* tclass */
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ /* otype */
+ id = queue_remove(id_queue);
+ free(id);
+ /* name */
+ id = queue_remove(id_queue);
+ free(id);
+ return 0;
+ }
+
+ type_set_init(&stypes);
+ type_set_init(&ttypes);
+ ebitmap_init(&e_stypes);
+ ebitmap_init(&e_ttypes);
+ ebitmap_init(&e_tclasses);
+
+ add = 1;
+ while ((id = queue_remove(id_queue))) {
+ if (set_types(&stypes, id, &add, 0))
+ goto bad;
+ }
+
+ self = 0;
+ add = 1;
+ while ((id = queue_remove(id_queue))) {
+ if (strcmp(id, "self") == 0) {
+ free(id);
+ if (add == 0) {
+ yyerror("-self is not supported");
+ goto bad;
+ }
+ self = 1;
+ continue;
+ }
+ if (set_types(&ttypes, id, &add, 0))
+ goto bad;
+ }
+
+ if (read_classes(&e_tclasses))
+ goto bad;
+
+ id = (char *)queue_remove(id_queue);
+ if (!id) {
+ yyerror("no otype in transition definition?");
+ goto bad;
+ }
+ if (!is_id_in_scope(SYM_TYPES, id)) {
+ yyerror2("type %s is not within scope", id);
+ free(id);
+ goto bad;
+ }
+ typdatum = hashtab_search(policydbp->p_types.table, id);
+ if (!typdatum) {
+ yyerror2("unknown type %s used in transition definition", id);
+ free(id);
+ goto bad;
+ }
+ free(id);
+ otype = typdatum->s.value;
+
+ name = queue_remove(id_queue);
+ if (!name) {
+ yyerror("no pathname specified in filename_trans definition?");
+ goto bad;
+ }
+
+ /* We expand the class set into separate rules. We expand the types
+ * just to make sure there are not duplicates. They will get turned
+ * into separate rules later */
+ if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
+ goto bad;
+
+ if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
+ goto bad;
+
+ ebitmap_for_each_positive_bit(&e_tclasses, cnode, c) {
+ ebitmap_for_each_positive_bit(&e_stypes, snode, s) {
+ ebitmap_for_each_positive_bit(&e_ttypes, tnode, t) {
+ avt_key.specified = AVTAB_TRANSITION;
+ avt_key.source_type = s + 1;
+ avt_key.target_type = t + 1;
+ avt_key.target_class = c + 1;
+ rc = avtab_insert_filename_trans(
+ &policydbp->te_avtab, &avt_key, otype,
+ name, NULL
+ );
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
+ name,
+ policydbp->p_type_val_to_name[s],
+ policydbp->p_type_val_to_name[t],
+ policydbp->p_class_val_to_name[c]);
+ goto bad;
+ }
+ yyerror("out of memory");
+ goto bad;
+ }
+ }
+ if (self) {
+ avt_key.specified = AVTAB_TRANSITION;
+ avt_key.source_type = s + 1;
+ avt_key.target_type = t + 1;
+ avt_key.target_class = c + 1;
+ rc = avtab_insert_filename_trans(
+ &policydbp->te_avtab, &avt_key, otype,
+ name, NULL
+ );
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
+ name,
+ policydbp->p_type_val_to_name[s],
+ policydbp->p_type_val_to_name[s],
+ policydbp->p_class_val_to_name[c]);
+ goto bad;
+ }
+ yyerror("out of memory");
+ goto bad;
+ }
+ }
+ }
+
+ /* Now add the real rule since we didn't find any duplicates */
+ ftr = malloc(sizeof(*ftr));
+ if (!ftr) {
+ yyerror("out of memory");
+ goto bad;
+ }
+ filename_trans_rule_init(ftr);
+ append_filename_trans(ftr);
+
+ ftr->name = strdup(name);
+ if (type_set_cpy(&ftr->stypes, &stypes)) {
+ yyerror("out of memory");
+ goto bad;
+ }
+ if (type_set_cpy(&ftr->ttypes, &ttypes)) {
+ yyerror("out of memory");
+ goto bad;
+ }
+ ftr->tclass = c + 1;
+ ftr->otype = otype;
+ ftr->flags = self ? RULE_SELF : 0;
+ }
+
+ free(name);
+ ebitmap_destroy(&e_stypes);
+ ebitmap_destroy(&e_ttypes);
+ ebitmap_destroy(&e_tclasses);
+ type_set_destroy(&stypes);
+ type_set_destroy(&ttypes);
+
+ return 0;
+
+bad:
+ free(name);
+ ebitmap_destroy(&e_stypes);
+ ebitmap_destroy(&e_ttypes);
+ ebitmap_destroy(&e_tclasses);
+ type_set_destroy(&stypes);
+ type_set_destroy(&ttypes);
+ return -1;
+}
+
static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
{
constraint_expr_t *h = NULL, *l = NULL, *newe;
@@ -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 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);
@@ -57,6 +57,7 @@ int define_role_trans(int class_specified);
int define_role_types(void);
int define_role_attr(void);
int define_roleattribute(void);
+int define_filename_trans(void);
int define_sens(void);
int define_te_avtab(int which);
int define_te_avtab_extended_perms(int which);
@@ -451,13 +451,13 @@ 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_filename_trans()) return -1; }
| TYPE_TRANSITION names names ':' names identifier ';'
- {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;}
+ {if (define_compute_type(AVRULE_TRANSITION)) return -1;}
| TYPE_MEMBER names names ':' names identifier ';'
- {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;}
+ {if (define_compute_type(AVRULE_MEMBER)) return -1;}
| TYPE_CHANGE names names ':' names identifier ';'
- {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;}
+ {if (define_compute_type(AVRULE_CHANGE)) return -1;}
;
range_trans_def : RANGE_TRANSITION names names mls_range_def ';'
{ if (define_range_trans(0)) return -1; }
@@ -50,6 +50,7 @@
#define DISPLAY_AVBLOCK_ROLE_ALLOW 4
#define DISPLAY_AVBLOCK_REQUIRES 5
#define DISPLAY_AVBLOCK_DECLARES 6
+#define DISPLAY_AVBLOCK_FILENAME_TRANS 7
static policydb_t policydb;
@@ -86,6 +87,7 @@ static struct command {
{CMD, 'c', "Display policy capabilities"},
{CMD|NOOPT, 'l', "Link in a module"},
{CMD, 'u', "Display the unknown handling setting"},
+ {CMD, 'F', "Display filename_trans rules"},
{CMD, 'v', "display the version of policy and/or module"},
{HEADER, 0, ""},
{CMD|NOOPT, 'f', "set output file"},
@@ -343,8 +345,6 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy,
policy, fp);
} else if (avrule->specified & AVRULE_TYPE) {
display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
- if (avrule->object_name)
- fprintf(fp, " \"%s\"", avrule->object_name);
} else if (avrule->specified & AVRULE_XPERMS) {
avtab_extended_perms_t xperms;
int i;
@@ -562,6 +562,18 @@ static void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp
}
}
+static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
+{
+ fprintf(fp, "filename transition");
+ for (; tr; tr = tr->next) {
+ display_type_set(&tr->stypes, 0, p, fp);
+ display_type_set(&tr->ttypes, 0, p, fp);
+ display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
+ display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
+ fprintf(fp, " %s\n", tr->name);
+ }
+}
+
static int role_display_callback(hashtab_key_t key __attribute__((unused)),
hashtab_datum_t datum, void *data)
{
@@ -726,6 +738,10 @@ static int display_avdecl(avrule_decl_t * decl, int field,
}
break;
}
+ case DISPLAY_AVBLOCK_FILENAME_TRANS:
+ display_filename_trans(decl->filename_trans_rules, policy,
+ out_fp);
+ break;
default:{
assert(0);
}
@@ -1059,6 +1075,11 @@ int main(int argc, char **argv)
if (out_fp != stdout)
printf("\nOutput to file: %s\n", OutfileName);
break;
+ case 'F':
+ fprintf(out_fp, "filename_trans rules:\n");
+ display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
+ &policydb, out_fp);
+ break;
case 'l':
link_module(&policydb, out_fp, ops? 0: 1);
break;
@@ -4650,7 +4650,6 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
__cil_init_sepol_type_set(&avrule->stypes);
__cil_init_sepol_type_set(&avrule->ttypes);
avrule->perms = NULL;
- avrule->object_name = NULL;
avrule->line = node->line;
avrule->source_filename = NULL;
@@ -4677,7 +4676,6 @@ static void __cil_destroy_sepol_avrules(avrule_t *curr)
ebitmap_destroy(&curr->stypes.negset);
ebitmap_destroy(&curr->ttypes.types);
ebitmap_destroy(&curr->ttypes.negset);
- free(curr->object_name);
__cil_destroy_sepol_class_perms(curr->perms);
free(curr);
curr = next;
@@ -278,7 +278,6 @@ typedef struct avrule {
type_set_t stypes;
type_set_t ttypes;
class_perm_node_t *perms;
- char *object_name; /* optional object name */
av_extended_perms_t *xperms;
unsigned long line; /* line number from policy.conf where
* this rule originated */
@@ -302,6 +301,16 @@ typedef struct role_allow_rule {
struct role_allow_rule *next;
} role_allow_rule_t;
+typedef struct filename_trans_rule {
+ uint32_t flags; /* may have RULE_SELF set */
+ type_set_t stypes;
+ type_set_t ttypes;
+ uint32_t tclass;
+ char *name;
+ uint32_t otype; /* new type */
+ struct filename_trans_rule *next;
+} filename_trans_rule_t;
+
typedef struct range_trans_rule {
type_set_t stypes;
type_set_t ttypes;
@@ -442,6 +451,9 @@ typedef struct avrule_decl {
scope_index_t required; /* symbols needed to activate this block */
scope_index_t declared; /* symbols declared within this block */
+ /* type transition rules with a 'name' component */
+ filename_trans_rule_t *filename_trans_rules;
+
/* for additive statements (type attribute, roles, and users) */
symtab_t symtab[SYM_NUM];
@@ -644,6 +656,8 @@ extern void avrule_destroy(avrule_t * x);
extern void avrule_list_destroy(avrule_t * x);
extern void role_trans_rule_init(role_trans_rule_t * x);
extern void role_trans_rule_list_destroy(role_trans_rule_t * x);
+extern void filename_trans_rule_init(filename_trans_rule_t * x);
+extern void filename_trans_rule_list_destroy(filename_trans_rule_t * x);
extern void role_datum_init(role_datum_t * x);
extern void role_datum_destroy(role_datum_t * x);
@@ -99,6 +99,7 @@ void avrule_decl_destroy(avrule_decl_t * x)
cond_list_destroy(x->cond_list);
avrule_list_destroy(x->avrules);
role_trans_rule_list_destroy(x->role_tr_rules);
+ filename_trans_rule_list_destroy(x->filename_trans_rules);
role_allow_rule_list_destroy(x->role_allow_rules);
range_trans_rule_list_destroy(x->range_tr_rules);
scope_index_destroy(&x->required);
@@ -1407,6 +1407,94 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
return 0;
}
+static int expand_filename_trans_helper(expand_state_t *state,
+ filename_trans_rule_t *rule,
+ unsigned int s, unsigned int t)
+{
+ uint32_t mapped_otype, present_otype;
+ int rc;
+ avtab_key_t avt_key;
+
+ mapped_otype = state->typemap[rule->otype - 1];
+
+ avt_key.specified = AVTAB_TRANSITION;
+ avt_key.source_type = s + 1;
+ avt_key.target_type = t + 1;
+ avt_key.target_class = rule->tclass;
+
+ rc = avtab_insert_filename_trans(&state->out->te_avtab, &avt_key,
+ mapped_otype, rule->name, &present_otype);
+ if (rc == SEPOL_EEXIST) {
+ /* duplicate rule, ignore */
+ if (present_otype == mapped_otype)
+ return 0;
+
+ ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s",
+ state->out->p_type_val_to_name[s],
+ state->out->p_type_val_to_name[t],
+ state->out->p_class_val_to_name[rule->tclass - 1],
+ rule->name,
+ state->out->p_type_val_to_name[present_otype - 1],
+ state->out->p_type_val_to_name[mapped_otype - 1]);
+ return -1;
+ } else if (rc < 0) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ return 0;
+}
+
+static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
+{
+ unsigned int i, j;
+ filename_trans_rule_t *cur_rule;
+ ebitmap_t stypes, ttypes;
+ ebitmap_node_t *snode, *tnode;
+ int rc;
+
+ cur_rule = rules;
+ while (cur_rule) {
+ ebitmap_init(&stypes);
+ ebitmap_init(&ttypes);
+
+ if (expand_convert_type_set(state->out, state->typemap,
+ &cur_rule->stypes, &stypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ if (expand_convert_type_set(state->out, state->typemap,
+ &cur_rule->ttypes, &ttypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+
+ ebitmap_for_each_positive_bit(&stypes, snode, i) {
+ ebitmap_for_each_positive_bit(&ttypes, tnode, j) {
+ rc = expand_filename_trans_helper(
+ state, cur_rule, i, j
+ );
+ if (rc)
+ return rc;
+ }
+ if (cur_rule->flags & RULE_SELF) {
+ rc = expand_filename_trans_helper(
+ state, cur_rule, i, i
+ );
+ if (rc)
+ return rc;
+ }
+ }
+
+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&ttypes);
+
+ cur_rule = cur_rule->next;
+ }
+ return 0;
+}
+
static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
mls_semantic_range_t * trange,
expand_state_t * state)
@@ -1620,7 +1708,7 @@ 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)
+ avtab_t * avtab, int enabled)
{
avtab_key_t avkey;
avtab_datum_t *avdatump;
@@ -1644,34 +1732,6 @@ static int expand_terule_helper(sepol_handle_t * handle,
typemap ? typemap[cur->data - 1] : cur->data;
avkey.target_class = cur->tclass;
- /*
- * if expanded node is a filename transition, insert it, insert
- * function checks for duplicates
- */
- if (specified & AVRULE_TRANSITION && object_name) {
- int rc = avtab_insert_filename_trans(avtab, &avkey,
- remapped_data,
- object_name,
- &oldtype);
- if (rc == SEPOL_EEXIST) {
- ERR(handle, "conflicting filename transition %s %s:%s \"%s\": %s vs %s",
- p->p_type_val_to_name[avkey.source_type - 1],
- p->p_type_val_to_name[avkey.target_type - 1],
- p->p_class_val_to_name[avkey.target_class - 1],
- object_name,
- p->p_type_val_to_name[oldtype - 1],
- p->p_type_val_to_name[remapped_data - 1]);
- return EXPAND_RULE_CONFLICT;
- }
- if (rc < 0)
- return EXPAND_RULE_ERROR;
- /*
- * filename transtion inserted, continue with next node
- */
- cur = cur->next;
- continue;
- }
-
conflict = 0;
/* check to see if the expanded TE already exists --
* either in the global scope or in another
@@ -1717,9 +1777,12 @@ static int expand_terule_helper(sepol_handle_t * handle,
|| node->parse_context == cond)
return EXPAND_RULE_SUCCESS;
ERR(handle, "duplicate TE rule for %s %s:%s %s",
- p->p_type_val_to_name[avkey.source_type - 1],
- p->p_type_val_to_name[avkey.target_type - 1],
- p->p_class_val_to_name[avkey.target_class - 1],
+ p->p_type_val_to_name[avkey.source_type -
+ 1],
+ p->p_type_val_to_name[avkey.target_type -
+ 1],
+ p->p_class_val_to_name[avkey.target_class -
+ 1],
p->p_type_val_to_name[oldtype - 1]);
return EXPAND_RULE_CONFLICT;
}
@@ -1884,7 +1947,6 @@ static int expand_rule_helper(sepol_handle_t * handle,
retval = expand_terule_helper(handle, p, typemap,
source_rule->specified, cond,
other, i, i, source_rule->perms,
- source_rule->object_name,
dest_avtab, enabled);
if (retval != EXPAND_RULE_SUCCESS)
return retval;
@@ -1901,7 +1963,6 @@ static int expand_rule_helper(sepol_handle_t * handle,
retval = expand_terule_helper(handle, p, typemap,
source_rule->specified, cond,
other, i, j, source_rule->perms,
- source_rule->object_name,
dest_avtab, enabled);
if (retval != EXPAND_RULE_SUCCESS)
return retval;
@@ -2730,6 +2791,9 @@ static int copy_and_expand_avrule_block(expand_state_t * state)
goto cleanup;
}
+ if (expand_filename_trans(state, decl->filename_trans_rules))
+ goto cleanup;
+
/* expand the range transition rules */
if (expand_range_trans(state, decl->range_tr_rules))
goto cleanup;
@@ -1249,12 +1249,6 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst,
goto cleanup;
}
- if (cur->object_name) {
- new_rule->object_name = strdup(cur->object_name);
- if (!new_rule->object_name)
- goto cleanup;
- }
-
cur_perm = cur->perms;
tail_perm = NULL;
while (cur_perm) {
@@ -1418,6 +1412,51 @@ static int copy_role_allow_list(role_allow_rule_t * list,
return -1;
}
+static int copy_filename_trans_list(filename_trans_rule_t * list,
+ filename_trans_rule_t ** dst,
+ policy_module_t * module,
+ link_state_t * state)
+{
+ filename_trans_rule_t *cur, *new_rule, *tail;
+
+ cur = list;
+ tail = *dst;
+ while (tail && tail->next)
+ tail = tail->next;
+
+ while (cur) {
+ new_rule = malloc(sizeof(*new_rule));
+ if (!new_rule)
+ goto err;
+
+ filename_trans_rule_init(new_rule);
+
+ if (*dst == NULL)
+ *dst = new_rule;
+ else
+ tail->next = new_rule;
+ tail = new_rule;
+
+ new_rule->name = strdup(cur->name);
+ if (!new_rule->name)
+ goto err;
+
+ if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) ||
+ type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module))
+ goto err;
+
+ new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1];
+ new_rule->otype = module->map[SYM_TYPES][cur->otype - 1];
+ new_rule->flags = cur->flags;
+
+ cur = cur->next;
+ }
+ return 0;
+err:
+ ERR(state->handle, "Out of memory!");
+ return -1;
+}
+
static int copy_range_trans_list(range_trans_rule_t * rules,
range_trans_rule_t ** dst,
policy_module_t * mod, link_state_t * state)
@@ -1640,6 +1679,11 @@ static int copy_avrule_decl(link_state_t * state, policy_module_t * module,
return -1;
}
+ if (copy_filename_trans_list(src_decl->filename_trans_rules,
+ &dest_decl->filename_trans_rules,
+ module, state))
+ return -1;
+
if (copy_range_trans_list(src_decl->range_tr_rules,
&dest_decl->range_tr_rules, module, state))
return -1;
@@ -547,7 +547,7 @@ 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 struct class_perm_node *classperms)
{
int rc = -1;
const char *rule;
@@ -597,12 +597,6 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const
rule, src, tgt,
pdb->p_class_val_to_name[classperm->tclass - 1],
perms + 1);
- } else if (object_name) {
- cil_println(indent, "(%s %s %s %s \"%s\" %s)",
- rule, src, tgt,
- pdb->p_class_val_to_name[classperm->tclass - 1],
- object_name,
- pdb->p_type_val_to_name[classperm->data - 1]);
} else {
cil_println(indent, "(%s %s %s %s %s)",
rule, src, tgt,
@@ -1205,7 +1199,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->perms);
}
if (rc != 0) {
goto exit;
@@ -1216,7 +1210,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->perms);
}
if (rc != 0) {
goto exit;
@@ -1582,6 +1576,60 @@ exit:
return rc;
}
+static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filename_trans_rule *rules, struct list *attr_list)
+{
+ int rc = -1;
+ char **stypes = NULL;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
+ char **ttypes = NULL;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
+ struct type_set *ts;
+ struct filename_trans_rule *rule;
+
+ for (rule = rules; rule != NULL; rule = rule->next) {
+ ts = &rule->stypes;
+ rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ ts = &rule->ttypes;
+ rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ for (stype = 0; stype < num_stypes; stype++) {
+ for (ttype = 0; ttype < num_ttypes; ttype++) {
+ cil_println(indent, "(typetransition %s %s %s \"%s\" %s)",
+ stypes[stype], ttypes[ttype],
+ pdb->p_class_val_to_name[rule->tclass - 1],
+ rule->name,
+ pdb->p_type_val_to_name[rule->otype - 1]);
+ }
+ if (rule->flags & RULE_SELF) {
+ cil_println(indent, "(typetransition %s self %s \"%s\" %s)",
+ stypes[stype],
+ pdb->p_class_val_to_name[rule->tclass - 1],
+ rule->name,
+ pdb->p_type_val_to_name[rule->otype - 1]);
+ }
+ }
+
+ names_destroy(&stypes, &num_stypes);
+ names_destroy(&ttypes, &num_ttypes);
+ }
+
+ rc = 0;
+exit:
+ names_destroy(&stypes, &num_stypes);
+ names_destroy(&ttypes, &num_ttypes);
+
+ return rc;
+}
+
struct class_perm_datum {
char *name;
uint32_t val;
@@ -3635,6 +3683,11 @@ static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct
goto exit;
}
+ rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules, type_attr_list);
+ if (rc != 0) {
+ goto exit;
+ }
+
rc = cond_list_to_cil(indent, pdb, decl->cond_list, type_attr_list);
if (rc != 0) {
goto exit;
@@ -638,7 +638,6 @@ void avrule_destroy(avrule_t * x)
}
free(x->xperms);
- free(x->object_name);
}
void role_trans_rule_init(role_trans_rule_t * x)
@@ -668,6 +667,33 @@ void role_trans_rule_list_destroy(role_trans_rule_t * x)
}
}
+void filename_trans_rule_init(filename_trans_rule_t * x)
+{
+ memset(x, 0, sizeof(*x));
+ type_set_init(&x->stypes);
+ type_set_init(&x->ttypes);
+}
+
+static void filename_trans_rule_destroy(filename_trans_rule_t * x)
+{
+ if (!x)
+ return;
+ type_set_destroy(&x->stypes);
+ type_set_destroy(&x->ttypes);
+ free(x->name);
+}
+
+void filename_trans_rule_list_destroy(filename_trans_rule_t * x)
+{
+ filename_trans_rule_t *next;
+ while (x) {
+ next = x->next;
+ filename_trans_rule_destroy(x);
+ free(x);
+ x = next;
+ }
+}
+
void role_allow_rule_init(role_allow_rule_t * x)
{
memset(x, 0, sizeof(role_allow_rule_t));
@@ -3467,32 +3493,31 @@ static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp)
return 0;
}
-static int filename_trans_rule_read(policydb_t *p, avrule_t **r,
+static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r,
struct policy_file *fp)
{
uint32_t buf[3], nel, i, len;
unsigned int entries;
- avrule_t *cur;
+ filename_trans_rule_t *ftr, *lftr;
int rc;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
nel = le32_to_cpu(buf[0]);
+ lftr = NULL;
for (i = 0; i < nel; i++) {
- cur = malloc(sizeof(avrule_t));
- if (!cur)
+ ftr = malloc(sizeof(*ftr));
+ if (!ftr)
return -1;
- avrule_init(cur);
- cur->next = *r;
- *r = cur;
+ filename_trans_rule_init(ftr);
- cur->specified = AVRULE_TRANSITION;
- cur->perms = malloc(sizeof(class_perm_node_t));
- if (!cur->perms)
- return -1;
- class_perm_node_init(cur->perms);
+ if (lftr)
+ lftr->next = ftr;
+ else
+ *r = ftr;
+ lftr = ftr;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
@@ -3502,14 +3527,19 @@ static int filename_trans_rule_read(policydb_t *p, avrule_t **r,
if (zero_or_saturated(len))
return -1;
- rc = str_read(&cur->object_name, fp, len);
+ ftr->name = malloc(len + 1);
+ if (!ftr->name)
+ return -1;
+
+ rc = next_entry(ftr->name, fp, len);
if (rc)
return -1;
+ ftr->name[len] = 0;
- if (type_set_read(&cur->stypes, fp))
+ if (type_set_read(&ftr->stypes, fp))
return -1;
- if (type_set_read(&cur->ttypes, fp))
+ if (type_set_read(&ftr->ttypes, fp))
return -1;
if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS)
@@ -3520,10 +3550,10 @@ static int filename_trans_rule_read(policydb_t *p, avrule_t **r,
rc = next_entry(buf, fp, sizeof(uint32_t) * entries);
if (rc < 0)
return -1;
- cur->perms->tclass = le32_to_cpu(buf[0]);
- cur->perms->data = le32_to_cpu(buf[1]);
+ ftr->tclass = le32_to_cpu(buf[0]);
+ ftr->otype = le32_to_cpu(buf[1]);
if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS)
- cur->flags = le32_to_cpu(buf[2]);
+ ftr->flags = le32_to_cpu(buf[2]);
}
return 0;
@@ -3626,7 +3656,7 @@ static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl,
}
if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
- filename_trans_rule_read(p, &decl->avrules, fp))
+ filename_trans_rule_read(p, &decl->filename_trans_rules, fp))
return -1;
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
@@ -1313,6 +1313,31 @@ bad:
return -1;
}
+
+static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, const policydb_t *p, validate_t flavors[])
+{
+ for (; filename_trans; filename_trans = filename_trans->next) {
+ if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_type_set(&filename_trans->ttypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] ))
+ goto bad;
+ if (validate_simpletype(filename_trans->otype, p, flavors))
+ goto bad;
+
+ /* currently only the RULE_SELF flag can be set */
+ if ((filename_trans->flags & ~RULE_SELF) != 0)
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid filename trans rule list");
+ return -1;
+}
+
static int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], validate_t flavors[])
{
unsigned int i;
@@ -1347,6 +1372,8 @@ static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *
goto bad;
if (validate_scope_index(handle, &decl->declared, flavors))
goto bad;
+ if (validate_filename_trans_rules(handle, decl->filename_trans_rules, p, flavors))
+ goto bad;
if (validate_symtabs(handle, decl->symtab, flavors))
goto bad;
}
@@ -1970,10 +1970,6 @@ static int avrule_write(policydb_t *p, avrule_t * avrule,
uint32_t buf[32], len;
class_perm_node_t *cur;
- /* skip filename transitions for now */
- if (avrule->specified & AVRULE_TRANSITION && avrule->object_name)
- return POLICYDB_SUCCESS;
-
if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
(avrule->specified & AVRULE_TYPE) &&
(avrule->flags & RULE_SELF)) {
@@ -2067,9 +2063,7 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
avrule = avrules;
len = 0;
while (avrule) {
- if (!(avrule->specified & AVRULE_TRANSITION &&
- avrule->object_name))
- len++;
+ len++;
avrule = avrule->next;
}
@@ -2168,67 +2162,55 @@ static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
return POLICYDB_SUCCESS;
}
-static int filename_trans_rule_write(policydb_t *p, avrule_t *rules,
+static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t,
struct policy_file *fp)
{
int nel = 0;
size_t items, entries;
uint32_t buf[3], len;
- avrule_t *rule;
- class_perm_node_t *perm;
+ filename_trans_rule_t *ftr;
- for (rule = rules; rule; rule = rule->next) {
- if (rule->specified & AVRULE_TRANSITION && rule->object_name) {
- for (perm = rule->perms; perm; perm = perm->next) {
- nel++;
- }
- }
- }
+ for (ftr = t; ftr; ftr = ftr->next)
+ nel++;
buf[0] = cpu_to_le32(nel);
items = put_entry(buf, sizeof(uint32_t), 1, fp);
if (items != 1)
return POLICYDB_ERROR;
- for (rule = rules; rule; rule = rule->next) {
- if (!(rule->specified & AVRULE_TRANSITION && rule->object_name))
- continue;
- len = strlen(rule->object_name);
- for (perm = rule->perms; perm; perm = perm->next) {
- buf[0] = cpu_to_le32(len);
- items = put_entry(buf, sizeof(uint32_t), 1, fp);
- if (items != 1)
- return POLICYDB_ERROR;
+ for (ftr = t; ftr; ftr = ftr->next) {
+ len = strlen(ftr->name);
+ buf[0] = cpu_to_le32(len);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
- items = put_entry(rule->object_name, sizeof(char), len,
- fp);
- if (items != len)
- return POLICYDB_ERROR;
+ items = put_entry(ftr->name, sizeof(char), len, fp);
+ if (items != len)
+ return POLICYDB_ERROR;
- if (type_set_write(&rule->stypes, fp))
- return POLICYDB_ERROR;
- if (type_set_write(&rule->ttypes, fp))
- return POLICYDB_ERROR;
+ if (type_set_write(&ftr->stypes, fp))
+ return POLICYDB_ERROR;
+ if (type_set_write(&ftr->ttypes, fp))
+ return POLICYDB_ERROR;
- buf[0] = cpu_to_le32(perm->tclass);
- buf[1] = cpu_to_le32(perm->data);
- buf[2] = cpu_to_le32(rule->flags);
-
- if (p->policyvers >=
- MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
- entries = 3;
- } else if (!(rule->flags & RULE_SELF)) {
- entries = 2;
- } else {
- ERR(fp->handle,
- "Module contains a self rule not supported by the target module policy version");
- return POLICYDB_ERROR;
- }
+ buf[0] = cpu_to_le32(ftr->tclass);
+ buf[1] = cpu_to_le32(ftr->otype);
+ buf[2] = cpu_to_le32(ftr->flags);
- items = put_entry(buf, sizeof(uint32_t), entries, fp);
- if (items != entries)
- return POLICYDB_ERROR;
+ if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
+ entries = 3;
+ } else if (!(ftr->flags & RULE_SELF)) {
+ entries = 2;
+ } else {
+ ERR(fp->handle,
+ "Module contains a self rule not supported by the target module policy version");
+ return POLICYDB_ERROR;
}
+
+ items = put_entry(buf, sizeof(uint32_t), entries, fp);
+ if (items != entries)
+ return POLICYDB_ERROR;
}
return POLICYDB_SUCCESS;
}
@@ -2302,7 +2284,7 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
}
if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
- filename_trans_rule_write(p, decl->avrules, fp))
+ filename_trans_rule_write(p, decl->filename_trans_rules, fp))
return POLICYDB_ERROR;
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
This reverts commit 565d87489bc00cab2e624aae1a40872d2a2232ba. Signed-off-by: James Carter <jwcart2@gmail.com> --- checkpolicy/checkpolicy.c | 9 + checkpolicy/module_compiler.c | 12 ++ checkpolicy/module_compiler.h | 1 + checkpolicy/policy_define.c | 215 ++++++++++++++++++--- checkpolicy/policy_define.h | 3 +- checkpolicy/policy_parse.y | 8 +- checkpolicy/test/dismod.c | 25 ++- libsepol/cil/src/cil_binary.c | 2 - libsepol/include/sepol/policydb/policydb.h | 16 +- libsepol/src/avrule_block.c | 1 + libsepol/src/expand.c | 132 +++++++++---- libsepol/src/link.c | 56 +++++- libsepol/src/module_to_cil.c | 71 ++++++- libsepol/src/policydb.c | 70 +++++-- libsepol/src/policydb_validate.c | 27 +++ libsepol/src/write.c | 86 ++++----- 16 files changed, 580 insertions(+), 154 deletions(-)