[PATCH v2 3/8] checkpolicy,libsepol: move filename transition rules to avrule

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Similarly to the previous patch, filename transition rules are stored
and parsed separately from other type enforcement rules. Moving them to
avrule makes it consistent with the filename transitions in avtab and
makes future improvements easier to implement.

This patch adds an optional object name attribute to the avrule
structure and uses this new attribute to move filename transition rules
to avrule. It also updates functions for parsing type enforcement rules
to accept rules with a filename as their last argument (filename
transition rules), separate functions for parsing filename transitions
are therefore no longer needed.

Reviewed-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
Signed-off-by: Juraj Marcin <juraj@xxxxxxxxxxxxxxx>
---
 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, 154 insertions(+), 580 deletions(-)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 6e8ed833..2485142d 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -611,15 +611,6 @@ 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)
diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
index 3188af89..5fe1729a 100644
--- a/checkpolicy/module_compiler.c
+++ b/checkpolicy/module_compiler.c
@@ -1278,18 +1278,6 @@ 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)
 {
diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h
index 29b824b4..6f8bb9b9 100644
--- a/checkpolicy/module_compiler.h
+++ b/checkpolicy/module_compiler.h
@@ -83,7 +83,6 @@ 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
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index dc2ee8f3..25dbf25d 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -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)
+static int define_compute_type_helper(int which, avrule_t ** rule, int has_filename)
 {
 	char *id;
 	type_datum_t *datum;
@@ -1669,6 +1669,14 @@ static int define_compute_type_helper(int which, avrule_t ** rule)
 	}
 	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) {
@@ -1692,7 +1700,7 @@ static int define_compute_type_helper(int which, avrule_t ** rule)
 	return -1;
 }
 
-int define_compute_type(int which)
+int define_compute_type(int which, int has_filename)
 {
 	char *id;
 	avrule_t *avrule;
@@ -1706,10 +1714,14 @@ int define_compute_type(int which)
 			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))
+	if (define_compute_type_helper(which, &avrule, has_filename))
 		return -1;
 
 	append_avrule(avrule);
@@ -1733,7 +1745,7 @@ avrule_t *define_cond_compute_type(int which)
 		return (avrule_t *) 1;
 	}
 
-	if (define_compute_type_helper(which, &avrule))
+	if (define_compute_type_helper(which, &avrule, 0))
 		return COND_ERR;
 
 	return avrule;
@@ -2375,6 +2387,13 @@ 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) {
@@ -3343,194 +3362,6 @@ 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;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 50a7ba78..5d0f70e4 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 define_compute_type(int which, int has_filename);
 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,7 +57,6 @@ 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);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index da32a776..2a14fc1e 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -451,13 +451,13 @@ cond_dontaudit_def	: DONTAUDIT names names ':' names names ';'
 		        ;
 			;
 transition_def		: TYPE_TRANSITION  names names ':' names identifier filename ';'
-			{if (define_filename_trans()) return -1; }
+			{if (define_compute_type(AVRULE_TRANSITION, 1)) return -1; }
 			| TYPE_TRANSITION names names ':' names identifier ';'
-                        {if (define_compute_type(AVRULE_TRANSITION)) return -1;}
+                        {if (define_compute_type(AVRULE_TRANSITION, 0)) return -1;}
                         | TYPE_MEMBER names names ':' names identifier ';'
-                        {if (define_compute_type(AVRULE_MEMBER)) return -1;}
+                        {if (define_compute_type(AVRULE_MEMBER, 0)) return -1;}
                         | TYPE_CHANGE names names ':' names identifier ';'
-                        {if (define_compute_type(AVRULE_CHANGE)) return -1;}
+                        {if (define_compute_type(AVRULE_CHANGE, 0)) return -1;}
     			;
 range_trans_def		: RANGE_TRANSITION names names mls_range_def ';'
 			{ if (define_range_trans(0)) return -1; }
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index 515fc9a5..cde80f95 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -50,7 +50,6 @@
 #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;
 extern unsigned int ss_initialized;
