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

[Patch 3/3] Loadable policy module infrastructure


diff -burNd a1/checkpolicy/Makefile b/checkpolicy/Makefile
--- a1/checkpolicy/Makefile	2005-05-25 13:14:58.691736752 -0400
+++ b/checkpolicy/Makefile	2005-05-25 13:11:19.295090112 -0400
@@ -1,20 +1,21 @@
 #
 # Makefile for building the checkpolicy program
 #
-PREFIX ?= ${DESTDIR}/usr
+PREFIX ?= $(DESTDIR)/usr
 BINDIR ?= $(PREFIX)/bin
 MANDIR ?= $(PREFIX)/share/man
-LIBDIR ?= ${PREFIX}/lib
-INCLUDEDIR ?= ${PREFIX}/include
+LIBDIR ?= $(PREFIX)/lib
+INCLUDEDIR ?= $(PREFIX)/include
 TARGETS = checkpolicy 
 
-CFLAGS = -g -Wall -O2 -pipe
+CFLAGS = -g -Wall -O2 -pipe -fno-strict-aliasing
 
-override CFLAGS += -I. -I${INCLUDEDIR}
+#override CFLAGS += -I. -I$(INCLUDEDIR)
+CFLAGS += -I. -I../libselinux/include -I../libsepol/include -I../libsemod/include
 
 OBJS += y.tab.o lex.yy.o queue.o checkpolicy.o
 
-LIBS=-lfl ${LIBDIR}/libsepol.a
+LIBS=-lfl $(LIBDIR)/libsepol.a
 
 all:  $(TARGETS)
 
diff -burNd a1/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
--- a1/checkpolicy/checkpolicy.c	2005-05-25 13:14:59.173663488 -0400
+++ b/checkpolicy/checkpolicy.c	2005-05-25 13:11:19.811011680 -0400
@@ -16,8 +16,14 @@
  *
  *	Added IPv6 support.
  *
+ * Updated: Joshua Brindle <jbrindle@xxxxxxxxxx>
+ *	    Karl MacMillan <kmacmillan@xxxxxxxxxx>
+ *          Jason Tang     <jtang@xxxxxxxxxx>
+ *
+ *	Policy Module support.
+ *
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
- * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@xxxxxxxxxx>
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
@@ -51,6 +57,11 @@
  * booleans or conditional rules are thrown away a warning is printed.
  */
 
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
 #include <getopt.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -59,9 +70,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
 #include <sys/mman.h>
 
 #include <sepol/policydb.h>
@@ -69,6 +77,7 @@
 #include <sepol/conditional.h>
 #include <sepol/hierarchy.h>
 #include <sepol/flask.h>
+#include <sepol/expand.h>
 
 #include "queue.h"
 #include "checkpolicy.h"
@@ -83,12 +92,12 @@
 extern queue_t id_queue;
 extern unsigned int policydb_errors;
 extern unsigned long policydb_lineno;
-extern unsigned long source_lineno;
 extern char source_file[];
-extern unsigned int pass;
 
 extern FILE *yyin;
+extern void init_parser(int);
 extern int yyparse(void);
+extern int yywarn(char *);
 extern void yyrestart(FILE *);
 
 char *txtfile = "policy.conf";
@@ -147,15 +150,6 @@
 	return 0;
 }
 
-static int type_attr_remove(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *p __attribute__ ((unused)))
-{
-	type_datum_t *typdatum;
-
-	typdatum = (type_datum_t *) datum;
-	if (typdatum->isattr)
-		return 1;
-	return 0;
-}
 
 #ifdef EQUIVTYPES
 static int insert_type_rule(avtab_key_t *k, avtab_datum_t *d, 
@@ -321,63 +315,6 @@
 
 extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
 
-void check_assertion_helper(unsigned int stype, unsigned int ttype, ebitmap_t *tclasses, 
-			    sepol_access_vector_t *avp, unsigned long line) 
-{
-	avtab_key_t avkey;
-	avtab_datum_t *avdatump;
-	unsigned int k;
-	
-
-	for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); k++) {
-		if (!ebitmap_get_bit(tclasses, k)) 
-			continue;
-		avkey.source_type = stype + 1;
-		avkey.target_type = ttype + 1;
-		avkey.target_class = k + 1;
-		avdatump = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
-		if (!avdatump) 
-			continue;
-
-		if ((avdatump->specified & AVTAB_ALLOWED) &&
-		    (avtab_allowed(avdatump) & avp[k])) {
-			fprintf(stderr, "assertion on line %ld violated by allow %s %s:%s {%s };\n", line, policydb.p_type_val_to_name[stype], policydb.p_type_val_to_name[ttype], policydb.p_class_val_to_name[k], 
-				av_to_string(k+1,
-					     avtab_allowed(avdatump) & avp[k]));
-			policydb_errors++;
-		}
-	}
-}
-
-void check_assertions(void) 
-{
-	te_assert_t *a, *tmp;
-	unsigned int i, j;
-
-	a = te_assertions;
-	while (a) {
-		for (i = ebitmap_startbit(&a->stypes); i < ebitmap_length(&a->stypes); i++) {
-			if (!ebitmap_get_bit(&a->stypes, i))
-				continue;
-			if (a->self) {
-				check_assertion_helper(i, i, &a->tclasses, a->avp, a->line);
-			}
-			for (j = ebitmap_startbit(&a->ttypes); j < ebitmap_length(&a->ttypes); j++) {
-				if (!ebitmap_get_bit(&a->ttypes, j)) 
-					continue;
-				check_assertion_helper(i, j, &a->tclasses, a->avp, a->line);
-			}
-		}
-		tmp = a;
-		a = a->next;
-		ebitmap_destroy(&tmp->stypes);
-		ebitmap_destroy(&tmp->ttypes);
-		ebitmap_destroy(&tmp->tclasses);
-		free(tmp->avp);
-		free(tmp);
-	}
-}
-
 int display_bools()
 {
 	int i;
@@ -389,11 +326,11 @@
 	return 0;
 }
 
-void display_expr(cond_expr_t *exp)
+void display_expr(cond_expr_t *expr)
 {
 
 	cond_expr_t *cur;
-	for (cur = exp; cur != NULL; cur = cur->next) {
+	for (cur = expr; cur != NULL; cur = cur->next) {
 		switch (cur->expr_type) {
 		case COND_BOOL:
 			printf("%s ", policydbp->p_bool_val_to_name[cur->bool - 1]);
@@ -472,7 +409,6 @@
 	int show_version = 0;
 	struct policy_file pf;
 
-
 	while ((ch = getopt(argc, argv, "o:dbMVc:")) != EOF) {
 		switch (ch) {
 		case 'o':
@@ -575,6 +511,8 @@
 			}
 		}
 	} else {
+                policydb_t parse_policy;
+
 		yyin = fopen(file, "r");
 		if (!yyin) {
 			fprintf(stderr, "%s:  unable to open %s\n", argv[0], 
@@ -582,7 +520,8 @@
 			exit(1);
 		}
 
-		if (policydb_init(&policydb))
+		/* We build this as a base policy first since that is all the parser understands */
+		if (policydb_init(&parse_policy, POLICY_BASE))
 			exit(1);
 
 		/* Let sepol know if we are dealing with MLS support */
@@ -593,65 +532,77 @@
 			fprintf(stderr, "%s:  out of memory\n", argv[0]);
 			exit(1);
 		}
-		policydbp = &policydb;
-		policydb_errors = 0;
-		pass = 1;
+		policydbp = &parse_policy;
+                init_parser(1);
 		if (yyparse() || policydb_errors) {
 			fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 			exit(1);
 		}
 		rewind(yyin);
-		policydb_lineno = 1;
+                init_parser(2);
 		source_file[0] = '\0';
-		source_lineno = 1;
 		yyrestart(yyin);
-		pass = 2;
 		if (yyparse() || policydb_errors) {
 			fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 			exit(1);
 		}
 		queue_destroy(id_queue);
-
 		cond_check_type_rules();
 		cond_optimize_lists(policydb.cond_list);
 
-		check_assertions();
 		if (policydb_errors) 
 			exit(1);
 
 		if (policyvers >= POLICYDB_VERSION_NLCLASS &&
-		    policydb.p_classes.nprim < SECCLASS_NETLINK_DNRT_SOCKET) {
+		    parse_policy.p_classes.nprim < SECCLASS_NETLINK_DNRT_SOCKET) {
 			fprintf(stderr, "%s:  policy lacks new netlink classes, unable to generate policy version %d\n", argv[0], policyvers);
 			exit(1);
 		}
 
-		if (hierarchy_check_constraints(&policydb, error_msg, sizeof(error_msg))) {
+		if (hierarchy_check_constraints(&parse_policy, error_msg, sizeof(error_msg))) {
 			fprintf(stderr, "%s\n", error_msg);
 			exit(1);
 		}
 
-		/* remove type attributes */
-		hashtab_map_remove_on_error(policydb.p_types.table, 
-					    type_attr_remove, 0, 0);
+		if (policydb_init(&policydb, POLICY_KERN))
+			exit(1);
+
+		if (expand_module(&parse_policy, &policydb, 0, error_msg, ERRMSG_LEN)) {
+                        fprintf(stderr, "Error while expanding policy: %s\n", error_msg);
+			exit(1);
+                }
+		policydbp = &policydb;
+
+		if (check_assertions(policydbp, policydbp->avrules, &policydbp->te_avtab)) {
+                        fprintf(stderr, "Check assertions failed.\n");
+			return -1;
+                }
 		
+		if (check_assertions(policydbp, policydbp->avrules, &policydbp->te_cond_avtab)) {
+                        fprintf(stderr, "Check assertions failed.\n");
+			return -1;
+                }
 		fclose(yyin);
 	}
 
 	if (policydb_load_isids(&policydb, &sidtab))
 		exit(1);
 
+	if (policydb_index_others(policydbp, 1))
+		exit(1);
+        
 	printf("%s:  policy configuration loaded\n", argv[0]);
 
 	if (outfile) {
 		printf("%s:  writing binary representation (version %d) to %s\n",
 		       argv[0], policyvers, outfile);
-		outfp = fopen(outfile, "w");
+		outfp = fopen(outfile, "wb");
 		if (!outfp) {
 			perror(outfile);
 			exit(1);
 		}
 
-		if (sepol_set_policyvers(policyvers)) {
+		if (sepol_set_policyvers(POLICY_KERN, policyvers)) {
 			fprintf(stderr,"%s:  incompatible policy (version %d) "
 				"for writing to %s\n", argv[0],
 				policyvers, outfile);
diff -burNd a1/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
--- a1/checkpolicy/policy_parse.y	2005-05-25 13:14:58.689737056 -0400
+++ b/checkpolicy/policy_parse.y	2005-05-25 13:11:19.301089200 -0400
@@ -1,4 +1,3 @@
-
 /*
  * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx> 
  */
@@ -12,8 +11,14 @@
  *
  * 	Added conditional policy language extensions
  *
+ * Updated: Joshua Brindle <jbrindle@xxxxxxxxxx>
+ *	    Karl MacMillan <kmacmillan@xxxxxxxxxx>
+ *          Jason Tang     <jtang@xxxxxxxxxx>
+ *
+ *	Added support for binary policy modules
+ *
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
- * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
@@ -22,13 +27,17 @@
 /* FLASK */
 
 %{
-#include <sys/types.h>
+#include <assert.h>
 #include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
-#include <netinet/in.h>
+#include <sys/types.h>
 #include <arpa/inet.h>
-#include <stdlib.h>
+#include <netinet/in.h>
 
+#include <sepol/expand.h>
 #include <sepol/policydb.h>
 #include <sepol/services.h>
 #include <sepol/conditional.h>
@@ -43,25 +52,37 @@
  * for NULL (ie 0) because that is a potentially valid return.
  */
 static cond_av_list_t *conditional_unused_error_code;
-#define COND_ERR (cond_av_list_t *)&conditional_unused_error_code
+#define COND_ERR (avrule_t *)&conditional_unused_error_code
 
 #define TRUE 1
 #define FALSE 0
 
 policydb_t *policydbp;
 queue_t id_queue = 0;
-unsigned int pass;
 char *curfile = 0;
-unsigned int curline; 
+
+static unsigned int pass;
+static avrule_t *last_avrule = NULL;
+
+/* So as to make it easier to verify the correctness of the module
+ * changes, keep track of how many types (sans attributes and aliases)
+ * have been found.  Conveniently this also acts as to ensure that
+ * type values are ordered based upon their declaration within the
+ * policy.conf file, which is what non-module policy_parse.y did. */
+static uint32_t num_types_found = 0;
 
 extern unsigned long policydb_lineno;
+extern unsigned long source_lineno;
+extern unsigned int policydb_errors;
+extern unsigned int policyvers;
 
 extern char yytext[];
 extern int yylex(void);
 extern int yywarn(char *msg);
 extern int yyerror(char *msg);
 
-static char errormsg[255];
+#define ERRORMSG_LEN 255
+static char errormsg[ERRORMSG_LEN + 1] = {0};
 
 static int insert_separator(int push);
 static int insert_id(char *id,int push);
@@ -78,6 +99,7 @@
 static int define_typealias(void);
 static int define_typeattribute(void);
 static int define_type(int alias);
+static int define_type_noalias(void);
 static int define_compute_type(int which);
 static int define_te_avtab(int which);
 static int define_role_types(void);
@@ -89,13 +111,11 @@
 static int define_constraint(constraint_expr_t *expr);
 static int define_validatetrans(constraint_expr_t *expr);
 static int define_bool();
-static int define_conditional(cond_expr_t *expr,cond_av_list_t *t_list, cond_av_list_t *f_list );
+static int define_conditional(cond_expr_t *expr, avrule_t *t_list, avrule_t *f_list );
 static cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2);
-static cond_av_list_t *define_cond_pol_list(cond_av_list_t *avlist, cond_av_list_t *stmt);
-static cond_av_list_t *define_cond_compute_type(int which);
-static cond_av_list_t *define_cond_te_avtab(int which);
-static cond_av_list_t *cond_list_append(cond_av_list_t *sl, avtab_key_t *key, avtab_datum_t *datum);
-static void cond_reduce_insert_list(cond_av_list_t *new, cond_av_list_t **active, cond_av_list_t **inactive, int state ); 
+static avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt);
+static avrule_t *define_cond_compute_type(int which);
+static avrule_t *define_cond_te_avtab(int which);
 static uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2);
 static int define_user(void);
 static int parse_security_context(context_struct_t *c);
@@ -182,11 +202,14 @@
 %right NOT
 %left EQUALS NOTEQUAL
 %%
-policy			: classes initial_sids access_vectors
-                          { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; } }
+policy			: base_policy
+                        ;
+base_policy             : classes initial_sids access_vectors
+                          { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; }
+                            else if (pass == 2) { if (policydb_index_others(policydbp, 0)) return -1; }}
 			  opt_mls te_rbac users opt_constraints 
                          { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
-			   if (pass == 2) { if (policydb_index_others(policydbp, 1)) return -1;} } 
+			   else if (pass == 2) { if (policydb_index_others(policydbp, 0)) return -1;}}
 			  initial_sid_contexts opt_fs_contexts fs_uses opt_genfs_contexts net_contexts 
 			;
 classes			: class_def 
@@ -321,13 +344,13 @@
 			{ if (insert_id("F",0)) return -1; }
                         ;
 cond_stmt_def           : IF cond_expr '{' cond_pol_list '}'
-                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (cond_av_list_t*)$4,(cond_av_list_t*) 0) < 0) return -1;  }}
+                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (avrule_t*)$4, (avrule_t*) 0) < 0) return -1;  }}
                         | IF cond_expr '{' cond_pol_list '}' ELSE '{' cond_pol_list '}'
