All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joshua Brindle <jbrindle@tresys.com>
To: selinux <selinux@tycho.nsa.gov>
Cc: selinux-dev@tresys.com
Subject: [Patch 3/3] Loadable policy module infrastructure
Date: Thu, 26 May 2005 13:27:05 -0400	[thread overview]
Message-ID: <1117128425.3483.21.camel@localhost> (raw)

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@tresys.com>
+ *	    Karl MacMillan <kmacmillan@tresys.com>
+ *          Jason Tang     <jtang@tresys.com>
+ *
+ *	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@redhat.com>
  *	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@epoch.ncsc.mil> 
  */
@@ -12,8 +11,14 @@
  *
  * 	Added conditional policy language extensions
  *
+ * Updated: Joshua Brindle <jbrindle@tresys.com>
+ *	    Karl MacMillan <kmacmillan@tresys.com>
+ *          Jason Tang     <jtang@tresys.com>
+ *
+ *	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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

                 reply	other threads:[~2005-05-26 18:30 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1117128425.3483.21.camel@localhost \
    --to=jbrindle@tresys.com \
    --cc=selinux-dev@tresys.com \
    --cc=selinux@tycho.nsa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.