@@ -90,7 +89,6 @@ 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"},
 	{HEADER, 0, ""},
 	{CMD|NOOPT, 'f',  "set output file"},
 	{CMD|NOOPT, 'm',  "display menu"},
@@ -339,6 +337,8 @@ 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;
@@ -556,18 +556,6 @@ 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)
 {
@@ -732,10 +720,6 @@ 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);
 		}
@@ -1061,11 +1045,6 @@ 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);
 			break;
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 7150d405..996bad70 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -4650,6 +4650,7 @@ 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;
@@ -4676,6 +4677,7 @@ 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;
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 8bb11d18..d30f26af 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -278,6 +278,7 @@ 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  */
@@ -301,16 +302,6 @@ 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;
@@ -451,9 +442,6 @@ 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];
 
@@ -656,8 +644,6 @@ 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);
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index dcfce8b8..fce4e772 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -99,7 +99,6 @@ 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);
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 878b0f21..a4c92f4f 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -1407,94 +1407,6 @@ 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)
@@ -1708,7 +1620,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,
-				avtab_t * avtab, int enabled)
+				char *object_name, avtab_t * avtab, int enabled)
 {
 	avtab_key_t avkey;
 	avtab_datum_t *avdatump;
@@ -1732,6 +1644,34 @@ 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
@@ -1777,12 +1717,9 @@ 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;
 			}
@@ -1947,6 +1884,7 @@ 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;
@@ -1963,6 +1901,7 @@ 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;
@@ -2791,9 +2730,6 @@ 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;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 3b7742bc..88b23594 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -1249,6 +1249,12 @@ 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) {
@@ -1412,51 +1418,6 @@ 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)
@@ -1679,11 +1640,6 @@ 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;
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 1a490089..1e002c4e 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -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 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, const struct class_perm_node *classperms)
 {
 	int rc = -1;
 	const char *rule;
@@ -597,6 +597,12 @@ 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,
@@ -1199,7 +1205,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->perms);
+					rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->object_name, avrule->perms);
 				}
 				if (rc != 0) {
 					goto exit;
@@ -1210,7 +1216,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->perms);
+					rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->object_name, avrule->perms);
 				}
 				if (rc != 0) {
 					goto exit;
@@ -1576,60 +1582,6 @@ 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;
@@ -3683,11 +3635,6 @@ 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;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index c1ce9c34..4913ee21 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -638,6 +638,7 @@ void avrule_destroy(avrule_t * x)
 	}
 
 	free(x->xperms);
+	free(x->object_name);
 }
 
 void role_trans_rule_init(role_trans_rule_t * x)
@@ -667,33 +668,6 @@ 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));
@@ -3493,31 +3467,32 @@ 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, filename_trans_rule_t **r,
+static int filename_trans_rule_read(policydb_t *p, avrule_t **r,
 				    struct policy_file *fp)
 {
 	uint32_t buf[3], nel, i, len;
 	unsigned int entries;
-	filename_trans_rule_t *ftr, *lftr;
+	avrule_t *cur;
 	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++) {
-		ftr = malloc(sizeof(*ftr));
-		if (!ftr)
+		cur = malloc(sizeof(avrule_t));
+		if (!cur)
 			return -1;
+		avrule_init(cur);
 
-		filename_trans_rule_init(ftr);
+		cur->next = *r;
+		*r = cur;
 
-		if (lftr)
-			lftr->next = ftr;
-		else
-			*r = ftr;
-		lftr = ftr;
+		cur->specified = AVRULE_TRANSITION;
+		cur->perms = malloc(sizeof(class_perm_node_t));
+		if (!cur->perms)
+			return -1;
+		class_perm_node_init(cur->perms);
 
 		rc = next_entry(buf, fp, sizeof(uint32_t));
 		if (rc < 0)
@@ -3527,19 +3502,14 @@ static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r,
 		if (zero_or_saturated(len))
 			return -1;
 
-		ftr->name = malloc(len + 1);
-		if (!ftr->name)
-			return -1;
-
-		rc = next_entry(ftr->name, fp, len);
+		rc = str_read(&cur->object_name, fp, len);
 		if (rc)
 			return -1;
-		ftr->name[len] = 0;
 
-		if (type_set_read(&ftr->stypes, fp))
+		if (type_set_read(&cur->stypes, fp))
 			return -1;
 
-		if (type_set_read(&ftr->ttypes, fp))
+		if (type_set_read(&cur->ttypes, fp))
 			return -1;
 
 		if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS)