-                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(cond_av_list_t*)$4,(cond_av_list_t*)$8) < 0 ) return -1;  }}       
+                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(avrule_t*)$4,(avrule_t*)$8) < 0 ) return -1;  }}       
                         | IF cond_expr '{' cond_pol_list '}' ELSE '{' '}'
-                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(cond_av_list_t*)$4,(cond_av_list_t*) 0) < 0 ) return -1;  }}       
+                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(avrule_t*)$4,(avrule_t*) 0) < 0 ) return -1;  }}       
                         | IF cond_expr '{' '}' ELSE '{' cond_pol_list '}'
-                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(cond_av_list_t*) 0,(cond_av_list_t*) $7) < 0 ) return -1;  }}       
+                        { if (pass == 2) { if (define_conditional((cond_expr_t*)$2,(avrule_t*) 0,(avrule_t*) $7) < 0 ) return -1;  }}       
                         | IF cond_expr '{' '}' ELSE '{' '}'
                         /* do nothing */
                         | IF cond_expr '{' '}' 
@@ -361,9 +384,9 @@
 			  if ($$ == COND_ERR) return   -1; }
                         ;
 cond_pol_list           : cond_rule_def
-                        { $$ = define_cond_pol_list((cond_av_list_t *) 0, (cond_av_list_t *)$1);}
+                        { $$ = define_cond_pol_list((avrule_t *) 0, (avrule_t *)$1);}
                         | cond_pol_list cond_rule_def 
-                        { $$ = define_cond_pol_list((cond_av_list_t *)$1, (cond_av_list_t *)$2); }
+                        { $$ = define_cond_pol_list((avrule_t *)$1, (avrule_t *)$2); }
 			;
 cond_rule_def           : cond_transition_def
                         { $$ = $1; }
@@ -371,13 +394,13 @@
                         { $$ = $1; }
                         ;
 cond_transition_def	: TYPE_TRANSITION names names ':' names identifier ';'
-                        { $$ = define_cond_compute_type(AVTAB_TRANSITION) ;
+                        { $$ = define_cond_compute_type(AVRULE_TRANSITION) ;
                           if ($$ == COND_ERR) return -1;}
                         | TYPE_MEMBER names names ':' names identifier ';'
-                        { $$ = define_cond_compute_type(AVTAB_MEMBER) ;
+                        { $$ = define_cond_compute_type(AVRULE_MEMBER) ;
                           if ($$ ==  COND_ERR) return -1;}
                         | TYPE_CHANGE names names ':' names identifier ';'
-                        { $$ = define_cond_compute_type(AVTAB_CHANGE) ;
+                        { $$ = define_cond_compute_type(AVRULE_CHANGE) ;
                           if ($$ == COND_ERR) return -1;}
     			;
 cond_te_avtab_def	: cond_allow_def
@@ -390,27 +413,27 @@
 			  { $$ = $1; }
 			;
 cond_allow_def		: ALLOW names names ':' names names  ';'
-			{ $$ = define_cond_te_avtab(AVTAB_ALLOWED) ;
+			{ $$ = define_cond_te_avtab(AVRULE_ALLOWED) ;
                           if ($$ == COND_ERR) return -1; }
 		        ;
 cond_auditallow_def	: AUDITALLOW names names ':' names names ';'
-			{ $$ = define_cond_te_avtab(AVTAB_AUDITALLOW) ;
+			{ $$ = define_cond_te_avtab(AVRULE_AUDITALLOW) ;
                           if ($$ == COND_ERR) return -1; }
 		        ;
 cond_auditdeny_def	: AUDITDENY names names ':' names names ';'
-			{ $$ = define_cond_te_avtab(AVTAB_AUDITDENY) ;
+			{ $$ = define_cond_te_avtab(AVRULE_AUDITDENY) ;
                           if ($$ == COND_ERR) return -1; }
 		        ;
 cond_dontaudit_def	: DONTAUDIT names names ':' names names ';'
-			{ $$ = define_cond_te_avtab(-AVTAB_AUDITDENY);
+			{ $$ = define_cond_te_avtab(AVRULE_DONTAUDIT);
                           if ($$ == COND_ERR) return -1; }
 		        ;
 transition_def		: TYPE_TRANSITION names names ':' names identifier ';'
-                        {if (define_compute_type(AVTAB_TRANSITION)) return -1;}
+                        {if (define_compute_type(AVRULE_TRANSITION)) return -1;}
                         | TYPE_MEMBER names names ':' names identifier ';'
-                        {if (define_compute_type(AVTAB_MEMBER)) return -1;}
+                        {if (define_compute_type(AVRULE_MEMBER)) return -1;}
                         | TYPE_CHANGE names names ':' names identifier ';'
-                        {if (define_compute_type(AVTAB_CHANGE)) return -1;}
+                        {if (define_compute_type(AVRULE_CHANGE)) return -1;}
     			;
 range_trans_def		: RANGE_TRANSITION names names mls_range_def ';'
 			{ if (define_range_trans()) return -1; }
@@ -422,22 +445,24 @@
 			| neverallow_def
 			;
 allow_def		: ALLOW names names ':' names names  ';'
-			{if (define_te_avtab(AVTAB_ALLOWED)) return -1; }
+			{if (define_te_avtab(AVRULE_ALLOWED)) return -1; }
 		        ;
 auditallow_def		: AUDITALLOW names names ':' names names ';'
-			{if (define_te_avtab(AVTAB_AUDITALLOW)) return -1; }
+			{if (define_te_avtab(AVRULE_AUDITALLOW)) return -1; }
 		        ;
 auditdeny_def		: AUDITDENY names names ':' names names ';'
-			{if (define_te_avtab(AVTAB_AUDITDENY)) return -1; }
+			{if (define_te_avtab(AVRULE_AUDITDENY)) return -1; }
 		        ;
 dontaudit_def		: DONTAUDIT names names ':' names names ';'
-			{if (define_te_avtab(-AVTAB_AUDITDENY)) return -1; }
+			{if (define_te_avtab(AVRULE_DONTAUDIT)) return -1; }
 		        ;
 neverallow_def		: NEVERALLOW names names ':' names names  ';'
-			{if (define_te_avtab(-AVTAB_ALLOWED)) return -1; }
+			{if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; }
 		        ;
 role_type_def		: ROLE identifier TYPES names ';'
 			{if (define_role_types()) return -1;}
+ 			| ROLE identifier';'
+ 			{if (define_role_types()) return -1;}
                         ;
 role_dominance		: DOMINANCE '{' roles '}'
 			;
@@ -643,11 +668,8 @@
                         | FSUSETRANS identifier security_context_def ';'
                         {if (define_fs_use(SECURITY_FS_USE_TRANS)) return -1;}
                         ;
-opt_genfs_contexts      : genfs_contexts
-                        | 
-                        ;
-genfs_contexts	        : genfs_context_def
-			| genfs_contexts genfs_context_def
+opt_genfs_contexts      : genfs_context_def opt_genfs_contexts
+                        | /* empty */
 			;
 genfs_context_def	: GENFSCON identifier path '-' identifier security_context_def
 			{if (define_genfs_context(1)) return -1;}
@@ -656,6 +678,7 @@
                         | GENFSCON identifier path security_context_def
 			{if (define_genfs_context(0)) return -1;}
 			;
+/* FIX ME: add policycon statements here */
 ipv4_addr_def		: number '.' number '.' number '.' number
 			{ 
 			  unsigned int addr;
@@ -763,6 +786,18 @@
 			{ if (insert_id(yytext,0)) return -1; }
 			;
 %%
+
+/* initialize all of the state variables for the scanner/parser */
+void init_parser(int pass_number)
+{
+        policydb_lineno = 1;
+        source_lineno = 1;
+        policydb_errors = 0;
+        pass = pass_number;
+        last_avrule = NULL;
+        num_types_found = 0;
+}
+
 #define DEBUG 1
 
 static int insert_separator(int push)
@@ -805,7 +840,44 @@
 	return 0;
 }
 
-/* If the identifier has a dot within it return 1, else return 0. */
+/* Add a rule onto an avtab hash table only if it does not already
+ * exist.  (Note that the avtab is discarded afterwards; it will be
+ * regenerated during expansion.)  Return 1 if rule was added (or
+ * otherwise handled successfully), 0 if it conflicted with something,
+ * or -1 on error. */
+static int insert_check_type_rule(avrule_t *rule, avtab_t *avtab, cond_av_list_t **list, cond_av_list_t **other)
+{
+	char *error_msg = NULL;
+	int ret;
+	
+	ret = expand_rule(policydbp, rule, avtab, list, other, 0, &error_msg);
+	switch (ret) {
+        case 0: {
+                if (error_msg == NULL) {
+                        yywarn("Conflicting rule");
+                }
+                else {
+                        yywarn(error_msg);
+                }
+                free(error_msg);
+                break;
+        }
+        case -1: {
+                if (error_msg == NULL) {
+                        yyerror("Error inserting rule");
+                }
+                else {
+                        yyerror(error_msg);
+                }
+                free(error_msg);
+                break;
+        }
+        }
+	return ret;
+}
+
+/* If the identifier has a dot within it and that its first character
+   is not a dot then return 1, else return 0. */
 static int id_has_dot(char *id)
 {
         if (strchr(id, '.') >= id + 1) {
@@ -819,7 +891,7 @@
 	char *id = 0;
 	class_datum_t *datum = 0;
 	int ret;
-
+	uint32_t value;
 
 	if (pass == 2) {
 		id = queue_remove(id_queue);
@@ -832,9 +904,12 @@
 		yyerror("no class name for class definition?");
 		return -1;
 	}
-        if (id_has_dot(id)) {
-                free(id);
-                yyerror("class identifiers may not contain periods");
+        datum = hashtab_search(policydbp->p_classes.table, id);
+        if (datum) {
+                snprintf(errormsg, ERRORMSG_LEN,
+                         "duplicate declaration for class %s\n", id);
+                free (id);
+                yyerror(errormsg);
                 return -1;
         }
 	datum = (class_datum_t *) malloc(sizeof(class_datum_t));
@@ -843,20 +918,13 @@
 		goto bad;
 	}
 	memset(datum, 0, sizeof(class_datum_t));
-	datum->value = ++policydbp->p_classes.nprim;
 
-	ret = hashtab_insert(policydbp->p_classes.table,
-			     (hashtab_key_t) id, (hashtab_datum_t) datum);
-
-	if (ret == HASHTAB_PRESENT) {
-		--policydbp->p_classes.nprim;
-		yyerror("duplicate class definition");
-		goto bad;
-	}
-	if (ret == HASHTAB_OVERFLOW) {
+        ret = symtab_insert(policydbp, SYM_CLASSES, id, datum, &value);
+        if (ret) {
 		yyerror("hash table overflow");
-		goto bad;
+                return -1;
 	}
+        datum->value = value;
 	return 0;
 
       bad:
@@ -939,13 +1007,19 @@
 		yyerror("no common name for common perm definition?");
 		return -1;
 	}
+        comdatum = hashtab_search(policydbp->p_commons.table, id);
+        if (comdatum) {
+                snprintf(errormsg, ERRORMSG_LEN,
+                         "duplicate declaration for common %s\n", id);
+                yyerror(errormsg);
+                return -1;
+        }
 	comdatum = (common_datum_t *) malloc(sizeof(common_datum_t));
 	if (!comdatum) {
 		yyerror("out of memory");
 		goto bad;
 	}
 	memset(comdatum, 0, sizeof(common_datum_t));
-	comdatum->value = ++policydbp->p_commons.nprim;
 	ret = hashtab_insert(policydbp->p_commons.table,
 			 (hashtab_key_t) id, (hashtab_datum_t) comdatum);
 
@@ -957,6 +1031,7 @@
 		yyerror("hash table overflow");
 		goto bad;
 	}
+        comdatum->value = ++policydbp->p_commons.nprim;
 	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) {
 		yyerror("out of memory");
 		goto bad;
@@ -1466,7 +1541,7 @@
 	char *id;
 	type_datum_t *attr;
 	int ret;
-
+	uint32_t value;
 
 	if (pass == 2) {
 		free(queue_remove(id_queue));
@@ -1493,12 +1568,14 @@
 	}
 	memset(attr, 0, sizeof(type_datum_t));
 	attr->isattr = TRUE;
-	ret = hashtab_insert(policydbp->p_types.table,
-			     id, (hashtab_datum_t) attr);
+        attr->primary = TRUE;
+        
+        ret = symtab_insert(policydbp, SYM_TYPES, id, attr, &value);
 	if (ret) {
 		yyerror("hash table overflow");
 		return -1;
 	}
+        attr->value = value;
 
 	return 0;
 }
@@ -1523,7 +1600,7 @@
 
 	t = hashtab_search(policydbp->p_types.table, id);
 	if (!t || t->isattr) {
-		sprintf(errormsg, "unknown type %s", id);
+		sprintf(errormsg, "unknown type %s, or it was already declared as an attribute", id);
 		yyerror(errormsg);
 		free(id);
 		return -1;
@@ -1544,6 +1621,12 @@
 		memset(aliasdatum, 0, sizeof(type_datum_t));
 		aliasdatum->value = t->value;
 
+                /* Type aliases are intentionally added to the global
+                   scope.  The reason is that they do not provide any
+                   new capabilities; they are still linked to its
+                   original type.  Thus, to determine the alias's
+                   scope, one must dereference to the original type
+                   and then look up that type's scope. */
 		ret = hashtab_insert(policydbp->p_types.table,
 				     (hashtab_key_t) id, (hashtab_datum_t) aliasdatum);
 
@@ -1622,7 +1705,7 @@
 	char *id;
 	type_datum_t *datum, *aliasdatum, *attr;
 	int ret, newattr = 0;
-
+	uint32_t value;
 
 	if (pass == 2) {
 		while ((id = queue_remove(id_queue))) 
@@ -1639,6 +1722,14 @@
 		yyerror("no type name for type definition?");
 		return -1;
 	}
+        datum = hashtab_search(policydbp->p_types.table, id);
+        if (datum) {
+                snprintf(errormsg, ERRORMSG_LEN,
+                         "duplicate declaration for type %s\n", id);
+                free(id);
+                yyerror(errormsg);
+                return -1;
+        }
 
 	datum = (type_datum_t *) malloc(sizeof(type_datum_t));
 	if (!datum) {
@@ -1648,25 +1739,16 @@
 	}
 	memset(datum, 0, sizeof(type_datum_t));
 	datum->primary = TRUE;
-	datum->value = ++policydbp->p_types.nprim;
 
-	ret = hashtab_insert(policydbp->p_types.table,
-			     (hashtab_key_t) id, (hashtab_datum_t) datum);
-
-	if (ret == HASHTAB_PRESENT) {
-		--policydbp->p_types.nprim;
-		free(datum);
-		sprintf(errormsg, "name conflict for type %s", id);
-		yyerror(errormsg);
-		free(id);
-		return -1;
-	}
-	if (ret == HASHTAB_OVERFLOW) {
+        ret = symtab_insert(policydbp, SYM_TYPES, (hashtab_key_t) id, (hashtab_datum_t) datum, &value);
+	if (ret) {
 		yyerror("hash table overflow");
 		free(datum);
 		free(id);
 		return -1;
 	}
+        datum->value = value;
+        datum->order = ++num_types_found;
 
 	if (alias) { 
 		while ((id = queue_remove(id_queue))) {
@@ -1677,18 +1759,8 @@
 			}
 			memset(aliasdatum, 0, sizeof(type_datum_t));
 			aliasdatum->value = datum->value;
-
-			ret = hashtab_insert(policydbp->p_types.table,
-					     (hashtab_key_t) id, (hashtab_datum_t) aliasdatum);
-
-			if (ret == HASHTAB_PRESENT) {
-				sprintf(errormsg, "name conflict for type alias %s", id);
-				yyerror(errormsg);
-				free(aliasdatum);
-				free(id);
-				return -1;
-			}
-			if (ret == HASHTAB_OVERFLOW) {
+                        ret = symtab_insert(policydbp, SYM_TYPES, id, (hashtab_datum_t) aliasdatum, NULL);
+			if (ret) {
 				yyerror("hash table overflow");
 				free(aliasdatum);
 				free(id);
@@ -1744,67 +1816,35 @@
 	return 0;
 }
 
-struct val_to_name {
-	unsigned int val;
-	char *name;
-};
-
-static int type_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p)
-{
-	type_datum_t *typdatum;
-	struct val_to_name *v = p;
-
-	typdatum = (type_datum_t *) datum;
-
-	if (v->val == typdatum->value) {
-		v->name = key;
-		return 1;
-	}
-
-	return 0;
-}
-
-static char *type_val_to_name(unsigned int val) 
-{
-	struct val_to_name v;
-	int rc;
-
-	v.val = val;
-	rc = hashtab_map(policydbp->p_types.table, 
-			 type_val_to_name_helper, &v);
-	if (rc)
-		return v.name;
-	return NULL;
+/* FIX ME: to be used by module requires */
+#if 0
+static int define_type_noalias(void) {
+    return define_type(0);
 }
+#endif
 
-
-static int set_types(ebitmap_t *set,
-		     ebitmap_t *negset,
+/* Adds a type, given by its textual name, to a typeset.  If *add is
+   0, then add the type to the negative set; otherwise if *add is 1
+   then add it to the positive side. */
+static int set_types(type_set_t *set,
 		     char *id,
 		     int *add)
 {
 	type_datum_t *t;
-	unsigned int i;
 
 	if (strcmp(id, "*") == 0) {
-		/* set all types not in negset */
-		for (i = 0; i < policydbp->p_types.nprim; i++) {
-			if (!ebitmap_get_bit(negset, i))
-				ebitmap_set_bit(set, i, TRUE);
-		}
+                /* set TYPE_STAR flag */
+                set->flags = TYPE_STAR;
 		free(id);
+                *add = 1;
 		return 0;
 	}
 
 	if (strcmp(id, "~") == 0) {
 		/* complement the set */
-		for (i = 0; i < policydbp->p_types.nprim; i++) {
-			if (ebitmap_get_bit(set, i))
-				ebitmap_set_bit(set, i, FALSE);
-			else 
-				ebitmap_set_bit(set, i, TRUE);
-		}
+                set->flags = TYPE_COMP;
 		free(id);
+                *add = 1;
 		return 0;
 	}
 
@@ -1816,103 +1856,73 @@
 
 	t = hashtab_search(policydbp->p_types.table, id);
 	if (!t) {
-		sprintf(errormsg, "unknown type %s", id);
+		snprintf(errormsg, ERRORMSG_LEN, "unknown type %s", id);
 		yyerror(errormsg);
 		free(id);
 		return -1;
 	}
 
-	if (t->isattr) {
-		/* set or clear all types with this attribute,
-		   but do not set anything explicitly cleared previously */
-		for (i = ebitmap_startbit(&t->types); i < ebitmap_length(&t->types); i++) {
-			if (!ebitmap_get_bit(&t->types, i)) 
-				continue;		
-			if (!(*add)) {
-				ebitmap_set_bit(set, i, FALSE);
-				ebitmap_set_bit(negset, i, TRUE);
-			} else if (!ebitmap_get_bit(negset, i)) {
-				ebitmap_set_bit(set, i, TRUE);
-#if VERBOSE
-			} else {
-				char *name = type_val_to_name(i+1);
-				sprintf(errormsg, "ignoring %s due to prior -%s", name, name);
-				yywarn(errormsg);
-#endif
-			}
-		}
-	} else {
-		/* set or clear one type, but do not set anything
-		   explicitly cleared previously */	
-		if (!(*add)) {
-			ebitmap_set_bit(set, t->value - 1, FALSE);
-			ebitmap_set_bit(negset, t->value - 1, TRUE);
-		} else if (!ebitmap_get_bit(negset, t->value - 1)) {
-			ebitmap_set_bit(set, t->value - 1, TRUE);
-#if VERBOSE
-		} else {
-			sprintf(errormsg, "ignoring %s due to prior -%s", id, id);
-			yywarn(errormsg);
-#endif
+        if (*add == 0) {
+                ebitmap_set_bit(&set->negset, t->value - 1, TRUE);
 		}
+        else {
+                ebitmap_set_bit(&set->types, t->value - 1, TRUE);
 	}
-
 	free(id);
 	*add = 1;
 	return 0;
 }
 
-
-static int define_compute_type(int which)
+static int define_compute_type_helper(int which, avrule_t **rule)
 {
 	char *id;
-	avtab_key_t avkey;
-	avtab_datum_t avdatum, *avdatump;
 	type_datum_t *datum;
 	class_datum_t *cladatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
-	uint32_t newtype = 0;
-	int ret, add = 1;
-	unsigned int i, j, k;
+	ebitmap_t tclasses;
+	avrule_t *avrule;
+	class_perm_node_t *perm;
+	int i, add = 1;
 
-	if (pass == 1) {
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		id = queue_remove(id_queue);
-		free(id);
-		return 0;
+	avrule = malloc(sizeof(avrule_t));
+	if (!avrule) {
+		yyerror("out of memory");
+		return -1;
 	}
+	avrule_init(avrule);
+        avrule->specified = which;
+        avrule->line = policydb_lineno;
 
-	ebitmap_init(&stypes);
-	ebitmap_init(&ttypes);
-	ebitmap_init(&tclasses);
-
-	ebitmap_init(&negset);
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&stypes, &negset, id, &add))
+                if (set_types(&avrule->stypes, id, &add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
-
-	ebitmap_init(&negset);
+        add = 1;
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&ttypes, &negset, id, &add))
+		if (set_types(&avrule->ttypes, id, &add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
 
+        ebitmap_init(&tclasses);
 	while ((id = queue_remove(id_queue))) {
+                uint32_t classvalue;
 		cladatum = hashtab_search(policydbp->p_classes.table, id);
 		if (!cladatum) {
 			sprintf(errormsg, "unknown class %s", id);
 			yyerror(errormsg);
 			goto bad;
 		}
-		ebitmap_set_bit(&tclasses, cladatum->value - 1, TRUE);
+                if (policyvers < POLICYDB_VERSION_NLCLASS &&
+		    (cladatum->value >= SECCLASS_NETLINK_ROUTE_SOCKET &&
+		     cladatum->value <= SECCLASS_NETLINK_DNRT_SOCKET)) {
+			sprintf(errormsg, "remapping class %s to netlink_socket "
+			        "for policy version %d", id, policyvers);
+			yywarn(errormsg);
+			classvalue = SECCLASS_NETLINK_SOCKET;
+                }
+                else {
+                        classvalue = cladatum->value;
+                }
+                ebitmap_set_bit(&tclasses, classvalue - 1, TRUE);
 		free(id);
 	}
 
@@ -1929,91 +1939,35 @@
 		goto bad;
 	}
 
-	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
-		if (!ebitmap_get_bit(&stypes, i)) 
-			continue;
-		for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) {
-			if (!ebitmap_get_bit(&ttypes, j)) 
-				continue;
-			for (k = ebitmap_startbit(&tclasses); k < ebitmap_length(&tclasses); k++) {
-				if (!ebitmap_get_bit(&tclasses, k)) 
-					continue;
-				avkey.source_type = i + 1;
-				avkey.target_type = j + 1;
-				avkey.target_class = k + 1;
-				avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_TYPE);
-				if (avdatump) {
-					switch (which) {
-					case AVTAB_TRANSITION:
-						newtype = avtab_transition(avdatump);
-						break;
-					case AVTAB_MEMBER:
-						newtype = avtab_member(avdatump);
-						break;
-					case AVTAB_CHANGE:
-						newtype = avtab_change(avdatump);
-						break;
-					}
-					if ( (avdatump->specified & which) &&
-					     (newtype != datum->value) ) {
-						sprintf(errormsg, "conflicting rule for (%s, %s:%s):  default was %s, is now %s", type_val_to_name(i+1), type_val_to_name(j+1), policydbp->p_class_val_to_name[k],
-							type_val_to_name(newtype),
-							type_val_to_name(datum->value));
-						yywarn(errormsg);
-					}
-					avdatump->specified |= which;
-					switch (which) {
-					case AVTAB_TRANSITION:
-						avtab_transition(avdatump) = datum->value;
-						break;
-					case AVTAB_MEMBER:
-						avtab_member(avdatump) = datum->value;
-						break;
-					case AVTAB_CHANGE:
-						avtab_change(avdatump) = datum->value;
-						break;
-					}
-				} else {
-					memset(&avdatum, 0, sizeof avdatum);
-					avdatum.specified |= which;
-					switch (which) {
-					case AVTAB_TRANSITION:
-					        avtab_transition(&avdatum) = datum->value;
-						break;
-					case AVTAB_MEMBER:
-						avtab_member(&avdatum) = datum->value;
-						break;
-					case AVTAB_CHANGE:
-						avtab_change(&avdatum) = datum->value;
-						break;
-					}
-					ret = avtab_insert(&policydbp->te_avtab, &avkey, &avdatum);
-					if (ret) {
-						yyerror("hash table overflow");
-						goto bad;
-					}
-				}
+	for (i = ebitmap_startbit(&tclasses); i < ebitmap_length(&tclasses); i++ ) {
+		if (ebitmap_get_bit(&tclasses, i)) {
+			perm = malloc(sizeof(class_perm_node_t));
+			if (!perm) {
+				yyerror("out of memory"); 
+				return -1;
 			}
+			class_perm_node_init(perm);
+			perm->class = i + 1;
+			perm->data = datum->value;
+			perm->next = avrule->perms;
+			avrule->perms = perm;
 		}
 	}
 
+        *rule = avrule;
 	return 0;
 
       bad:
+      	avrule_destroy(avrule);
+      	free(avrule);
 	return -1;
 }
 
-static cond_av_list_t *define_cond_compute_type(int which)
+static int define_compute_type(int which)
 {
 	char *id;
-	cond_av_list_t *sub_list;
-	avtab_key_t avkey;
-	avtab_datum_t avdatum, *avdatump;
-	type_datum_t *datum;
-	class_datum_t *cladatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
-	uint32_t newtype = 0;
-	int i, j, k, add = 1;
+	avrule_t *avrule;
+        int retval;
 
 	if (pass == 1) {
 		while ((id = queue_remove(id_queue)))
@@ -2024,217 +1978,63 @@
 			free(id);
 		id = queue_remove(id_queue);
 		free(id);
-		return (cond_av_list_t *)1; /* any non-NULL value */
-	}
-	
-	ebitmap_init(&stypes);
-	ebitmap_init(&ttypes);
-	ebitmap_init(&tclasses);
-
-	ebitmap_init(&negset);
-	while ((id = queue_remove(id_queue))) {
-		if (set_types(&stypes, &negset, id, &add))
-			return  COND_ERR;
-	}
-	ebitmap_destroy(&negset);
-
-	ebitmap_init(&negset);
-	while ((id = queue_remove(id_queue))) {
-		if (set_types(&ttypes, &negset, id, &add))
-			return COND_ERR;
-	}
-	ebitmap_destroy(&negset);
-
-	while ((id = queue_remove(id_queue))) {
-		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!cladatum) {
-			sprintf(errormsg, "unknown class %s", id);
-			yyerror(errormsg);
-			goto bad;
-		}
-		ebitmap_set_bit(&tclasses, cladatum->value - 1, TRUE);
-		free(id);
-	}
-
-	id = (char *) queue_remove(id_queue);
-	if (!id) {
-		yyerror("no newtype?");
-		goto bad;
-	}
-	datum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
-						(hashtab_key_t) id);
-	if (!datum || datum->isattr) {
-		sprintf(errormsg, "unknown type %s", id);
-		yyerror(errormsg);
-		goto bad;
+		return 0;
 	}
 
-	/* create sub_list to be passed back and appended to true or false list */
-	sub_list = (cond_av_list_t *) 0;
-
-	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
-		if (!ebitmap_get_bit(&stypes, i)) 
-			continue;
-		for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) {
-			if (!ebitmap_get_bit(&ttypes, j)) 
-				continue;
-			for (k = ebitmap_startbit(&tclasses); k < ebitmap_length(&tclasses); k++) {
-				if (!ebitmap_get_bit(&tclasses, k)) 
-					continue;
-				avkey.source_type = i + 1;
-				avkey.target_type = j + 1;
-				avkey.target_class = k + 1;
-				avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_TYPE);
+	if (define_compute_type_helper(which, &avrule))
+		return -1;
 				
-				/* does rule exist in base policy? */
-				if ((avdatump) && (avdatump->specified & which)) {
-					switch (which) {
-					case AVTAB_TRANSITION:
-						newtype = avtab_transition(avdatump);
-						break;
-					case AVTAB_MEMBER:
-						newtype = avtab_member(avdatump);
-						break;
-					case AVTAB_CHANGE:
-						newtype = avtab_change(avdatump);
-						break;
-					}
-					if ( (newtype != datum->value) ) {
-						sprintf(errormsg, "conflicting type rule for conditional "
-							"(%s, %s:%s) in base: default is %s, conditional %s "
-							"will be ignored", 
-							type_val_to_name(i+1), 
-							type_val_to_name(j+1), 
-							policydbp->p_class_val_to_name[k],
-							type_val_to_name(newtype),
-							type_val_to_name(datum->value));
-						yywarn(errormsg);
-					} else {
-						sprintf(errormsg, "conditional type rule (%s, %s:%s): "
-							"has same default, %s, as rule in base policy; "
-							"conditional %s will be ignored", 
-							type_val_to_name(i+1), 
-							type_val_to_name(j+1), 
-							policydbp->p_class_val_to_name[k],
-							type_val_to_name(newtype),
-							type_val_to_name(datum->value));
-						yywarn(errormsg);
-					}
+	retval = insert_check_type_rule(avrule, &policydbp->te_avtab, NULL, NULL);
+	switch (retval) {
+        case 1: {
+                /* append this avrule to the end of the rules list */
+                if (last_avrule == NULL) {
+                        policydbp->avrules = last_avrule = avrule;
 				}
-				/* rule does not exist in base policy */
 				else {
-					
-					memset(&avdatum, 0, sizeof avdatum);
-					avdatum.specified |= which;
-					switch (which) {
-					case AVTAB_TRANSITION:
-					        avtab_transition(&avdatum) = datum->value;
-						break;
-					case AVTAB_MEMBER:
-						avtab_member(&avdatum) = datum->value;
-						break;
-					case AVTAB_CHANGE:
-						avtab_change(&avdatum) = datum->value;
-						break;
-					}
-					/* add rule to sub list */
-					sub_list = cond_list_append(sub_list, &avkey, &avdatum);
-					if (sub_list == COND_ERR) {
-						yyerror("list overflow");
-						goto bad;
-					}
-				}
+                        last_avrule->next = avrule;
+                        last_avrule = avrule;
 			}
+                return 0;
 		}
+        case 0: {
+                /* rule conflicted, so don't actually add this rule */
+                avrule_destroy(avrule);
+                free(avrule);
+                return 0;
 	}
-	
-	return sub_list;
-
-      bad:
-	return COND_ERR;
-}
-
-static cond_av_list_t *cond_list_append(cond_av_list_t *sl, avtab_key_t *key, avtab_datum_t *datum) {
-
-	cond_av_list_t  *n, *end;
-
-	n = (cond_av_list_t *) malloc(sizeof(cond_av_list_t));
-	if (!n) {
-		  yyerror("out of memory");
-		  return COND_ERR;
+        case -1: {
+                avrule_destroy(avrule);
+                free(avrule);
+                return -1;
 	}
-	memset(n, 0, sizeof(cond_av_list_t));
-	if (sl) {
-		for(end=sl; end->next != NULL; end = end->next);
-		end->next = n;
+        default: {
+                assert(0); /* should never get here */
 	}
-	else sl = n;
-	n->next = NULL;
-	
-	/* construct new node */
-	n->node = (avtab_ptr_t) malloc(sizeof(struct avtab_node));
-	if (!n->node) {
-		yyerror("out of memory");
-		return COND_ERR;
 	}
-	memset(n->node, 0, sizeof(struct avtab_node));
-	n->node->key = *key;
-	n->node->datum = *datum;
-	/* the next two fields get filled in when we add to true/false list  */
-	n->node->next = (avtab_ptr_t) 0;
-	n->node->parse_context = (void *) 0;
-	
-	return(sl);
 }
 
-
-static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
+static avrule_t *define_cond_compute_type(int which)
 {
-	struct val_to_name *v = data;
-	perm_datum_t *perdatum;
-
-	perdatum = (perm_datum_t *) datum;
+	char *id;
+	avrule_t *avrule;
 
-	if (v->val == perdatum->value) {
-		v->name = key;
-		return 1;
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		id = queue_remove(id_queue);
+		free(id);
+		return (avrule_t*)1;
 	}
 
-	return 0;
-}
-
-
-char *av_to_string(uint32_t tclass, sepol_access_vector_t av)
-{
-	struct val_to_name v;
-	static char avbuf[1024];
-	class_datum_t *cladatum;
-	char *perm = NULL, *p;
-	unsigned int i;
-	int rc;
-
-	cladatum = policydbp->class_val_to_struct[tclass-1];
-	p = avbuf;
-	for (i = 0; i < cladatum->permissions.nprim; i++) {
-		if (av & (1 << i)) {
-			v.val = i+1;
-			rc = hashtab_map(cladatum->permissions.table,
-					 perm_name, &v);
-			if (!rc && cladatum->comdatum) {
-				rc = hashtab_map(
-					cladatum->comdatum->permissions.table,
-					perm_name, &v);
-			}
-			if (rc)
-				perm = v.name;
-			if (perm) {
-				sprintf(p, " %s", perm);
-				p += strlen(p);
-			}
-		}
-	}
+	if (define_compute_type_helper(which, &avrule))
+		return COND_ERR;
 
-	return avbuf;
+	return avrule;
 }
 
 static int define_bool()
@@ -2242,7 +2042,7 @@
 	char *id, *name;
 	cond_bool_datum_t *datum;
 	int ret;
-
+	uint32_t value;
 
 	if (pass == 2) {
 		while ((id = queue_remove(id_queue)))
@@ -2262,10 +2062,20 @@
         }
 	name = id;
 
+        datum = hashtab_search(policydbp->p_bools.table, name);
+        if (datum) {
+                snprintf(errormsg, ERRORMSG_LEN, 
+                         "duplicate declaration for bool %s\n", id);
+                free(id);
+                yyerror(errormsg);
+                return -1;
+        }
+
 	id = (char *) queue_remove(id_queue);
 	if (!id) {
 		yyerror("no default value for bool definition?");
 		free(name);
+                /* FIX ME: allow this if in a module's require section */
 		return -1;
 	}
 
@@ -2278,213 +2088,74 @@
 	}
 	memset(datum, 0, sizeof(cond_bool_datum_t));
 	datum->state = (int)(id[0] == 'T') ? 1 : 0;
-	datum->value = ++policydbp->p_bools.nprim;
-
-	ret = hashtab_insert(policydbp->p_bools.table,
-			     (hashtab_key_t) name, (hashtab_datum_t) datum);
+        ret = symtab_insert(policydbp, SYM_BOOLS, name, datum, &value);
 
-	if (ret == HASHTAB_PRESENT) {
-		--policydbp->p_bools.nprim;
-		free(datum);
-		sprintf(errormsg, "name conflict for bool %s", id);
-		yyerror(errormsg);
-		free(id);
-		free(name);
-		return -1;
-	}
-	if (ret == HASHTAB_OVERFLOW) {
+	if (ret) {
 		yyerror("hash table overflow");
 		free(datum);
 		free(id);
 		free(name);
 		return -1;
 	}
+	datum->value = value;
+
 	return 0;
 }
 
-static cond_av_list_t *define_cond_pol_list( cond_av_list_t *avlist, cond_av_list_t *sl )
+static avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *sl)
 {
-	cond_av_list_t *end;
-
 	if (pass == 1) {
 		/* return something so we get through pass 1 */
-		return (cond_av_list_t *)1;
-	}
-
-	/* if we've started collecting sub lists, prepend to start of collection
-	   because it's probably less iterations than appending. */
-	if (!sl) return avlist;
-	else if (!avlist) return sl;
-	else {
-		end = sl;
-		while (end->next) end = end->next;
-		end->next = avlist;
-	} 
-	return sl;
-}
-
-static int te_avtab_helper(int which, unsigned int stype, unsigned int ttype, 
-			   ebitmap_t *tclasses, sepol_access_vector_t *avp)
-
-{
-	avtab_key_t avkey;
-	avtab_datum_t avdatum, *avdatump;
-	int ret;
-	unsigned int k;
-
-	if (which == -AVTAB_ALLOWED) {
-		yyerror("neverallow should not reach this function.");
-		return -1;
-	}
-
-	for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); k++) {
-		if (!ebitmap_get_bit(tclasses, k)) 
-			continue;
-		avkey.source_type = stype + 1;
-		avkey.target_type = ttype + 1;
-		avkey.target_class = k + 1;
-		avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_AV);
-		if (!avdatump) {
-			memset(&avdatum, 0, sizeof avdatum);
-			avdatum.specified = (which > 0) ? which : -which;
-			ret = avtab_insert(&policydbp->te_avtab, &avkey, &avdatum);
-			if (ret) {
-				yyerror("hash table overflow");
-				return -1;
-			}
-			avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_AV);
-			if (!avdatump) {
-				yyerror("inserted entry vanished!");
-				return -1;
-			}
-		}
-
-		avdatump->specified |= ((which > 0) ? which : -which);
-
-		switch (which) {
-		case AVTAB_ALLOWED:
-			avtab_allowed(avdatump) |= avp[k];
-			break;
-		case AVTAB_AUDITALLOW:
-			avtab_auditallow(avdatump) |= avp[k];
-			break;
-		case AVTAB_AUDITDENY:
-			avtab_auditdeny(avdatump) |= avp[k];
-			break;
-		case -AVTAB_AUDITDENY:
-			if (avtab_auditdeny(avdatump))
-				avtab_auditdeny(avdatump) &= ~avp[k];
-			else
-				avtab_auditdeny(avdatump) = ~avp[k];
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static  cond_av_list_t *cond_te_avtab_helper(int which, int stype, int ttype, 
-			   ebitmap_t *tclasses, sepol_access_vector_t *avp )
-
-{
-	cond_av_list_t *sl;
-	avtab_key_t avkey;
-	avtab_datum_t avdatum;
-	int  k;
-
-	if (which == -AVTAB_ALLOWED) {
-		yyerror("neverallow should not reach this function.");
-		return COND_ERR;
-	}
-
-	/* create sub_list to be passed back and appended to true or false list */
-	sl = (cond_av_list_t *) 0;
-
-	for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); k++) {
-		if (!ebitmap_get_bit(tclasses, k)) 
-			continue;
-		/* build the key */
-		avkey.source_type = stype + 1;
-		avkey.target_type = ttype + 1;
-		avkey.target_class = k + 1;
-		
-		/* build the datum */
-		memset(&avdatum, 0, sizeof avdatum);
-		avdatum.specified = (which > 0) ? which : -which;
-
-		switch (which) {
-		case AVTAB_ALLOWED:
-			avtab_allowed(&avdatum) = avp[k];
-			break;
-		case AVTAB_AUDITALLOW:
-			avtab_auditallow(&avdatum) = avp[k];
-			break;
-		case AVTAB_AUDITDENY:
-			yyerror("AUDITDENY statements are not allowed in a conditional block; use DONTAUDIT");
-			return COND_ERR;
-		case -AVTAB_AUDITDENY:
-			avtab_auditdeny(&avdatum) = ~avp[k];
-			break;
-		}
-
-		/* add to temporary list */
-		sl = cond_list_append(sl, &avkey, &avdatum);
-
-		if (sl == COND_ERR) {
-			yyerror("list overflow");
-			return COND_ERR;
-		}
+		return (avrule_t *)1;
 	}
 
+        /* prepend the new avlist to the pre-existing one */
+        sl->next = avlist;
 	return sl;
 }
 
-static cond_av_list_t *define_cond_te_avtab(int which)
+static int define_te_avtab_helper(int which, avrule_t **rule)
 {
 	char *id;
-	cond_av_list_t *sub_list, *final_list, *tail;
 	class_datum_t *cladatum;
-	perm_datum_t *perdatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
-	sepol_access_vector_t *avp;
-	int i, j, hiclass, self = 0, add = 1;
+	perm_datum_t *perdatum = NULL;
+	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
+	ebitmap_t tclasses;
+	avrule_t *avrule;
+	unsigned int i, hiclass;
+	int add = 1, ret = 0;
 	int suppress = 0;
 
-	if (pass == 1) {
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		return (cond_av_list_t *) 1; /* any non-NULL value */
+	avrule = (avrule_t*)malloc(sizeof(avrule_t));
+	if (!avrule) {
+		yyerror("memory error");
+		ret = -1;
+		goto out;
 	}
+	avrule_init(avrule);
+        avrule->specified = which;
+        avrule->line = policydb_lineno;
 
-	ebitmap_init(&stypes);
-	ebitmap_init(&ttypes);
-	ebitmap_init(&tclasses);
-
-	ebitmap_init(&negset);
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&stypes, &negset, id, &add))
-			return COND_ERR;
+		if (set_types(&avrule->stypes, id, &add)) {
+			ret = -1;
+			goto out;
 	}
-	ebitmap_destroy(&negset);
-
-	ebitmap_init(&negset);
+	}
+        add = 1;
 	while ((id = queue_remove(id_queue))) {
 		if (strcmp(id, "self") == 0) {
-			self = 1;
+			avrule->flags |= RULE_SELF;
 			continue;
 		}
-		if (set_types(&ttypes, &negset, id, &add))
-			return COND_ERR;
+		if (set_types(&avrule->ttypes, id, &add)) {
+			ret = -1;
+			goto out;
+		}
 	}
-	ebitmap_destroy(&negset);
 
 	hiclass = 0;
+	ebitmap_init(&tclasses);
 	while ((id = queue_remove(id_queue))) {
 		uint32_t classvalue;
 
@@ -2492,9 +2163,9 @@
 		if (!cladatum) 	{
 			sprintf(errormsg, "unknown class %s used in rule", id);
 			yyerror(errormsg);
-			goto bad;
+			ret = -1;
+			goto out;
 		}
-		
 		if (policyvers < POLICYDB_VERSION_NLCLASS &&
 		    (cladatum->value >= SECCLASS_NETLINK_ROUTE_SOCKET &&
 		     cladatum->value <= SECCLASS_NETLINK_DNRT_SOCKET)) {
@@ -2512,14 +2183,27 @@
 		free(id);
 	}
 
-	avp = malloc(hiclass * sizeof(sepol_access_vector_t));
-	if (!avp) {
+	perms = NULL;
+	for (i = ebitmap_startbit(&tclasses); i < ebitmap_length(&tclasses); i++) {
+		if (!ebitmap_get_bit(&tclasses, i))
+			continue;
+		cur_perms = (class_perm_node_t *)malloc(sizeof(class_perm_node_t));
+		if (!cur_perms) {
 		yyerror("out of memory");
-		return COND_ERR;
+			ret = -1;
+			goto out;
 	}
-	for (i = 0; i < hiclass; i++)
-		avp[i] = 0;
+		class_perm_node_init(cur_perms);
+		cur_perms->class = i + 1;
+		if (!perms)
+			perms = cur_perms;
+		if (tail)
+			tail->next = cur_perms;
+		tail = cur_perms;
+	}
+
 	while ((id = queue_remove(id_queue))) {
+		cur_perms = perms;
 		for (i = ebitmap_startbit(&tclasses); i < ebitmap_length(&tclasses); i++) {
 			if (!ebitmap_get_bit(&tclasses, i)) 
 				continue;
@@ -2527,20 +2211,19 @@
 
 			if (strcmp(id, "*") == 0) {
 				/* set all permissions in the class */
-				avp[i] = ~0;
-				continue;
+				cur_perms->data = ~0U;
+				goto next;
 			}
 
 			if (strcmp(id, "~") == 0) {
 				/* complement the set */
-				if (which == -AVTAB_AUDITDENY) 
+				if (which == AVRULE_DONTAUDIT) 
 					yywarn("dontaudit rule with a ~?");
-				avp[i] = ~avp[i];
-				continue;
+				cur_perms->data = ~cur_perms->data;
+				goto next;
 			}
 
-			perdatum = hashtab_search(cladatum->permissions.table,
-						  id);
+			perdatum = hashtab_search(cladatum->permissions.table, id);
 			if (!perdatum) {
 				if (cladatum->comdatum) {
 					perdatum = hashtab_search(cladatum->comdatum->permissions.table,
@@ -2552,272 +2235,116 @@
 				if (!suppress)
 				  yyerror(errormsg);
 				continue;
-			}
-
-			avp[i] |= (1 << (perdatum->value - 1));
-		}
-
-		free(id);
-	}
-
-	sub_list = NULL;
-	tail = NULL;
-	final_list = NULL;
-
-	if (self) {
-		for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
-			if (!ebitmap_get_bit(&stypes, i)) 
-				continue;
-			if (self) {
-				if ((sub_list = cond_te_avtab_helper(which, i, i, &tclasses, avp )) == COND_ERR)
-					return COND_ERR;
-				if (final_list) {
-					tail->next = sub_list;
-					while (tail->next != NULL)
-						tail = tail->next;
 				} else {
-					final_list = sub_list;
-					tail = final_list;
-					while (tail->next != NULL)
-						tail = tail->next;
-				}
-			}
-		}
-	}
-	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
-		if (!ebitmap_get_bit(&stypes, i)) 
-			continue;
-		for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) {
-			if (!ebitmap_get_bit(&ttypes, j)) 
-				continue;
-			if ((sub_list = cond_te_avtab_helper(which, i, j, &tclasses, avp)) == COND_ERR)
-				return COND_ERR;
-			if (final_list) {
-				tail->next = sub_list;
-				while (tail->next != NULL)
-					tail = tail->next;
-			} else {
-				final_list = sub_list;
-				tail = final_list;
-				while (tail->next != NULL)
-					tail = tail->next;
+                                cur_perms->data |= 1U << (perdatum->value - 1);
 			}
+next:
+                        cur_perms = cur_perms->next;
 		}
+		free(id);
 	}
 
-	ebitmap_destroy(&stypes);
-	ebitmap_destroy(&ttypes);
-	ebitmap_destroy(&tclasses);
-	free(avp);
+        avrule->perms = perms;
+        *rule = avrule;
 	
-	return final_list;
- bad:
-	return COND_ERR;
+out:
+	return ret;
 }
 
-
-static int define_te_avtab(int which)
+static avrule_t *define_cond_te_avtab(int which)
 {
 	char *id;
-	class_datum_t *cladatum;
-	perm_datum_t *perdatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
-	sepol_access_vector_t *avp;
-	unsigned int i, j, hiclass;
-	int self = 0, add = 1;
-	te_assert_t *newassert;
-	int suppress = 0;
+	avrule_t *avrule;
+	int i;
 
 	if (pass == 1) {
+		for (i = 0; i < 4; i++) {
 		while ((id = queue_remove(id_queue))) 
 			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		while ((id = queue_remove(id_queue))) 
-			free(id);
-		return 0;
 	}
-
-	ebitmap_init(&stypes);
-	ebitmap_init(&ttypes);
-	ebitmap_init(&tclasses);
-
-	ebitmap_init(&negset);
-	while ((id = queue_remove(id_queue))) {
-		if (set_types(&stypes, &negset, id, &add))
-			return -1;
-	}
-	ebitmap_destroy(&negset);
-
-	ebitmap_init(&negset);
-	while ((id = queue_remove(id_queue))) {
-		if (strcmp(id, "self") == 0) {
-			self = 1;
-			continue;
-		}
-		if (set_types(&ttypes, &negset, id, &add))
-			return -1;
+		return (avrule_t *) 1; /* any non-NULL value */
 	}
-	ebitmap_destroy(&negset);
 
-	hiclass = 0;
-	while ((id = queue_remove(id_queue))) {
-		uint32_t classvalue;
+	if (define_te_avtab_helper(which, &avrule))
+		return COND_ERR;
 
-		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!cladatum) {
-			sprintf(errormsg, "unknown class %s used in rule", id);
-			yyerror(errormsg);
-			goto bad;
-		}
+	return avrule;
+}
 		
-		if (policyvers < POLICYDB_VERSION_NLCLASS &&
-		    (cladatum->value >= SECCLASS_NETLINK_ROUTE_SOCKET &&
-		     cladatum->value <= SECCLASS_NETLINK_DNRT_SOCKET)) {
-			sprintf(errormsg, "remapping class %s to netlink_socket "
-			        "for policy version %d", id, policyvers);
-			yywarn(errormsg);
-			classvalue = SECCLASS_NETLINK_SOCKET;
-			suppress = 1;
-		} else
-			classvalue = cladatum->value;
+static int define_te_avtab(int which)
+{
+	char *id;
+	avrule_t *avrule;
+	int i;
 				
-		ebitmap_set_bit(&tclasses, classvalue - 1, TRUE);	
-		if (classvalue > hiclass)
-			hiclass = classvalue;
+	if (pass == 1) {
+		for (i = 0; i < 4; i++) {
+			while ((id = queue_remove(id_queue))) 
 		free(id);
 	}
-
-	avp = malloc(hiclass * sizeof(sepol_access_vector_t));
-	if (!avp) {
-		yyerror("out of memory");
-		return -1;
-	}
-	for (i = 0; i < hiclass; i++)
-		avp[i] = 0;
-
-	while ((id = queue_remove(id_queue))) {
-		for (i = ebitmap_startbit(&tclasses); i < ebitmap_length(&tclasses); i++) {
-			if (!ebitmap_get_bit(&tclasses, i)) 
-				continue;
-			cladatum = policydbp->class_val_to_struct[i];
-
-			if (strcmp(id, "*") == 0) {
-				/* set all permissions in the class */
-				avp[i] = ~0U;
-				continue;
+		return 0;
 			}
 
-			if (strcmp(id, "~") == 0) {
-				/* complement the set */
-				if (which == -AVTAB_AUDITDENY) 
-					yywarn("dontaudit rule with a ~?");
-				avp[i] = ~avp[i];
-				continue;
-			}
+	if (define_te_avtab_helper(which, &avrule))
+		return -1;
 
-			perdatum = hashtab_search(cladatum->permissions.table,
-						  id);
-			if (!perdatum) {
-				if (cladatum->comdatum) {
-					perdatum = hashtab_search(cladatum->comdatum->permissions.table,
-								  id);
-				}
-			}
-			if (!perdatum) {
-				sprintf(errormsg, "permission %s is not defined for class %s", id, policydbp->p_class_val_to_name[i]);
-				if (!suppress)
-				  yyerror(errormsg);
-				continue;
+        /* append this avrule to the end of the rules list */
+        if (last_avrule == NULL) {
+                policydbp->avrules = last_avrule = avrule;
 			}
-
-			avp[i] |= (1 << (perdatum->value - 1));
+        else {
+                last_avrule->next = avrule;
+                last_avrule = avrule;
 		}
+	return 0;
+}
 
-		free(id);
-	}
+static int define_role(char *id)
+{
+	role_datum_t *role;
+	uint32_t value;
+	int ret;
 
-	if (which == -AVTAB_ALLOWED) {
-		newassert = malloc(sizeof(te_assert_t));
-		if (!newassert) {
+	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
+					       id);
+	if (!role) {
+		role = (role_datum_t *) malloc(sizeof(role_datum_t));
+		if (!role) {
 			yyerror("out of memory");
+			free(id);
 			return -1;
 		}
-		memset(newassert, 0, sizeof(te_assert_t));
-		newassert->stypes = stypes;
-		newassert->ttypes = ttypes;
-		newassert->tclasses = tclasses;
-		newassert->self = self;
-		newassert->avp = avp;
-		newassert->line = policydb_lineno;
-		newassert->next = te_assertions;
-		te_assertions = newassert;
-		return 0;
-	}
-
-	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
-		if (!ebitmap_get_bit(&stypes, i)) 
-			continue;
-		if (self) {
-			if (te_avtab_helper(which, i, i, &tclasses, avp))
-				return -1;
-		}
-		for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) {
-			if (!ebitmap_get_bit(&ttypes, j)) 
-				continue;
-			if (te_avtab_helper(which, i, j, &tclasses, avp))
-				return -1;
-		}
-	}
+		role_datum_init(role);
 
-	ebitmap_destroy(&stypes);
-	ebitmap_destroy(&ttypes);
-	ebitmap_destroy(&tclasses);
-	free(avp);
+		ret = symtab_insert(policydbp, SYM_ROLES, id, (hashtab_datum_t*)role, &value);
 
-	return 0;
- bad:
+		if (ret) {
+			yyerror("hash table overflow");
+			free(role);
 	return -1;
-}
-
-
-static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p)
-{
-	struct val_to_name *v = p;
-	role_datum_t *roldatum;
-
-	roldatum = (role_datum_t *) datum;
-
-	if (v->val == roldatum->value) {
-		v->name = key;
-		return 1;
 	}
 
+		role->value = value;
+		ebitmap_set_bit(&role->dominates, value - 1, TRUE);
+        }
 	return 0;
 }
 
-
-static char *role_val_to_name(unsigned int val) 
+/* FIX ME: to be used by module requires */
+#if 0
+static int define_role_require(void)
 {
-	struct val_to_name v;
-	int rc;
-
-	v.val = val;
-	rc = hashtab_map(policydbp->p_roles.table, 
-			 role_val_to_name_helper, &v);
-	if (rc)
-		return v.name;
-	return NULL;
+        char *id = queue_remove(id_queue);
+        int retval = define_role(id);
+        return retval;
 }
+#endif
 
 static int define_role_types(void)
 {
 	role_datum_t *role;
-	char *role_id, *id;
-	int ret, add = 1;
-	ebitmap_t negset;
+	char *id;
+	int add = 1;
 
 	if (pass == 1) {
 		while ((id = queue_remove(id_queue))) 
@@ -2825,43 +2352,19 @@
 		return 0;
 	}
 
-	role_id = queue_remove(id_queue);
-
-	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
-					       role_id);
-	if (!role) {
-		role = (role_datum_t *) malloc(sizeof(role_datum_t));
-		if (!role) {
-			yyerror("out of memory");
-			free(role_id);
-			return -1;
-		}
-		memset(role, 0, sizeof(role_datum_t));
-		role->value = ++policydbp->p_roles.nprim;
-		ebitmap_set_bit(&role->dominates, role->value-1, TRUE);
-		ret = hashtab_insert(policydbp->p_roles.table,
-				     (hashtab_key_t) role_id, (hashtab_datum_t) role);
-
-		if (ret) {
-			yyerror("hash table overflow");
-			free(role);
-			free(role_id);
+	id = queue_remove(id_queue);
+        if (define_role(id))
 			return -1;
-		}
-	} else
-		free(role_id);
-
-	ebitmap_init(&negset);
+	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
+					       id);
+        assert(role);
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&role->types, &negset, id, &add))
+                if (set_types(&role->types, id,&add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
-
 	return 0;
 }
 
-
 static role_datum_t *
  merge_roles_dom(role_datum_t * r1, role_datum_t * r2)
 {
@@ -2882,20 +2385,20 @@
 		yyerror("out of memory");
 		return NULL;
 	}
-	if (ebitmap_or(&new->types, &r1->types, &r2->types)) {
+	if (ebitmap_or(&new->types.types, &r1->types.types, &r2->types.types)) {
 		yyerror("out of memory");
 		return NULL;
 	}
 	if (!r1->value) {
 		/* free intermediate result */
-		ebitmap_destroy(&r1->types);
+		type_set_destroy(&r1->types);
 		ebitmap_destroy(&r1->dominates);
 		free(r1);
 	}
 	if (!r2->value) {
 		/* free intermediate result */
 		yyerror("right hand role is temporary?");
-		ebitmap_destroy(&r2->types);
+		type_set_destroy(&r2->types);
 		ebitmap_destroy(&r2->dominates);
 		free(r2);
 	}
@@ -2907,6 +2410,7 @@
 {
 	role_datum_t *rdp = (role_datum_t *) arg;
 	role_datum_t *rdatum = (role_datum_t *) datum;
+	ebitmap_t *types = NULL;
 	int i;
 
 	/* Don't bother to process against self role */
@@ -2916,6 +2420,8 @@
 	/* If a dominating role found */
 	if (ebitmap_get_bit(&(rdatum->dominates), rdp->value - 1))
 	{
+		if (type_set_expand(&rdp->types, types, policydbp)) 
+			return -1;
 		/* raise types and dominates from dominated role */
 		for (i = ebitmap_startbit(&rdp->dominates); 
 			i < ebitmap_length(&rdp->dominates); i++) 
@@ -2923,11 +2429,11 @@
 			if (ebitmap_get_bit(&rdp->dominates, i))
 				ebitmap_set_bit(&rdatum->dominates, i, TRUE);
 		}
-		for (i = ebitmap_startbit(&rdp->types); 
-			i < ebitmap_length(&rdp->types); i++)	
+		for (i = ebitmap_startbit(types); 
+			i < ebitmap_length(types); i++)	
 		{
-			if (ebitmap_get_bit(&rdp->types, i))
-				ebitmap_set_bit(&rdatum->types, i, TRUE);
+			if (ebitmap_get_bit(types, i))
+				ebitmap_set_bit(&rdatum->types.types, i, TRUE);
 		}		
 	}
 
@@ -2940,6 +2446,7 @@
 {
 	role_datum_t *role;
 	char *role_id;
+	ebitmap_t *types = NULL;
 	unsigned int i;
 	int ret;
 
@@ -2977,13 +2484,15 @@
 			if (ebitmap_get_bit(&r->dominates, i))
 				ebitmap_set_bit(&role->dominates, i, TRUE);
 		}
-		for (i = ebitmap_startbit(&r->types); i < ebitmap_length(&r->types); i++)	{
-			if (ebitmap_get_bit(&r->types, i))
-				ebitmap_set_bit(&role->types, i, TRUE);
+		if (type_set_expand(&r->types, types, policydbp)) 
+			return NULL;
+		for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++)	{
+			if (ebitmap_get_bit(types, i))
+				ebitmap_set_bit(&role->types.types, i, TRUE);
 		}
 		if (!r->value) {
 			/* free intermediate result */
-			ebitmap_destroy(&r->types);
+			type_set_destroy(&r->types);
 			ebitmap_destroy(&r->dominates);
 			free(r);
 		}
@@ -2997,29 +2506,21 @@
 	return role;
 }
 
-
-static int set_roles(ebitmap_t *set,
+static int set_roles(role_set_t *set,
 		     char *id)
 {
 	role_datum_t *r;
-	unsigned int i;
 
 	if (strcmp(id, "*") == 0) {
 		/* set all roles */
-		for (i = 0; i < policydbp->p_roles.nprim; i++) 
-			ebitmap_set_bit(set, i, TRUE);
+		set->flags = ROLE_STAR;
 		free(id);
 		return 0;
 	}
 
 	if (strcmp(id, "~") == 0) {
 		/* complement the set */
-		for (i = 0; i < policydbp->p_roles.nprim; i++) {
-			if (ebitmap_get_bit(set, i))
-				ebitmap_set_bit(set, i, FALSE);
-			else 
-				ebitmap_set_bit(set, i, TRUE);
-		}
+		set->flags = ROLE_COMP;
 		free(id);
 		return 0;
 	}
@@ -3032,19 +2533,20 @@
 		return -1;
 	}
 
-	/* set one role */
-	ebitmap_set_bit(set, r->value - 1, TRUE);
+        ebitmap_set_bit(&set->roles, r->value - 1, TRUE);
 	free(id);
 	return 0;
 }
 
-
 static int define_role_trans(void)
 {
 	char *id;
 	role_datum_t *role;
-	ebitmap_t roles, types, negset;
-	struct role_trans *tr = 0;
+	role_set_t roles;
+	type_set_t types;
+	ebitmap_t e_types, e_roles;
+	struct role_trans *tr = NULL;
+	struct role_trans_rule *rule = NULL;
 	unsigned int i, j;
 	int add = 1;
 
@@ -3058,20 +2560,20 @@
 		return 0;
 	}
 
-	ebitmap_init(&roles);
-	ebitmap_init(&types);
+	role_set_init(&roles);
+	ebitmap_init(&e_roles);
+	type_set_init(&types);
+	ebitmap_init(&e_types);
 
 	while ((id = queue_remove(id_queue))) {
 		if (set_roles(&roles, id))
 			return -1;
 	}
-
-	ebitmap_init(&negset);
+        add = 1;
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&types, &negset, id, &add))
+		if (set_types(&types, id, &add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
 
 	id = (char *) queue_remove(id_queue);
 	if (!id) {
@@ -3085,17 +2587,24 @@
 		goto bad;
 	}
 
-	for (i = ebitmap_startbit(&roles); i < ebitmap_length(&roles); i++) {
-		if (!ebitmap_get_bit(&roles, i)) 
+	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
+	if (role_set_expand(&roles, &e_roles, policydbp))
+		goto bad;
+		
+	if (type_set_expand(&types, &e_types, policydbp))
+		goto bad;
+
+	for (i = ebitmap_startbit(&e_roles); i < ebitmap_length(&e_roles); i++) {
+		if (!ebitmap_get_bit(&e_roles, i)) 
 			continue;
-		for (j = ebitmap_startbit(&types); j < ebitmap_length(&types); j++) {
-			if (!ebitmap_get_bit(&types, j)) 
+		for (j = ebitmap_startbit(&e_types); j < ebitmap_length(&e_types); j++) {
+			if (!ebitmap_get_bit(&e_types, j))
 				continue;
 
 			for (tr = policydbp->role_tr; tr; tr = tr->next) {
 				if (tr->role == (i+1) && tr->type == (j+1)) {
 					sprintf(errormsg, "duplicate role transition defined for (%s,%s)", 
-						role_val_to_name(i+1), type_val_to_name(j+1));
+						policydbp->p_role_val_to_name[i], policydbp->p_type_val_to_name[j]);
 					yyerror(errormsg);
 					goto bad;
 				}
@@ -3112,8 +2621,26 @@
 			tr->new_role = role->value;
 			tr->next = policydbp->role_tr;
 			policydbp->role_tr = tr;
+
+		}
 		}
+
+	/* Now add the real rule */
+	rule = malloc(sizeof(struct role_trans_rule));
+	if (!rule) {
+		yyerror("out of memory");
+		return -1;
 	}
+	memset(rule, 0, sizeof(struct role_trans_rule));
+	rule->roles = roles;
+	rule->types = types;
+	rule->new_role = role->value;
+			
+        rule->next = policydbp->role_tr_rules;
+        policydbp->role_tr_rules = rule;
+
+	ebitmap_destroy(&e_roles);
+	ebitmap_destroy(&e_types);
 
 	return 0;
 
@@ -3121,13 +2648,10 @@
 	return -1;
 }
 
-
 static int define_role_allow(void)
 {
 	char *id;
-	ebitmap_t roles, new_roles;
-	struct role_allow *ra = 0;
-	unsigned int i, j;
+	struct role_allow_rule *ra = 0;
 
 	if (pass == 1) {
 		while ((id = queue_remove(id_queue))) 
@@ -3137,47 +2661,25 @@
 		return 0;
 	}
 
-	ebitmap_init(&roles);
-	ebitmap_init(&new_roles);
-
-	while ((id = queue_remove(id_queue))) {
-		if (set_roles(&roles, id))
+	ra = malloc(sizeof(role_allow_rule_t));
+	if (!ra) {
+		yyerror("out of memory");
 			return -1;
 	}
-
+	role_allow_rule_init(ra);
 
 	while ((id = queue_remove(id_queue))) {
-		if (set_roles(&new_roles, id))
+		if (set_roles(&ra->roles, id))
 			return -1;
 	}
 
-	for (i = ebitmap_startbit(&roles); i < ebitmap_length(&roles); i++) {
-		if (!ebitmap_get_bit(&roles, i)) 
-			continue;
-		for (j = ebitmap_startbit(&new_roles); j < ebitmap_length(&new_roles); j++) {
-			if (!ebitmap_get_bit(&new_roles, j)) 
-				continue;
-
-			for (ra = policydbp->role_allow; ra; ra = ra->next) {
-				if (ra->role == (i+1) && ra->new_role == (j+1))
-					break;
-			}
-
-			if (ra) 
-				continue;
-
-			ra = malloc(sizeof(struct role_allow));
-			if (!ra) {
-				yyerror("out of memory");
+	while ((id = queue_remove(id_queue))) {
+		if (set_roles(&ra->new_roles, id))
 				return -1;
 			}
-			memset(ra, 0, sizeof(struct role_allow));
-			ra->role = i+1;
-			ra->new_role = j+1;
-			ra->next = policydbp->role_allow;
-			policydbp->role_allow = ra;
-		}
-	}
+
+        ra->next = policydbp->role_allow_rules;
+        policydbp->role_allow_rules = ra;
 
 	return 0;
 }
@@ -3399,10 +2901,10 @@
 	struct constraint_expr *expr, *e1 = NULL, *e2;
 	user_datum_t *user;
 	role_datum_t *role;
+        type_datum_t *type;
 	ebitmap_t negset;
 	char *id;
 	uint32_t val;
-	int add = 1;
 
 	if (pass == 1) {
 		if (expr_type == CEXPR_NAMES) {
@@ -3493,11 +2995,15 @@
 				}
 				val = role->value;
 			} else if (expr->attr & CEXPR_TYPE) {
-				if (set_types(&expr->names, &negset, id, &add)) {
+				type = (type_datum_t *) hashtab_search(policydbp->p_types.table,
+									(hashtab_key_t) id);
+				if (!type) {
+					sprintf(errormsg, "unknown type %s", id);
+					yyerror(errormsg);
 					free(expr);
 					return 0;
 				}
-				continue;
+                                val = type->value;
 			} else {
 				yyerror("invalid constraint expression");
 				free(expr);
@@ -3524,12 +3030,12 @@
 	return 0;
 }
 
-static int define_conditional(cond_expr_t *expr, cond_av_list_t *t, cond_av_list_t *f )
+static int define_conditional(cond_expr_t *expr, avrule_t *t, avrule_t *f )
 {
 	cond_expr_t *e;
-	cond_node_t *cn, tmp, *cn_new;
-	int depth;
-
+	int depth, retval;
+        cond_node_t cn, *cn_old;
+        avrule_t *tmp, *last_tmp;
 
 	/* expression cannot be NULL */
 	if ( !expr) {
@@ -3590,169 +3096,128 @@
 	}
 
         /*  use tmp conditional node to partially build new node */
-	cn = &tmp;
-	cn->expr = expr;
-	cn->true_list = t;
-	cn->false_list = f;
+        memset(&cn, 0, sizeof(cn));
+        cn.expr = expr;
+        cn.avtrue_list = t;
+        cn.avfalse_list = f;
       
 	/* normalize/precompute expression */
-	if (cond_normalize_expr(policydbp, cn) < 0) {
+	if (cond_normalize_expr(policydbp, &cn) < 0) {
 		yyerror("problem normalizing conditional expression");
 		return -1;
 	}
 
 	/* get the existing conditional node, or a new one*/
-	cn_new = cond_node_search(policydbp, cn);
-	if(cn_new) {
-		cond_reduce_insert_list (cn->true_list, &cn_new->true_list, &cn_new->false_list, cn_new->cur_state);
-		cond_reduce_insert_list (cn->false_list, &cn_new->false_list, &cn_new->true_list, !cn_new->cur_state);
-	} else { 
-		yyerror("could not get a conditional node");
+        cn_old = cond_node_search(policydbp, policydbp->cond_list, &cn);
+        if (!cn_old) {
 		return -1;
 	}
 
-
-	return 0;
-}
-
-
-/*  Set the ENABLE bit and parse_context for each rule and check rules to see if they already exist.
- * Insert rules into the conditional db when appropriate.
- *  
- * new - list of rules to potentially add/insert
- * active - list to add rule to, and address to use as parse_context
- * inactive - opposite rule list in same conditional
- * state - whether rules in new are on or off by default.
- *
- * There are 4 possible conditions for a TYPE_* rule.  Allow rules are always inserted or
- * OR'd with existing allow rules on the same side of the same conditional.
- *
- * 1) Not present anywhere -> add it
- * 2) Already in cond, same side -> warn, replace default in prev rule, delete this rule
- * 3) Just added to opp side -> search again (we may still add this rule)
- * 4) In another conditional (either side) -> warn, delete this rule
- */
-static void cond_reduce_insert_list(cond_av_list_t *new, cond_av_list_t **active, cond_av_list_t **inactive, int state)
-{
-	int add_rule = 1;
-	cond_av_list_t *c, *top;
-	avtab_ptr_t dup;
-	uint32_t old_data = 0, new_data = 0;
-
-	top = c = new; 
-	/* loop through all the rules in the list */
-	while(c) {
-
-                /* is conditional rule a TYPE_* rule that's already in a conditional? */
-                /* [note that we checked to see if it's in the base when we parsed the rule] */
-		if ((c->node->datum.specified & AVTAB_TYPE) &&
-		    ((dup = avtab_search_node(&policydbp->te_cond_avtab, &c->node->key, c->node->datum.specified & AVTAB_TYPE)) != NULL) ){
-			do {
-				/* is the rule we found in the current rule list or the equivalent */
-				if (dup->parse_context == active) {
-					/* change original default */
-					switch(c->node->datum.specified & AVTAB_TYPE) {
-					case AVTAB_TRANSITION:
-						old_data = avtab_transition(&dup->datum);
-						new_data = avtab_transition(&c->node->datum);
-						avtab_transition(&dup->datum) = new_data;
-						break;
-					case AVTAB_MEMBER:
-						old_data = avtab_member(&dup->datum);
-						new_data = avtab_member(&c->node->datum);
-						avtab_member(&dup->datum) = new_data;
-						break;
-					case AVTAB_CHANGE:
-						old_data = avtab_change(&dup->datum);
-						new_data = avtab_change(&c->node->datum);
-						avtab_change(&dup->datum) = new_data;
+        /* verify te rules */
+	tmp = cn.avtrue_list;
+        last_tmp = NULL;
+	while (tmp) {
+		if (!tmp->specified & AVRULE_TRANSITION)
+			continue;
+		retval = insert_check_type_rule(tmp,
+                                                &policydbp->te_cond_avtab,
+                                                &cn_old->true_list, &cn_old->false_list);
+                switch (retval) {
+                case 1: {
+                        last_tmp = tmp;
+                        tmp = tmp->next;
 						break;
 					}
-					sprintf(errormsg, "duplicate type rule on same side of conditional for (%s, %s:%s); overwrote original default %s with %s",
-						type_val_to_name(c->node->key.source_type), 
-						type_val_to_name(c->node->key.target_type), 
-						policydbp->p_class_val_to_name[c->node->key.target_class],
-						type_val_to_name(old_data),
-						type_val_to_name(new_data));					
-					yywarn(errormsg);
-					add_rule = 0;
-					break;
+                case 0: {
+                        /* rule conflicted, so remove it from consideration */
+                        if (last_tmp == NULL) {
+                                cn.avtrue_list = cn.avtrue_list->next;
+                                avrule_destroy(tmp);
+                                tmp = cn.avtrue_list;
+                        }
+                        else {
+                                last_tmp->next = tmp->next;
+                                avrule_destroy(tmp);
+                                tmp = last_tmp->next;
 				}
-				/* if the rule we found is in the opposite rule list that's OK*/
-				if (dup->parse_context == inactive) {
-					continue;
-				} else {
-					/* the rule we found must be in another conditional */
-					sprintf(errormsg, "discarding conflicting conditional type rule for (%s, %s:%s); may only be in one conditional",
-						type_val_to_name(c->node->key.source_type), 
-						type_val_to_name(c->node->key.target_type), 
-						policydbp->p_class_val_to_name[c->node->key.target_class]);
-					yywarn(errormsg);
-					add_rule = 0;
 					break;
 				}
-			} while ( (dup = avtab_search_node_next(dup, c->node->datum.specified & AVTAB_TYPE)) != NULL);
+                case -1: {
+                        return -1;
+                }
+                default: {
+                        assert(0);  /* should never get here */
+                }
+                }
+	}
 
-		} /* end dealing with TYPE_* rules */
-		else if ( (c->node->datum.specified & AVTAB_AV ) &&
-		     ((dup = avtab_search_node(&policydbp->te_cond_avtab, &c->node->key, c->node->datum.specified & AVTAB_AV)) != NULL) ){
-			do {
-				/* we only care if the same AV rule is on the same side of the same conditional */
-				if (dup->parse_context == active) {
-					/* add to original */
-					switch(c->node->datum.specified & AVTAB_AV) {
-					case AVTAB_ALLOWED:
-						new_data = avtab_allowed(&c->node->datum);
-						avtab_allowed(&dup->datum) |= new_data;
-						break;
-					case AVTAB_AUDITALLOW:
-						new_data = avtab_auditallow(&c->node->datum);
-						avtab_auditallow(&dup->datum) |= new_data;
-						break;
-					case AVTAB_AUDITDENY:
-						new_data = avtab_auditdeny(&c->node->datum);
-						/* Since a '0' in an auditdeny mask represents a 
-						 * permission we do NOT want to audit (dontaudit), we use
-						 * the '&' operand to ensure that all '0's in the mask
-						 * are retained (much unlike the allow and auditallow cases).
-						 */
-						avtab_auditdeny(&dup->datum) &= new_data;
+	tmp = cn.avfalse_list;
+        last_tmp = NULL;
+	while (tmp) {
+		if (!tmp->specified & AVRULE_TRANSITION)
+			continue;
+		retval = insert_check_type_rule(tmp,
+                                                &policydbp->te_cond_avtab,
+                                                &cn_old->false_list, &cn_old->true_list);
+                switch (retval) {
+                case 1: {
+                        last_tmp = tmp;
+                        tmp = tmp->next;
 						break;
 					}
-					add_rule = 0;
+                case 0: {
+                        /* rule conflicted, so remove it from consideration  */
+                        if (last_tmp == NULL) {
+                                cn.avfalse_list = cn.avfalse_list->next;
+                                avrule_destroy(tmp);
+                                tmp = cn.avfalse_list;
+                        }
+                        else {
+                                last_tmp->next = tmp->next;
+                                avrule_destroy(tmp);
+                                tmp = last_tmp->next;
+                        }
 					break;
 				}
-			} while ( (dup = avtab_search_node_next(dup, c->node->datum.specified & AVTAB_AV)) != NULL);
-		} /* end dealing with ALLOW rules */
+                case -1: {
+                        return -1;
+                }
+                default: {
+                        assert(0);  /* should never get here */
+                }
+                }
+	}
 
-		top = c->next;
-		/* Either insert the rule into the policy and active list, or discard the rule */
-		if (add_rule) {
-			c->node = avtab_insert_with_parse_context(&policydbp->te_cond_avtab, 
-								  &c->node->key,
-								  &c->node->datum,
-								  active);
-			/* set whether the rule is enabled/disabled */
-			if (state) {
-				c->node->datum.specified |= AVTAB_ENABLED;
-			} else {
-				c->node->datum.specified &= ~AVTAB_ENABLED;
+        /* append the new conditional node to the existing ones.
+         * during expansion the list will be reversed -- i.e., the
+         * last AV rule will be the first one listed in the policy.
+         * this matches the behavior of the upstream compiler. */
+        if (cn_old->avtrue_list == NULL) {
+                cn_old->avtrue_list = cn.avtrue_list;
+        }
+        else {
+                for (tmp = cn_old->avtrue_list; tmp->next != NULL; tmp = tmp->next)
+                        ;
+                tmp->next = cn.avtrue_list;
+        }
+        if (cn_old->avfalse_list == NULL) {
+                cn_old->avfalse_list = cn.avfalse_list;
+        }
+        else {
+                for (tmp = cn_old->avfalse_list; tmp->next != NULL; tmp = tmp->next)
+                        ;
+                tmp->next = cn.avfalse_list;
 			}
 
-			/* prepend new rule to active list */
- 			c->next = *active; 
- 			*active = c; 
-		} else {
-			/* discard rule */
-			free(c->node);
-			free(c);
+        /* note that there is no check here for duplicate rules, nor
+         * check that rule already exists in base -- that will be
+         * handled during conditional expansion, in expand.c */
 			
-			add_rule = 1;
-		}
-                /* next rule */
-		c = top;
+	cn.avtrue_list = NULL;
+	cn.avfalse_list = NULL;
+	cond_node_destroy(&cn);
 		
-	} /* while */
+	return 0;
 }
 
 static cond_expr_t *
@@ -3855,7 +3320,7 @@
 }
 

-static int set_user_roles(ebitmap_t *set,
+static int set_user_roles(role_set_t *set,
 			  char *id)
 {
 	role_datum_t *r;
@@ -3863,20 +3328,14 @@
 
 	if (strcmp(id, "*") == 0) {
 		/* set all roles */
-		for (i = 0; i < policydbp->p_roles.nprim; i++) 
-			ebitmap_set_bit(set, i, TRUE);
+		set->flags = ROLE_STAR;
 		free(id);
 		return 0;
 	}
 
 	if (strcmp(id, "~") == 0) {
 		/* complement the set */
-		for (i = 0; i < policydbp->p_roles.nprim; i++) {
-			if (ebitmap_get_bit(set, i))
-				ebitmap_set_bit(set, i, FALSE);
-			else 
-				ebitmap_set_bit(set, i, TRUE);
-		}
+		set->flags = ROLE_COMP;
 		free(id);
 		return 0;
 	}
@@ -3892,7 +3351,7 @@
 	/* set the role and every role it dominates */
 	for (i = ebitmap_startbit(&r->dominates); i < ebitmap_length(&r->dominates); i++) {
 		if (ebitmap_get_bit(&r->dominates, i))
-			ebitmap_set_bit(set, i, TRUE);
+			ebitmap_set_bit(&set->roles, i, TRUE);
 	}
 	free(id);
 	return 0;
@@ -3967,6 +3426,7 @@
 	int ret;
 	level_datum_t *levdatum;
 	int l;
+	uint32_t value;
 
 	if (pass == 1) {
 		while ((id = queue_remove(id_queue))) 
@@ -4002,17 +3462,15 @@
 			free(id);
 			return -1;
 		}
-		memset(usrdatum, 0, sizeof(user_datum_t));
-		usrdatum->value = ++policydbp->p_users.nprim;
-		ebitmap_init(&usrdatum->roles);
-		ret = hashtab_insert(policydbp->p_users.table,
-				     (hashtab_key_t) id, (hashtab_datum_t) usrdatum);
+                user_datum_init(usrdatum);
+                ret = symtab_insert(policydbp, SYM_USERS, id, (hashtab_datum_t*)usrdatum, &value);
 		if (ret) {
 			yyerror("hash table overflow");
 			free(usrdatum);
 			free(id);
 			return -1;
 		}
+		usrdatum->value = value;
 	} else
 		free(id);
 
@@ -4806,7 +4264,7 @@
 	char *id;
 	level_datum_t *levdatum = 0;
 	mls_range_t range;
-	ebitmap_t doms, types, negset;
+	type_set_t doms, types;
 	range_trans_t *rt = 0;
 	unsigned int i, j;
 	int l, add = 1;
@@ -4834,22 +4292,18 @@
 		return 0;
 	}
 
-	ebitmap_init(&doms);
-	ebitmap_init(&types);
+	type_set_init(&doms);
+	type_set_init(&types);
 
-	ebitmap_init(&negset);
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&doms, &negset, id, &add))
+		if (set_types(&doms, id, &add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
-
-	ebitmap_init(&negset);
+        add = 1;
 	while ((id = queue_remove(id_queue))) {
-		if (set_types(&types, &negset, id, &add))
+		if (set_types(&types, id, &add))
 			return -1;
 	}
-	ebitmap_destroy(&negset);
 
 	id = (char *)queue_remove(id_queue);
 	if (!id) {
@@ -4895,17 +4349,18 @@
 		return -1;
 	}
 
-	for (i = ebitmap_startbit(&doms); i < ebitmap_length(&doms); i++) {
-		if (!ebitmap_get_bit(&doms, i))
+	for (i = ebitmap_startbit(&doms.types); i < ebitmap_length(&doms.types); i++) {
+		if (!ebitmap_get_bit(&doms.types, i))
 			continue;
-		for (j = ebitmap_startbit(&types); j < ebitmap_length(&types); j++) {
-			if (!ebitmap_get_bit(&types, j))
+		for (j = ebitmap_startbit(&types.types); j < ebitmap_length(&types.types); j++) {
+			if (!ebitmap_get_bit(&types.types, j))
 				continue;
 
 			for (rt = policydbp->range_tr; rt; rt = rt->next) {
 				if (rt->dom == (i + 1) && rt->type == (j + 1)) {
 					sprintf(errormsg, "duplicate range_transition defined for (%s,%s)",
-					        type_val_to_name(i + 1), type_val_to_name(j + 1));
+					        policydbp->p_type_val_to_name[i + 1],
+                                                policydbp->p_type_val_to_name[j + 1]);
 					yyerror(errormsg);
 					return -1;
 				}
@@ -4938,13 +4393,11 @@
 		}
 	}
 
-	ebitmap_destroy(&doms);
-	ebitmap_destroy(&types);
+	type_set_destroy(&doms);
+	type_set_destroy(&types);
 	ebitmap_destroy(&range.level[0].cat);
 	ebitmap_destroy(&range.level[1].cat);
 	return 0;
 }
 
 /* FLASK */
-
-


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.


This mailing list archive is a service of Copilot Consulting.