Dan Walsh 66140a
diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
Dan Walsh 66140a
index d6ebd78..0946ff6 100644
Dan Walsh 66140a
--- a/checkpolicy/module_compiler.c
Dan Walsh 66140a
+++ b/checkpolicy/module_compiler.c
Dan Walsh 66140a
@@ -1313,6 +1313,18 @@ void append_role_allow(role_allow_rule_t * role_allow_rules)
Dan Walsh 9d5bc6
 }
Dan Walsh 9d5bc6
 
Dan Walsh 9d5bc6
 /* this doesn't actually append, but really prepends it */
Dan Walsh 9d5bc6
+void append_filename_trans(filename_trans_rule_t * filename_trans_rules)
Dan Walsh 9d5bc6
+{
Dan Walsh 9d5bc6
+	avrule_decl_t *decl = stack_top->decl;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	/* filename transitions are not allowed within conditionals */
Dan Walsh 9d5bc6
+	assert(stack_top->type == 1);
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	filename_trans_rules->next = decl->filename_trans_rules;
Dan Walsh 9d5bc6
+	decl->filename_trans_rules = filename_trans_rules;
Dan Walsh 9d5bc6
+}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+/* this doesn't actually append, but really prepends it */
Dan Walsh 9d5bc6
 void append_range_trans(range_trans_rule_t * range_tr_rules)
Dan Walsh 9d5bc6
 {
Dan Walsh 9d5bc6
 	avrule_decl_t *decl = stack_top->decl;
Dan Walsh 66140a
diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h
Dan Walsh 66140a
index fa91400..ae33753 100644
Dan Walsh 66140a
--- a/checkpolicy/module_compiler.h
Dan Walsh 66140a
+++ b/checkpolicy/module_compiler.h
Dan Walsh 9d5bc6
@@ -80,6 +80,7 @@ void append_avrule(avrule_t * avrule);
Dan Walsh 9d5bc6
 void append_role_trans(role_trans_rule_t * role_tr_rules);
Dan Walsh 9d5bc6
 void append_role_allow(role_allow_rule_t * role_allow_rules);
Dan Walsh 9d5bc6
 void append_range_trans(range_trans_rule_t * range_tr_rules);
Dan Walsh 9d5bc6
+void append_filename_trans(filename_trans_rule_t * filename_trans_rules);
Dan Walsh 9d5bc6
 
Dan Walsh 9d5bc6
 /* Create a new optional block and add it to the global policy.
Dan Walsh 9d5bc6
  * During the second pass resolve the block's requirements.  Return 0
Dan Walsh 66140a
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
Dan Walsh 66140a
index 5e99b30..f75a682 100644
Dan Walsh 66140a
--- a/checkpolicy/policy_define.c
Dan Walsh 66140a
+++ b/checkpolicy/policy_define.c
Dan Walsh 66140a
@@ -2241,6 +2241,190 @@ int define_role_allow(void)
Dan Walsh 9d5bc6
 	return 0;
Dan Walsh 9d5bc6
 }
Dan Walsh 9d5bc6
 
Dan Walsh 9d5bc6
+avrule_t *define_cond_filename_trans(void)
Dan Walsh 9d5bc6
+{
Dan Walsh 9d5bc6
+	yyerror("type transitions with a filename not allowed inside "
Dan Walsh 9d5bc6
+		"conditionals\n");
Dan Walsh 9d5bc6
+	return COND_ERR;
Dan Walsh 9d5bc6
+}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+int define_filename_trans(void)
Dan Walsh 9d5bc6
+{
Dan Walsh 9d5bc6
+	char *id, *name = NULL;
Dan Walsh 9d5bc6
+	type_set_t stypes, ttypes;
Dan Walsh 9d5bc6
+	ebitmap_t e_stypes, e_ttypes;
Dan Walsh 9d5bc6
+	ebitmap_t e_tclasses;
Dan Walsh 9d5bc6
+	ebitmap_node_t *snode, *tnode, *cnode;
Dan Walsh 9d5bc6
+	filename_trans_t *ft;
Dan Walsh 9d5bc6
+	filename_trans_rule_t *ftr;
Dan Walsh 9d5bc6
+	class_datum_t *cladatum;
Dan Walsh 9d5bc6
+	type_datum_t *typdatum;
Dan Walsh 9d5bc6
+	uint32_t otype;
Dan Walsh 9d5bc6
+	unsigned int c, s, t;
Dan Walsh 9d5bc6
+	int add;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	if (pass == 1) {
Dan Walsh 9d5bc6
+		/* stype */
Dan Walsh 9d5bc6
+		while ((id = queue_remove(id_queue)))
Dan Walsh 9d5bc6
+			free(id);
Dan Walsh 9d5bc6
+		/* ttype */
Dan Walsh 9d5bc6
+		while ((id = queue_remove(id_queue)))
Dan Walsh 9d5bc6
+			free(id);
Dan Walsh 9d5bc6
+		/* tclass */
Dan Walsh 9d5bc6
+		while ((id = queue_remove(id_queue)))
Dan Walsh 9d5bc6
+			free(id);
Dan Walsh 9d5bc6
+		/* otype */
Dan Walsh 9d5bc6
+		id = queue_remove(id_queue);
Dan Walsh 9d5bc6
+		free(id);
Dan Walsh 9d5bc6
+		/* name */
Dan Walsh 9d5bc6
+		id = queue_remove(id_queue);
Dan Walsh 9d5bc6
+		free(id);
Dan Walsh 9d5bc6
+		return 0;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	add = 1;
Dan Walsh 9d5bc6
+	type_set_init(&stypes);
Dan Walsh 9d5bc6
+	while ((id = queue_remove(id_queue))) {
Dan Walsh 9d5bc6
+		if (set_types(&stypes, id, &add, 0))
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	add =1;
Dan Walsh 9d5bc6
+	type_set_init(&ttypes);
Dan Walsh 9d5bc6
+	while ((id = queue_remove(id_queue))) {
Dan Walsh 9d5bc6
+		if (set_types(&ttypes, id, &add, 0))
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	ebitmap_init(&e_tclasses);
Dan Walsh 9d5bc6
+	while ((id = queue_remove(id_queue))) {
Dan Walsh 9d5bc6
+		if (!is_id_in_scope(SYM_CLASSES, id)) {
Dan Walsh 9d5bc6
+			yyerror2("class %s is not within scope", id);
Dan Walsh 9d5bc6
+			free(id);
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+		}
Dan Walsh 9d5bc6
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
Dan Walsh 9d5bc6
+		if (!cladatum) {
Dan Walsh 9d5bc6
+			yyerror2("unknown class %s", id);
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+		}
Dan Walsh 9d5bc6
+		if (ebitmap_set_bit(&e_tclasses, cladatum->s.value - 1, TRUE)) {
Dan Walsh 9d5bc6
+			yyerror("Out of memory");
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+		}
Dan Walsh 9d5bc6
+		free(id);
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	id = (char *)queue_remove(id_queue);
Dan Walsh 9d5bc6
+	if (!id) {
Dan Walsh 9d5bc6
+		yyerror("no otype in transition definition?");
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+	if (!is_id_in_scope(SYM_TYPES, id)) {
Dan Walsh 9d5bc6
+		yyerror2("type %s is not within scope", id);
Dan Walsh 9d5bc6
+		free(id);
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+	typdatum = hashtab_search(policydbp->p_types.table, id);
Dan Walsh 9d5bc6
+	if (!typdatum) {
Dan Walsh 9d5bc6
+		yyerror2("unknown type %s used in transition definition", id);
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+	free(id);
Dan Walsh 9d5bc6
+	otype = typdatum->s.value;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	name = queue_remove(id_queue);
Dan Walsh 9d5bc6
+	if (!name) {
Dan Walsh 9d5bc6
+		yyerror("no pathname specified in filename_trans definition?");
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	/* We expand the class set into seperate rules.  We expand the types
Dan Walsh 9d5bc6
+	 * just to make sure there are not duplicates.  They will get turned
Dan Walsh 9d5bc6
+	 * into seperate rules later */
Dan Walsh 9d5bc6
+	ebitmap_init(&e_stypes);
Dan Walsh 9d5bc6
+	if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	ebitmap_init(&e_ttypes);
Dan Walsh 9d5bc6
+	if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
Dan Walsh 9d5bc6
+		goto bad;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	ebitmap_for_each_bit(&e_tclasses, cnode, c) {
Dan Walsh 9d5bc6
+		if (!ebitmap_node_get_bit(cnode, c))
Dan Walsh 9d5bc6
+			continue;
Dan Walsh 9d5bc6
+		ebitmap_for_each_bit(&e_stypes, snode, s) {
Dan Walsh 9d5bc6
+			if (!ebitmap_node_get_bit(snode, s))
Dan Walsh 9d5bc6
+				continue;
Dan Walsh 9d5bc6
+			ebitmap_for_each_bit(&e_ttypes, tnode, t) {
Dan Walsh 9d5bc6
+				if (!ebitmap_node_get_bit(tnode, t))
Dan Walsh 9d5bc6
+					continue;
Dan Walsh 9d5bc6
+	
Dan Walsh 9d5bc6
+				for (ft = policydbp->filename_trans; ft; ft = ft->next) {
Dan Walsh 9d5bc6
+					if (ft->stype == (s + 1) &&
Dan Walsh 9d5bc6
+					    ft->ttype == (t + 1) &&
Dan Walsh 9d5bc6
+					    ft->tclass == (c + 1) &&
Dan Walsh 9d5bc6
+					    !strcmp(ft->name, name)) {
Dan Walsh 9d5bc6
+						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
Dan Walsh 9d5bc6
+							 name, 
Dan Walsh 9d5bc6
+							 policydbp->p_type_val_to_name[s],
Dan Walsh 9d5bc6
+							 policydbp->p_type_val_to_name[t],
Dan Walsh 9d5bc6
+							 policydbp->p_class_val_to_name[c]);
Dan Walsh 9d5bc6
+						goto bad;
Dan Walsh 9d5bc6
+					}
Dan Walsh 9d5bc6
+				}
Dan Walsh 9d5bc6
+	
Dan Walsh 9d5bc6
+				ft = malloc(sizeof(*ft));
Dan Walsh 9d5bc6
+				if (!ft) {
Dan Walsh 9d5bc6
+					yyerror("out of memory");
Dan Walsh 9d5bc6
+					goto bad;
Dan Walsh 9d5bc6
+				}
Dan Walsh 9d5bc6
+				memset(ft, 0, sizeof(*ft));
Dan Walsh 9d5bc6
+	
Dan Walsh 9d5bc6
+				ft->next = policydbp->filename_trans;
Dan Walsh 9d5bc6
+				policydbp->filename_trans = ft;
Dan Walsh 9d5bc6
+	
Dan Walsh 9d5bc6
+				ft->name = strdup(name);
Dan Walsh 9d5bc6
+				if (!ft->name) {
Dan Walsh 9d5bc6
+					yyerror("out of memory");
Dan Walsh 9d5bc6
+					goto bad;
Dan Walsh 9d5bc6
+				}
Dan Walsh 9d5bc6
+				ft->stype = s + 1;
Dan Walsh 9d5bc6
+				ft->ttype = t + 1;
Dan Walsh 9d5bc6
+				ft->tclass = c + 1;
Dan Walsh 9d5bc6
+				ft->otype = otype;
Dan Walsh 9d5bc6
+			}
Dan Walsh 9d5bc6
+		}
Dan Walsh 9d5bc6
+	
Dan Walsh 9d5bc6
+		/* Now add the real rule since we didn't find any duplicates */
Dan Walsh 9d5bc6
+		ftr = malloc(sizeof(*ftr));
Dan Walsh 9d5bc6
+		if (!ftr) {
Dan Walsh 9d5bc6
+			yyerror("out of memory");
Dan Walsh 9d5bc6
+			goto bad;
Dan Walsh 9d5bc6
+		}
Dan Walsh 9d5bc6
+		filename_trans_rule_init(ftr);
Dan Walsh 9d5bc6
+		append_filename_trans(ftr);
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+		ftr->name = strdup(name);
Dan Walsh 9d5bc6
+		ftr->stypes = stypes;
Dan Walsh 9d5bc6
+		ftr->ttypes = ttypes;
Dan Walsh 9d5bc6
+		ftr->tclass = c + 1;
Dan Walsh 9d5bc6
+		ftr->otype = otype;
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	free(name);
Dan Walsh 9d5bc6
+	ebitmap_destroy(&e_stypes);
Dan Walsh 9d5bc6
+	ebitmap_destroy(&e_ttypes);
Dan Walsh 9d5bc6
+	ebitmap_destroy(&e_tclasses);
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	return 0;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+bad:
Dan Walsh 9d5bc6
+	free(name);
Dan Walsh 9d5bc6
+	return -1;
Dan Walsh 9d5bc6
+}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
 static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
Dan Walsh 9d5bc6
 {
Dan Walsh 9d5bc6
 	constraint_expr_t *h = NULL, *l = NULL, *e, *newe;
Dan Walsh 66140a
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
Dan Walsh 66140a
index 2f7a78f..890a6af 100644
Dan Walsh 66140a
--- a/checkpolicy/policy_define.h
Dan Walsh 66140a
+++ b/checkpolicy/policy_define.h
Dan Walsh 9d5bc6
@@ -16,6 +16,7 @@
Dan Walsh 9d5bc6
 avrule_t *define_cond_compute_type(int which);
Dan Walsh 9d5bc6
 avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt);
Dan Walsh 9d5bc6
 avrule_t *define_cond_te_avtab(int which);
Dan Walsh 9d5bc6
+avrule_t *define_cond_filename_trans(void);
Dan Walsh 9d5bc6
 cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2);
Dan Walsh 9d5bc6
 int define_attrib(void);
Dan Walsh 9d5bc6
 int define_av_perms(int inherits);
Dan Walsh 66140a
@@ -47,6 +48,7 @@ int define_range_trans(int class_specified);
Dan Walsh 9d5bc6
 int define_role_allow(void);
Dan Walsh 66140a
 int define_role_trans(int class_specified);
Dan Walsh 9d5bc6
 int define_role_types(void);
Dan Walsh 9d5bc6
+int define_filename_trans(void);
Dan Walsh 9d5bc6
 int define_sens(void);
Dan Walsh 9d5bc6
 int define_te_avtab(int which);
Dan Walsh 9d5bc6
 int define_typealias(void);
Dan Walsh 66140a
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
Dan Walsh 66140a
index 8c29e2b..8274d36 100644
Dan Walsh 66140a
--- a/checkpolicy/policy_parse.y
Dan Walsh 66140a
+++ b/checkpolicy/policy_parse.y
Dan Walsh 66140a
@@ -81,6 +81,7 @@ typedef int (* require_func_t)();
Dan Walsh 66140a
 %type <require_func> require_decl_def
Dan Walsh 66140a
 
Dan Walsh 66140a
 %token PATH
Dan Walsh 66140a
+%token FILENAME
Dan Walsh 66140a
 %token CLONE
Dan Walsh 66140a
 %token COMMON
Dan Walsh 66140a
 %token CLASS
Dan Walsh 66140a
@@ -341,7 +342,10 @@ cond_rule_def           : cond_transition_def
Dan Walsh 9d5bc6
 			| require_block
Dan Walsh 9d5bc6
 			{ $$ = NULL; }
Dan Walsh 9d5bc6
                         ;
Dan Walsh 9d5bc6
-cond_transition_def	: TYPE_TRANSITION names names ':' names identifier ';'
Dan Walsh 66140a
+cond_transition_def	: TYPE_TRANSITION names names ':' names identifier filename ';'
Dan Walsh 9d5bc6
+                        { $$ = define_cond_filename_trans() ;
Dan Walsh 9d5bc6
+                          if ($$ == COND_ERR) return -1;}
Dan Walsh 9d5bc6
+			| TYPE_TRANSITION names names ':' names identifier ';'
Dan Walsh 9d5bc6
                         { $$ = define_cond_compute_type(AVRULE_TRANSITION) ;
Dan Walsh 9d5bc6
                           if ($$ == COND_ERR) return -1;}
Dan Walsh 9d5bc6
                         | TYPE_MEMBER names names ':' names identifier ';'
Dan Walsh 66140a
@@ -376,7 +380,9 @@ cond_dontaudit_def	: DONTAUDIT names names ':' names names ';'
Dan Walsh 9d5bc6
 			{ $$ = define_cond_te_avtab(AVRULE_DONTAUDIT);
Dan Walsh 9d5bc6
                           if ($$ == COND_ERR) return -1; }
Dan Walsh 9d5bc6
 		        ;
Dan Walsh 9d5bc6
-transition_def		: TYPE_TRANSITION names names ':' names identifier ';'
Dan Walsh 66140a
+transition_def		: TYPE_TRANSITION names names ':' names identifier filename';'
Dan Walsh 66140a
+                        {if (define_filename_trans()) return -1; }
Dan Walsh 66140a
+                        |TYPE_TRANSITION names names ':' names identifier ';'
Dan Walsh 9d5bc6
                         {if (define_compute_type(AVRULE_TRANSITION)) return -1;}
Dan Walsh 9d5bc6
                         | TYPE_MEMBER names names ':' names identifier ';'
Dan Walsh 9d5bc6
                         {if (define_compute_type(AVRULE_MEMBER)) return -1;}
Dan Walsh 66140a
@@ -639,7 +645,7 @@ opt_fs_uses             : fs_uses
Dan Walsh 66140a
 fs_uses                 : fs_use_def
Dan Walsh 66140a
                         | fs_uses fs_use_def
Dan Walsh 66140a
                         ;
Dan Walsh 66140a
-fs_use_def              : FSUSEXATTR identifier security_context_def ';'
Dan Walsh 66140a
+fs_use_def              : FSUSEXATTR filename security_context_def ';'
Dan Walsh 66140a
                         {if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;}
Dan Walsh 66140a
                         | FSUSETASK identifier security_context_def ';'
Dan Walsh 66140a
                         {if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;}
Dan Walsh 66140a
@@ -652,11 +658,11 @@ opt_genfs_contexts      : genfs_contexts
Dan Walsh 66140a
 genfs_contexts          : genfs_context_def
Dan Walsh 66140a
                         | genfs_contexts genfs_context_def
Dan Walsh 66140a
                         ;
Dan Walsh 66140a
-genfs_context_def	: GENFSCON identifier path '-' identifier security_context_def
Dan Walsh 66140a
+genfs_context_def	: GENFSCON filename path '-' identifier security_context_def
Dan Walsh 66140a
 			{if (define_genfs_context(1)) return -1;}
Dan Walsh 66140a
-			| GENFSCON identifier path '-' '-' {insert_id("-", 0);} security_context_def
Dan Walsh 66140a
+			| GENFSCON filename path '-' '-' {insert_id("-", 0);} security_context_def
Dan Walsh 66140a
 			{if (define_genfs_context(1)) return -1;}
Dan Walsh 66140a
-                        | GENFSCON identifier path security_context_def
Dan Walsh 66140a
+                        | GENFSCON filename path security_context_def
Dan Walsh 66140a
 			{if (define_genfs_context(0)) return -1;}
Dan Walsh 66140a
 			;
Dan Walsh 66140a
 ipv4_addr_def		: IPV4_ADDR
Dan Walsh 66140a
@@ -733,6 +739,17 @@ identifier		: IDENTIFIER
Dan Walsh 66140a
 path     		: PATH
Dan Walsh 66140a
 			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
 			;
Dan Walsh 66140a
+filename     		: FILENAME
Dan Walsh 66140a
+			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+                        | NUMBER
Dan Walsh 66140a
+			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+                        | IPV4_ADDR
Dan Walsh 66140a
+			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+                        | VERSION_IDENTIFIER
Dan Walsh 66140a
+			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+                        | IDENTIFIER
Dan Walsh 66140a
+			{ if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+                        ;
Dan Walsh 66140a
 number			: NUMBER 
Dan Walsh 66140a
 			{ $$ = strtoul(yytext,NULL,0); }
Dan Walsh 66140a
 			;
Dan Walsh 66140a
@@ -757,6 +774,8 @@ module_def              : MODULE identifier version_identifier ';'
Dan Walsh 66140a
                         ;
Dan Walsh 66140a
 version_identifier      : VERSION_IDENTIFIER
Dan Walsh 66140a
                         { if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
+			| number
Dan Walsh 66140a
+                        { if (insert_id(yytext,0)) return -1; }
Dan Walsh 66140a
                         | ipv4_addr_def /* version can look like ipv4 address */
Dan Walsh 66140a
                         ;
Dan Walsh 66140a
 avrules_block           : avrule_decls avrule_user_defs
Dan Walsh 66140a
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
Dan Walsh 66140a
index 48128a8..427c189 100644
Dan Walsh 66140a
--- a/checkpolicy/policy_scan.l
Dan Walsh 66140a
+++ b/checkpolicy/policy_scan.l
Dan Walsh 66140a
@@ -218,9 +218,12 @@ PERMISSIVE			{ return(PERMISSIVE); }
Dan Walsh 66140a
 "/"({alnum}|[_\.\-/])*	        { return(PATH); }
Dan Walsh 66140a
 {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))*	{ return(IDENTIFIER); }
Dan Walsh 66140a
 {digit}+|0x{hexval}+            { return(NUMBER); }
Dan Walsh 66140a
+{alnum}*                        { return(FILENAME); }
Dan Walsh 66140a
 {digit}{1,3}(\.{digit}{1,3}){3}    { return(IPV4_ADDR); }
Dan Walsh 66140a
 {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])*  { return(IPV6_ADDR); }
Dan Walsh 66140a
 {digit}+(\.({alnum}|[_.])*)?    { return(VERSION_IDENTIFIER); }
Dan Walsh 66140a
+{alnum}+([_\.]|{alnum})+      { return(FILENAME); }
Dan Walsh 66140a
+([_\.]){alnum}+                 { return(FILENAME); }
Dan Walsh 66140a
 #line[ ]1[ ]\"[^\n]*\"		{ set_source_file(yytext+9); }
Dan Walsh 66140a
 #line[ ]{digit}+	        { source_lineno = atoi(yytext+6)-1; }
Dan Walsh 66140a
 #[^\n]*                         { /* delete comments */ }
Dan Walsh 66140a
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
Dan Walsh 66140a
index 33a29e4..66f976f 100644
Dan Walsh 66140a
--- a/checkpolicy/test/dismod.c
Dan Walsh 66140a
+++ b/checkpolicy/test/dismod.c
Dan Walsh 66140a
@@ -45,6 +45,15 @@
Dan Walsh 66140a
 #define le32_to_cpu(x) bswap_32(x)
Dan Walsh 66140a
 #endif
Dan Walsh 9d5bc6
 
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_COND_AVTAB	0
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_UNCOND_AVTAB	1
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_ROLE_TYPE_NODE	2 /* unused? */
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_ROLE_TRANS	3
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_ROLE_ALLOW	4
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_REQUIRES	5
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_DECLARES	6
Dan Walsh 66140a
+#define DISPLAY_AVBLOCK_FILENAME_TRANS	7
Dan Walsh 66140a
+
Dan Walsh 9d5bc6
 static policydb_t policydb;
Dan Walsh 9d5bc6
 extern unsigned int ss_initialized;
Dan Walsh 66140a
 
Dan Walsh 66140a
@@ -497,6 +506,18 @@ void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
Dan Walsh 9d5bc6
 	}
Dan Walsh 9d5bc6
 }
Dan Walsh 9d5bc6
 
Dan Walsh 9d5bc6
+void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
Dan Walsh 9d5bc6
+{
Dan Walsh 9d5bc6
+	for (; tr; tr = tr->next) {
Dan Walsh 9d5bc6
+		fprintf(fp, "filename transition %s", tr->name);
Dan Walsh 9d5bc6
+		display_type_set(&tr->stypes, 0, p, fp);
Dan Walsh 9d5bc6
+		display_type_set(&tr->ttypes, 0, p, fp);
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
Dan Walsh 9d5bc6
+		fprintf(fp, "\n");
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
 int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
Dan Walsh 9d5bc6
 {
Dan Walsh 9d5bc6
 	role_datum_t *role;
Dan Walsh 66140a
@@ -596,7 +617,7 @@ int display_avdecl(avrule_decl_t * decl, int field, uint32_t what,
Dan Walsh 66140a
 	fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
Dan Walsh 66140a
 		(decl->enabled ? " [enabled]" : ""));
Dan Walsh 66140a
 	switch (field) {
Dan Walsh 66140a
-	case 0:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_COND_AVTAB:{
Dan Walsh 66140a
 			cond_list_t *cond = decl->cond_list;
Dan Walsh 66140a
 			avrule_t *avrule;
Dan Walsh 66140a
 			while (cond) {
Dan Walsh 66140a
@@ -624,7 +645,7 @@ int display_avdecl(avrule_decl_t * decl, int field, uint32_t what,
Dan Walsh 66140a
 			}
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 1:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
Dan Walsh 66140a
 			avrule_t *avrule = decl->avrules;
Dan Walsh 66140a
 			if (avrule == NULL) {
Dan Walsh 66140a
 				fprintf(out_fp, "  <empty>\n");
Dan Walsh 66140a
@@ -638,32 +659,37 @@ int display_avdecl(avrule_decl_t * decl, int field, uint32_t what,
Dan Walsh 66140a
 			}
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 2:{		/* role_type_node */
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{	/* role_type_node */
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 3:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_ROLE_TRANS:{
Dan Walsh 66140a
 			display_role_trans(decl->role_tr_rules, policy, out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 4:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_ROLE_ALLOW:{
Dan Walsh 66140a
 			display_role_allow(decl->role_allow_rules, policy,
Dan Walsh 66140a
 					   out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 5:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_REQUIRES:{
Dan Walsh 66140a
 			if (display_scope_index
Dan Walsh 66140a
 			    (&decl->required, policy, out_fp)) {
Dan Walsh 66140a
 				return -1;
Dan Walsh 66140a
 			}
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		}
Dan Walsh 66140a
-	case 6:{
Dan Walsh 66140a
+	case DISPLAY_AVBLOCK_DECLARES:{
Dan Walsh 66140a
 			if (display_scope_index
Dan Walsh 66140a
 			    (&decl->declared, policy, out_fp)) {
Dan Walsh 66140a
 				return -1;
Dan Walsh 9d5bc6
 			}
Dan Walsh 9d5bc6
 			break;
Dan Walsh 9d5bc6
 		}
Dan Walsh 9d5bc6
+	case DISPLAY_AVBLOCK_FILENAME_TRANS:
Dan Walsh 9d5bc6
+		display_filename_trans(decl->filename_trans_rules, policy,
Dan Walsh 9d5bc6
+				       out_fp);
Dan Walsh 9d5bc6
+			return -1;
Dan Walsh 9d5bc6
+		break;
Dan Walsh 9d5bc6
 	default:{
Dan Walsh 9d5bc6
 			assert(0);
Dan Walsh 9d5bc6
 		}
Dan Walsh 66140a
@@ -829,6 +855,7 @@ int menu()
Dan Walsh 9d5bc6
 	printf("c)  Display policy capabilities\n");
Dan Walsh 9d5bc6
 	printf("l)  Link in a module\n");
Dan Walsh 9d5bc6
 	printf("u)  Display the unknown handling setting\n");
Dan Walsh 9d5bc6
+	printf("F)  Display filename_trans rules\n");
Dan Walsh 9d5bc6
 	printf("\n");
Dan Walsh 9d5bc6
 	printf("f)  set output file\n");
Dan Walsh 9d5bc6
 	printf("m)  display menu\n");
Dan Walsh 66140a
@@ -886,15 +913,16 @@ int main(int argc, char **argv)
Dan Walsh 66140a
 		fgets(ans, sizeof(ans), stdin);
Dan Walsh 66140a
 		switch (ans[0]) {
Dan Walsh 66140a
 
Dan Walsh 66140a
-		case '1':{
Dan Walsh 66140a
-				fprintf(out_fp, "unconditional avtab:\n");
Dan Walsh 66140a
-				display_avblock(1, RENDER_UNCONDITIONAL,
Dan Walsh 66140a
-						&policydb, out_fp);
Dan Walsh 66140a
-				break;
Dan Walsh 66140a
-			}
Dan Walsh 66140a
+		case '1':
Dan Walsh 66140a
+			fprintf(out_fp, "unconditional avtab:\n");
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
Dan Walsh 66140a
+					RENDER_UNCONDITIONAL, &policydb,
Dan Walsh 66140a
+					out_fp);
Dan Walsh 66140a
+			break;
Dan Walsh 66140a
 		case '2':
Dan Walsh 66140a
 			fprintf(out_fp, "conditional avtab:\n");
Dan Walsh 66140a
-			display_avblock(0, RENDER_UNCONDITIONAL, &policydb,
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
Dan Walsh 66140a
+					RENDER_UNCONDITIONAL, &policydb,
Dan Walsh 66140a
 					out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case '3':
Dan Walsh 66140a
@@ -917,11 +945,13 @@ int main(int argc, char **argv)
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case '7':
Dan Walsh 66140a
 			fprintf(out_fp, "role transitions:\n");
Dan Walsh 66140a
-			display_avblock(3, 0, &policydb, out_fp);
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, 0,
Dan Walsh 66140a
+					&policydb, out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case '8':
Dan Walsh 66140a
 			fprintf(out_fp, "role allows:\n");
Dan Walsh 66140a
-			display_avblock(4, 0, &policydb, out_fp);
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, 0,
Dan Walsh 66140a
+					&policydb, out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case '9':
Dan Walsh 66140a
 			display_policycon(&policydb, out_fp);
Dan Walsh 66140a
@@ -931,11 +961,13 @@ int main(int argc, char **argv)
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case 'a':
Dan Walsh 66140a
 			fprintf(out_fp, "avrule block requirements:\n");
Dan Walsh 66140a
-			display_avblock(5, 0, &policydb, out_fp);
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_REQUIRES, 0,
Dan Walsh 66140a
+					&policydb, out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case 'b':
Dan Walsh 66140a
 			fprintf(out_fp, "avrule block declarations:\n");
Dan Walsh 66140a
-			display_avblock(6, 0, &policydb, out_fp);
Dan Walsh 66140a
+			display_avblock(DISPLAY_AVBLOCK_DECLARES, 0,
Dan Walsh 66140a
+					&policydb, out_fp);
Dan Walsh 66140a
 			break;
Dan Walsh 66140a
 		case 'c':
Dan Walsh 66140a
 			display_policycaps(&policydb, out_fp);
Dan Walsh 66140a
@@ -959,6 +991,11 @@ int main(int argc, char **argv)
Dan Walsh 9d5bc6
 			if (out_fp != stdout)
Dan Walsh 9d5bc6
 				printf("\nOutput to file: %s\n", OutfileName);
Dan Walsh 9d5bc6
 			break;
Dan Walsh 9d5bc6
+		case 'F':
Dan Walsh 9d5bc6
+			fprintf(out_fp, "filename_trans rules:\n");
Dan Walsh 9d5bc6
+			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
Dan Walsh 9d5bc6
+					0, &policydb, out_fp);
Dan Walsh 9d5bc6
+			break;
Dan Walsh 9d5bc6
 		case 'l':
Dan Walsh 9d5bc6
 			link_module(&policydb, out_fp);
Dan Walsh 9d5bc6
 			break;
Dan Walsh 66140a
diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c
Dan Walsh 66140a
index f8c05e6..ee2cf02 100644
Dan Walsh 66140a
--- a/checkpolicy/test/dispol.c
Dan Walsh 66140a
+++ b/checkpolicy/test/dispol.c
Dan Walsh 66140a
@@ -341,6 +341,21 @@ static void display_permissive(policydb_t *p, FILE *fp)
Dan Walsh 9d5bc6
 	}
Dan Walsh 9d5bc6
 }
Dan Walsh 9d5bc6
 
Dan Walsh 9d5bc6
+static void display_filename_trans(policydb_t *p, FILE *fp)
Dan Walsh 9d5bc6
+{
Dan Walsh 9d5bc6
+	filename_trans_t *ft;
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
+	fprintf(fp, "filename_trans rules:\n");
Dan Walsh 9d5bc6
+	for (ft = p->filename_trans; ft; ft = ft->next) {
Dan Walsh 9d5bc6
+		fprintf(fp, "%s\n", ft->name);
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
Dan Walsh 9d5bc6
+		display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
Dan Walsh 9d5bc6
+		fprintf(fp, "\n");
Dan Walsh 9d5bc6
+	}
Dan Walsh 9d5bc6
+}
Dan Walsh 9d5bc6
+
Dan Walsh 9d5bc6
 int menu()
Dan Walsh 9d5bc6
 {
Dan Walsh 9d5bc6
 	printf("\nSelect a command:\n");
Dan Walsh 9d5bc6
@@ -355,6 +370,8 @@ int menu()
Dan Walsh 9d5bc6
 	printf("c)  display policy capabilities\n");
Dan Walsh 9d5bc6
 	printf("p)  display the list of permissive types\n");
Dan Walsh 9d5bc6
 	printf("u)  display unknown handling setting\n");
Dan Walsh 9d5bc6
+	printf("F)  display filename_trans rules\n");
Dan Walsh 9d5bc6
+	printf("\n");
Dan Walsh 9d5bc6
 	printf("f)  set output file\n");
Dan Walsh 9d5bc6
 	printf("m)  display menu\n");
Dan Walsh 9d5bc6
 	printf("q)  quit\n");
Dan Walsh 9d5bc6
@@ -492,6 +509,9 @@ int main(int argc, char **argv)
Dan Walsh 9d5bc6
 			if (out_fp != stdout)
Dan Walsh 9d5bc6
 				printf("\nOutput to file: %s\n", OutfileName);
Dan Walsh 9d5bc6
 			break;
Dan Walsh 9d5bc6
+		case 'F':
Dan Walsh 9d5bc6
+			display_filename_trans(&policydb, out_fp);
Dan Walsh 9d5bc6
+			break;
Dan Walsh 9d5bc6
 		case 'q':
Dan Walsh 9d5bc6
 			policydb_destroy(&policydb);
Dan Walsh 9d5bc6
 			exit(0);