@@ -3550,10 +3520,10 @@ static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r,
 		rc = next_entry(buf, fp, sizeof(uint32_t) * entries);
 		if (rc < 0)
 			return -1;
-		ftr->tclass = le32_to_cpu(buf[0]);
-		ftr->otype = le32_to_cpu(buf[1]);
+		cur->perms->tclass = le32_to_cpu(buf[0]);
+		cur->perms->data = le32_to_cpu(buf[1]);
 		if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS)
-			ftr->flags = le32_to_cpu(buf[2]);
+			cur->flags = le32_to_cpu(buf[2]);
 	}
 
 	return 0;
@@ -3656,7 +3626,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->filename_trans_rules, fp))
+	    filename_trans_rule_read(p, &decl->avrules, fp))
 		return -1;
 
 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index 89306185..0b8e8eee 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -1313,31 +1313,6 @@ 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;
@@ -1372,8 +1347,6 @@ 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;
 		}
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index c4d593ab..2035b350 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1970,6 +1970,10 @@ 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)) {
@@ -2063,7 +2067,9 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
 	avrule = avrules;
 	len = 0;
 	while (avrule) {
-		len++;
+		if (!(avrule->specified & AVRULE_TRANSITION &&
+		      avrule->object_name))
+			len++;
 		avrule = avrule->next;
 	}
 
@@ -2162,55 +2168,67 @@ 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, filename_trans_rule_t *t,
+static int filename_trans_rule_write(policydb_t *p, avrule_t *rules,
 				     struct policy_file *fp)
 {
 	int nel = 0;
 	size_t items, entries;
 	uint32_t buf[3], len;
-	filename_trans_rule_t *ftr;
+	avrule_t *rule;
+	class_perm_node_t *perm;
 
-	for (ftr = t; ftr; ftr = ftr->next)
-		nel++;
+	for (rule = rules; rule; rule = rule->next) {
+		if (rule->specified & AVRULE_TRANSITION && rule->object_name) {
+			for (perm = rule->perms; perm; perm = perm->next) {
+				nel++;
+			}
+		}
+	}
 
 	buf[0] = cpu_to_le32(nel);
 	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;
+	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;
 
-		items = put_entry(ftr->name, sizeof(char), len, fp);
-		if (items != len)
-			return POLICYDB_ERROR;
+			items = put_entry(rule->object_name, sizeof(char), len,
+					  fp);
+			if (items != len)
+				return POLICYDB_ERROR;
 
-		if (type_set_write(&ftr->stypes, fp))
-			return POLICYDB_ERROR;
-		if (type_set_write(&ftr->ttypes, fp))
-			return POLICYDB_ERROR;
+			if (type_set_write(&rule->stypes, fp))
+				return POLICYDB_ERROR;
+			if (type_set_write(&rule->ttypes, fp))
+				return POLICYDB_ERROR;
 
-		buf[0] = cpu_to_le32(ftr->tclass);
-		buf[1] = cpu_to_le32(ftr->otype);
-		buf[2] = cpu_to_le32(ftr->flags);
+			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;
+			}
 
-		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;
 		}
-
-		items = put_entry(buf, sizeof(uint32_t), entries, fp);
-		if (items != entries)
-			return POLICYDB_ERROR;
 	}
 	return POLICYDB_SUCCESS;
 }
@@ -2284,7 +2302,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->filename_trans_rules, fp))
+	    filename_trans_rule_write(p, decl->avrules, fp))
 		return POLICYDB_ERROR;
 
 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
-- 
2.40.0




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux