changeset 7828:f6ed606f3a50

Integration of contributed Flask/TE V15
author John Weeks <jweeks@opensolaris.org>
date Thu, 01 May 2008 16:48:12 -0700
parents 79999447a15b
children c5e66da7b20d
files usr/src/cmd/Makefile usr/src/cmd/fmac/Makefile usr/src/cmd/fmac/checkpolicy/Makefile usr/src/cmd/fmac/checkpolicy/checkpolicy.c usr/src/cmd/fmac/checkpolicy/checkpolicy.h usr/src/cmd/fmac/checkpolicy/policy_parse.y usr/src/cmd/fmac/checkpolicy/policy_scan.l usr/src/cmd/fmac/checkpolicy/queue.c usr/src/cmd/fmac/checkpolicy/queue.h usr/src/cmd/fmac/checkpolicy/write.c usr/src/cmd/fmac/policy/Makefile usr/src/cmd/fmac/policy/README usr/src/cmd/fmac/policy/assert.te usr/src/cmd/fmac/policy/attrib.te usr/src/cmd/fmac/policy/constraints usr/src/cmd/fmac/policy/domains/admin/sysadm.te usr/src/cmd/fmac/policy/domains/every.te usr/src/cmd/fmac/policy/domains/program/crontab.te usr/src/cmd/fmac/policy/domains/program/fsadm.te usr/src/cmd/fmac/policy/domains/program/gnome-pty-helper.te usr/src/cmd/fmac/policy/domains/program/ifconfig.te usr/src/cmd/fmac/policy/domains/program/logrotate.te usr/src/cmd/fmac/policy/domains/program/lpr.te usr/src/cmd/fmac/policy/domains/program/mail.te usr/src/cmd/fmac/policy/domains/program/modutil.te usr/src/cmd/fmac/policy/domains/program/netscape.te usr/src/cmd/fmac/policy/domains/program/newrole.te usr/src/cmd/fmac/policy/domains/program/passwd.te usr/src/cmd/fmac/policy/domains/program/su.te usr/src/cmd/fmac/policy/domains/program/utempter.te usr/src/cmd/fmac/policy/domains/program/xserver.te usr/src/cmd/fmac/policy/domains/system/apmd.te usr/src/cmd/fmac/policy/domains/system/atd.te usr/src/cmd/fmac/policy/domains/system/cardmgr.te usr/src/cmd/fmac/policy/domains/system/crond.te usr/src/cmd/fmac/policy/domains/system/ftpd.te usr/src/cmd/fmac/policy/domains/system/getty.te usr/src/cmd/fmac/policy/domains/system/gpm.te usr/src/cmd/fmac/policy/domains/system/inetd.te usr/src/cmd/fmac/policy/domains/system/init.te usr/src/cmd/fmac/policy/domains/system/initrc.te usr/src/cmd/fmac/policy/domains/system/kernel.te usr/src/cmd/fmac/policy/domains/system/klogd.te usr/src/cmd/fmac/policy/domains/system/kmod.te usr/src/cmd/fmac/policy/domains/system/login.te usr/src/cmd/fmac/policy/domains/system/lpd.te usr/src/cmd/fmac/policy/domains/system/portmap.te usr/src/cmd/fmac/policy/domains/system/rlogind.te usr/src/cmd/fmac/policy/domains/system/rpcd.te usr/src/cmd/fmac/policy/domains/system/rshd.te usr/src/cmd/fmac/policy/domains/system/sendmail.te usr/src/cmd/fmac/policy/domains/system/sshd.te usr/src/cmd/fmac/policy/domains/system/syslogd.te usr/src/cmd/fmac/policy/domains/system/tcpd.te usr/src/cmd/fmac/policy/domains/system/xfs.te usr/src/cmd/fmac/policy/domains/system/ypbind.te usr/src/cmd/fmac/policy/domains/user/user.te usr/src/cmd/fmac/policy/file_contexts usr/src/cmd/fmac/policy/fs_use usr/src/cmd/fmac/policy/init.te usr/src/cmd/fmac/policy/initial_sid_contexts usr/src/cmd/fmac/policy/macros.te usr/src/cmd/fmac/policy/mls usr/src/cmd/fmac/policy/net_contexts usr/src/cmd/fmac/policy/rbac usr/src/cmd/fmac/policy/types/device.te usr/src/cmd/fmac/policy/types/devpts.te usr/src/cmd/fmac/policy/types/file.te usr/src/cmd/fmac/policy/types/network.te usr/src/cmd/fmac/policy/types/nfs.te usr/src/cmd/fmac/policy/types/procfs.te usr/src/cmd/fmac/policy/types/security.te usr/src/cmd/fmac/policy/users usr/src/cmd/fmac/setfiles/Makefile usr/src/cmd/fmac/setfiles/setfiles.c usr/src/common/fmac/policy/flask/access_vectors usr/src/common/fmac/policy/flask/initial_sids usr/src/common/fmac/policy/flask/security_classes usr/src/common/fmac/ss/avtab.c usr/src/common/fmac/ss/avtab.h usr/src/common/fmac/ss/constraint.h usr/src/common/fmac/ss/context.h usr/src/common/fmac/ss/ebitmap.c usr/src/common/fmac/ss/ebitmap.h usr/src/common/fmac/ss/hashtab.c usr/src/common/fmac/ss/hashtab.h usr/src/common/fmac/ss/mls.c usr/src/common/fmac/ss/mls.h usr/src/common/fmac/ss/mls_types.h usr/src/common/fmac/ss/policydb.c usr/src/common/fmac/ss/policydb.h usr/src/common/fmac/ss/services.c usr/src/common/fmac/ss/services.h usr/src/common/fmac/ss/sidtab.c usr/src/common/fmac/ss/sidtab.h usr/src/common/fmac/ss/ss_impl.h usr/src/common/fmac/ss/symtab.c usr/src/common/fmac/ss/symtab.h usr/src/pkgdefs/SUNWcsr/prototype_com usr/src/pkgdefs/SUNWhea/prototype_com usr/src/uts/common/Makefile.files usr/src/uts/common/Makefile.rules usr/src/uts/common/fmac/avc.c usr/src/uts/common/fmac/fmac.c usr/src/uts/common/os/main.c usr/src/uts/common/sys/Makefile usr/src/uts/common/sys/Makefile.syshdrs usr/src/uts/common/sys/fmac/Makefile usr/src/uts/common/sys/fmac/avc.h usr/src/uts/common/sys/fmac/avc_ss.h usr/src/uts/common/sys/fmac/flask_types.h usr/src/uts/common/sys/fmac/fmac.h usr/src/uts/common/sys/fmac/generated_defs usr/src/uts/common/sys/fmac/mkaccess_vector.awk usr/src/uts/common/sys/fmac/mkflask.awk usr/src/uts/common/sys/fmac/security.h
diffstat 116 files changed, 23435 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/Makefile	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/cmd/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -161,6 +161,7 @@
 	filebench	\
 	find		\
 	fm		\
+	fmac		\
 	fmli		\
 	fmt		\
 	fmthard		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.cmd
+
+SUBDIRS =	checkpolicy	\
+		setfiles	\
+		policy
+
+all :=		TARGET = all
+install :=	TARGET = install
+clean :=	TARGET = clean
+clobber :=	TARGET = clobber
+lint :=		TARGET = lint
+_msg :=		TARGET = _msg
+
+.KEEP_STATE:
+
+all install line clean clobber: $(SUBDIRS)
+
+$(SUBDIRS):
+	@cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,146 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Makefile for building the checkpolicy program
+#
+
+MYPROG =		checkpolicy
+PROG =			$(MYPROG)
+
+include ../../Makefile.cmd
+
+LOCAL_OBJS =		queue.o		\
+			write.o		\
+			policy_parse.o	\
+			policy_scan.o	\
+			checkpolicy.o
+
+COMMON_OBJS =
+
+COMMON_SS_OBJS =	ebitmap.o	\
+			hashtab.o	\
+			symtab.o	\
+			sidtab.o	\
+			avtab.o		\
+			policydb.o	\
+			services.o
+
+CHECK_FOR_MLS =		if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS'	\
+				$(SRC)/common/fmac/ss/ss_impl.h ; then	\
+				echo "mls.o" ;				\
+			else						\
+				echo "" ;				\
+			fi ;
+
+MLS_OBJ =		$(CHECK_FOR_MLS:sh)
+
+COMMON_SS_OBJS +=	$(MLS_OBJ)
+
+OBJS =			$(LOCAL_OBJS)	\
+			$(COMMON_OBJS)	\
+			$(COMMON_SS_OBJS)
+
+LOCAL_SRCS =		$(LOCAL_OBJS:%.o=%.c)
+
+COMMON_SRCS =		$(COMMON_OBJS:%.o=$(SRC)/common/fmac/%.c)
+
+COMMON_SS_SRCS =	$(COMMON_SS_OBJS:%.o=$(SRC)/common/fmac/ss/%.c)
+
+SRCS =			$(LOCAL_SRCS)	\
+			$(COMMON_SRCS)	\
+			$(COMMON_SS_SRCS)
+
+LNTS =			$(OBJS:.o=.po)
+
+INCS += -I.
+INCS += -I../../../common/fmac/ss
+
+CPPFLAGS += $(INCS)
+
+LFLAGS += -t
+YFLAGS += -d
+
+C99MODE = -xc99=%all
+
+CLOBBERFILES += policy_scan.c policy_parse.c policy_parse.h
+
+PDFILES = 	$(PROG)_all.po
+LDLIBS +=	-ll -lnsl
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+	$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+$(PROFILE): $(POFILES)
+	$(CAT) $(PROFILES) > $(POFILE)
+
+policy_scan.c: policy_scan.l policy_parse.h
+	$(LEX) $(LFLAGS) policy_scan.l > $@
+
+policy_parse.h policy_parse.c: policy_parse.y
+	$(YACC) $(YFLAGS) policy_parse.y
+	@$(MV) y.tab.h policy_parse.h
+	@$(MV) y.tab.c policy_parse.c
+
+install: all $(ROOTSBINPROG)
+
+clean:
+	$(RM) $(OBJS)
+
+lint:	lint_SRCS
+
+%.o: %.c
+	$(COMPILE.c) $<
+
+%.o: $(SRC)/common/fmac/%.c
+	$(COMPILE.c) $<
+
+%.o: $(SRC)/common/fmac/ss/%.c
+	$(COMPILE.c) $<
+
+%.ln: $(SRCS)
+	$(LINT.c) $(LINTFLAGS) $(SRCS) $(@:.ln=.c)
+
+%.ln: $(SRC)/common/fmac/%.c
+	$(LINT.c) $(LINTFLAGS) -c $<
+
+%.ln: $(SRC)/common/fmac/ss/%.c
+	$(LINT.c) $(LINTFLAGS) -c $<
+
+relabel: install
+	setfilecon system_u:object_r:checkpolicy_exec_t $(BINDIR)/checkpolicy
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/checkpolicy.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,900 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+/*
+ * checkpolicy
+ *
+ * Load and check a policy configuration.
+ *
+ * A policy configuration is created in a text format,
+ * and then compiled into a binary format for use by
+ * the security server.  By default, checkpolicy reads
+ * the text format.   If '-b' is specified, then checkpolicy
+ * reads the binary format instead.
+ *
+ * If '-o output_file' is specified, then checkpolicy
+ * writes the binary format version of the configuration
+ * to the specified output file.
+ *
+ * If '-d' is specified, then checkpolicy permits the user
+ * to interactively test the security server functions with
+ * the loaded policy configuration.
+ */
+
+#include <policydb.h>
+#include <services.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/mman.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/fmac/security.h>
+#include "queue.h"
+#include "checkpolicy.h"
+
+extern char *optarg;
+extern int optind;
+
+extern policydb_t *policydbp;
+extern queue_info_ptr_t id_queue;
+extern unsigned int policydb_errors;
+extern unsigned long policydb_lineno;
+extern unsigned int pass;
+extern unsigned int ss_initialized;
+
+extern int policydb_write(policydb_t * p, FILE * fp);
+
+extern FILE *yyin;
+extern int yyparse(void);
+
+#if !defined(__sun)
+extern void yyrestart(FILE *);
+#endif
+
+char *txtfile = "policy.conf";
+char *binfile = "policy";
+
+int
+avc_ss_reset(uint32_t seqno)
+{
+	return (0);
+}
+
+void
+usage(char *progname)
+{
+	printf("usage:  %s [-b] [-d] [-o output_file] [input_file]\n",
+		progname);
+
+	exit(1);
+}
+
+static int
+print_sid(security_id_t sid, context_struct_t *context, void *data)
+{
+	security_context_t scontext;
+	unsigned int scontext_len;
+	int rc;
+
+	rc = security_sid_to_context(sid, &scontext, &scontext_len);
+	if (rc)
+		printf("sid %d -> error %d\n", sid, rc);
+	else {
+		printf("sid %d -> scontext %s\n", sid, scontext);
+		free(scontext);
+	}
+	return (0);
+}
+
+struct val_to_name {
+	unsigned int val;
+	char *name;
+};
+
+static int
+find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	struct val_to_name *v = p;
+	perm_datum_t *perdatum;
+
+	perdatum = (perm_datum_t *) datum;
+
+	if (v->val == perdatum->value) {
+		v->name = key;
+		return (1);
+	}
+
+	return (0);
+}
+
+static int
+type_attr_remove(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	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,
+    struct avtab_node *type_rules)
+{
+	struct avtab_node *p;
+	struct avtab_node *c;
+	struct avtab_node *n;
+
+	for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) {
+		/*
+		 * Find the insertion point, keeping the list
+		 * ordered by source type, then target type, then
+		 * target class.
+		 */
+		if (k->source_type < c->key.source_type)
+			break;
+		if (k->source_type == c->key.source_type &&
+		    k->target_type < c->key.target_type)
+			break;
+		if (k->source_type == c->key.source_type &&
+		    k->target_type == c->key.target_type &&
+		    k->target_class < c->key.target_class)
+			break;
+	}
+
+	/* Insert the rule */
+	n = malloc(sizeof (struct avtab_node));
+	if (!n) {
+		fprintf(stderr, "out of memory\n");
+		exit(1);
+	}
+
+	n->key = *k;
+	n->datum = *d;
+	n->next = p->next;
+	p->next = n;
+	return (0);
+}
+
+static int
+create_type_rules(avtab_key_t *k, avtab_datum_t *d, void *args)
+{
+	struct avtab_node *type_rules = args;
+
+	if (d->specified & AVTAB_ALLOWED) {
+		/*
+		 * Insert the rule into the lists for both
+		 * the source type and the target type.
+		 */
+		if (insert_type_rule(k, d, &type_rules[k->source_type-1]))
+			return (-1);
+		if (insert_type_rule(k, d, &type_rules[k->target_type-1]))
+			return (-1);
+	}
+
+	return (0);
+}
+
+static void
+free_type_rules(struct avtab_node *l)
+{
+	struct avtab_node *tmp;
+
+	while (l) {
+		tmp = l;
+		l = l->next;
+		free(tmp);
+	}
+}
+
+static int
+identify_equiv_types(void)
+{
+	struct avtab_node *type_rules, *l1, *l2;
+	int i, j;
+
+	/*
+	 * Create a list of access vector rules for each type
+	 * from the access vector table.
+	 */
+	type_rules = malloc(sizeof (struct avtab_node)*policydb.p_types.nprim);
+	if (!type_rules) {
+		fprintf(stderr, "out of memory\n");
+		exit(1);
+	}
+	memset(type_rules,
+		0,
+		sizeof (struct avtab_node)*policydb.p_types.nprim);
+	if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules))
+		exit(1);
+
+	/*
+	 * Compare the type lists and identify equivalent types.
+	 */
+	for (i = 0; i < policydb.p_types.nprim - 1; i++) {
+		if (!type_rules[i].next)
+			continue;
+		for (j = i + 1; j < policydb.p_types.nprim; j++) {
+			for (l1 = type_rules[i].next,
+			    l2 = type_rules[j].next; l1 && l2;
+				l1 = l1->next, l2 = l2->next) {
+				if (l2->key.source_type == (j+1)) {
+					if (l1->key.source_type != (i+1))
+						break;
+				} else {
+					if (l1->key.source_type !=
+					    l2->key.source_type)
+						break;
+				}
+				if (l2->key.target_type == (j+1)) {
+					if (l1->key.target_type != (i+1))
+						break;
+				} else {
+					if (l1->key.target_type !=
+					    l2->key.target_type)
+						break;
+				}
+				if (l1->key.target_class !=
+				    l2->key.target_class ||
+				    l1->datum.allowed != l2->datum.allowed)
+					break;
+			}
+			if (l1 || l2)
+				continue;
+			free_type_rules(type_rules[j].next);
+			type_rules[j].next = NULL;
+			printf("Types %s and %s are equivalent.\n",
+				policydb.p_type_val_to_name[i],
+				policydb.p_type_val_to_name[j]);
+		}
+		free_type_rules(type_rules[i].next);
+		type_rules[i].next = NULL;
+	}
+
+	free(type_rules);
+	return (0);
+}
+#endif
+
+extern char *av_to_string(uint32_t tclass, access_vector_t av);
+
+void
+check_assertion_helper(int stype, int ttype, ebitmap_t *tclasses,
+    access_vector_t *avp, unsigned long line)
+{
+	avtab_key_t avkey;
+	avtab_datum_t *avdatump;
+	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;
+	te_assert_t *tmp;
+	int i;
+	int 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
+main(int argc, char **argv)
+{
+	security_class_t tclass;
+	security_id_t ssid, tsid, *sids;
+	security_context_t scontext;
+	struct av_decision avd;
+	class_datum_t *cladatum;
+	char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype;
+	unsigned int scontext_len, pathlen, i;
+	unsigned int protocol, port, addr;
+	unsigned int binary = 0, debug = 0;
+	struct val_to_name v;
+	int ret, ch, fd;
+	unsigned int nel, uret;
+	struct stat sb;
+	void *map;
+	FILE *outfp = NULL;
+
+	while ((ch = getopt(argc, argv, "o:dbV")) != EOF) {
+		switch (ch) {
+		case 'o':
+			outfile = optarg;
+			break;
+		case 'b':
+			binary = 1;
+			file = binfile;
+			break;
+		case 'd':
+			debug = 1;
+			break;
+		case 'V':
+#ifdef CONFIG_FLASK_MLS
+			printf("%d-mls\n", POLICYDB_VERSION);
+#else
+			printf("%d\n", POLICYDB_VERSION);
+#endif
+			exit(0);
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	if (optind != argc) {
+		file = argv[optind++];
+		if (optind != argc)
+			usage(argv[0]);
+	}
+	printf("%s:  loading policy configuration from %s\n", argv[0],
+		file);
+
+	if (binary) {
+		fd = open(file, O_RDONLY);
+		if (fd < 0) {
+			fprintf(stderr, "Can't open '%s':  %s\n",
+				file, strerror(errno));
+			exit(1);
+		}
+		if (fstat(fd, &sb) < 0) {
+			fprintf(stderr, "Can't stat '%s':  %s\n",
+				file, strerror(errno));
+			exit(1);
+		}
+		map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+		if (map == MAP_FAILED) {
+			fprintf(stderr, "Can't map '%s':  %s\n",
+				file, strerror(errno));
+			exit(1);
+		}
+		ret = security_load_policy(map, sb.st_size);
+		if (ret) {
+			fprintf(stderr, "%s:  error(s) encountered while "
+			    "parsing configuration\n",
+			    argv[0]);
+			exit(1);
+		}
+	} else {
+		yyin = fopen(file, "r");
+		if (!yyin) {
+			fprintf(stderr, "%s:  unable to open %s\n", argv[0],
+				file);
+			exit(1);
+		}
+
+		if (policydb_init(&policydb))
+			exit(1);
+
+		id_queue = queue_create();
+		if (!id_queue) {
+			fprintf(stderr, "%s:  out of memory\n", argv[0]);
+			exit(1);
+		}
+		policydbp = &policydb;
+		policydb_errors = 0;
+		pass = 1;
+		if (yyparse() || policydb_errors) {
+			fprintf(stderr, "%s:  error(s) encountered while "
+			    "parsing configuration\n",
+			    argv[0]);
+			exit(1);
+		}
+		rewind(yyin);
+		policydb_lineno = 1;
+#if !defined(__sun)
+		yyrestart(yyin);
+#endif
+		pass = 2;
+		if (yyparse() || policydb_errors) {
+			fprintf(stderr, "%s:  error(s) encountered while "
+			    "parsing configuration\n",
+			    argv[0]);
+			exit(1);
+		}
+		queue_destroy(id_queue);
+
+		check_assertions();
+		if (policydb_errors)
+			exit(1);
+
+		/* remove type attributes */
+		hashtab_map_remove_on_error(policydb.p_types.table,
+					    type_attr_remove, 0, 0);
+		fclose(yyin);
+	}
+
+	if (policydb_load_isids(&policydb, &sidtab))
+		exit(1);
+
+	printf("%s:  policy configuration loaded\n", argv[0]);
+
+	if (outfile) {
+		printf("%s:  writing binary representation (version %d) "
+		    "to %s\n",
+		    argv[0], POLICYDB_VERSION, outfile);
+		outfp = fopen(outfile, "w");
+		if (!outfp) {
+			perror(outfile);
+			exit(1);
+		}
+		ret = policydb_write(&policydb, outfp);
+		if (ret) {
+			fprintf(stderr, "%s:  error writing %s\n",
+				argv[0], outfile);
+			exit(1);
+		}
+		fclose(outfp);
+	}
+	if (!debug)
+		exit(0);
+
+	ss_initialized = 1;
+
+	menu:
+	printf("\nSelect an option:\n");
+	printf("0)  Call compute_access_vector\n");
+	printf("1)  Call sid_to_context\n");
+	printf("2)  Call context_to_sid\n");
+	printf("3)  Call transition_sid\n");
+	printf("4)  Call member_sid\n");
+	printf("5)  Call change_sid\n");
+	printf("6)  Call list_sids\n");
+	printf("7)  Call load_policy\n");
+	printf("8)  Call fs_sid\n");
+	printf("9)  Call port_sid\n");
+	printf("a)  Call netif_sid\n");
+	printf("b)  Call node_sid\n");
+	printf("c)  Call fs_use\n");
+	printf("d)  Call genfs_sid\n");
+	printf("e)  Call get_user_sids\n");
+#ifdef EQUIVTYPES
+	printf("z)  Show equivalent types\n");
+#endif
+	printf("m)  Show menu again\n");
+	printf("q)  Exit\n");
+	while (1) {
+		printf("\nChoose:  ");
+		fgets(ans, sizeof (ans), stdin);
+		switch (ans[0]) {
+		case '0':
+			printf("source sid?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ssid = atoi(ans);
+
+			printf("target sid?  ");
+			fgets(ans, sizeof (ans), stdin);
+			tsid = atoi(ans);
+
+			printf("target class?  ");
+			fgets(ans, sizeof (ans), stdin);
+			if (isdigit(ans[0])) {
+				tclass = atoi(ans);
+				if (!tclass ||
+				    tclass > policydb.p_classes.nprim) {
+					printf("\nNo such class.\n");
+					break;
+				}
+				cladatum =
+				    policydb.class_val_to_struct[tclass - 1];
+			} else {
+				ans[strlen(ans) - 1] = 0;
+				cladatum = (class_datum_t *) hashtab_search(
+				    policydb.p_classes.table, ans);
+				if (!cladatum) {
+					printf("\nNo such class\n");
+					break;
+				}
+				tclass = cladatum->value;
+			}
+
+			if (!cladatum->comdatum &&
+			    !cladatum->permissions.nprim) {
+				printf("\nNo access vector definition for "
+				    "that class\n");
+				break;
+			}
+			ret = security_compute_av(ssid, tsid, tclass, 0,
+				&avd);
+			switch (ret) {
+			case 0:
+				printf("\nallowed {");
+				for (i = 1; i <= sizeof (avd.allowed) * 8;
+				    i++) {
+					if (avd.allowed & (1 << (i - 1))) {
+						v.val = i;
+						ret = hashtab_map(
+						    cladatum->permissions.table,
+						    find_perm, &v);
+						if (!ret &&
+						    cladatum->comdatum) {
+							ret = hashtab_map(cladatum->comdatum->permissions.table,
+								find_perm, &v);
+						}
+						if (ret)
+							printf(" %s", v.name);
+					}
+				}
+				printf(" }\n");
+				break;
+			case EINVAL:
+				printf("\ninvalid sid\n");
+				break;
+			default:
+				printf("return code 0x%x\n", ret);
+			}
+			break;
+		case '1':
+			printf("sid?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ssid = atoi(ans);
+			ret = security_sid_to_context(ssid,
+				&scontext, &scontext_len);
+			switch (ret) {
+			case 0:
+				printf("\nscontext %s\n", scontext);
+				free(scontext);
+				break;
+			case EINVAL:
+				printf("\ninvalid sid\n");
+				break;
+			case ENOMEM:
+				printf("\nout of memory\n");
+				break;
+			default:
+				printf("return code 0x%x\n", ret);
+			}
+			break;
+		case '2':
+			printf("scontext?  ");
+			fgets(ans, sizeof (ans), stdin);
+			scontext_len = strlen(ans);
+			ans[scontext_len - 1] = 0;
+			ret = security_context_to_sid(ans, scontext_len,
+				&ssid);
+			switch (ret) {
+			case 0:
+				printf("\nsid %d\n", ssid);
+				break;
+			case EINVAL:
+				printf("\ninvalid context\n");
+				break;
+			case ENOMEM:
+				printf("\nout of memory\n");
+				break;
+			default:
+				printf("return code 0x%x\n", ret);
+			}
+			break;
+		case '3':
+		case '4':
+		case '5':
+			ch = ans[0];
+
+			printf("source sid?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ssid = atoi(ans);
+			printf("target sid?  ");
+			fgets(ans, sizeof (ans), stdin);
+			tsid = atoi(ans);
+
+			printf("object class?  ");
+			fgets(ans, sizeof (ans), stdin);
+			if (isdigit(ans[0])) {
+				tclass = atoi(ans);
+				if (!tclass ||
+				    tclass > policydb.p_classes.nprim) {
+					printf("\nNo such class.\n");
+					break;
+				}
+			} else {
+				ans[strlen(ans) - 1] = 0;
+				cladatum = (class_datum_t *) hashtab_search(
+				    policydb.p_classes.table, ans);
+				if (!cladatum) {
+					printf("\nNo such class\n");
+					break;
+				}
+				tclass = cladatum->value;
+			}
+
+			if (ch == '3')
+				ret = security_transition_sid(ssid, tsid,
+				    tclass, &ssid);
+			else if (ch == '4')
+				ret = security_member_sid(ssid, tsid, tclass,
+				    &ssid);
+			else
+				ret = security_change_sid(ssid, tsid, tclass,
+				    &ssid);
+			switch (ret) {
+			case 0:
+				printf("\nsid %d\n", ssid);
+				break;
+			case EINVAL:
+				printf("\ninvalid sid\n");
+				break;
+			case ENOMEM:
+				printf("\nout of memory\n");
+				break;
+			default:
+				printf("return code 0x%x\n", ret);
+			}
+			break;
+		case '6':
+			sidtab_map(&sidtab, print_sid, 0);
+			break;
+		case '7':
+			printf("pathname?  ");
+			fgets(ans, sizeof (ans), stdin);
+			pathlen = strlen(ans);
+			ans[pathlen - 1] = 0;
+			printf("%s:  loading policy configuration "
+			    "from %s\n",
+			    argv[0], ans);
+			fd = open(ans, O_RDONLY);
+			if (fd < 0) {
+				fprintf(stderr, "Can't open '%s':  %s\n",
+					ans, strerror(errno));
+				break;
+			}
+			if (fstat(fd, &sb) < 0) {
+				fprintf(stderr, "Can't stat '%s':  %s\n",
+					ans, strerror(errno));
+				break;
+			}
+			map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED,
+			    fd, 0);
+			if (map == MAP_FAILED) {
+				fprintf(stderr, "Can't map '%s':  %s\n",
+					ans, strerror(errno));
+				break;
+			}
+			ret = security_load_policy(map, sb.st_size);
+			switch (ret) {
+			case 0:
+				printf("\nsuccess\n");
+				break;
+			case EINVAL:
+				printf("\ninvalid policy\n");
+				break;
+			case ENOMEM:
+				printf("\nout of memory\n");
+				break;
+			default:
+				printf("return code 0x%x\n", ret);
+			}
+			break;
+		case '8':
+			printf("fs kdevname?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			security_fs_sid(ans, &ssid, &tsid);
+			printf("fs_sid %d default_file_sid %d\n",
+				ssid, tsid);
+			break;
+		case '9':
+			printf("protocol?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			if (strcmp(ans, "tcp") == 0 || strcmp(ans, "TCP") == 0)
+				protocol = IPPROTO_TCP;
+			else if (strcmp(ans, "udp") == 0 ||
+				    strcmp(ans, "UDP") == 0)
+				protocol = IPPROTO_UDP;
+			else {
+				printf("unknown protocol\n");
+				break;
+			}
+			printf("port? ");
+			fgets(ans, sizeof (ans), stdin);
+			port = atoi(ans);
+			security_port_sid(0, 0, protocol, port, &ssid);
+			printf("sid %d\n", ssid);
+			break;
+		case 'a':
+			printf("netif name?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			security_netif_sid(ans, &ssid, &tsid);
+			printf("if_sid %d default_msg_sid %d\n",
+				ssid, tsid);
+			break;
+		case 'b':
+			printf("node address?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			addr = inet_addr(ans);
+			security_node_sid(AF_INET, &addr, sizeof (addr), &ssid);
+			printf("sid %d\n", ssid);
+			break;
+		case 'c':
+			printf("fstype?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			security_fs_use(ans, &uret, &ssid);
+			switch (uret) {
+			case SECURITY_FS_USE_XATTR:
+				printf("use extended attributes\n");
+				break;
+			case SECURITY_FS_USE_TRANS:
+				printf("use transition SIDs\n");
+				break;
+			case SECURITY_FS_USE_TASK:
+				printf("use task SIDs\n");
+				break;
+			case SECURITY_FS_USE_GENFS:
+				printf("use genfs\n");
+				break;
+			case SECURITY_FS_USE_NONE:
+				printf("no labeling support\n");
+				break;
+			}
+			printf("sid %d\n", ssid);
+			break;
+		case 'd':
+			printf("fstype?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			fstype = strdup(ans);
+			printf("path?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			path = strdup(ans);
+			printf("object class?  ");
+			fgets(ans, sizeof (ans), stdin);
+			if (isdigit(ans[0])) {
+				tclass = atoi(ans);
+				if (!tclass ||
+				    tclass > policydb.p_classes.nprim) {
+					printf("\nNo such class.\n");
+					break;
+				}
+			} else {
+				ans[strlen(ans) - 1] = 0;
+				cladatum = (class_datum_t *) hashtab_search(
+				    policydb.p_classes.table, ans);
+				if (!cladatum) {
+					printf("\nNo such class\n");
+					break;
+				}
+				tclass = cladatum->value;
+			}
+			security_genfs_sid(fstype, path, tclass, &ssid);
+			printf("sid %d\n", ssid);
+			free(fstype);
+			free(path);
+			break;
+		case 'e':
+			printf("from SID?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+			ssid = atoi(ans);
+
+			printf("username?  ");
+			fgets(ans, sizeof (ans), stdin);
+			ans[strlen(ans) - 1] = 0;
+
+			ret = security_get_user_sids(ssid, ans, &sids, &nel);
+			switch (ret) {
+			case 0:
+				if (!nel)
+					printf("\nnone\n");
+				for (i = 0; i < nel; i++)
+					print_sid(sids[i], NULL, NULL);
+				free(sids);
+				break;
+			case ENOMEM:
+				printf("\nout of memory\n");
+				break;
+			case EINVAL:
+				printf("\ninvalid argument\n");
+				break;
+			default:
+				printf("\nerror\n");
+				break;
+			}
+			break;
+#ifdef EQUIVTYPES
+		case 'z':
+			identify_equiv_types();
+			break;
+#endif
+		case 'm':
+			goto menu;
+		case 'q':
+			exit(0);
+			break;
+		default:
+			printf("\nUnknown option %s.\n", ans);
+		}
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/checkpolicy.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+#ifndef _CHECKPOLICY_H
+#define	_CHECKPOLICY_H
+
+#include "ebitmap.h"
+#include <sys/fmac/flask_types.h>
+
+typedef struct te_assert {
+	ebitmap_t		stypes;
+	ebitmap_t		ttypes;
+	ebitmap_t		tclasses;
+	int			self;
+	access_vector_t		*avp;
+	unsigned long		line;
+	struct te_assert	*next;
+} te_assert_t;
+
+te_assert_t *te_assertions;
+
+#endif /* _CHECKPOLICY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/policy_parse.y	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,3535 @@
+%{
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 
+ */
+
+#include <policydb.h>
+#include <services.h>
+#include "queue.h"
+#include <sys/fmac/av_inherit.h>
+#include <sys/fmac/security.h>
+#include <netinet/in.h>
+#include "checkpolicy.h"
+#include <stdint.h>
+#include <stdio.h>
+
+policydb_t *policydbp;
+queue_info_ptr_t id_queue = 0;
+unsigned int pass;
+
+extern unsigned long policydb_lineno;
+
+extern char yytext[];
+extern int yywarn(char *msg);
+extern int yyerror(char *msg);
+
+static char errormsg[255];
+
+static int insert_separator(int push);
+static int insert_id(char *id,int push);
+static int define_class(void);
+static int define_initial_sid(void);
+static int define_common_perms(void);
+static int define_av_perms(int inherits);
+static int define_sens(void);
+static int define_dominance(void);
+static int define_category(void);
+static int define_level(void);
+static int define_common_base(void);
+static int define_av_base(void);
+static int define_attrib(void);
+static int define_type(int alias);
+static int define_compute_type(int which);
+static int define_te_avtab(int which);
+static int define_role_types(void);
+static role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2);
+static role_datum_t *define_role_dom(role_datum_t *r);
+static int define_role_trans(void);
+static int define_role_allow(void);
+static int define_constraint(constraint_expr_t *expr);
+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);
+static int define_initial_sid_context(void);
+static int define_fs_use(int behavior);
+static int define_genfs_context(int has_type);
+static int define_fs_context(int major, int minor);
+static int define_port_context(int low, int high);
+static int define_netif_context(void);
+static int define_node_context(int addr, int mask);
+%}
+
+%union {
+	unsigned int val;
+	uintptr_t valptr;
+	void *ptr;
+}
+
+%type <ptr> role_def roles 
+%type <valptr> cexpr cexpr_prim op roleop
+%type <val> ipv4_addr_def number 
+
+%token PATH
+%token CLONE
+%token COMMON
+%token CLASS
+%token CONSTRAIN
+%token INHERITS
+%token SID
+%token ROLE
+%token ROLES
+%token TYPE
+%token TYPES
+%token ALIAS
+%token ATTRIBUTE
+%token TYPE_TRANSITION
+%token TYPE_MEMBER
+%token TYPE_CHANGE
+%token ROLE_TRANSITION
+%token SENSITIVITY
+%token DOMINANCE
+%token DOM DOMBY INCOMP
+%token CATEGORY
+%token LEVEL
+%token RANGES
+%token USER
+%token NEVERALLOW
+%token ALLOW
+%token AUDITALLOW
+%token AUDITDENY
+%token DONTAUDIT
+%token SOURCE
+%token TARGET
+%token SAMEUSER
+%token FSCON PORTCON NETIFCON NODECON 
+%token FSUSEXATTR FSUSETASK FSUSETRANS
+%token GENFSCON
+%token U1 U2 R1 R2 T1 T2
+%token NOT AND OR 
+%token IDENTIFIER
+%token USER_IDENTIFIER
+%token NUMBER
+%token EQUALS
+%token NOTEQUAL
+
+%left OR
+%left AND
+%right NOT
+%left EQUALS NOTEQUAL
+%%
+policy			: classes initial_sids access_vectors 
+                          { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; } }
+			  opt_mls te_rbac users opt_constraints 
+			  { if (pass == 2) { if (policydb_index_others(policydbp)) return -1;} } 
+			  initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts 
+			;
+classes			: class_def 
+			| classes class_def
+			;
+class_def		: CLASS identifier
+			{if (define_class()) return -1;}
+			;
+initial_sids 		: initial_sid_def 
+			| initial_sids initial_sid_def
+			;
+initial_sid_def		: SID identifier
+                        {if (define_initial_sid()) return -1;}
+			;
+access_vectors		: opt_common_perms av_perms
+			;
+opt_common_perms        : common_perms
+                        |
+                        ;
+common_perms		: common_perms_def
+			| common_perms common_perms_def
+			;
+common_perms_def	: COMMON identifier '{' identifier_list '}'
+			{if (define_common_perms()) return -1;}
+			;
+av_perms		: av_perms_def
+			| av_perms av_perms_def
+			;
+av_perms_def		: CLASS identifier '{' identifier_list '}'
+			{if (define_av_perms(FALSE)) return -1;}
+                        | CLASS identifier INHERITS identifier 
+			{if (define_av_perms(TRUE)) return -1;}
+                        | CLASS identifier INHERITS identifier '{' identifier_list '}'
+			{if (define_av_perms(TRUE)) return -1;}
+			;
+opt_mls			: mls
+                        | 
+			;
+mls			: sensitivities dominance opt_categories levels base_perms
+			;
+sensitivities	 	: sensitivity_def 
+			| sensitivities sensitivity_def
+			;
+sensitivity_def		: SENSITIVITY identifier alias_def ';'
+			{if (define_sens()) return -1;}
+			| SENSITIVITY identifier ';'
+			{if (define_sens()) return -1;}
+	                ;
+alias_def		: ALIAS names
+			;
+dominance		: DOMINANCE identifier 
+			{if (define_dominance()) return -1;}
+                        | DOMINANCE '{' identifier_list '}' 
+			{if (define_dominance()) return -1;}
+			;
+opt_categories          : categories
+                        |
+                        ;
+categories 		: category_def 
+			| categories category_def
+			;
+category_def		: CATEGORY identifier alias_def ';'
+			{if (define_category()) return -1;}
+			| CATEGORY identifier ';'
+			{if (define_category()) return -1;}
+			;
+levels	 		: level_def 
+			| levels level_def
+			;
+level_def		: LEVEL identifier ':' id_comma_list ';'
+			{if (define_level()) return -1;}
+			| LEVEL identifier ';' 
+			{if (define_level()) return -1;}
+			;
+base_perms		: opt_common_base av_base
+			;
+opt_common_base         : common_base
+                        |
+                        ;
+common_base		: common_base_def
+			| common_base common_base_def
+			;
+common_base_def	        : COMMON identifier '{' perm_base_list '}'
+	                {if (define_common_base()) return -1;}
+			;
+av_base		        : av_base_def
+			| av_base av_base_def
+			;
+av_base_def		: CLASS identifier '{' perm_base_list '}'
+	                {if (define_av_base()) return -1;}
+                        | CLASS identifier
+	                {if (define_av_base()) return -1;}
+			;
+perm_base_list		: perm_base
+			| perm_base_list perm_base
+			;
+perm_base		: identifier ':' identifier
+			{if (insert_separator(0)) return -1;}
+                        | identifier ':' '{' identifier_list '}'
+			{if (insert_separator(0)) return -1;}
+			;
+te_rbac			: te_rbac_decl
+			| te_rbac te_rbac_decl
+			;
+te_rbac_decl		: te_decl
+			| rbac_decl
+			| ';'
+                        ;
+rbac_decl		: role_type_def
+                        | role_dominance
+                        | role_trans_def
+ 			| role_allow_def
+			;
+te_decl			: attribute_def
+                        | type_def
+                        | transition_def
+                        | te_avtab_def
+			;
+attribute_def           : ATTRIBUTE identifier ';'
+                        { if (define_attrib()) return -1;}
+                        ;
+type_def		: TYPE identifier alias_def opt_attr_list ';'
+                        {if (define_type(1)) return -1;}
+	                | TYPE identifier opt_attr_list ';'
+                        {if (define_type(0)) return -1;}
+    			;
+opt_attr_list           : ',' id_comma_list
+			| 
+			;
+transition_def		: TYPE_TRANSITION names names ':' names identifier ';'
+                        {if (define_compute_type(AVTAB_TRANSITION)) return -1;}
+                        | TYPE_MEMBER names names ':' names identifier ';'
+                        {if (define_compute_type(AVTAB_MEMBER)) return -1;}
+                        | TYPE_CHANGE names names ':' names identifier ';'
+                        {if (define_compute_type(AVTAB_CHANGE)) return -1;}
+    			;
+te_avtab_def		: allow_def
+			| auditallow_def
+			| auditdeny_def
+			| dontaudit_def
+			| neverallow_def
+			;
+allow_def		: ALLOW names names ':' names names  ';'
+			{if (define_te_avtab(AVTAB_ALLOWED)) return -1; }
+		        ;
+auditallow_def		: AUDITALLOW names names ':' names names ';'
+			{if (define_te_avtab(AVTAB_AUDITALLOW)) return -1; }
+		        ;
+auditdeny_def		: AUDITDENY names names ':' names names ';'
+			{if (define_te_avtab(AVTAB_AUDITDENY)) return -1; }
+		        ;
+dontaudit_def		: DONTAUDIT names names ':' names names ';'
+			{if (define_te_avtab(-AVTAB_AUDITDENY)) return -1; }
+		        ;
+neverallow_def		: NEVERALLOW names names ':' names names  ';'
+			{if (define_te_avtab(-AVTAB_ALLOWED)) return -1; }
+		        ;
+role_type_def		: ROLE identifier TYPES names ';'
+			{if (define_role_types()) return -1;}
+                        ;
+role_dominance		: DOMINANCE '{' roles '}'
+			;
+role_trans_def		: ROLE_TRANSITION names names identifier ';'
+			{if (define_role_trans()) return -1; }
+			;
+role_allow_def		: ALLOW names names ';'
+			{if (define_role_allow()) return -1; }
+			;
+roles			: role_def
+			{ $$ = $1; }
+			| roles role_def
+			{ $$ = merge_roles_dom((role_datum_t*)$1, (role_datum_t*)$2); if ($$ == 0) return -1;}
+			;
+role_def		: ROLE identifier_push ';'
+                        {$$ = define_role_dom(NULL); if ($$ == 0) return -1;}
+			| ROLE identifier_push '{' roles '}'
+                        {$$ = define_role_dom((role_datum_t*)$4); if ($$ == 0) return -1;}
+			;
+opt_constraints         : constraints
+                        |
+                        ;
+constraints		: constraint_def
+			| constraints constraint_def
+			;
+constraint_def		: CONSTRAIN names names cexpr ';'
+			{ if (define_constraint((constraint_expr_t*)$4)) return -1; }
+			;
+cexpr			: '(' cexpr ')'
+			{ $$ = $2; }
+			| NOT cexpr
+			{ $$ = define_cexpr(CEXPR_NOT, $2, 0);
+			  if ($$ == 0) return -1; }
+			| cexpr AND cexpr
+			{ $$ = define_cexpr(CEXPR_AND, $1, $3);
+			  if ($$ == 0) return -1; }
+			| cexpr OR cexpr
+			{ $$ = define_cexpr(CEXPR_OR, $1, $3);
+			  if ($$ == 0) return -1; }
+			| cexpr_prim
+			{ $$ = $1; }
+			;
+cexpr_prim		: U1 op U2
+			{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, $2);
+			  if ($$ == 0) return -1; }
+			| R1 roleop R2
+			{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2);
+			  if ($$ == 0) return -1; }
+			| T1 op T2
+			{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_TYPE, $2);
+			  if ($$ == 0) return -1; }
+			| U1 op { if (insert_separator(1)) return -1; } user_names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_USER, $2);
+			  if ($$ == 0) return -1; }
+			| U2 op { if (insert_separator(1)) return -1; } user_names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_TARGET), $2);
+			  if ($$ == 0) return -1; }
+			| R1 op { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, $2);
+			  if ($$ == 0) return -1; }
+			| R2 op { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), $2);
+			  if ($$ == 0) return -1; }
+			| T1 op { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, $2);
+			  if ($$ == 0) return -1; }
+			| T2 op { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), $2);
+			  if ($$ == 0) return -1; }
+			| SAMEUSER
+			{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, CEXPR_EQ);
+			  if ($$ == 0) return -1; }
+			| SOURCE ROLE { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, CEXPR_EQ);
+			  if ($$ == 0) return -1; }
+			| TARGET ROLE { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), CEXPR_EQ);
+			  if ($$ == 0) return -1; }
+			| ROLE roleop
+			{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2);
+			  if ($$ == 0) return -1; }
+			| SOURCE TYPE { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, CEXPR_EQ);
+			  if ($$ == 0) return -1; }
+			| TARGET TYPE { if (insert_separator(1)) return -1; } names_push
+			{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), CEXPR_EQ);
+			  if ($$ == 0) return -1; }
+			;
+op			: EQUALS
+			{ $$ = CEXPR_EQ; }
+			| NOTEQUAL
+			{ $$ = CEXPR_NEQ; }
+			;
+roleop			: op 
+			{ $$ = $1; }
+			| DOM
+			{ $$ = CEXPR_DOM; }
+			| DOMBY
+			{ $$ = CEXPR_DOMBY; }
+			| INCOMP
+			{ $$ = CEXPR_INCOMP; }
+			;
+users			: user_def
+			| users user_def
+			;
+user_id			: identifier
+			| user_identifier
+			;
+user_def		: USER user_id ROLES names opt_user_ranges ';'
+	                {if (define_user()) return -1;}
+			;
+opt_user_ranges		: RANGES user_ranges 
+			|
+			;
+user_ranges		: mls_range_def
+			| '{' user_range_def_list '}' 
+			;
+user_range_def_list	: mls_range_def
+			| user_range_def_list mls_range_def
+			;
+initial_sid_contexts	: initial_sid_context_def
+			| initial_sid_contexts initial_sid_context_def
+			;
+initial_sid_context_def	: SID identifier security_context_def
+			{if (define_initial_sid_context()) return -1;}
+			;
+opt_fs_contexts         : fs_contexts 
+                        |
+                        ;
+fs_contexts		: fs_context_def
+			| fs_contexts fs_context_def
+			;
+fs_context_def		: FSCON number number security_context_def security_context_def
+			{if (define_fs_context($2,$3)) return -1;}
+			;
+net_contexts		: opt_port_contexts opt_netif_contexts opt_node_contexts 
+			;
+opt_port_contexts       : port_contexts
+                        |
+                        ;
+port_contexts		: port_context_def
+			| port_contexts port_context_def
+			;
+port_context_def	: PORTCON identifier number security_context_def
+			{if (define_port_context($3,$3)) return -1;}
+			| PORTCON identifier number '-' number security_context_def
+			{if (define_port_context($3,$5)) return -1;}
+			;
+opt_netif_contexts      : netif_contexts 
+                        |
+                        ;
+netif_contexts		: netif_context_def
+			| netif_contexts netif_context_def
+			;
+netif_context_def	: NETIFCON identifier security_context_def security_context_def
+			{if (define_netif_context()) return -1;} 
+			;
+opt_node_contexts       : node_contexts 
+                        |
+                        ;
+node_contexts		: node_context_def
+			| node_contexts node_context_def
+			;
+node_context_def	: NODECON ipv4_addr_def ipv4_addr_def security_context_def
+			{if (define_node_context($2,$3)) return -1;}
+			;
+fs_uses                 : fs_use_def
+                        | fs_uses fs_use_def
+                        ;
+opt_fs_uses		: fs_uses
+			|
+			;
+fs_use_def              : FSUSEXATTR identifier security_context_def ';' 
+                        {if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;}
+                        | FSUSETASK identifier security_context_def ';'
+                        {if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;}
+                        | 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
+			;
+genfs_context_def	: GENFSCON identifier path '-' identifier security_context_def
+			{if (define_genfs_context(1)) return -1;}
+			| GENFSCON identifier path '-' '-' {insert_id("-", 0);} security_context_def
+			{if (define_genfs_context(1)) return -1;}
+                        | GENFSCON identifier path security_context_def
+			{if (define_genfs_context(0)) return -1;}
+			;
+ipv4_addr_def		: number '.' number '.' number '.' number
+			{ 
+			  unsigned int addr;
+	  		  unsigned char *p = ((unsigned char *)&addr);
+
+			  p[0] = $1 & 0xff;				
+			  p[1] = $3 & 0xff;
+			  p[2] = $5 & 0xff;
+			  p[3] = $7 & 0xff;
+			  $$ = addr;
+			}
+    			;
+security_context_def	: user_id ':' identifier ':' identifier opt_mls_range_def
+	                ;
+opt_mls_range_def	: ':' mls_range_def
+			|	
+			;
+mls_range_def		: mls_level_def '-' mls_level_def
+			{if (insert_separator(0)) return -1;}
+	                | mls_level_def
+			{if (insert_separator(0)) return -1;}
+	                ;
+mls_level_def		: identifier ':' id_comma_list
+			{if (insert_separator(0)) return -1;}
+	                | identifier 
+			{if (insert_separator(0)) return -1;}
+	                ;
+id_comma_list           : identifier
+			| id_comma_list ',' identifier
+			;
+tilde			: '~'
+			;
+asterisk		: '*'
+			;
+names           	: identifier
+			{ if (insert_separator(0)) return -1; }
+			| nested_id_set
+			{ if (insert_separator(0)) return -1; }
+			| asterisk
+                        { if (insert_id("*", 0)) return -1; 
+			  if (insert_separator(0)) return -1; }
+			| tilde identifier
+                        { if (insert_id("~", 0)) return -1;
+			  if (insert_separator(0)) return -1; }
+			| tilde nested_id_set
+	 		{ if (insert_id("~", 0)) return -1; 
+			  if (insert_separator(0)) return -1; }
+			;
+tilde_push              : tilde
+                        { if (insert_id("~", 1)) return -1; }
+			;
+asterisk_push           : asterisk
+                        { if (insert_id("*", 1)) return -1; }
+			;
+names_push		: identifier_push
+			| '{' identifier_list_push '}'
+			| asterisk_push
+			| tilde_push identifier_push
+			| tilde_push '{' identifier_list_push '}'
+			;
+identifier_list_push	: identifier_push
+			| identifier_list_push identifier_push
+			;
+identifier_push		: IDENTIFIER
+			{ if (insert_id(yytext, 1)) return -1; }
+			;
+identifier_list		: identifier
+			| identifier_list identifier
+			;
+nested_id_set           : '{' nested_id_list '}'
+                        ;
+nested_id_list          : nested_id_element | nested_id_list nested_id_element
+                        ;
+nested_id_element       : identifier | nested_id_set
+                        ;
+identifier		: IDENTIFIER
+			{ if (insert_id(yytext,0)) return -1; }
+			;
+user_identifier		: USER_IDENTIFIER
+			{ if (insert_id(yytext,0)) return -1; }
+			;
+user_identifier_push	: USER_IDENTIFIER
+			{ if (insert_id(yytext, 1)) return -1; }
+			;
+user_identifier_list_push : user_identifier_push
+			| identifier_list_push user_identifier_push
+			| user_identifier_list_push identifier_push
+			| user_identifier_list_push user_identifier_push
+			;
+user_names_push		: names_push
+			| user_identifier_push
+			| '{' user_identifier_list_push '}'
+			| tilde_push user_identifier_push
+			| tilde_push '{' user_identifier_list_push '}'
+			;
+path     		: PATH
+			{ if (insert_id(yytext,0)) return -1; }
+			;
+number			: NUMBER 
+			{ $$ = strtoul(yytext,NULL,0); }
+			;
+%%
+static int insert_separator(int push)
+{
+	int error;
+
+	if (push)
+		error = queue_push(id_queue, 0);
+	else
+		error = queue_insert(id_queue, 0);
+
+	if (error) {
+		yyerror("queue overflow");
+		return -1;
+	}
+	return 0;
+}
+
+static int insert_id(char *id, int push)
+{
+	char *newid = 0;
+	int error;
+
+	newid = (char *) malloc(strlen(id) + 1);
+	if (!newid) {
+		yyerror("out of memory");
+		return -1;
+	}
+	strcpy(newid, id);
+	if (push)
+		error = queue_push(id_queue, (queue_element_t) newid);
+	else
+		error = queue_insert(id_queue, (queue_element_t) newid);
+
+	if (error) {
+		yyerror("queue overflow");
+		free(newid);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int define_class(void)
+{
+	char *id = 0;
+	class_datum_t *datum = 0;
+	int ret;
+
+
+	if (pass == 2) {
+		id = queue_remove(id_queue);
+		free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no class name for class definition?");
+		return -1;
+	}
+	datum = (class_datum_t *) malloc(sizeof(class_datum_t));
+	if (!datum) {
+		yyerror("out of memory");
+		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) {
+		yyerror("hash table overflow");
+		goto bad;
+	}
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (datum)
+		free(datum);
+	return -1;
+}
+
+static int define_initial_sid(void)
+{
+	char *id = 0;
+	ocontext_t *newc = 0, *c, *head;
+
+
+	if (pass == 2) {
+		id = queue_remove(id_queue);
+		free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no sid name for SID definition?");
+		return -1;
+	}
+	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		goto bad;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+	newc->u.name = id;
+	context_init(&newc->context[0]);
+	head = policydbp->ocontexts[OCON_ISID];
+
+	for (c = head; c; c = c->next) {
+		if (!strcmp(newc->u.name, c->u.name)) {
+			sprintf(errormsg, "duplicate initial SID %s", id);
+			yyerror(errormsg);
+			goto bad;
+		}
+	}
+
+	if (head) {
+		newc->sid[0] = head->sid[0] + 1;
+	} else {
+		newc->sid[0] = 1;
+	}
+	newc->next = head;
+	policydbp->ocontexts[OCON_ISID] = newc;
+
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (newc)
+		free(newc);
+	return -1;
+}
+
+static int define_common_perms(void)
+{
+	char *id = 0, *perm = 0;
+	common_datum_t *comdatum = 0;
+	perm_datum_t *perdatum = 0;
+	int ret;
+
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no common name for common perm definition?");
+		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);
+
+	if (ret == HASHTAB_PRESENT) {
+		yyerror("duplicate common definition");
+		goto bad;
+	}
+	if (ret == HASHTAB_OVERFLOW) {
+		yyerror("hash table overflow");
+		goto bad;
+	}
+	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) {
+		yyerror("out of memory");
+		goto bad;
+	}
+	while ((perm = queue_remove(id_queue))) {
+		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
+		if (!perdatum) {
+			yyerror("out of memory");
+			goto bad_perm;
+		}
+		memset(perdatum, 0, sizeof(perm_datum_t));
+		perdatum->value = ++comdatum->permissions.nprim;
+
+#ifdef CONFIG_FLASK_MLS
+		/*
+		 * By default, we set all four base permissions on this
+		 * permission. This means that if base_permissions is not
+		 * explicitly defined for this permission, then this
+		 * permission will only be granted in the equivalent case.
+		 */
+		perdatum->base_perms = MLS_BASE_READ | MLS_BASE_WRITE |
+		    MLS_BASE_READBY | MLS_BASE_WRITEBY;
+#endif
+
+		if (perdatum->value >= (sizeof(access_vector_t) * 8)) {
+			yyerror("too many permissions to fit in an access vector");
+			goto bad_perm;
+		}
+		ret = hashtab_insert(comdatum->permissions.table,
+				     (hashtab_key_t) perm,
+				     (hashtab_datum_t) perdatum);
+
+		if (ret == HASHTAB_PRESENT) {
+			sprintf(errormsg, "duplicate permission %s in common %s",
+				perm, id);
+			yyerror(errormsg);
+			goto bad_perm;
+		}
+		if (ret == HASHTAB_OVERFLOW) {
+			yyerror("hash table overflow");
+			goto bad_perm;
+		}
+	}
+
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (comdatum)
+		free(comdatum);
+	return -1;
+
+      bad_perm:
+	if (perm)
+		free(perm);
+	if (perdatum)
+		free(perdatum);
+	return -1;
+}
+
+
+static int define_av_perms(int inherits)
+{
+	char *id;
+	class_datum_t *cladatum;
+	common_datum_t *comdatum;
+	perm_datum_t *perdatum = 0, *perdatum2 = 0;
+	int ret;
+
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no tclass name for av perm definition?");
+		return -1;
+	}
+	cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
+						    (hashtab_key_t) id);
+	if (!cladatum) {
+		sprintf(errormsg, "class %s is not defined", id);
+		yyerror(errormsg);
+		goto bad;
+	}
+	free(id);
+
+	if (cladatum->comdatum || cladatum->permissions.nprim) {
+		yyerror("duplicate access vector definition");
+		return -1;
+	}
+	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) {
+		yyerror("out of memory");
+		return -1;
+	}
+	if (inherits) {
+		id = (char *) queue_remove(id_queue);
+		if (!id) {
+			yyerror("no inherits name for access vector definition?");
+			return -1;
+		}
+		comdatum = (common_datum_t *) hashtab_search(policydbp->p_commons.table,
+						     (hashtab_key_t) id);
+
+		if (!comdatum) {
+			sprintf(errormsg, "common %s is not defined", id);
+			yyerror(errormsg);
+			goto bad;
+		}
+		cladatum->comkey = id;
+		cladatum->comdatum = comdatum;
+
+		/*
+		 * Class-specific permissions start with values 
+		 * after the last common permission.
+		 */
+		cladatum->permissions.nprim += comdatum->permissions.nprim;
+	}
+	while ((id = queue_remove(id_queue))) {
+		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
+		if (!perdatum) {
+			yyerror("out of memory");
+			goto bad;
+		}
+		memset(perdatum, 0, sizeof(perm_datum_t));
+		perdatum->value = ++cladatum->permissions.nprim;
+
+#ifdef CONFIG_FLASK_MLS
+		/*
+		 * By default, we set all four base permissions on this
+		 * permission. This means that if base_permissions is not
+		 * explicitly defined for this permission, then this
+		 * permission will only be granted in the equivalent case.
+		 */
+		perdatum->base_perms = MLS_BASE_READ | MLS_BASE_WRITE |
+		    MLS_BASE_READBY | MLS_BASE_WRITEBY;
+		/* actual value set in define_av_base */
+#endif
+
+		if (perdatum->value >= (sizeof(access_vector_t) * 8)) {
+			yyerror("too many permissions to fit in an access vector");
+			goto bad;
+		}
+		if (inherits) {
+			/*
+			 * Class-specific permissions and 
+			 * common permissions exist in the same
+			 * name space.
+			 */
+			perdatum2 = (perm_datum_t *) hashtab_search(cladatum->comdatum->permissions.table,
+						     (hashtab_key_t) id);
+			if (perdatum2) {
+				sprintf(errormsg, "permission %s conflicts with an inherited permission", id);
+				yyerror(errormsg);
+				goto bad;
+			}
+		}
+		ret = hashtab_insert(cladatum->permissions.table,
+				     (hashtab_key_t) id,
+				     (hashtab_datum_t) perdatum);
+
+		if (ret == HASHTAB_PRESENT) {
+			sprintf(errormsg, "duplicate permission %s", id);
+			yyerror(errormsg);
+			goto bad;
+		}
+		if (ret == HASHTAB_OVERFLOW) {
+			yyerror("hash table overflow");
+			goto bad;
+		}
+	}
+
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (perdatum)
+		free(perdatum);
+	return -1;
+}
+
+
+static int define_sens(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	char *id;
+	mls_level_t *level = 0;
+	level_datum_t *datum = 0, *aliasdatum = 0;
+	int ret;
+
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no sensitivity name for sensitivity definition?");
+		return -1;
+	}
+	level = (mls_level_t *) malloc(sizeof(mls_level_t));
+	if (!level) {
+		yyerror("out of memory");
+		goto bad;
+	}
+	memset(level, 0, sizeof(mls_level_t));
+	level->sens = 0;	/* actual value set in define_dominance */
+	++policydbp->p_levels.nprim;
+	ebitmap_init(&level->cat);	/* actual value set in define_level */
+
+	datum = (level_datum_t *) malloc(sizeof(level_datum_t));
+	if (!datum) {
+		yyerror("out of memory");
+		goto bad;
+	}
+	memset(datum, 0, sizeof(level_datum_t));
+	datum->isalias = FALSE;
+	datum->level = level;
+
+	ret = hashtab_insert(policydbp->p_levels.table,
+			     (hashtab_key_t) id, (hashtab_datum_t) datum);
+
+	if (ret == HASHTAB_PRESENT) {
+		--policydbp->p_levels.nprim;
+		sprintf(errormsg, "duplicate definition for sensitivity %s", id);
+		yyerror(errormsg);
+		goto bad;
+	}
+	if (ret == HASHTAB_OVERFLOW) {
+		yyerror("hash table overflow");
+		goto bad;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t));
+		if (!aliasdatum) {
+			yyerror("out of memory");
+			goto bad_alias;
+		}
+		memset(aliasdatum, 0, sizeof(level_datum_t));
+		aliasdatum->isalias = TRUE;
+		aliasdatum->level = level;
+
+		ret = hashtab_insert(policydbp->p_levels.table,
+		       (hashtab_key_t) id, (hashtab_datum_t) aliasdatum);
+
+		if (ret == HASHTAB_PRESENT) {
+			sprintf(errormsg, "duplicate definition for level %s", id);
+			yyerror(errormsg);
+			goto bad_alias;
+		}
+		if (ret == HASHTAB_OVERFLOW) {
+			yyerror("hash table overflow");
+			goto bad_alias;
+		}
+	}
+
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (level)
+		free(level);
+	if (datum)
+		free(datum);
+	return -1;
+
+      bad_alias:
+	if (id)
+		free(id);
+	if (aliasdatum)
+		free(aliasdatum);
+	return -1;
+#else
+	yyerror("sensitivity definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+static int define_dominance(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	level_datum_t *datum;
+	int order;
+	char *id;
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	order = 0;
+	while ((id = (char *) queue_remove(id_queue))) {
+		datum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+						     (hashtab_key_t) id);
+		if (!datum) {
+			sprintf(errormsg, "unknown sensitivity %s used in dominance definition", id);
+			yyerror(errormsg);
+			free(id);
+			continue;
+		}
+		if (datum->level->sens != 0) {
+			sprintf(errormsg, "sensitivity %s occurs multiply in dominance definition", id);
+			yyerror(errormsg);
+			free(id);
+			return -1;
+		}
+		datum->level->sens = ++order;
+
+		/* no need to keep sensitivity name */
+		free(id);
+	}
+
+	if (order != policydbp->p_levels.nprim) {
+		yyerror("all sensitivities must be specified in dominance definition");
+		return -1;
+	}
+	return 0;
+#else
+	yyerror("dominance definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+static int define_category(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	char *id;
+	cat_datum_t *datum = 0, *aliasdatum = 0;
+	int ret;
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no category name for category definition?");
+		return -1;
+	}
+	datum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
+	if (!datum) {
+		yyerror("out of memory");
+		goto bad;
+	}
+	memset(datum, 0, sizeof(cat_datum_t));
+	datum->isalias = FALSE;
+	datum->value = ++policydbp->p_cats.nprim;
+
+	ret = hashtab_insert(policydbp->p_cats.table,
+			     (hashtab_key_t) id, (hashtab_datum_t) datum);
+
+	if (ret == HASHTAB_PRESENT) {
+		--policydbp->p_cats.nprim;
+		sprintf(errormsg, "duplicate definition for category %s", id);
+		yyerror(errormsg);
+		goto bad;
+	}
+	if (ret == HASHTAB_OVERFLOW) {
+		yyerror("hash table overflow");
+		goto bad;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
+		if (!aliasdatum) {
+			yyerror("out of memory");
+			goto bad_alias;
+		}
+		memset(aliasdatum, 0, sizeof(cat_datum_t));
+		aliasdatum->isalias = TRUE;
+		aliasdatum->value = datum->value;
+
+		ret = hashtab_insert(policydbp->p_cats.table,
+		       (hashtab_key_t) id, (hashtab_datum_t) aliasdatum);
+
+		if (ret == HASHTAB_PRESENT) {
+			sprintf(errormsg, "duplicate definition for category %s", id);
+			yyerror(errormsg);
+			goto bad_alias;
+		}
+		if (ret == HASHTAB_OVERFLOW) {
+			yyerror("hash table overflow");
+			goto bad_alias;
+		}
+	}
+
+	return 0;
+
+      bad:
+	if (id)
+		free(id);
+	if (datum)
+		free(datum);
+	return -1;
+
+      bad_alias:
+	if (id)
+		free(id);
+	if (aliasdatum)
+		free(aliasdatum);
+	return -1;
+#else
+	yyerror("category definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+
+static int define_level(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	int n;
+	char *id, *levid;
+	level_datum_t *levdatum;
+	cat_datum_t *catdatum;
+
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no level name for level definition?");
+		return -1;
+	}
+	levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+						    (hashtab_key_t) id);
+	if (!levdatum) {
+		sprintf(errormsg, "unknown sensitivity %s used in level definition", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	if (ebitmap_length(&levdatum->level->cat)) {
+		sprintf(errormsg, "sensitivity %s used in multiple level definitions", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	levid = id;
+	n = 1;
+	while ((id = queue_remove(id_queue))) {
+		catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
+						     (hashtab_key_t) id);
+		if (!catdatum) {
+			sprintf(errormsg, "unknown category %s used in level definition", id);
+			yyerror(errormsg);
+			free(id);
+			continue;
+		}
+		if (!ebitmap_set_bit(&levdatum->level->cat, catdatum->value - 1, TRUE)) {
+			yyerror("out of memory");
+			free(id);
+			free(levid);
+			return -1;
+		}
+		/* no need to keep category name */
+		free(id);
+
+		n = n * 2;
+	}
+
+	free(levid);
+
+	policydbp->nlevels += n;
+
+	return 0;
+#else
+	yyerror("level definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+
+static int define_common_base(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	char *id, *perm, *base;
+	common_datum_t *comdatum;
+	perm_datum_t *perdatum;
+
+
+	if (pass == 2) {
+		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;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no common name for common base definition?");
+		return -1;
+	}
+	comdatum = (common_datum_t *) hashtab_search(policydbp->p_commons.table,
+						     (hashtab_key_t) id);
+	if (!comdatum) {
+		sprintf(errormsg, "common %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	while ((perm = queue_remove(id_queue))) {
+		perdatum = (perm_datum_t *) hashtab_search(comdatum->permissions.table,
+						   (hashtab_key_t) perm);
+		if (!perdatum) {
+			sprintf(errormsg, "permission %s is not defined for common %s", perm, id);
+			yyerror(errormsg);
+			free(id);
+			free(perm);
+			return -1;
+		}
+
+		/*
+		 * An explicit definition of base_permissions for this
+		 * permission.  Reset the value to zero.
+		 */
+		perdatum->base_perms = 0;
+
+		while ((base = queue_remove(id_queue))) {
+			if (!strcmp(base, "read"))
+				perdatum->base_perms |= MLS_BASE_READ;
+			else if (!strcmp(base, "write"))
+				perdatum->base_perms |= MLS_BASE_WRITE;
+			else if (!strcmp(base, "readby"))
+				perdatum->base_perms |= MLS_BASE_READBY;
+			else if (!strcmp(base, "writeby"))
+				perdatum->base_perms |= MLS_BASE_WRITEBY;
+			else if (strcmp(base, "none")) {
+				sprintf(errormsg, "base permission %s is not defined", base);
+				yyerror(errormsg);
+				free(base);
+				return -1;
+			}
+			free(base);
+		}
+
+		free(perm);
+	}
+
+	free(id);
+
+	return 0;
+#else
+	yyerror("MLS base permission definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+
+#ifdef CONFIG_FLASK_MLS
+static int common_base_set(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	perm_datum_t *perdatum;
+	class_datum_t *cladatum;
+
+	perdatum = (perm_datum_t *) datum;
+	cladatum = (class_datum_t *) p;
+
+	if (perdatum->base_perms & MLS_BASE_READ)
+		cladatum->mlsperms.read |= (1 << (perdatum->value - 1));
+
+	if (perdatum->base_perms & MLS_BASE_WRITE)
+		cladatum->mlsperms.write |= (1 << (perdatum->value - 1));
+
+	if (perdatum->base_perms & MLS_BASE_READBY)
+		cladatum->mlsperms.readby |= (1 << (perdatum->value - 1));
+
+	if (perdatum->base_perms & MLS_BASE_WRITEBY)
+		cladatum->mlsperms.writeby |= (1 << (perdatum->value - 1));
+
+	return 0;
+}
+#endif
+
+static int define_av_base(void)
+{
+#ifdef CONFIG_FLASK_MLS
+	char *id, *base;
+	class_datum_t *cladatum;
+	perm_datum_t *perdatum;
+
+	if (pass == 2) {
+		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;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no tclass name for av base definition?");
+		return -1;
+	}
+	cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
+						    (hashtab_key_t) id);
+	if (!cladatum) {
+		sprintf(errormsg, "class %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	free(id);
+
+	/*
+	 * Determine which common permissions should be included in each MLS
+	 * vector for this access vector definition.
+	 */
+	if (cladatum->comdatum)
+		hashtab_map(cladatum->comdatum->permissions.table, common_base_set, cladatum);
+
+	while ((id = queue_remove(id_queue))) {
+		perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
+						     (hashtab_key_t) id);
+		if (!perdatum) {
+			sprintf(errormsg, "permission %s is not defined", id);
+			yyerror(errormsg);
+			free(id);
+			return -1;
+		}
+		/*
+		 * An explicit definition of base_permissions for this
+		 * permission.  Reset the value to zero.
+		 */
+		perdatum->base_perms = 0;
+
+		while ((base = queue_remove(id_queue))) {
+			if (!strcmp(base, "read")) {
+				perdatum->base_perms |= MLS_BASE_READ;
+				cladatum->mlsperms.read |= (1 << (perdatum->value - 1));
+			} else if (!strcmp(base, "write")) {
+				perdatum->base_perms |= MLS_BASE_WRITE;
+				cladatum->mlsperms.write |= (1 << (perdatum->value - 1));
+			} else if (!strcmp(base, "readby")) {
+				perdatum->base_perms |= MLS_BASE_READBY;
+				cladatum->mlsperms.readby |= (1 << (perdatum->value - 1));
+			} else if (!strcmp(base, "writeby")) {
+				perdatum->base_perms |= MLS_BASE_WRITEBY;
+				cladatum->mlsperms.writeby |= (1 << (perdatum->value - 1));
+			} else if (strcmp(base, "none")) {
+				sprintf(errormsg, "base permission %s is not defined", base);
+				yyerror(errormsg);
+				free(base);
+				continue;
+			}
+			free(base);
+		}
+
+		free(id);
+	}
+
+	return 0;
+#else
+	yyerror("MLS base permission definition in non-MLS configuration");
+	return -1;
+#endif
+}
+
+static int define_attrib(void)
+{
+	char *id;
+	type_datum_t *attr;
+	int ret;
+
+
+	if (pass == 2) {
+		free(queue_remove(id_queue));
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		return -1;
+	}
+
+	attr = hashtab_search(policydbp->p_types.table, id);
+	if (attr) {
+		sprintf(errormsg, "duplicate declaration for attribute %s\n",
+			id);
+		yyerror(errormsg);
+		return -1;
+	}
+
+	attr = (type_datum_t *) malloc(sizeof(type_datum_t));
+	if (!attr) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(attr, 0, sizeof(type_datum_t));
+	attr->isattr = TRUE;
+	ret = hashtab_insert(policydbp->p_types.table,
+			     id, (hashtab_datum_t) attr);
+	if (ret) {
+		yyerror("hash table overflow");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int define_type(int alias)
+{
+	char *id;
+	type_datum_t *datum, *aliasdatum, *attr;
+	int ret, newattr = 0;
+
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		if (alias) {
+			while ((id = queue_remove(id_queue))) 
+				free(id);
+		}
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no type name for type definition?");
+		return -1;
+	}
+
+	datum = (type_datum_t *) malloc(sizeof(type_datum_t));
+	if (!datum) {
+		yyerror("out of memory");
+		free(id);
+		return -1;
+	}
+	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) {
+		yyerror("hash table overflow");
+		free(datum);
+		free(id);
+		return -1;
+	}
+
+	if (alias) { 
+		while ((id = queue_remove(id_queue))) {
+			aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
+			if (!aliasdatum) {
+				yyerror("out of memory");
+				return -1;
+			}
+			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) {
+				yyerror("hash table overflow");
+				free(aliasdatum);
+				free(id);
+				return -1;
+			}
+		}
+	}
+
+	while ((id = queue_remove(id_queue))) {
+#ifdef CONFIG_FLASK_MLS
+		if (!strcmp(id, "mlstrustedreader")) {
+			if (!ebitmap_set_bit(&policydbp->trustedreaders, datum->value - 1, TRUE)) {
+				yyerror("out of memory");
+				free(id);
+				return -1;
+			}
+		} else if (!strcmp(id, "mlstrustedwriter")) {
+			if (!ebitmap_set_bit(&policydbp->trustedwriters, datum->value - 1, TRUE)) {
+				yyerror("out of memory");
+				free(id);
+				return -1;
+			}
+		} else if (!strcmp(id, "mlstrustedobject")) {
+			if (!ebitmap_set_bit(&policydbp->trustedobjects, datum->value - 1, TRUE)) {
+				yyerror("out of memory");
+				free(id);
+				return -1;
+			}
+		}
+#endif
+		attr = hashtab_search(policydbp->p_types.table, id);
+		if (!attr) {
+			sprintf(errormsg, "attribute %s is not declared", id);
+#if 1
+			/* treat it as a fatal error */
+			yyerror(errormsg);
+			return -1;
+#else
+			/* Warn but automatically define the attribute.
+			   Useful for quickly finding all those attributes you
+			   forgot to declare. */
+			yywarn(errormsg);
+			attr = (type_datum_t *) malloc(sizeof(type_datum_t));
+			if (!attr) {
+				yyerror("out of memory");
+				return -1;
+			}
+			memset(attr, 0, sizeof(type_datum_t));
+			attr->isattr = TRUE;
+			ret = hashtab_insert(policydbp->p_types.table,
+					     id, (hashtab_datum_t) attr);
+			if (ret) {
+				yyerror("hash table overflow");
+				return -1;
+			}
+			newattr = 1;
+#endif
+		} else {
+			newattr = 0;
+		}
+
+		if (!attr->isattr) {
+			sprintf(errormsg, "%s is a type, not an attribute", id);
+			yyerror(errormsg);
+			return -1;
+		}
+
+		if (!newattr)
+			free(id);
+
+		ebitmap_set_bit(&attr->types, datum->value - 1, TRUE);
+	}
+
+	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;
+}
+
+
+static int set_types(ebitmap_t *set,
+		     char *id)
+{
+	type_datum_t *t;
+	int i;
+
+	if (strcmp(id, "*") == 0) {
+		/* set all types */
+		for (i = 0; i < policydbp->p_types.nprim; i++) 
+			ebitmap_set_bit(set, i, TRUE);
+		free(id);
+		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);
+		}
+		free(id);
+		return 0;
+	}
+
+	t = hashtab_search(policydbp->p_types.table, id);
+	if (!t) {
+		sprintf(errormsg, "unknown type %s", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+
+	if (t->isattr) {
+		/* set all types with this attribute */
+		for (i = ebitmap_startbit(&t->types); i < ebitmap_length(&t->types); i++) {
+			if (!ebitmap_get_bit(&t->types, i)) 
+				continue;		
+			ebitmap_set_bit(set, i, TRUE);
+		}
+	} else {
+		/* set one type */
+		ebitmap_set_bit(set, t->value - 1, TRUE);
+	}
+
+	free(id);
+	return 0;
+}
+
+
+static int define_compute_type(int which)
+{
+	char *id;
+	avtab_key_t avkey;
+	avtab_datum_t avdatum, *avdatump;
+	type_datum_t *datum;
+	class_datum_t *cladatum;
+	ebitmap_t stypes, ttypes, tclasses;
+	uint32_t newtype = 0;
+	int ret, i, j, k;
+
+	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;
+	}
+
+	ebitmap_init(&stypes);
+	ebitmap_init(&ttypes);
+	ebitmap_init(&tclasses);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_types(&stypes, id))
+			return -1;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_types(&ttypes, id))
+			return -1;
+	}
+
+	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;
+	}
+
+	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;
+					}
+				}
+			}
+		}
+	}
+
+	return 0;
+
+      bad:
+	return -1;
+}
+
+
+static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
+{
+	struct val_to_name *v = data;
+	perm_datum_t *perdatum;
+
+	perdatum = (perm_datum_t *) datum;
+
+	if (v->val == perdatum->value) {
+		v->name = key;
+		return 1;
+	}
+
+	return 0;
+}
+
+
+char *av_to_string(uint32_t tclass, access_vector_t av)
+{
+	struct val_to_name v;
+	static char avbuf[1024];
+	class_datum_t *cladatum;
+	char *perm = NULL, *p;
+	int i, 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);
+			}
+		}
+	}
+
+	return avbuf;
+}
+
+
+static int te_avtab_helper(int which, int stype, int ttype, 
+			   ebitmap_t *tclasses, access_vector_t *avp)
+
+{
+	avtab_key_t avkey;
+	avtab_datum_t avdatum, *avdatump;
+	int ret, 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 int define_te_avtab(int which)
+{
+	char *id;
+	class_datum_t *cladatum;
+	perm_datum_t *perdatum;
+	ebitmap_t stypes, ttypes, tclasses;
+	access_vector_t *avp;
+	int i, j, hiclass, self = 0;
+	te_assert_t *newassert;
+
+	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 0;
+	}
+
+	ebitmap_init(&stypes);
+	ebitmap_init(&ttypes);
+	ebitmap_init(&tclasses);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_types(&stypes, id))
+			return -1;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (strcmp(id, "self") == 0) {
+			self = 1;
+			continue;
+		}
+		if (set_types(&ttypes, id))
+			return -1;
+	}
+
+	hiclass = 0;
+	while ((id = queue_remove(id_queue))) {
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
+		if (!cladatum) {
+			sprintf(errormsg, "unknown class %s used in rule", id);
+			yyerror(errormsg);
+			goto bad;
+		}
+		ebitmap_set_bit(&tclasses, cladatum->value - 1, TRUE);	
+		if (cladatum->value > hiclass)
+			hiclass = cladatum->value;
+		free(id);
+	}
+
+	avp = malloc(hiclass * sizeof(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] = ~0;
+				continue;
+			}
+
+			if (strcmp(id, "~") == 0) {
+				/* complement the set */
+				if (which == -AVTAB_AUDITDENY) 
+					yywarn("dontaudit rule with a ~?");
+				avp[i] = ~avp[i];
+				continue;
+			}
+
+			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]);
+				yyerror(errormsg);
+				continue;
+			}
+
+			avp[i] |= (1 << (perdatum->value - 1));
+		}
+
+		free(id);
+	}
+
+	if (which == -AVTAB_ALLOWED) {
+		newassert = malloc(sizeof(te_assert_t));
+		if (!newassert) {
+			yyerror("out of memory");
+			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;
+		}
+	}
+
+	ebitmap_destroy(&stypes);
+	ebitmap_destroy(&ttypes);
+	ebitmap_destroy(&tclasses);
+	free(avp);
+
+	return 0;
+ bad:
+	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;
+	}
+
+	return 0;
+}
+
+
+static char *role_val_to_name(unsigned int val) 
+{
+	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;
+}
+
+static int define_role_types(void)
+{
+	role_datum_t *role;
+	char *role_id, *id;
+	int ret;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		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);
+			return -1;
+		}
+	} else
+		free(role_id);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_types(&role->types, id))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+static role_datum_t *
+ merge_roles_dom(role_datum_t * r1, role_datum_t * r2)
+{
+	role_datum_t *new;
+
+	if (pass == 1) {
+		return (role_datum_t *)1; /* any non-NULL value */
+	}
+
+	new = malloc(sizeof(role_datum_t));
+	if (!new) {
+		yyerror("out of memory");
+		return NULL;
+	}
+	memset(new, 0, sizeof(role_datum_t));
+	new->value = 0;		/* temporary role */
+	if (!ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) {
+		yyerror("out of memory");
+		return NULL;
+	}
+	if (!ebitmap_or(&new->types, &r1->types, &r2->types)) {
+		yyerror("out of memory");
+		return NULL;
+	}
+	if (!r1->value) {
+		/* free intermediate result */
+		ebitmap_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);
+		ebitmap_destroy(&r2->dominates);
+		free(r2);
+	}
+	return new;
+}
+
+
+static role_datum_t *
+ define_role_dom(role_datum_t * r)
+{
+	role_datum_t *role;
+	char *role_id;
+	int i, ret;
+
+	if (pass == 1) {
+		role_id = queue_remove(id_queue);
+		free(role_id);
+		return (role_datum_t *)1; /* any non-NULL value */
+	}
+
+	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 NULL;
+		}
+		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);
+			return NULL;
+		}
+	}
+	if (r) {
+		for (i = ebitmap_startbit(&r->dominates); i < ebitmap_length(&r->dominates); i++) {
+			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 (!r->value) {
+			/* free intermediate result */
+			ebitmap_destroy(&r->types);
+			ebitmap_destroy(&r->dominates);
+			free(r);
+		}
+	}
+	return role;
+}
+
+
+static int set_roles(ebitmap_t *set,
+		     char *id)
+{
+	role_datum_t *r;
+	int i;
+
+	if (strcmp(id, "*") == 0) {
+		/* set all roles */
+		for (i = 0; i < policydbp->p_roles.nprim; i++) 
+			ebitmap_set_bit(set, i, TRUE);
+		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);
+		}
+		free(id);
+		return 0;
+	}
+
+	r = hashtab_search(policydbp->p_roles.table, id);
+	if (!r) {
+		sprintf(errormsg, "unknown role %s", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+
+	/* set one role */
+	ebitmap_set_bit(set, r->value - 1, TRUE);
+	free(id);
+	return 0;
+}
+
+
+static int define_role_trans(void)
+{
+	char *id;
+	role_datum_t *role;
+	ebitmap_t roles, types;
+	struct role_trans *tr = 0;
+	int i, j;
+
+	if (pass == 1) {
+		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;
+	}
+
+	yywarn("Role transition rules are DEPRECATED, use domain transitions.");
+
+	ebitmap_init(&roles);
+	ebitmap_init(&types);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_roles(&roles, id))
+			return -1;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_types(&types, id))
+			return -1;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no new role in transition definition?");
+		goto bad;
+	}
+	role = hashtab_search(policydbp->p_roles.table, id);
+	if (!role) {
+		sprintf(errormsg, "unknown role %s used in transition definition", id);
+		yyerror(errormsg);
+		goto bad;
+	}
+
+	for (i = ebitmap_startbit(&roles); i < ebitmap_length(&roles); i++) {
+		if (!ebitmap_get_bit(&roles, i)) 
+			continue;
+		for (j = ebitmap_startbit(&types); j < ebitmap_length(&types); j++) {
+			if (!ebitmap_get_bit(&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));
+					yyerror(errormsg);
+					goto bad;
+				}
+			}
+
+			tr = malloc(sizeof(struct role_trans));
+			if (!tr) {
+				yyerror("out of memory");
+				return -1;
+			}
+			memset(tr, 0, sizeof(struct role_trans));
+			tr->role = i+1;
+			tr->type = j+1;
+			tr->new_role = role->value;
+			tr->next = policydbp->role_tr;
+			policydbp->role_tr = tr;
+		}
+	}
+
+	return 0;
+
+ bad:
+	return -1;
+}
+
+
+static int define_role_allow(void)
+{
+	char *id;
+	ebitmap_t roles, new_roles;
+	struct role_allow *ra = 0;
+	int i, j;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	ebitmap_init(&roles);
+	ebitmap_init(&new_roles);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_roles(&roles, id))
+			return -1;
+	}
+
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_roles(&new_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");
+				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;
+		}
+	}
+
+	return 0;
+}
+
+
+static int define_constraint(constraint_expr_t * expr)
+{
+	struct constraint_node *node;
+	char *id;
+	class_datum_t *cladatum;
+	perm_datum_t *perdatum;
+	ebitmap_t classmap;
+	constraint_expr_t *e;
+	int i, depth;
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+		return 0;
+	}
+
+	depth = -1;
+	for (e = expr; e; e = e->next) {
+		switch (e->expr_type) {
+		case CEXPR_NOT:
+			if (depth < 0) {
+				yyerror("illegal constraint expression");
+				return -1;
+			}
+			break;
+		case CEXPR_AND:
+		case CEXPR_OR:
+			if (depth < 1) {
+				yyerror("illegal constraint expression");
+				return -1;
+			}
+			depth--;
+			break;
+		case CEXPR_ATTR:
+		case CEXPR_NAMES:
+			if (depth == (CEXPR_MAXDEPTH-1)) {
+				yyerror("constraint expression is too deep");
+				return -1;
+			}
+			depth++;
+			break;
+		default:
+			yyerror("illegal constraint expression");
+			return -1;
+		}
+	}
+	if (depth != 0) {
+		yyerror("illegal constraint expression");
+		return -1;
+	}
+
+	ebitmap_init(&classmap);
+	while ((id = queue_remove(id_queue))) {
+		cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
+						     (hashtab_key_t) id);
+		if (!cladatum) {
+			sprintf(errormsg, "class %s is not defined", id);
+			ebitmap_destroy(&classmap);
+			yyerror(errormsg);
+			free(id);
+			return -1;
+		}
+		if (!ebitmap_set_bit(&classmap, cladatum->value - 1, TRUE)) {
+			yyerror("out of memory");
+			ebitmap_destroy(&classmap);
+			free(id);
+			return -1;
+		}
+		node = malloc(sizeof(struct constraint_node));
+		if (!node) {
+			yyerror("out of memory");
+			return -1;
+		}
+		memset(node, 0, sizeof(constraint_node_t));
+		node->expr = expr;
+		node->permissions = 0;
+
+		node->next = cladatum->constraints;
+		cladatum->constraints = node;
+
+		free(id);
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		for (i = ebitmap_startbit(&classmap); i < ebitmap_length(&classmap); i++) {
+			if (ebitmap_get_bit(&classmap, i)) {
+				cladatum = policydbp->class_val_to_struct[i];
+				node = cladatum->constraints;
+
+				perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
+						     (hashtab_key_t) id);
+				if (!perdatum) {
+					if (cladatum->comdatum) {
+						perdatum = (perm_datum_t *) hashtab_search(cladatum->comdatum->permissions.table,
+						     (hashtab_key_t) id);
+					}
+					if (!perdatum) {
+						sprintf(errormsg, "permission %s is not defined", id);
+						yyerror(errormsg);
+						free(id);
+						ebitmap_destroy(&classmap);
+						return -1;
+					}
+				}
+				node->permissions |= (1 << (perdatum->value - 1));
+			}
+		}
+		free(id);
+	}
+
+	ebitmap_destroy(&classmap);
+
+	return 0;
+}
+
+
+static uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2)
+{
+	struct constraint_expr *expr, *e1 = NULL, *e2;
+	user_datum_t *user;
+	role_datum_t *role;
+	char *id;
+	uint32_t val;
+
+	if (pass == 1) {
+		if (expr_type == CEXPR_NAMES) {
+			while ((id = queue_remove(id_queue))) 
+				free(id);
+		}
+		return 1; /* any non-NULL value */
+	}
+
+	expr = malloc(sizeof(struct constraint_expr));
+	if (!expr) {
+		yyerror("out of memory");
+		return 0;
+	}
+	memset(expr, 0, sizeof(constraint_expr_t));
+	expr->expr_type = expr_type;
+
+	switch (expr_type) {
+	case CEXPR_NOT:
+		e1 = NULL;
+		e2 = (struct constraint_expr *) arg1;
+		while (e2) {
+			e1 = e2;
+			e2 = e2->next;
+		}
+		if (!e1 || e1->next) {
+			yyerror("illegal constraint expression");
+			free(expr);
+			return 0;
+		}
+		e1->next = expr;
+		return arg1;
+	case CEXPR_AND:
+	case CEXPR_OR:
+		e1 = NULL;
+		e2 = (struct constraint_expr *) arg1;
+		while (e2) {
+			e1 = e2;
+			e2 = e2->next;
+		}
+		if (!e1 || e1->next) {
+			yyerror("illegal constraint expression");
+			free(expr);
+			return 0;
+		}
+		e1->next = (struct constraint_expr *) arg2;
+
+		e1 = NULL;
+		e2 = (struct constraint_expr *) arg2;
+		while (e2) {
+			e1 = e2;
+			e2 = e2->next;
+		}
+		if (!e1 || e1->next) {
+			yyerror("illegal constraint expression");
+			free(expr);
+			return 0;
+		}
+		e1->next = expr;
+		return arg1;
+	case CEXPR_ATTR:
+		expr->attr = arg1;
+		expr->op = arg2;
+		return (uintptr_t)expr;
+	case CEXPR_NAMES:
+		expr->attr = arg1;
+		expr->op = arg2;
+		while ((id = (char *) queue_remove(id_queue))) {
+			if (expr->attr & CEXPR_USER) {
+				user = (user_datum_t *) hashtab_search(policydbp->p_users.table,
+								       (hashtab_key_t) id);
+				if (!user) {
+					sprintf(errormsg, "unknown user %s", id);
+					yyerror(errormsg);
+					free(expr);
+					return 0;
+				}
+				val = user->value;
+			} else if (expr->attr & CEXPR_ROLE) {
+				role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
+								       (hashtab_key_t) id);
+				if (!role) {
+					sprintf(errormsg, "unknown role %s", id);
+					yyerror(errormsg);
+					free(expr);
+					return 0;
+				}
+				val = role->value;
+			} else if (expr->attr & CEXPR_TYPE) {
+				if (set_types(&expr->names, id)) {
+					free(expr);
+					return 0;
+				}
+				continue;
+			} else {
+				yyerror("invalid constraint expression");
+				free(expr);
+				return 0;
+			}
+			if (!ebitmap_set_bit(&expr->names, val - 1, TRUE)) {
+				yyerror("out of memory");
+				ebitmap_destroy(&expr->names);
+				free(expr);
+				return 0;
+			}
+			free(id);
+		}
+		return (uintptr_t)expr;
+	default:
+		yyerror("invalid constraint expression");
+		free(expr);
+		return 0;
+	}
+
+	yyerror("invalid constraint expression");
+	free(expr);
+	return 0;
+}
+
+
+static int set_user_roles(ebitmap_t *set,
+			  char *id)
+{
+	role_datum_t *r;
+	int i;
+
+	if (strcmp(id, "*") == 0) {
+		/* set all roles */
+		for (i = 0; i < policydbp->p_roles.nprim; i++) 
+			ebitmap_set_bit(set, i, TRUE);
+		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);
+		}
+		free(id);
+		return 0;
+	}
+
+	r = hashtab_search(policydbp->p_roles.table, id);
+	if (!r) {
+		sprintf(errormsg, "unknown role %s", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+
+	/* 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);
+	}
+	free(id);
+	return 0;
+}
+
+
+static int define_user(void)
+{
+	char *id;
+	user_datum_t *usrdatum;
+	int ret;
+#ifdef CONFIG_FLASK_MLS
+	mls_range_list_t *rnode;
+	level_datum_t *levdatum;
+	cat_datum_t *catdatum;
+	int relation, l;
+	char *levid;
+#endif
+
+	if (pass == 1) {
+		while ((id = queue_remove(id_queue))) 
+			free(id);
+#ifdef CONFIG_FLASK_MLS
+		while ((id = queue_remove(id_queue))) { 
+			free(id);
+			for (l = 0; l < 2; l++) {
+				while ((id = queue_remove(id_queue))) { 
+					free(id);
+				}
+			}
+		}
+#endif
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no user name for user definition?");
+		return -1;
+	}
+	usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table,
+						   (hashtab_key_t) id);
+	if (!usrdatum) {
+		usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t));
+		if (!usrdatum) {
+			yyerror("out of memory");
+			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);
+		if (ret) {
+			yyerror("hash table overflow");
+			free(usrdatum);
+			free(id);
+			return -1;
+		}
+	} else
+		free(id);
+
+	while ((id = queue_remove(id_queue))) {
+		if (set_user_roles(&usrdatum->roles, id))
+			continue;
+	}
+
+#ifdef CONFIG_FLASK_MLS
+	id = queue_remove(id_queue);
+	if (!id) {
+		rnode = (mls_range_list_t *) malloc(sizeof(mls_range_list_t));
+		if (!rnode) {
+			yyerror("out of memory");
+			free(id);
+			return -1;
+		}
+		memset(rnode, 0, sizeof(mls_range_list_t));
+		levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+							    (hashtab_key_t) "unclassified");
+		if (!levdatum) {
+			yyerror("no range for user");
+			return -1;
+		}
+		rnode->range.level[0].sens = levdatum->level->sens;
+		rnode->range.level[1].sens = levdatum->level->sens;
+		rnode->next = usrdatum->ranges;
+		usrdatum->ranges = rnode;
+		goto skip_mls;
+	} 
+	do {
+		rnode = (mls_range_list_t *) malloc(sizeof(mls_range_list_t));
+		if (!rnode) {
+			yyerror("out of memory");
+			free(id);
+			return -1;
+		}
+		memset(rnode, 0, sizeof(mls_range_list_t));
+
+		for (l = 0; l < 2; l++) {
+			levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+						     (hashtab_key_t) id);
+			if (!levdatum) {
+				sprintf(errormsg, "unknown sensitivity %s used in user range definition", id);
+				yyerror(errormsg);
+				free(rnode);
+				free(id);
+				continue;
+			}
+			rnode->range.level[l].sens = levdatum->level->sens;
+			ebitmap_init(&rnode->range.level[l].cat);
+
+			levid = id;
+
+			while ((id = queue_remove(id_queue))) {
+				catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
+						     (hashtab_key_t) id);
+				if (!catdatum) {
+					sprintf(errormsg, "unknown category %s used in user range definition", id);
+					yyerror(errormsg);
+					free(id);
+					continue;
+				}
+				if (!(ebitmap_get_bit(&levdatum->level->cat, catdatum->value - 1))) {
+					sprintf(errormsg, "category %s cannot be associated with level %s", id, levid);
+					yyerror(errormsg);
+					free(id);
+					continue;
+				}
+				if (!ebitmap_set_bit(&rnode->range.level[l].cat, catdatum->value - 1, TRUE)) {
+					yyerror("out of memory");
+					free(id);
+					free(levid);
+					ebitmap_destroy(&rnode->range.level[l].cat);
+					free(rnode);
+					return -1;
+				}
+
+				/*
+				 * no need to keep category name
+				 */
+				free(id);
+			}
+
+			/*
+			 * no need to keep sensitivity name
+			 */
+			free(levid);
+
+			id = queue_remove(id_queue);
+			if (!id)
+				break;
+		}
+
+		if (l == 0) {
+			rnode->range.level[1].sens = rnode->range.level[0].sens;
+			if (!ebitmap_cpy(&rnode->range.level[1].cat, &rnode->range.level[0].cat)) {
+				yyerror("out of memory");
+				free(id);
+				ebitmap_destroy(&rnode->range.level[0].cat);
+				free(rnode);
+				return -1;
+			}
+		}
+		relation = mls_level_relation(rnode->range.level[1], rnode->range.level[0]);
+		if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ))) {
+			/* high does not dominate low */
+			yyerror("high does not dominate low");
+			ebitmap_destroy(&rnode->range.level[0].cat);
+			ebitmap_destroy(&rnode->range.level[1].cat);
+			free(rnode);
+			return -1;
+		}
+		rnode->next = usrdatum->ranges;
+		usrdatum->ranges = rnode;
+	} while ((id = queue_remove(id_queue)));
+skip_mls:
+#endif
+
+	return 0;
+}
+
+
+static int parse_security_context(context_struct_t * c)
+{
+	char *id;
+	role_datum_t *role;
+	type_datum_t *typdatum;
+	user_datum_t *usrdatum;
+#ifdef CONFIG_FLASK_MLS
+	char *levid;
+	level_datum_t *levdatum;
+	cat_datum_t *catdatum;
+	int l;
+#endif
+
+	if (pass == 1) {
+		id = queue_remove(id_queue); free(id); /* user  */
+		id = queue_remove(id_queue); free(id); /* role  */
+		id = queue_remove(id_queue); free(id); /* type  */
+#ifdef CONFIG_FLASK_MLS
+		id = queue_remove(id_queue); free(id); 
+		for (l = 0; l < 2; l++) {
+			while ((id = queue_remove(id_queue))) {
+				free(id);
+			}
+		}
+#endif 
+		return 0;
+	}
+
+	context_init(c);
+
+	/* extract the user */
+	id = queue_remove(id_queue);
+	if (!id) {
+		yyerror("no effective user?");
+		goto bad;
+	}
+	usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table,
+						   (hashtab_key_t) id);
+	if (!usrdatum) {
+		sprintf(errormsg, "user %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		goto bad;
+	}
+	c->user = usrdatum->value;
+
+	/* no need to keep the user name */
+	free(id);
+
+	/* extract the role */
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no role name for sid context definition?");
+		return -1;
+	}
+	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
+					       (hashtab_key_t) id);
+	if (!role) {
+		sprintf(errormsg, "role %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	c->role = role->value;
+
+	/* no need to keep the role name */
+	free(id);
+
+
+	/* extract the type */
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no type name for sid context definition?");
+		return -1;
+	}
+	typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
+						   (hashtab_key_t) id);
+	if (!typdatum || typdatum->isattr) {
+		sprintf(errormsg, "type %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	c->type = typdatum->value;
+
+	/* no need to keep the type name */
+	free(id);
+
+#ifdef CONFIG_FLASK_MLS
+	/* extract the low sensitivity */
+	id = (char *) queue_head(id_queue);
+	if (!id || strcmp(id, "system_u") == 0 /* hack */) {
+		/* No MLS component to the security context.  Try
+		   to use a default 'unclassified' value. */
+		levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+							    (hashtab_key_t) "unclassified");
+		if (!levdatum) {
+			yyerror("no sensitivity name for sid context definition?");
+			return -1;
+		}
+		c->range.level[0].sens = levdatum->level->sens;
+		c->range.level[1].sens = levdatum->level->sens;
+		goto skip_mls;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	for (l = 0; l < 2; l++) {
+		levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
+						     (hashtab_key_t) id);
+		if (!levdatum) {
+			sprintf(errormsg, "Sensitivity %s is not defined", id);
+			yyerror(errormsg);
+			free(id);
+			return -1;
+		}
+		c->range.level[l].sens = levdatum->level->sens;
+
+		/* extract low category set */
+		levid = id;
+		while ((id = queue_remove(id_queue))) {
+			catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
+						     (hashtab_key_t) id);
+			if (!catdatum) {
+				sprintf(errormsg, "unknown category %s used in initial sid context", id);
+				yyerror(errormsg);
+				free(levid);
+				free(id);
+				goto bad;
+			}
+			if (!ebitmap_set_bit(&c->range.level[l].cat,
+					     catdatum->value - 1, TRUE)) {
+				yyerror("out of memory");
+				free(levid);
+				free(id);
+				goto bad;
+			}
+			/* no need to keep category name */
+			free(id);
+		}
+
+		/* no need to keep the sensitivity name */
+		free(levid);
+
+		/* extract high sensitivity */
+		id = (char *) queue_remove(id_queue);
+		if (!id)
+			break;
+	}
+
+	if (l == 0) {
+		c->range.level[1].sens = c->range.level[0].sens;
+		if (!ebitmap_cpy(&c->range.level[1].cat, &c->range.level[0].cat)) {
+
+			yyerror("out of memory");
+			goto bad;
+		}
+	}
+skip_mls:
+#endif
+
+	if (!policydb_context_isvalid(policydbp, c)) {
+		yyerror("invalid security context");
+		goto bad;
+	}
+	return 0;
+
+      bad:
+	context_destroy(c);
+
+	return -1;
+}
+
+
+static int define_initial_sid_context(void)
+{
+	char *id;
+	ocontext_t *c, *head;
+
+	if (pass == 1) {
+		id = (char *) queue_remove(id_queue); free(id);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		yyerror("no sid name for SID context definition?");
+		return -1;
+	}
+	head = policydbp->ocontexts[OCON_ISID];
+	for (c = head; c; c = c->next) {
+		if (!strcmp(id, c->u.name))
+			break;
+	}
+
+	if (!c) {
+		sprintf(errormsg, "SID %s is not defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	if (c->context[0].user) {
+		sprintf(errormsg, "The context for SID %s is multiply defined", id);
+		yyerror(errormsg);
+		free(id);
+		return -1;
+	}
+	/* no need to keep the sid name */
+	free(id);
+
+	if (parse_security_context(&c->context[0]))
+		return -1;
+
+	return 0;
+}
+
+static int define_fs_context(int major, int minor)
+{
+	ocontext_t *newc, *c, *head;
+
+	if (pass == 1) {
+		parse_security_context(NULL);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	newc->u.name = (char *) malloc(6);
+	if (!newc->u.name) {
+		yyerror("out of memory");
+		free(newc);
+		return -1;
+	}
+	sprintf(newc->u.name, "%02x:%02x", major, minor);
+
+	if (parse_security_context(&newc->context[0])) {
+		free(newc->u.name);
+		free(newc);
+		return -1;
+	}
+	if (parse_security_context(&newc->context[1])) {
+		context_destroy(&newc->context[0]);
+		free(newc->u.name);
+		free(newc);
+		return -1;
+	}
+	head = policydbp->ocontexts[OCON_FS];
+
+	for (c = head; c; c = c->next) {
+		if (!strcmp(newc->u.name, c->u.name)) {
+			sprintf(errormsg, "duplicate entry for file system %s", newc->u.name);
+			yyerror(errormsg);
+			context_destroy(&newc->context[0]);
+			context_destroy(&newc->context[1]);
+			free(newc->u.name);
+			free(newc);
+			return -1;
+		}
+	}
+
+	newc->next = head;
+	policydbp->ocontexts[OCON_FS] = newc;
+
+	return 0;
+}
+
+static int define_port_context(int low, int high)
+{
+	ocontext_t *newc;
+	char *id;
+
+	if (pass == 1) {
+		id = (char *) queue_remove(id_queue); free(id);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	id = (char *) queue_remove(id_queue);
+	if (!id) {
+		free(newc);
+		return -1;
+	}
+	if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) {
+		newc->u.port.protocol = IPPROTO_TCP;
+	} else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) {
+		newc->u.port.protocol = IPPROTO_UDP;
+	} else {
+		sprintf(errormsg, "unrecognized protocol %s", id);
+		yyerror(errormsg);
+		free(newc);
+		return -1;
+	}
+
+	newc->u.port.low_port = low;
+	newc->u.port.high_port = high;
+
+	if (parse_security_context(&newc->context[0])) {
+		free(newc);
+		return -1;
+	}
+	newc->next = policydbp->ocontexts[OCON_PORT];
+	policydbp->ocontexts[OCON_PORT] = newc;
+	return 0;
+}
+
+static int define_netif_context(void)
+{
+	ocontext_t *newc, *c, *head;
+
+	if (pass == 1) {
+		free(queue_remove(id_queue));
+		parse_security_context(NULL);
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	newc->u.name = (char *) queue_remove(id_queue);
+	if (!newc->u.name) {
+		free(newc);
+		return -1;
+	}
+	if (parse_security_context(&newc->context[0])) {
+		free(newc->u.name);
+		free(newc);
+		return -1;
+	}
+	if (parse_security_context(&newc->context[1])) {
+		context_destroy(&newc->context[0]);
+		free(newc->u.name);
+		free(newc);
+		return -1;
+	}
+	head = policydbp->ocontexts[OCON_NETIF];
+
+	for (c = head; c; c = c->next) {
+		if (!strcmp(newc->u.name, c->u.name)) {
+			sprintf(errormsg, "duplicate entry for network interface %s", newc->u.name);
+			yyerror(errormsg);
+			context_destroy(&newc->context[0]);
+			context_destroy(&newc->context[1]);
+			free(newc->u.name);
+			free(newc);
+			return -1;
+		}
+	}
+
+	newc->next = head;
+	policydbp->ocontexts[OCON_NETIF] = newc;
+	return 0;
+}
+
+static int define_node_context(int addr, int mask)
+{
+	ocontext_t *newc, *c, *l, *head;
+
+	if (pass == 1) {
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	newc->u.node.addr = addr;
+	newc->u.node.mask = mask;
+
+	if (parse_security_context(&newc->context[0])) {
+		free(newc);
+		return -1;
+	}
+	/* Place this at the end of the list, to retain
+	   the matching order specified in the configuration. */
+	head = policydbp->ocontexts[OCON_NODE];
+	for (l = NULL, c = head; c; l = c, c = c->next);
+
+	if (l)
+		l->next = newc;
+	else
+		policydbp->ocontexts[OCON_NODE] = newc;
+
+	return 0;
+}
+
+static int define_fs_use(int behavior)
+{
+	ocontext_t *newc, *c, *head;
+
+	if (pass == 1) {
+		free(queue_remove(id_queue));
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	newc->u.name = (char *) queue_remove(id_queue);
+	if (!newc->u.name) {
+		free(newc);
+		return -1;
+	}
+	newc->v.behavior = behavior;
+	if (parse_security_context(&newc->context[0])) {
+		free(newc->u.name);
+		free(newc);
+		return -1;
+	}
+
+	head = policydbp->ocontexts[OCON_FSUSE];
+
+	for (c = head; c; c = c->next) {
+		if (!strcmp(newc->u.name, c->u.name)) {
+			sprintf(errormsg, "duplicate fs_use entry for filesystem type %s", newc->u.name);
+			yyerror(errormsg);
+			context_destroy(&newc->context[0]);
+			free(newc->u.name);
+			free(newc);
+			return -1;
+		}
+	}
+
+	newc->next = head;
+	policydbp->ocontexts[OCON_FSUSE] = newc;
+	return 0;
+}
+
+static int define_genfs_context_helper(char *fstype, int has_type)
+{
+	struct genfs *genfs_p, *genfs, *newgenfs;
+	ocontext_t *newc, *c, *head, *p;
+	char *type = NULL;
+	int len, len2;
+
+	if (pass == 1) {
+		free(fstype);
+		free(queue_remove(id_queue));
+		if (has_type)
+			free(queue_remove(id_queue));
+		parse_security_context(NULL);
+		return 0;
+	}
+
+	for (genfs_p = NULL, genfs = policydbp->genfs; 
+	     genfs; genfs_p = genfs, genfs = genfs->next) {
+		if (strcmp(fstype, genfs->fstype) <= 0)
+			break;
+	}
+
+	if (!genfs || strcmp(fstype, genfs->fstype)) {
+		newgenfs = malloc(sizeof(struct genfs));
+		if (!newgenfs) {
+			yyerror("out of memory");
+			return -1;
+		}
+		memset(newgenfs, 0, sizeof(struct genfs));
+		newgenfs->fstype = fstype;
+		newgenfs->next = genfs;
+		if (genfs_p) 
+			genfs_p->next = newgenfs;
+		else
+			policydbp->genfs = newgenfs;
+		genfs = newgenfs;
+	}
+
+	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
+	if (!newc) {
+		yyerror("out of memory");
+		return -1;
+	}
+	memset(newc, 0, sizeof(ocontext_t));
+
+	newc->u.name = (char *) queue_remove(id_queue);
+	if (!newc->u.name) 
+		goto fail;
+	if (has_type) {
+		type = (char *) queue_remove(id_queue);
+		if (!type) 
+			goto fail;
+		if (type[1] != 0) {
+			sprintf(errormsg, "invalid type %s", type);
+			yyerror(errormsg);
+			goto fail;
+		}
+		switch (type[0]) {
+		case 'b':
+			newc->v.sclass = SECCLASS_BLK_FILE;
+			break;
+		case 'c':
+			newc->v.sclass = SECCLASS_CHR_FILE;
+			break;
+		case 'd':
+			newc->v.sclass = SECCLASS_DIR;
+			break;
+		case 'p':
+			newc->v.sclass = SECCLASS_FIFO_FILE;
+			break;
+		case 'l':
+			newc->v.sclass = SECCLASS_LNK_FILE;
+			break;
+		case 's':
+			newc->v.sclass = SECCLASS_SOCK_FILE;
+			break;
+		case '-':
+			newc->v.sclass = SECCLASS_FILE;
+			break;
+		default:
+			sprintf(errormsg, "invalid type %s", type);
+			yyerror(errormsg);
+			goto fail;
+		}
+	}
+	if (parse_security_context(&newc->context[0])) 
+		goto fail;
+
+	head = genfs->head;
+
+	for (p = NULL, c = head; c; p = c, c = c->next) {
+		if (!strcmp(newc->u.name, c->u.name) && 
+		    (!newc->v.sclass || !c->v.sclass || newc->v.sclass == c->v.sclass)) {
+			sprintf(errormsg, "duplicate entry for genfs entry (%s, %s)", fstype, newc->u.name);
+			yyerror(errormsg);
+			goto fail;
+		}
+		len = strlen(newc->u.name);
+		len2 = strlen(c->u.name);
+		if (len > len2)
+			break;
+	}
+
+	newc->next = c;
+	if (p) 
+		p->next = newc;
+	else
+		genfs->head = newc;
+	return 0;
+fail:
+	if (type)
+		free(type);
+	context_destroy(&newc->context[0]);
+	if (fstype)
+		free(fstype);
+	if (newc->u.name)
+		free(newc->u.name);
+	free(newc);
+	return -1;
+}
+
+static int define_genfs_context(int has_type)
+{
+	return define_genfs_context_helper(queue_remove(id_queue), has_type);
+}
+
+/* FLASK */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/policy_scan.l	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,207 @@
+%array
+
+%{
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* 
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 
+ */
+
+#include <strings.h>
+#include "policy_parse.h"
+
+static char linebuf[2][255];
+static unsigned int lno = 0;
+
+unsigned long policydb_lineno = 1;
+
+unsigned int policydb_errors = 0;
+
+int yywarn(char *msg);
+%}
+%e 5000
+%p 12500
+%a 10000
+%n 2500
+letter  [A-Za-z]
+digit   [0-9]
+%%
+\n.*				{ strncpy(linebuf[lno], yytext+1, 255);
+                                  linebuf[lno][254] = 0;
+                                  lno = 1 - lno; 
+                                  policydb_lineno++;
+                                  yyless(1); }
+CLONE |
+clone				{ return(CLONE); }
+COMMON |
+common				{ return(COMMON); }
+CLASS |
+class				{ return(CLASS); }
+CONSTRAIN |
+constrain			{ return(CONSTRAIN); }
+INHERITS |
+inherits			{ return(INHERITS); }
+SID |
+sid				{ return(SID); }
+ROLE |
+role				{ return(ROLE); }
+ROLES |
+roles				{ return(ROLES); }
+TYPES |
+types				{ return(TYPES); }
+TYPE |
+type				{ return(TYPE); }
+ALIAS |
+alias				{ return(ALIAS); }
+ATTRIBUTE |
+attribute			{ return(ATTRIBUTE); }
+TYPE_TRANSITION |
+type_transition			{ return(TYPE_TRANSITION); }
+TYPE_MEMBER |
+type_member			{ return(TYPE_MEMBER); }
+TYPE_CHANGE |
+type_change			{ return(TYPE_CHANGE); }
+ROLE_TRANSITION |
+role_transition			{ return(ROLE_TRANSITION); }
+SENSITIVITY |
+sensitivity		{ return(SENSITIVITY); }
+DOMINANCE |
+dominance			{ return(DOMINANCE); }
+CATEGORY |
+category			{ return(CATEGORY); }
+LEVEL |
+level				{ return(LEVEL); }
+RANGES |
+ranges				{ return(RANGES); }
+USER |
+user				{ return(USER); }
+NEVERALLOW |
+neverallow		        { return(NEVERALLOW); }
+ALLOW |
+allow			        { return(ALLOW); }
+AUDITALLOW |
+auditallow		        { return(AUDITALLOW); }
+AUDITDENY |
+auditdeny		        { return(AUDITDENY); }
+DONTAUDIT |
+dontaudit                       { return(DONTAUDIT); }
+SOURCE |
+source			        { return(SOURCE); }
+TARGET |
+target			        { return(TARGET); }
+SAMEUSER |
+sameuser			{ return(SAMEUSER);}
+OR |
+or     			        { return(OR);}
+AND |
+and				{ return(AND);}
+NOT |
+not				{ return(NOT);}
+eq |
+EQ				{ return(EQUALS);}
+dom |
+DOM				{ return(DOM);}
+domby |
+DOMBY				{ return(DOMBY);}
+INCOMP |
+incomp				{ return(INCOMP);}
+fscon |
+FSCON                           { return(FSCON);}
+portcon |
+PORTCON                        { return(PORTCON);}
+netifcon |                     
+NETIFCON                       { return(NETIFCON);}
+nodecon |                     
+NODECON                       { return(NODECON);}
+fs_use_xattr |
+FS_USE_XATTR                     {return(FSUSEXATTR);}
+fs_use_task |
+FS_USE_TASK                     {return(FSUSETASK);}
+fs_use_trans |
+FS_USE_TRANS                    {return(FSUSETRANS);}
+genfscon |
+GENFSCON                        { return(GENFSCON);}
+r1 |
+R1				{ return(R1); }
+r2 |
+R2				{ return(R2); }
+u1 |
+U1				{ return(U1); }
+u2 |
+U2				{ return(U2); }
+t1 |
+T1				{ return(T1); }
+t2 |
+T2				{ return(T2); }
+"/"({letter}|{digit}|_|"."|"-"|"/")*	{ return(PATH); }
+{letter}({letter}|{digit}|_)*	{ return(IDENTIFIER); }
+{letter}({letter}|{digit}|_|"."|"-")*	{ return(USER_IDENTIFIER); }
+{digit}{digit}*                 { return(NUMBER); }
+#[^\n]*                         { /* delete comments */ }
+[ \t\f]+			{ /* delete whitespace */ }
+"==" 				{ return(EQUALS); }
+"!="				{ return (NOTEQUAL); }
+"&&"				{ return (AND); }
+"||"				{ return (OR); }
+"!"				{ return (NOT); }
+"," |
+":" |
+";" |
+"(" | 
+")" |
+"{" | 
+"}" |
+"[" |
+"-" |
+"." |
+"]" |
+"~" |
+"*"				{ return(yytext[0]); } 
+.                               { yywarn("unrecognized character");}
+%%
+int yyerror(char *msg)
+{
+	fprintf(stderr, "ERROR '%s' at token '%s' on line %ld:\n%s\n%s\n",
+			msg,
+			yytext,
+			policydb_lineno,
+			linebuf[0], linebuf[1]);
+	policydb_errors++;
+	return -1;
+}
+
+int yywarn(char *msg)
+{
+	fprintf(stderr, "WARNING '%s' at token '%s' on line %ld:\n%s\n%s\n",
+			msg,
+			yytext,
+			policydb_lineno,
+			linebuf[0], linebuf[1]);
+	return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/queue.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,214 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the double-ended queue type.
+ */
+
+#include <stdlib.h>
+#include <queue.h>
+
+queue_info_ptr_t
+queue_create(void)
+{
+	queue_info_ptr_t q;
+
+	q = (queue_info_ptr_t) malloc(sizeof (struct queue_info));
+	if (q == NULL)
+		return (NULL);
+
+	q->head = q->tail = NULL;
+
+	return (q);
+}
+
+int
+queue_insert(queue_info_ptr_t q, queue_element_t e)
+{
+	queue_node_ptr_t newnode;
+
+
+	if (!q)
+		return (-1);
+
+	newnode = (queue_node_ptr_t) malloc(sizeof (struct queue_node));
+	if (newnode == NULL)
+		return (-1);
+
+	newnode->element = e;
+	newnode->next = NULL;
+
+	if (q->head == NULL) {
+		q->head = q->tail = newnode;
+	} else {
+		q->tail->next = newnode;
+		q->tail = newnode;
+	}
+
+	return (0);
+}
+
+int
+queue_push(queue_info_ptr_t q, queue_element_t e)
+{
+	queue_node_ptr_t newnode;
+
+
+	if (!q)
+		return (-1);
+
+	newnode = (queue_node_ptr_t) malloc(sizeof (struct queue_node));
+	if (newnode == NULL)
+		return (-1);
+
+	newnode->element = e;
+	newnode->next = NULL;
+
+	if (q->head == NULL) {
+		q->head = q->tail = newnode;
+	} else {
+		newnode->next = q->head;
+		q->head = newnode;
+	}
+
+	return (0);
+}
+
+queue_element_t
+queue_remove(queue_info_ptr_t q)
+{
+	queue_node_ptr_t node;
+	queue_element_t e;
+
+
+	if (!q)
+		return (NULL);
+
+	if (q->head == NULL)
+		return (NULL);
+
+	node = q->head;
+	q->head = q->head->next;
+	if (q->head == NULL)
+		q->tail = NULL;
+
+	e = node->element;
+	free(node);
+
+	return (e);
+}
+
+queue_element_t
+queue_head(queue_info_ptr_t q)
+{
+	if (!q)
+		return (NULL);
+
+	if (q->head == NULL)
+		return (NULL);
+
+	return (q->head->element);
+}
+
+void
+queue_destroy(queue_info_ptr_t q)
+{
+	queue_node_ptr_t p, temp;
+
+
+	if (!q)
+		return;
+
+	p = q->head;
+	while (p != NULL) {
+		temp = p;
+		p = p->next;
+		free(temp);
+	}
+
+	free(q);
+}
+
+int
+queue_map(queue_info_ptr_t q, int (*f) (queue_element_t, void *), void *vp)
+{
+	queue_node_ptr_t p;
+	int ret;
+
+
+	if (!q)
+		return (0);
+
+	p = q->head;
+	while (p != NULL) {
+		ret = f(p->element, vp);
+		if (ret)
+			return (ret);
+		p = p->next;
+	}
+	return (0);
+}
+
+
+void
+queue_map_remove_on_error(queue_info_ptr_t q,
+    int (*f) (queue_element_t, void *), void (*g) (queue_element_t, void *),
+    void *vp)
+{
+	queue_node_ptr_t p, last, temp;
+	int ret;
+
+
+	if (!q)
+		return;
+
+	last = NULL;
+	p = q->head;
+	while (p != NULL) {
+		ret = f(p->element, vp);
+		if (ret) {
+			if (last) {
+				last->next = p->next;
+				if (last->next == NULL)
+					q->tail = last;
+			} else {
+				q->head = p->next;
+				if (q->head == NULL)
+					q->tail = NULL;
+			}
+
+			temp = p;
+			p = p->next;
+			g(temp->element, vp);
+			free(temp);
+		} else {
+			last = p;
+			p = p->next;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/queue.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A double-ended queue is a singly linked list of
+ * elements of arbitrary type that may be accessed
+ * at either end.
+ */
+
+#ifndef _QUEUE_H
+#define	_QUEUE_H
+
+typedef void *queue_element_t;
+
+typedef struct queue_node *queue_node_ptr_t;
+
+typedef struct queue_node {
+	queue_element_t element;
+	queue_node_ptr_t next;
+} queue_node_t;
+
+typedef struct queue_info {
+	queue_node_ptr_t head;
+	queue_node_ptr_t tail;
+} queue_info_t;
+
+typedef queue_info_t *queue_info_ptr_t;
+
+queue_info_ptr_t queue_create(void);
+int queue_insert(queue_info_ptr_t, queue_element_t);
+int queue_push(queue_info_ptr_t, queue_element_t);
+queue_element_t queue_remove(queue_info_ptr_t);
+queue_element_t queue_head(queue_info_ptr_t);
+void queue_destroy(queue_info_ptr_t);
+
+/*
+ * Applies the specified function f to each element in the
+ * specified queue.
+ *
+ * In addition to passing the element to f, queue_map
+ * passes the specified void* pointer to f on each invocation.
+ *
+ * If f returns a non-zero status, then queue_map will cease
+ * iterating through the hash table and will propagate the error
+ * return to its caller.
+ */
+int queue_map(queue_info_ptr_t, int (*f) (queue_element_t, void *), void *);
+
+/*
+ * Same as queue_map, except that if f returns a non-zero status,
+ * then the element will be removed from the queue and the g
+ * function will be applied to the element.
+ */
+void queue_map_remove_on_error(
+	queue_info_ptr_t,
+	int (*f) (queue_element_t, void *),
+	void (*g) (queue_element_t, void *),
+	void *);
+
+#endif /* _QUEUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/checkpolicy/write.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,808 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+#include "ss_impl.h"
+#include <ebitmap.h>
+#include <avtab.h>
+#include <mls.h>
+#include <policydb.h>
+
+int
+ebitmap_write(ebitmap_t *e, FILE *fp)
+{
+	ebitmap_node_t *n;
+	uint32_t buf[32], bit, count;
+	uint64_t map;
+	size_t items;
+
+	buf[0] = SS_CPU_TO_LE32(MAPSIZE);
+	buf[1] = SS_CPU_TO_LE32(e->highbit);
+
+	count = 0;
+	for (n = e->node; n; n = n->next)
+		count++;
+	buf[2] = SS_CPU_TO_LE32(count);
+
+	items = fwrite(buf, sizeof (uint32_t), 3, fp);
+	if (items != 3)
+		return (FALSE);
+
+	for (n = e->node; n; n = n->next) {
+		bit = SS_CPU_TO_LE32(n->startbit);
+		items = fwrite(&bit, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			return (FALSE);
+		map = SS_CPU_TO_LE64(n->map);
+		items = fwrite(&map, sizeof (uint64_t), 1, fp);
+		if (items != 1)
+			return (FALSE);
+
+	}
+
+	return (TRUE);
+}
+
+int
+avtab_write(avtab_t *a, FILE *fp)
+{
+	int i;
+	avtab_ptr_t cur;
+	uint32_t buf[32];
+	uint32_t nel;
+	size_t items, items2;
+
+	nel = SS_CPU_TO_LE32(a->nel);
+	items = fwrite(&nel, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+
+	for (i = 0; i < AVTAB_SIZE; i++) {
+		for (cur = a->htable[i]; cur; cur = cur->next) {
+			items = 1;	/* item 0 is used for the item count */
+			buf[items++] = SS_CPU_TO_LE32(cur->key.source_type);
+			buf[items++] = SS_CPU_TO_LE32(cur->key.target_type);
+			buf[items++] = SS_CPU_TO_LE32(cur->key.target_class);
+			buf[items++] = SS_CPU_TO_LE32(cur->datum.specified);
+			if (!(cur->datum.specified & (AVTAB_AV | AVTAB_TYPE))) {
+				printf("security: avtab: null entry\n");
+				return (-1);
+			}
+			if ((cur->datum.specified & AVTAB_AV) &&
+			    (cur->datum.specified & AVTAB_TYPE)) {
+				printf("security: avtab: entry has both "
+					"access vectors and types\n");
+				return (-1);
+			}
+			if (cur->datum.specified & AVTAB_AV) {
+				if (cur->datum.specified & AVTAB_ALLOWED)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_allowed(&cur->datum));
+				if (cur->datum.specified & AVTAB_AUDITDENY)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_auditdeny(&cur->datum));
+				if (cur->datum.specified & AVTAB_AUDITALLOW)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_auditallow(&cur->datum));
+			} else {
+				if (cur->datum.specified & AVTAB_TRANSITION)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_transition(&cur->datum));
+				if (cur->datum.specified & AVTAB_CHANGE)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_change(&cur->datum));
+				if (cur->datum.specified & AVTAB_MEMBER)
+					buf[items++] = SS_CPU_TO_LE32(
+						avtab_member(&cur->datum));
+			}
+			buf[0] = SS_CPU_TO_LE32(items - 1);
+
+			items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+			if (items != items2)
+				return (-1);
+		}
+	}
+
+	return (0);
+}
+
+#ifdef CONFIG_FLASK_MLS
+/*
+ * Write a MLS level structure to a policydb binary
+ * representation file.
+ */
+int
+mls_write_level(mls_level_t *l, FILE *fp)
+{
+	uint32_t sens;
+	int items;
+
+	sens = SS_CPU_TO_LE32(l->sens);
+	items = fwrite(&sens, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+
+	if (!ebitmap_write(&l->cat, fp))
+		return (-1);
+
+	return (0);
+}
+
+
+/*
+ * Write a MLS range structure to a policydb binary
+ * representation file.
+ */
+static int
+mls_write_range_helper(mls_range_t *r, FILE *fp)
+{
+	uint32_t buf[3];
+	int items, items2;
+	int rel;
+
+	rel = mls_level_relation(r->level[1], r->level[0]);
+
+	items = 1;		/* item 0 is used for the item count */
+	buf[items++] = SS_CPU_TO_LE32(r->level[0].sens);
+	if (rel != MLS_RELATION_EQ)
+		buf[items++] = SS_CPU_TO_LE32(r->level[1].sens);
+	buf[0] = SS_CPU_TO_LE32(items - 1);
+
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items2 != items)
+		return (-1);
+
+	if (!ebitmap_write(&r->level[0].cat, fp))
+		return (-1);
+	if (rel != MLS_RELATION_EQ)
+		if (!ebitmap_write(&r->level[1].cat, fp))
+			return (-1);
+
+	return (0);
+}
+
+int
+mls_write_range(context_struct_t *c, FILE *fp)
+{
+	return (mls_write_range_helper(&c->range, fp));
+}
+
+
+/*
+ * Write a MLS perms structure to a policydb binary
+ * representation file.
+ */
+int
+mls_write_class(class_datum_t *cladatum, FILE *fp)
+{
+	mls_perms_t *p = &cladatum->mlsperms;
+	uint32_t buf[32];
+	int items, items2;
+
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(p->read);
+	buf[items++] = SS_CPU_TO_LE32(p->readby);
+	buf[items++] = SS_CPU_TO_LE32(p->write);
+	buf[items++] = SS_CPU_TO_LE32(p->writeby);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items2 != items)
+		return (-1);
+
+	return (0);
+}
+
+#define	mls_write_perm(buf, items, perdatum) \
+	buf[items++] = SS_CPU_TO_LE32(perdatum->base_perms);
+
+int
+mls_write_user(user_datum_t *usrdatum, FILE *fp)
+{
+	mls_range_list_t *r;
+	uint32_t nel;
+	uint32_t buf[32];
+	int items;
+
+	nel = 0;
+	for (r = usrdatum->ranges; r; r = r->next)
+		nel++;
+	buf[0] = SS_CPU_TO_LE32(nel);
+	items = fwrite(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	for (r = usrdatum->ranges; r; r = r->next) {
+		if (mls_write_range_helper(&r->range, fp))
+			return (-1);
+	}
+	return (0);
+}
+
+int
+mls_write_nlevels(policydb_t *p, FILE *fp)
+{
+	uint32_t buf[32];
+	size_t items;
+
+	buf[0] = SS_CPU_TO_LE32(p->nlevels);
+	items = fwrite(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	return (0);
+}
+
+int
+mls_write_trusted(policydb_t *p, FILE *fp)
+{
+	if (!ebitmap_write(&p->trustedreaders, fp))
+		return (-1);
+	if (!ebitmap_write(&p->trustedwriters, fp))
+		return (-1);
+	if (!ebitmap_write(&p->trustedobjects, fp))
+		return (-1);
+	return (0);
+}
+
+int
+sens_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	level_datum_t *levdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+	levdatum = (level_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(levdatum->isalias);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	if (mls_write_level(levdatum->level, fp))
+		return (-1);
+
+	return (0);
+}
+
+int
+cat_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	cat_datum_t *catdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+
+	catdatum = (cat_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(catdatum->value);
+	buf[items++] = SS_CPU_TO_LE32(catdatum->isalias);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	return (0);
+}
+#else
+#define	mls_write_range(c, fp) 0
+#define	mls_write_class(c, fp) 0
+#define	mls_write_perm(buf, items, perdatum)
+#define	mls_write_user(u, fp) 0
+#define	mls_write_nlevels(p, fp) 0
+#define	mls_write_trusted(p, fp) 0
+#endif
+
+/*
+ * Write a security context structure
+ * to a policydb binary representation file.
+ */
+static int
+context_write(context_struct_t *c, FILE *fp)
+{
+	uint32_t buf[32];
+	size_t items, items2;
+
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(c->user);
+	buf[items++] = SS_CPU_TO_LE32(c->role);
+	buf[items++] = SS_CPU_TO_LE32(c->type);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items2 != items)
+		return (-1);
+	if (mls_write_range(c, fp))
+		return (-1);
+
+	return (0);
+}
+
+
+/*
+ * The following *_write functions are used to
+ * write the symbol data to a policy database
+ * binary representation file.
+ */
+
+static int
+perm_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	perm_datum_t *perdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+	perdatum = (perm_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(perdatum->value);
+	mls_write_perm(buf, items, perdatum);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	return (0);
+}
+
+
+static int
+common_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	common_datum_t *comdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+	comdatum = (common_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(comdatum->value);
+	buf[items++] = SS_CPU_TO_LE32(comdatum->permissions.nprim);
+	buf[items++] = SS_CPU_TO_LE32(comdatum->permissions.table->nel);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	if (hashtab_map(comdatum->permissions.table, perm_write, fp))
+		return (-1);
+
+	return (0);
+}
+
+
+static int
+class_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	class_datum_t *cladatum;
+	constraint_node_t *c;
+	constraint_expr_t *e;
+	uint32_t buf[32], len, len2, ncons, nexpr;
+	int items, items2;
+	FILE *fp = p;
+
+	cladatum = (class_datum_t *) datum;
+
+	len = strlen(key);
+	if (cladatum->comkey)
+		len2 = strlen(cladatum->comkey);
+	else
+		len2 = 0;
+
+	ncons = 0;
+	for (c = cladatum->constraints; c; c = c->next) {
+		ncons++;
+	}
+
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(len2);
+	buf[items++] = SS_CPU_TO_LE32(cladatum->value);
+	buf[items++] = SS_CPU_TO_LE32(cladatum->permissions.nprim);
+	if (cladatum->permissions.table)
+		buf[items++] = SS_CPU_TO_LE32(
+			cladatum->permissions.table->nel);
+	else
+		buf[items++] = 0;
+	buf[items++] = SS_CPU_TO_LE32(ncons);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	if (cladatum->comkey) {
+		items = fwrite(cladatum->comkey, 1, len2, fp);
+		if (items != len2)
+			return (-1);
+	}
+	if (hashtab_map(cladatum->permissions.table, perm_write, fp))
+		return (-1);
+
+	for (c = cladatum->constraints; c; c = c->next) {
+		nexpr = 0;
+		for (e = c->expr; e; e = e->next) {
+			nexpr++;
+		}
+		buf[0] = SS_CPU_TO_LE32(c->permissions);
+		buf[1] = SS_CPU_TO_LE32(nexpr);
+		items = fwrite(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			return (-1);
+		for (e = c->expr; e; e = e->next) {
+			items = 0;
+			buf[items++] = SS_CPU_TO_LE32(e->expr_type);
+			buf[items++] = SS_CPU_TO_LE32(e->attr);
+			buf[items++] = SS_CPU_TO_LE32(e->op);
+			items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+			if (items != items2)
+				return (-1);
+
+			switch (e->expr_type) {
+			case CEXPR_NAMES:
+				if (!ebitmap_write(&e->names, fp))
+					return (-1);
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	if (mls_write_class(cladatum, fp))
+		return (-1);
+
+	return (0);
+}
+
+static int
+role_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	role_datum_t *role;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+	role = (role_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(role->value);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	if (!ebitmap_write(&role->dominates, fp))
+		return (-1);
+
+	if (!ebitmap_write(&role->types, fp))
+		return (-1);
+
+	return (0);
+}
+
+static int
+type_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	type_datum_t *typdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+	typdatum = (type_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(typdatum->value);
+	buf[items++] = SS_CPU_TO_LE32(typdatum->primary);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	return (0);
+}
+
+static int
+user_write(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	user_datum_t *usrdatum;
+	uint32_t buf[32], len;
+	int items, items2;
+	FILE *fp = p;
+
+
+	usrdatum = (user_datum_t *) datum;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(len);
+	buf[items++] = SS_CPU_TO_LE32(usrdatum->value);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	items = fwrite(key, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	if (!ebitmap_write(&usrdatum->roles, fp))
+		return (-1);
+
+	return (mls_write_user(usrdatum, fp));
+}
+
+
+static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
+    void *datap) =
+{
+	common_write,
+	class_write,
+	role_write,
+	type_write,
+	user_write
+	mls_write_f
+};
+
+
+/*
+ * Write the configuration data in a policy database
+ * structure to a policy database binary representation
+ * file.
+ */
+int
+policydb_write(policydb_t *p, FILE *fp)
+{
+	struct role_allow *ra;
+	struct role_trans *tr;
+	ocontext_t *c;
+	genfs_t *genfs;
+	int i, j;
+	uint32_t buf[32], len, config, nel;
+	size_t items, items2;
+	char *policydb_str = POLICYDB_STRING;
+
+	config = 0;
+	mls_set_config(config);
+
+	/* Write the magic number and string identifiers. */
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(POLICYDB_MAGIC);
+	len = strlen(POLICYDB_STRING);
+	buf[items++] = SS_CPU_TO_LE32(len);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+	items = fwrite(policydb_str, 1, len, fp);
+	if (items != len)
+		return (-1);
+
+	/* Write the version, config, and table sizes. */
+	items = 0;
+	buf[items++] = SS_CPU_TO_LE32(POLICYDB_VERSION);
+	buf[items++] = SS_CPU_TO_LE32(config);
+	buf[items++] = SS_CPU_TO_LE32(SYM_NUM);
+	buf[items++] = SS_CPU_TO_LE32(OCON_NUM);
+	items2 = fwrite(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		return (-1);
+
+	if (mls_write_nlevels(p, fp))
+		return (-1);
+
+	for (i = 0; i < SYM_NUM; i++) {
+		buf[0] = SS_CPU_TO_LE32(p->symtab[i].nprim);
+		buf[1] = SS_CPU_TO_LE32(p->symtab[i].table->nel);
+		items = fwrite(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			return (-1);
+		if (hashtab_map(p->symtab[i].table, write_f[i], fp))
+			return (-1);
+	}
+
+	if (avtab_write(&p->te_avtab, fp))
+		return (-1);
+
+	nel = 0;
+	for (tr = p->role_tr; tr; tr = tr->next)
+		nel++;
+	buf[0] = SS_CPU_TO_LE32(nel);
+	items = fwrite(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	for (tr = p->role_tr; tr; tr = tr->next) {
+		buf[0] = SS_CPU_TO_LE32(tr->role);
+		buf[1] = SS_CPU_TO_LE32(tr->type);
+		buf[2] = SS_CPU_TO_LE32(tr->new_role);
+		items = fwrite(buf, sizeof (uint32_t), 3, fp);
+		if (items != 3)
+			return (-1);
+	}
+
+	nel = 0;
+	for (ra = p->role_allow; ra; ra = ra->next)
+		nel++;
+	buf[0] = SS_CPU_TO_LE32(nel);
+	items = fwrite(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	for (ra = p->role_allow; ra; ra = ra->next) {
+		buf[0] = SS_CPU_TO_LE32(ra->role);
+		buf[1] = SS_CPU_TO_LE32(ra->new_role);
+		items = fwrite(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			return (-1);
+	}
+
+	for (i = 0; i < OCON_NUM; i++) {
+		nel = 0;
+		for (c = p->ocontexts[i]; c; c = c->next)
+			nel++;
+		buf[0] = SS_CPU_TO_LE32(nel);
+		items = fwrite(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			return (-1);
+		for (c = p->ocontexts[i]; c; c = c->next) {
+			switch (i) {
+			case OCON_ISID:
+				buf[0] = SS_CPU_TO_LE32(c->sid[0]);
+				items = fwrite(buf, sizeof (uint32_t), 1, fp);
+				if (items != 1)
+					return (-1);
+				if (context_write(&c->context[0], fp))
+					return (-1);
+				break;
+			case OCON_FS:
+			case OCON_NETIF:
+				len = strlen(c->u.name);
+				buf[0] = SS_CPU_TO_LE32(len);
+				items = fwrite(buf, sizeof (uint32_t), 1, fp);
+				if (items != 1)
+					return (-1);
+				items = fwrite(c->u.name, 1, len, fp);
+				if (items != len)
+					return (-1);
+				if (context_write(&c->context[0], fp))
+					return (-1);
+				if (context_write(&c->context[1], fp))
+					return (-1);
+				break;
+			case OCON_PORT:
+				buf[0] = c->u.port.protocol;
+				buf[1] = c->u.port.low_port;
+				buf[2] = c->u.port.high_port;
+				for (j = 0; j < 3; j++) {
+					buf[j] = SS_CPU_TO_LE32(buf[j]);
+				}
+				items = fwrite(buf, sizeof (uint32_t), 3, fp);
+				if (items != 3)
+					return (-1);
+				if (context_write(&c->context[0], fp))
+					return (-1);
+				break;
+			case OCON_NODE:
+				buf[0] = SS_CPU_TO_LE32(c->u.node.addr);
+				buf[1] = SS_CPU_TO_LE32(c->u.node.mask);
+				items = fwrite(buf, sizeof (uint32_t), 2, fp);
+				if (items != 2)
+					return (-1);
+				if (context_write(&c->context[0], fp))
+					return (-1);
+				break;
+			case OCON_FSUSE:
+				buf[0] = SS_CPU_TO_LE32(c->v.behavior);
+				len = strlen(c->u.name);
+				buf[1] = SS_CPU_TO_LE32(len);
+				items = fwrite(buf, sizeof (uint32_t), 2, fp);
+				if (items != 2)
+					return (-1);
+				items = fwrite(c->u.name, 1, len, fp);
+				if (items != len)
+					return (-1);
+				if (context_write(&c->context[0], fp))
+					return (-1);
+				break;
+			}
+		}
+	}
+
+	nel = 0;
+	for (genfs = p->genfs; genfs; genfs = genfs->next)
+		nel++;
+	buf[0] = SS_CPU_TO_LE32(nel);
+	items = fwrite(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	for (genfs = p->genfs; genfs; genfs = genfs->next) {
+		len = strlen(genfs->fstype);
+		buf[0] = SS_CPU_TO_LE32(len);
+		items = fwrite(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			return (-1);
+		items = fwrite(genfs->fstype, 1, len, fp);
+		if (items != len)
+			return (-1);
+		nel = 0;
+		for (c = genfs->head; c; c = c->next)
+			nel++;
+		buf[0] = SS_CPU_TO_LE32(nel);
+		items = fwrite(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			return (-1);
+		for (c = genfs->head; c; c = c->next) {
+			len = strlen(c->u.name);
+			buf[0] = SS_CPU_TO_LE32(len);
+			items = fwrite(buf, sizeof (uint32_t), 1, fp);
+			if (items != 1)
+				return (-1);
+			items = fwrite(c->u.name, 1, len, fp);
+			if (items != len)
+				return (-1);
+			buf[0] = SS_CPU_TO_LE32(c->v.sclass);
+			items = fwrite(buf, sizeof (uint32_t), 1, fp);
+			if (items != 1)
+				return (-1);
+			if (context_write(&c->context[0], fp))
+				return (-1);
+		}
+	}
+
+	if (mls_write_trusted(p, fp))
+		return (-1);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,234 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Makefile for the security policy.
+#
+# Targets:
+# 
+# policy - compile the policy configuration.
+# install - compile and install the policy configuration.
+# load    - compile, install, and load the policy configuration.
+# relabel - relabel the file system based on file_contexts.
+# initpolicy - compile the initial policy configuration.
+# initinstall - compile and install the initial policy configuration.
+#
+# The default target is 'policy'.
+#
+
+include ../../Makefile.cmd
+
+M4FLAGS = -B81920
+
+COMMONBASE = $(SRC)/common
+
+# Detect if MLS is enabled
+CHECK_FOR_MLS =		if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS'	\
+				$(SRC)/common/fmac/ss/ss_impl.h ; then	\
+				echo "yes" ;				\
+			else						\
+				echo "" ;				\
+			fi ;
+
+CHECKPOLICY = ../checkpolicy/checkpolicy
+
+SETFILES = ../setfiles/setfiles
+
+MLS_FLAG =		$(CHECK_FOR_MLS:sh)
+
+ADMIN_DOMAINS =		domains/admin/sysadm.te
+
+PROGRAM_DOMAINS =	domains/program/crontab.te		\
+			domains/program/fsadm.te		\
+			domains/program/gnome-pty-helper.te	\
+			domains/program/ifconfig.te		\
+			domains/program/logrotate.te		\
+			domains/program/lpr.te			\
+			domains/program/mail.te			\
+			domains/program/modutil.te		\
+			domains/program/netscape.te		\
+			domains/program/newrole.te		\
+			domains/program/passwd.te		\
+			domains/program/su.te			\
+			domains/program/utempter.te		\
+			domains/program/xserver.te
+
+SYSTEM_DOMAINS =	domains/system/apmd.te			\
+			domains/system/atd.te			\
+			domains/system/cardmgr.te		\
+			domains/system/crond.te			\
+			domains/system/ftpd.te			\
+			domains/system/getty.te			\
+			domains/system/gpm.te			\
+			domains/system/inetd.te			\
+			domains/system/init.te			\
+			domains/system/initrc.te		\
+			domains/system/kernel.te		\
+			domains/system/klogd.te			\
+			domains/system/kmod.te			\
+			domains/system/login.te			\
+			domains/system/lpd.te			\
+			domains/system/portmap.te		\
+			domains/system/rlogind.te		\
+			domains/system/rpcd.te			\
+			domains/system/rshd.te			\
+			domains/system/sendmail.te		\
+			domains/system/sshd.te			\
+			domains/system/syslogd.te		\
+			domains/system/tcpd.te			\
+			domains/system/xfs.te			\
+			domains/system/ypbind.te
+
+USER_DOMAINS =		domains/user/user.te
+
+ALL_DOMAINS =		$(ADMIN_DOMAINS)			\
+			$(PROGRAM_DOMAINS)			\
+			$(SYSTEM_DOMAINS)			\
+			$(USER_DOMAINS)
+
+TYPES =			types/device.te				\
+			types/devpts.te				\
+			types/file.te				\
+			types/network.te			\
+			types/nfs.te				\
+			types/procfs.te				\
+			types/security.te
+
+FLASK_FILES =		$(COMMONBASE)/fmac/policy/flask/security_classes    \
+			$(COMMONBASE)/fmac/policy/flask/initial_sids	    \
+			$(COMMONBASE)/fmac/policy/flask/access_vectors
+
+USERS_FILE =		users$(MLS_SUFFIX)
+
+POLICY_FILES = 		initial_sid_contexts$(MLS_SUFFIX)		\
+			fs_use$(MLS_SUFFIX)				\
+			net_contexts$(MLS_SUFFIX)
+
+FILECONTEXT_FILE =	file_contexts$(MLS_SUFFIX)
+
+MLS_FILE =		$(MLS_FLAG:yes=mls)
+
+MLS_SUFFIX =		$(MLS_FLAG:yes=.mls)
+
+POLICYFILES += $(FLASK_FILES)
+
+POLICYFILES += $(MLS_FILE)
+
+POLICYFILES += all.te rbac
+
+POLICYFILES += $(USERS_FILE)
+
+POLICYFILES += constraints 
+
+POLICYFILES += $(POLICY_FILES)
+
+CLOBBERFILES +=	all.te all_types.te all_domains.te system_domains.te	\
+		program_domains.te user_domains.te admin_domains.te	\
+		file_contexts.mls fs_use.mls initial_sid_contexts.mls	\
+		net_contexts.mls fs_contexts.mls users.mls
+
+.KEEP_STATE:
+
+all: policy
+
+policy:  policy.conf
+	$(CHECKPOLICY) -o $@ policy.conf
+	$(CHECKPOLICY) -b $@
+
+policy.conf: $(POLICYFILES)
+	$(M4) $(M4FLAGS) -s $^ > policy.conf
+
+fs_contexts.mls: fs_contexts
+	$(SED) 's/_t/_t:u/g' $^ > $@
+
+fs_use.mls: fs_use
+	$(SED) 's/_t/_t:u/g' $^ > $@
+
+net_contexts.mls: net_contexts
+	$(SED) 's/_t/_t:u/g' $^ > $@
+
+initial_sid_contexts.mls: initial_sid_contexts
+	$(SED) 's/_t/_t:u/g' $^ > $@
+
+users.mls: users
+	$(SED) 's/;/ ranges u;/' $^ > $@
+
+install: policy
+	install -s -m 744 -d $(ROOT)/etc/security/fmac
+	cp policy ss_policy
+	install -s -m 644 -f $(ROOT)/etc/security/fmac ss_policy
+
+load: install
+	load_policy /ss_policy
+
+file_contexts.mls: file_contexts
+	$(SED) 's/_t/_t:u/g' $^ > $@
+
+relabel:  $(FILECONTEXT_FILE) 
+	$(SETFILES) -v $(FILECONTEXT_FILE) `mount -p | awk '/ufs/{print $$3}; /zfs/{print $$3}'`
+	$(TOUCH) relabel
+
+initpolicy: initpolicy.conf $(CHECKPOLICY)
+	$(CHECKPOLICY) -o $@ initpolicy.conf
+	$(CHECKPOLICY) -b $@
+
+initpolicy.conf: $(INITPOLICYFILES) all.te
+	$(M4) $(M4FLAGS) -s $(INITPOLICYFILES) > initpolicy.conf
+
+initinstall:  initpolicy
+	install -m 644 -o root -g root initpolicy /ss_policy
+
+all.te: macros.te attrib.te all_types.te all_domains.te assert.te
+	$(CAT) $^ > $@
+
+all_types.te: $(TYPES)
+	$(CAT) $^ > $@
+
+all_domains.te: domains/every.te system_domains.te program_domains.te user_domains.te admin_domains.te
+	$(CAT) $^ > $@
+
+system_domains.te: $(SYSTEM_DOMAINS)
+	$(CAT) $^ > $@
+
+program_domains.te: $(PROGRAM_DOMAINS)
+	$(CAT) $^ > $@
+
+user_domains.te: $(USER_DOMAINS)
+	$(CAT) $^ > $@
+
+admin_domains.te: $(ADMIN_DOMAINS)
+	$(CAT) $^ > $@
+
+clean:
+	$(RM) -f policy ss_policy policy.conf
+	$(RM) -f initpolicy initpolicy.conf 
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/README	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,130 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+The Makefile targets are:
+policy - compile the policy configuration.
+install - compile and install the policy configuration.
+load    - compile, install, and load the policy configuration.
+relabel - relabel the file system based on file_contexts.
+
+The flask/* configuration files are independent of the particular
+security policy, and are also used to generate kernel headers
+with class, permission, and initial SID definitions.
+These files are:
+1) security_classes -
+   This file has a simple declaration for each security class.
+   The corresponding symbol definitions are in the automatically
+   generated header file flask.h. 
+
+2) initial_sids - 
+   This file has a simple declaration for each initial SID.
+   The corresponding symbol definitions are in the automatically
+   generated header file flask.h. 
+
+3) access_vectors - 
+   This file defines the access vectors.  Common prefixes for
+   access vectors may be defined at the beginning of the file.
+   After the common prefixes are defined, an access vector
+   may be defined for each security class.
+   The corresponding symbol definitions are in the automatically
+   generated header file av_permissions.h.
+
+In addition to being read by the security server, these configuration
+files are used during the kernel build to automatically generate
+symbol definitions used by the kernel for security classes, initial
+SIDs and permissions.  Since the symbol definitions generated from
+these files are used during the kernel build, the values of existing
+security classes and permissions may not be modified by load_policy.
+However, new classes may be appended to the list of classes and new
+permissions may be appended to the list of permissions associated with
+each access vector definition.
+
+The policy-dependent configuration files are:
+1) all.te -  
+   This file defines the Type Enforcement (TE) configuration.
+   This file is automatically generated from a collection of files.
+
+   The macros.te file contains global macros used throughout the
+   configuration for common groupings of classes and permissions
+   and for common sets of rules.  The assert.te file contains assertions
+   that are checked after evaluating the entire TE configuration.
+
+   The types subdirectory contains several files with declarations for
+   general types (types not associated with a particular domain) and 
+   some rules defining relationships among those types.  Related types 
+   are grouped together into each file in this directory, e.g. all
+   device type declarations are in the device.te file.
+
+   The domains subdirectory contains several subdirectories with
+   a separate file containing the declarations and rules for each 
+   domain.  Related domains are grouped together into each subdirectory,
+   e.g. all domain definitions for system processes are in the 
+   domains/system subdirectory.  The domains/every.te file contains rules 
+   that apply to every domain.
+
+2) rbac - 
+   This file defines the Role-Based Access Control (RBAC) configuration.
+
+3) mls - 
+   This file defines the Multi-Level Security (MLS) configuration.
+
+4) users and users.mls -
+   This file defines the users recognized by the security policy.
+
+5) constraints - 
+   This file defines additional constraints on permissions
+   in the form of boolean expressions that must be satisfied in order
+   for specified permissions to be granted.  These constraints
+   are used to further refine the type enforcement tables and
+   the role allow rules.
+
+6) initial_sid_contexts and initial_sid_contexts.mls -
+   This file defines the security context for each initial SID.
+   A security context consists of a user identity, a role, a type and
+   a MLS range.  If left unspecified, the high MLS level defaults to the
+   low MLS level.  The syntax of a valid security context is:
+
+     user:role:type:sensitivity[:category,...][-sensitivity[:category,...]]
+
+7) fs_contexts and fs_contexts.mls -
+   This file defines the security contexts to use when an unlabeled
+   file system is mounted.
+
+8) net_contexts and net_contexts.mls -
+   This file defines the security contexts of network objects
+   such as ports, interfaces, and nodes.
+
+9) file_contexts and file_contexts.mls -
+   This file defines the labels to be assigned to files.
+
+It is possible to test the security server functions on a given policy
+configuration by running the checkpolicy program with the -d option.
+This program is built from the same sources as the security server
+component of the kernel, so it may be used both to verify that a
+policy configuration will load successfully and to determine how the
+security server would respond if it were using that policy
+configuration.  A menu-based interface is provided for calling any of
+the security server functions after the policy is loaded. 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/assert.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,152 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+##############################
+#
+# Assertions for the type enforcement (TE) configuration.
+#
+
+#
+
+##################################
+#
+# Access vector assertions.
+#
+# An access vector assertion specifies permissions that should not be in
+# an access vector based on a source type, a target type, and a class.
+# If any of the specified permissions are in the corresponding access
+# vector, then the policy compiler will reject the policy configuration.
+# The assertion is checked against the access vectors that have been
+# previously defined in the configuration, so access vector rules after
+# an assertion are not checked.  Currently, there is only one kind of
+# access vector assertion, neverallow, but support for the other
+# kinds of vectors could be easily added.  Access vector assertions use
+# the same syntax as access vector rules.
+#
+
+#
+# Verify that every type that can be entered by
+# a domain is also tagged as a domain.
+#
+neverallow domain ~domain:process transition;
+
+#
+# Verify that only the kmod_t, insmod_t, rmmod_t, and ifconfig_t domains 
+# have the sys_module capability.
+#
+neverallow ~{ kmod_t insmod_t rmmod_t ifconfig_t } self:capability sys_module;
+
+#
+# Verify that executable types, the system dynamic loaders, and the
+# system shared libraries can only be modified by administrators.
+#
+neverallow ~admin { exec_type ld_so_t shlib_t }:file { write append unlink rename };
+
+#
+# Verify that other system software can only be modified by administrators.
+#
+neverallow ~admin { lib_t bin_t sbin_t }:dir { add_name remove_name rename };
+neverallow ~admin { lib_t bin_t sbin_t }:file { write append unlink rename };
+
+#
+# Verify that the shadow password file may only be read
+# and written by the passwd domain and by administrator domains.
+# Verify that the authentication domains are the only other domains
+# that can read this file.
+#
+neverallow ~{ admin passwd_t } etc_auth_t:dir { add_name remove_name rename };
+neverallow ~{ admin passwd_t } etc_auth_t:file { write append unlink rename };
+neverallow ~{ admin auth } etc_auth_t:file { read };
+
+#
+# Verify that only the administrator domain and the
+# file system administration domain have access to the raw disk devices.
+#
+neverallow ~{ admin fsadm_t } fixed_disk_device_t:devfile_class_set { read write append };
+
+#
+# Verify that only the X server and klogd have access to memory devices.
+#
+neverallow ~privmem memory_device_t:devfile_class_set { read write append };
+
+#
+# Verify that only the administrator domain and 
+# cardmgr can create, rename or unlink device special files.
+#
+neverallow ~{ cardmgr_t admin } file_type:devfile_class_set { create unlink rename };
+
+#
+# Verify that /proc/kmsg is only accessible to klogd.
+#
+neverallow ~klogd_t proc_kmsg_t:file ~stat_file_perms;
+
+#
+# Verify that /proc/kcore is inaccessible.
+#
+neverallow * proc_kcore_t:file ~stat_file_perms;
+
+#
+# Verify that sysctl variables are only changeable
+# by initrc and administrators.
+#
+neverallow ~{ initrc_t admin } sysctl_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_fs_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_kernel_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_net_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_vm_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_dev_t:file { write append };
+neverallow ~{ initrc_t admin } sysctl_modprobe_t:file { write append };
+
+#
+# Verify that certain domains are limited to executing
+# code from their entrypoint executables, the dynamic
+# loader or the shared libraries.
+#
+
+define(`assert_execute', `
+    ifelse($#, 0, , 
+           $#, 1, 
+           ``neverallow $1_t ~{ $1_exec_t ld_so_t shlib_t }:process execute;'',
+           `assert_execute($1) assert_execute(shift($@))')')
+
+assert_execute(getty, klogd, atd, inetd, tcpd, rlogind, 
+    	       ypbind, portmap, syslogd, rpcd, gpm, xfs, fsadm)
+
+neverallow local_login_t ~{ login_exec_t ld_so_t shlib_t }:process execute;
+neverallow remote_login_t ~{ login_exec_t ld_so_t shlib_t }:process execute;
+
+#
+# Verify that the passwd domain can only execute code from 
+# its entrypoint executable, the ordinary passwd program,
+# the dynamic loader, or the shared libraries.
+#
+neverallow passwd_t ~{ passwd_exec_t bin_t ld_so_t shlib_t }:process execute;
+
+
+#
+# Verify that only the admin domains and initrc_t have avc_toggle.
+#
+neverallow ~{ admin initrc_t } kernel_t:system avc_toggle;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/attrib.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,194 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Declarations for type attributes.
+# 
+
+# A type attribute can be used to identify a set of types with a similar
+# property.  Each type can have any number of attributes, and each
+# attribute can be associated with any number of types.  Attributes are
+# explicitly declared here, and can then be associated with particular
+# types in type declarations.  Attribute names can then be used throughout 
+# the configuration to express the set of types that are associated with 
+# the attribute.  Except for the MLS attributes, attributes have no implicit
+# meaning to SELinux.  The meaning of all other attributes are completely 
+# defined through their usage within the configuration, but should be 
+# documented here as comments preceding the attribute declaration.  
+
+#####################
+# Attributes for MLS:
+#
+
+# The mlstrustedreader attribute identifies every domain that can
+# override the normal MLS restrictions on reading (i.e. domains
+# that can read up).  
+attribute mlstrustedreader;
+
+# The mlstrustedwriter attribute identifies every domain that can
+# override the normal MLS restrictions on writing (i.e. domains
+# that can write down).  
+attribute mlstrustedwriter;
+
+# The mlstrustedobject attribute identifies every type that can
+# be accessed without normal MLS restrictions (i.e. processes can
+# read or write objects with this type regardless of MLS level).  
+# Examples:  /dev/null, descriptors created by login
+attribute mlstrustedobject;
+
+
+#########################
+# Attributes for domains:
+#
+
+# The domain attribute identifies every type that can be 
+# assigned to a process.  This attribute is used in TE rules 
+# that should be applied to all domains, e.g. permitting 
+# init to kill all processes or permitting all processes
+# to read a particular file.
+attribute domain;
+
+# The privuser attribute identifies every domain that can 
+# change its SELinux user identity.  This attribute is used 
+# in the constraints configuration.  NOTE:  This attribute
+# is not required for domains that merely change the Linux
+# uid attributes, only for domains that must change the
+# SELinux user identity.
+attribute privuser;
+
+# The privrole attribute identifies every domain that can 
+# change its SELinux role.  This attribute is used in the 
+# constraints configuration.
+attribute privrole;
+
+# The privowner attribute identifies every domain that can 
+# assign a different SELinux user identity to a file.  This 
+# attribute is used in the constraints configuration.
+attribute privowner;
+
+# The privlog attribute identifies every domain that can 
+# communicate with syslogd through its Unix domain socket.
+# This attribute is used in the TE rules in 
+# domains/program/syslogd.te to grant such access.  
+attribute privlog;
+
+# The privmem attribute identifies every domain that can 
+# access kernel memory devices.
+# This attribute is used in the TE assertions to verify
+# that such access is limited to domains that are explicitly
+# tagged with this attribute.
+attribute privmem;
+
+# The auth attribute identifies every domain that needs
+# to perform user authentication and requires access to
+# the corresponding authentication data.  
+attribute auth;
+
+# The admin attribute identifies every administrator domain.
+# It is used in TE assertions when verifying that only authorized 
+# domains have certain permissions.  
+attribute admin;
+
+# The userdomain attribute identifies every user domain, presently
+# user_t and sysadm_t.  It is used in TE rules that should be applied
+# to all user domains.
+attribute userdomain;
+
+############################
+# Attributes for file types:
+#
+
+# The file_type attribute identifies all types assigned to files 
+# in persistent filesystems.  It is used in TE rules to permit
+# the association of all such file types with persistent filesystem
+# types, and to permit certain domains to access all such types as 
+# appropriate.
+attribute file_type;
+
+# The sysadmfile attribute identifies all types assigned to files 
+# that should be completely accessible to administrators.  It is used
+# in TE rules to grant such access for administrator domains.
+attribute sysadmfile;
+
+# The fs_type attribute identifies all types assigned to filesystems
+# (not limited to persistent filesystems).
+# It is used in TE rules to permit certain domains to mount
+# any filesystem and to permit most domains to obtain the
+# overall filesystem statistics.
+attribute fs_type;
+
+# The root_dir_type attribute identifies all types assigned to 
+# root directories of filesystems (not limited to persistent
+# filesystems).
+attribute root_dir_type;
+
+# The exec_type attribute identifies all types assigned
+# to entrypoint executables for domains.  This attribute is 
+# used in TE rules and assertions that should be applied to all 
+# such executables.
+attribute exec_type;
+
+# The tmpfile attribute identifies all types assigned to temporary 
+# files.  This attribute is used in TE rules to grant certain 
+# domains the ability to remove all such files (e.g. init, crond).
+attribute tmpfile;
+
+# The home_type attribute identifies all types assigned to home
+# directories.  This attribute is used in TE rules to grant certain
+# domains the ability to access all home directory types.
+attribute home_type;
+
+# The pidfile attribute identifies all types assigned to pid files.
+# It is used in TE rules to grant certain domains the ability to
+# access all such files.
+attribute pidfile;
+
+
+############################
+# Attributes for network types:
+#
+
+# The socket_type attribute identifies all types assigned to 
+# kernel-created sockets.  Ordinary sockets are assigned the 
+# domain of the creating process.
+attribute socket_type;
+
+# Identifies all types assigned to port numbers to control binding.
+attribute port_type;
+
+# Identifies all types assigned to network interfaces to control
+# operations on the interface (obsolete) and to control traffic
+# sent or received on the interface.
+attribute netif_type;
+
+# Identifies all default types assigned to packets received 
+# on network interfaces.  
+attribute netmsg_type;
+
+# Identifies all types assigned to network nodes/hosts to control
+# traffic sent to or received from the node.
+attribute node_type;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/constraints	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,77 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define m4 macros for the constraints
+#
+
+#
+# Define the constraints
+#
+# constrain class_set perm_set expression ;
+#
+# expression : ( expression ) 
+#	     | not expression
+#	     | expression and expression
+#	     | expression or expression
+#	     | u1 op u2
+#	     | r1 role_op r2
+#	     | t1 op t2
+#	     | u1 op names
+#	     | u2 op names
+#	     | r1 op names
+#	     | r2 op names
+#	     | t1 op names
+#	     | t2 op names
+#
+# op : == | != 
+# role_op : == | != | eq | dom | domby | incomp
+#
+# names : name | { name_list }
+# name_list : name | name_list name#		
+#
+
+#
+# Restrict the ability to transition to other users
+# or roles to a few privileged types.
+#
+
+constrain process transition 
+	( u1 == u2 or t1 == privuser );
+
+constrain process transition 
+	( r1 == r2 or t1 == privrole) ;
+
+#
+# Restrict the ability to label objects with other
+# user identities to a few privileged types.
+#
+
+constrain dir_file_class_set { create relabelto relabelfrom } 
+	( u1 == u2 or t1 == privowner );
+
+constrain socket_class_set { create relabelto relabelfrom } 
+	( u1 == u2 or t1 == privowner );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/admin/sysadm.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,194 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# The admin_domain macro and the 
+# sysadm_t domain.
+#
+
+#################################
+# 
+# admin_domain(domain)
+#
+# Rules for all user admin domains.
+#
+define(`admin_domain',`
+
+# Inherit rules for ordinary users.
+user_domain($1)
+
+# Use capabilities other than sys_module.
+allow $1_t self:capability ~sys_module;
+
+# Use system operations.
+allow $1_t kernel_t:system *;
+
+# Change system parameters.
+can_sysctl($1_t)
+
+# Mount and unmount file systems.
+allow $1_t fs_type:filesystem mount_fs_perms;
+allow $1_t file_t:dir mounton;
+
+# Create and use all files that have the sysadmfile attribute.
+allow $1_t sysadmfile:notdevfile_class_set create_file_perms;
+allow $1_t sysadmfile:dir create_dir_perms;
+
+# Use /sbin/lilo to update the boot loader.
+# XXX FIXME!  Move lilo into separate domain.
+allow $1_t fixed_disk_device_t:devfile_class_set rw_file_perms;
+
+# Access removable devices.
+allow $1_t removable_device_t:devfile_class_set rw_file_perms;
+
+# Run fs admin programs in the fsadm_t domain.
+domain_auto_trans($1_t, fsadm_exec_t, fsadm_t)
+allow fsadm_t $1_tty_device_t:chr_file rw_file_perms;
+allow fsadm_t $1_devpts_t:chr_file rw_file_perms;
+allow fsadm_t $1_gph_t:fd inherit_fd_perms;
+
+# Run ifconfig program in the ifconfig_t domain.
+domain_auto_trans($1_t, ifconfig_exec_t, ifconfig_t)
+allow ifconfig_t $1_tty_device_t:chr_file rw_file_perms;
+allow ifconfig_t $1_devpts_t:chr_file rw_file_perms;
+allow ifconfig_t $1_gph_t:fd inherit_fd_perms;
+
+# Run logrotate program in the logrotate_t domain.
+domain_auto_trans($1_t, logrotate_exec_t, logrotate_t)
+allow logrotate_t $1_tty_device_t:chr_file rw_file_perms;
+allow logrotate_t $1_devpts_t:chr_file rw_file_perms;
+allow logrotate_t $1_gph_t:fd inherit_fd_perms;
+
+# Run init (telinit).
+can_exec($1_t, init_exec_t)
+
+# Communicate with the init process.
+allow $1_t initctl_t:fifo_file rw_file_perms;
+
+# Examine all processes.
+allow $1_t domain:dir r_dir_perms;
+allow $1_t domain:notdevfile_class_set r_file_perms;
+
+# Send signals to all processes.
+allow $1_t domain:process signal_perms;
+
+# Run modules programs in their own domains.
+domain_auto_trans($1_t, depmod_exec_t, depmod_t)
+allow depmod_t $1_tty_device_t:chr_file rw_file_perms;
+allow depmod_t $1_devpts_t:chr_file rw_file_perms;
+allow depmod_t $1_gph_t:fd inherit_fd_perms;
+
+domain_auto_trans($1_t, modprobe_exec_t, modprobe_t)
+allow modprobe_t $1_tty_device_t:chr_file rw_file_perms;
+allow modprobe_t $1_devpts_t:chr_file rw_file_perms;
+allow modprobe_t $1_gph_t:fd inherit_fd_perms;
+
+domain_auto_trans($1_t, insmod_exec_t, insmod_t)
+allow insmod_t $1_tty_device_t:chr_file rw_file_perms;
+allow insmod_t $1_devpts_t:chr_file rw_file_perms;
+allow insmod_t $1_gph_t:fd inherit_fd_perms;
+
+domain_auto_trans($1_t, rmmod_exec_t, rmmod_t)
+allow rmmod_t $1_tty_device_t:chr_file rw_file_perms;
+allow rmmod_t $1_devpts_t:chr_file rw_file_perms;
+allow rmmod_t $1_gph_t:fd inherit_fd_perms;
+
+# Reload the policy configuration.
+allow $1_t policy_config_t:security load_policy;
+
+# Execute setfiles.
+can_exec($1_t, policy_src_t)
+
+# Relabel all files.
+allow $1_t file_type:dir_file_class_set { getattr relabelfrom relabelto };
+
+# Relabel the default file type to any file type. 
+allow file_t   file_type:dir_file_class_set transition;
+
+# Change the owner of any file to system_u. 
+allow file_type self:dir_file_class_set transition;
+
+# Label the policy configuration file during install.
+allow root_t policy_config_t:file transition;
+
+# Label bin programs during install.
+allow bin_t { passwd_exec_t login_exec_t }:file transition;
+
+# Label sbin programs during install.
+allow sbin_t { sulogin_exec_t rshd_exec_t crond_exec_t logrotate_exec_t }:file transition;
+
+# Label shared libraries during install.
+allow lib_t shlib_t:file transition;
+
+# Create files in /tmp/orbit-* and /tmp/.ICE-unix
+# with our derived tmp type rather than user_tmp_t.
+file_type_auto_trans($1_t, user_tmp_t, $1_tmp_t)
+
+# Create files in /tmp/.X11-unix with our X servers derived
+# tmp type rather than user_xserver_tmp_t.
+file_type_auto_trans($1_xserver_t, user_xserver_tmp_t, $1_xserver_tmp_t)
+
+# Allow our mail domain to write to dead.letter.
+allow $1_mail_t user_home_t:dir rw_dir_perms;
+allow $1_mail_t user_home_t:file create_file_perms;
+
+# Allow our su domain to write to .Xauthority.
+allow $1_su_t user_home_t:dir rw_dir_perms;
+allow $1_su_t user_home_t:file create_file_perms;
+
+# Allow searching of /tmp/.X11-unix.
+allow $1_netscape_t user_xserver_tmp_t:dir r_dir_perms;
+
+# Allow our netscape domain to write to .netscape.
+allow $1_netscape_t user_netscape_rw_t:dir create_dir_perms;
+allow $1_netscape_t user_netscape_rw_t:{ file lnk_file } create_file_perms;
+
+# Allow our domain to relabel downloaded files to its home type.
+allow $1_t user_netscape_rw_t:{ dir file lnk_file } relabelfrom;
+allow user_netscape_rw_t $1_home_t:{ dir file lnk_file } transition;
+
+# Allow our crontab domain to unlink a user cron spool file.
+allow $1_crontab_t user_cron_spool_t:file unlink;
+
+')
+
+
+#################################
+# 
+# Rules for the sysadm_t domain.
+#
+# sysadm_t is the system administrator domain.
+#
+type sysadm_t, domain, privlog, privowner, admin, userdomain;
+
+admin_domain(sysadm)
+
+# Inherit and use descriptors from remote_login_t.
+allow sysadm_t remote_login_t:fd inherit_fd_perms;
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/every.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,211 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+##################################
+#
+# Rules for every domain.
+#
+
+# Access other processes in the same domain.
+allow domain self:process ~{ execute entrypoint };
+
+# Access file descriptions, pipes, and sockets
+# created by processes in the same domain.
+allow domain self:fd *;
+allow domain self:pipe *;
+allow domain self:{ socket udp_socket unix_dgram_socket } *;
+allow domain self:{ tcp_socket unix_stream_socket } *;
+
+# Use the system shared libraries.
+uses_shlib(domain)
+
+# Obtain the context of any SID.
+allow domain *:security sid_to_context;
+
+# Obtains SIDs for contexts and obtain the
+# list of active SIDs.
+allow domain security_t:security { context_to_sid get_sids };
+
+# Read/search default file type.
+allow domain file_t:dir r_dir_perms;
+allow domain file_t:file r_file_perms;
+
+# Get attributes of file systems.
+allow domain fs_type:filesystem getattr;
+
+# Read /proc/PID files for processes in the same domain.
+allow domain self:dir r_dir_perms;
+allow domain self:notdevfile_class_set r_file_perms;
+
+# Read system information files in /proc.
+allow domain proc_t:dir r_dir_perms;
+allow domain proc_t:notdevfile_class_set r_file_perms;
+
+# Stat /proc/kmsg and /proc/kcore.
+allow domain proc_kmsg_t:file stat_file_perms;
+allow domain proc_kcore_t:file stat_file_perms;
+
+# Read system variables in /proc/sys.
+allow domain sysctl_modprobe_t:file r_file_perms;
+allow domain sysctl_t:file r_file_perms;
+allow domain sysctl_t:dir r_dir_perms;
+allow domain sysctl_fs_t:file r_file_perms;
+allow domain sysctl_fs_t:dir r_dir_perms;
+allow domain sysctl_kernel_t:file r_file_perms;
+allow domain sysctl_kernel_t:dir r_dir_perms;
+allow domain sysctl_net_t:file r_file_perms;
+allow domain sysctl_net_t:dir r_dir_perms;
+allow domain sysctl_vm_t:file r_file_perms;
+allow domain sysctl_vm_t:dir r_dir_perms;
+allow domain sysctl_dev_t:file r_file_perms;
+allow domain sysctl_dev_t:dir r_dir_perms;
+
+# Read /dev/pts.
+allow domain devpts_t:dir r_dir_perms;
+
+# Read /.
+allow domain root_t:dir r_dir_perms;
+allow domain root_t:notdevfile_class_set r_file_perms;
+
+# Create and unlink files from /tmp.
+allow domain tmp_t:dir rw_dir_perms;
+
+# Read /var.
+allow domain var_t:dir r_dir_perms;
+allow domain var_t:notdevfile_class_set r_file_perms;
+
+# Read /var/lib.
+allow domain var_lib_t:dir r_dir_perms;
+allow domain var_lib_t:notdevfile_class_set r_file_perms;
+
+# Read /var/yp.
+allow domain var_yp_t:dir r_dir_perms;
+allow domain var_yp_t:notdevfile_class_set r_file_perms;
+
+# Read /var/spool.
+allow domain var_spool_t:dir r_dir_perms;
+allow domain var_spool_t:notdevfile_class_set r_file_perms;
+
+# Read /var/run, /var/lock, /var/log.
+allow domain var_run_t:dir r_dir_perms;
+allow domain var_run_t:file r_file_perms;
+allow domain var_log_t:dir r_dir_perms;
+allow domain var_log_t:file r_file_perms;
+allow domain var_lock_t:dir r_dir_perms;
+allow domain var_lock_t:file r_file_perms;
+
+# Read /var/run/utmp and /var/log/wtmp.
+allow domain initrc_var_run_t:file r_file_perms;
+allow domain wtmp_t:file r_file_perms;
+
+# Read /boot and /boot/kernel.h.
+allow domain boot_t:dir r_dir_perms;
+allow domain boot_t:file r_file_perms;
+allow domain boot_runtime_t:file r_file_perms;
+
+# Read /etc.
+allow domain etc_t:dir r_dir_perms;
+allow domain etc_t:notdevfile_class_set r_file_perms;
+allow domain etc_runtime_t:file r_file_perms;
+allow domain etc_aliases_t:file r_file_perms;
+allow domain etc_mail_t:dir r_dir_perms;
+allow domain etc_mail_t:file r_file_perms;
+
+# Read /lib.
+allow domain lib_t:dir r_dir_perms;
+allow domain lib_t:notdevfile_class_set r_file_perms;
+
+# Read /bin and /sbin.
+allow domain bin_t:dir r_dir_perms;
+allow domain bin_t:notdevfile_class_set r_file_perms;
+allow domain sbin_t:dir r_dir_perms;
+allow domain sbin_t:notdevfile_class_set r_file_perms;
+
+# Read /usr.
+allow domain usr_t:dir r_dir_perms;
+allow domain usr_t:notdevfile_class_set r_file_perms;
+
+# Read man directories and files.
+allow domain man_t:dir r_dir_perms;
+allow domain man_t:notdevfile_class_set r_file_perms;
+
+# Read /usr/src.
+allow domain src_t:dir r_dir_perms;
+allow domain src_t:notdevfile_class_set r_file_perms;
+
+# Read home directory types.
+allow domain home_type:dir r_dir_perms;
+allow domain home_type:notdevfile_class_set r_file_perms;
+
+# Read polyinstantiated directories.
+allow domain poly_t:dir r_dir_perms;
+
+# Search and read module-related files.
+allow domain modules_object_t:dir r_dir_perms;
+allow domain modules_object_t:file r_file_perms;
+allow domain modules_dep_t:file r_file_perms;
+allow domain modules_conf_t:file r_file_perms;
+
+# Read /dev.
+allow domain device_t:dir r_dir_perms;
+
+# Read and write /dev/tty, /dev/null, /dev/random,
+# and (for now) /dev/console.
+allow domain devtty_t:chr_file rw_file_perms;
+allow domain null_device_t:chr_file rw_file_perms;
+allow domain random_device_t:chr_file r_file_perms;
+# FIXME! Only grant to domains which require console access.
+allow domain console_device_t:chr_file rw_file_perms;
+
+# Send SIGCHLD to init.
+allow domain init_t:process sigchld;
+
+# Inherit and use descriptors from login.
+allow domain local_login_t:fd inherit_fd_perms;
+allow domain remote_login_t:fd inherit_fd_perms;
+allow domain sshd_login_t:fd inherit_fd_perms;
+
+# Create and use NFS files.
+# FIXME!  Only grant to domains that truly need this access.
+allow domain nfs_t:dir create_dir_perms;
+allow domain nfs_t:notdevfile_class_set create_file_perms;
+allow domain nfs_clipper_t:dir create_dir_perms;
+allow domain nfs_clipper_t:notdevfile_class_set create_file_perms;
+
+# Use the network.
+# FIXME!  Only grant to domains that truly need this access.
+can_network(domain)
+
+# Bind to port numbers with the default port number type.
+# FIXME!  Only grant to domains that truly need this access.
+allow domain port_t:udp_socket name_bind;
+allow domain port_t:tcp_socket name_bind;
+
+# Communicate with portmap.
+# FIXME!  Only grant to domains that truly need this access.
+can_udp_send(domain,portmap_t)
+can_udp_send(portmap_t, domain)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/crontab.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,84 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+type crontab_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+#
+# The crontab_domain macro.
+#
+
+define(`crontab_domain',`
+
+###########################################
+# crontab
+#
+# define crontab domain for a user domain
+#
+
+# Domain of crontab process
+type $1_crontab_t, domain, privlog;
+
+type $1_crontab_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans($1_crontab_t, tmp_t, $1_crontab_tmp_t)
+
+# Type of user crontabs once moved to cron spool
+type $1_cron_spool_t, file_type, sysadmfile;
+
+# Allow crond to read those crontabs in cron spool.
+allow crond_t $1_cron_spool_t:file r_file_perms;
+
+# Enter by the crontab executable
+domain_auto_trans($1_t, crontab_exec_t, $1_crontab_t)
+
+# Run helper programs.
+can_exec_any($1_crontab_t)
+
+# Use capabilities
+allow $1_crontab_t $1_crontab_t:capability { setuid chown dac_override net_bind_service };
+
+# Use the network for NIS.
+can_network($1_crontab_t)
+
+# Read user crontabs 
+allow $1_crontab_t $1_home_t:dir r_dir_perms;  
+
+# Create crontabs in /var/spool/cron as $1_cron_spool_t
+file_type_auto_trans($1_crontab_t, cron_spool_t, $1_cron_spool_t)
+
+# Use the cron log file
+allow $1_crontab_t cron_log_t:file r_file_perms;
+allow $1_crontab_t cron_log_t:file { append };
+
+# Write to user domain tty.
+allow $1_crontab_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_crontab_t $1_devpts_t:chr_file rw_file_perms;
+
+# Inherit and use descriptors from gnome-pty-helper.
+allow $1_crontab_t $1_gph_t:fd inherit_fd_perms;
+
+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/fsadm.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the fsadm_t domain.
+#
+# fsadm_t is the domain for disk and file system
+# administration.
+# fsadm_exec_t is the type of the corresponding programs.
+#
+type fsadm_t, domain, privlog;
+type fsadm_exec_t, file_type, sysadmfile, exec_type;
+
+type fsadm_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(fsadm_t, tmp_t, fsadm_tmp_t)
+
+# Use capabilities.
+allow fsadm_t fsadm_t:capability { sys_admin sys_rawio };
+
+# Write to /etc/mtab.
+allow fsadm_t etc_runtime_t:file rw_file_perms;
+
+# Inherit and use descriptors from init.
+allow fsadm_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow fsadm_t initrc_t:pipe rw_file_perms;
+
+# Run other fs admin programs in the fsadm_t domain.
+allow fsadm_t fsadm_exec_t:file rx_file_perms;
+
+# Access disk devices.
+allow fsadm_t fixed_disk_device_t:devfile_class_set rw_file_perms;
+allow fsadm_t removable_device_t:devfile_class_set rw_file_perms;
+
+# Access lost+found.
+allow fsadm_t lost_found_t:dir create_dir_perms;
+allow fsadm_t lost_found_t:notdevfile_class_set create_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/gnome-pty-helper.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,81 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# The gph_exec_t type is the type of the gnome-pty-helper
+# binary.
+#
+type gph_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+# gph_domain(user_domain)
+#
+# Define a gph ("gnome-pty-helper") domain for a user domain.
+#
+# The *_gph_t domains are for the gnome_pty_helper program.
+# This program is executed by gnome-terminal to handle
+# updates to utmp and wtmp.  In this regard, it is similar
+# to utempter.  However, unlike utempter, gnome-pty-helper
+# also creates the pty file for the terminal program.
+# There is one *_gph_t domain for each user domain.  
+#
+define(`gph_domain',`
+
+# This is the gph domain for the user domain specified by $1.
+type $1_gph_t, domain;
+
+# Allow gnome-pty-helper to be setgid.
+allow $1_gph_t $1_gph_t:capability { setgid };
+
+# Allow gnome-pty-helper to create ptys.
+can_create_other_pty($1_gph, $1)
+
+# Allow gnome-pty-helper to update /var/run/utmp and /var/log/wtmp.
+allow $1_gph_t initrc_var_run_t:file rw_file_perms;
+allow $1_gph_t wtmp_t:file rw_file_perms;
+
+# Allow gph to rw to stream sockets of appropriate user type.
+# (Need this so gnome-pty-helper can pass pty fd to parent 
+#  gnome-terminal which is running in a user domain.)
+allow $1_gph_t $1_t:unix_stream_socket rw_stream_socket_perms;
+
+# Allow gph to inherit tty fd from login
+allow $1_gph_t local_login_t:fd inherit_fd_perms;
+
+# Allow $1 user domain to receive pty fd from gnome-pty-helper.
+allow $1_t $1_gph_t:fd receive_fd_perms;
+
+# Cause the $1 user domain to run gnome-pty-helper in the 
+# appropriate gph_*_t domain. The gph_exec_t type is the one
+# and only type for the gnome-pty-helper binary.  We defined
+# it previously, outside of this macro.
+domain_auto_trans($1_t, gph_exec_t, $1_gph_t)
+
+# Allow NIS authentication
+can_network($1_gph_t)
+')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/ifconfig.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,50 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the ifconfig_t domain.
+#
+# ifconfig_t is the domain for the ifconfig program.
+# ifconfig_exec_t is the type of the corresponding program.
+#
+type ifconfig_t, domain, privlog;
+type ifconfig_exec_t, file_type, sysadmfile, exec_type;
+
+# Use capabilities.
+allow ifconfig_t ifconfig_t:capability { sys_module net_admin };
+
+# Use system ops.
+allow ifconfig_t kernel_t:system { net_io_control };
+
+# Configure network interfaces.
+allow ifconfig_t netif_type:netif { getattr setattr };
+
+# Inherit and use descriptors from init.
+allow ifconfig_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow ifconfig_t initrc_t:pipe rw_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/logrotate.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,68 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the logrotate_t domain.
+#
+# logrotate_t is the domain for the logrotate program.
+# logrotate_exec_t is the type of the corresponding program.
+#
+type logrotate_t, domain, privowner;
+type logrotate_exec_t, file_type, sysadmfile, exec_type;
+
+# Create temporary files.
+type logrotate_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(logrotate_t, tmp_t, logrotate_tmp_t)
+
+# Run helper programs.
+can_exec_any(logrotate_t)
+
+# Read PID files.
+allow logrotate_t pidfile:file r_file_perms;
+
+# Read /proc/PID directories for all domains.
+allow logrotate_t domain:notdevfile_class_set r_file_perms;
+allow logrotate_t domain:dir r_dir_perms;
+
+# Signal processes.
+allow logrotate_t domain:process signal;
+
+# Modify /var/log.
+allow logrotate_t var_log_t:dir rw_dir_perms;
+
+# Create, rename, and truncate log files.
+allow logrotate_t var_log_t:file create_file_perms;
+allow logrotate_t cron_log_t:file create_file_perms;
+allow logrotate_t sendmail_var_log_t:file create_file_perms;
+allow logrotate_t wtmp_t:file create_file_perms;
+
+# Change ownership on log files.
+allow logrotate_t logrotate_t:capability chown;
+
+# Write to /var/lib/logrotate.status.
+allow logrotate_t var_lib_t:dir rw_dir_perms;
+allow logrotate_t var_lib_t:file create_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/lpr.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,87 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# lpr_exec_t is the type of the lpr, lpq, and lprm executables.
+#
+type lpr_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+#
+# lpr_domain(user_domain)
+#
+# Define a lpr/lpq/lprm domain for a user domain.
+#
+define(`lpr_domain',`
+
+type $1_lpr_t, domain, privlog;
+type $1_lpr_tmp_t, file_type, sysadmfile, tmpfile;
+type $1_lpd_spool_t, file_type, sysadmfile;
+
+# Enter by the lpr/lpq/lprm executables.
+domain_auto_trans($1_t, lpr_exec_t, $1_lpr_t)
+
+# Use capabilities.
+allow $1_lpr_t $1_lpr_t:capability { dac_override net_bind_service chown };
+
+# Use the network.
+can_network($1_lpr_t)
+
+# Inherit and use descriptors from login.
+allow $1_lpr_t local_login_t:fd inherit_fd_perms;
+allow $1_lpr_t remote_login_t:fd inherit_fd_perms;
+
+# Write to the user domain tty.
+allow $1_lpr_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_lpr_t $1_devpts_t:chr_file rw_file_perms;
+
+# Inherit and use descriptors from gnome-pty-helper.
+allow $1_lpr_t $1_gph_t:fd inherit_fd_perms;
+
+# Read from a user domain pipe.
+allow $1_lpr_t $1_t:pipe r_file_perms;
+
+# Create lpd spool files.
+file_type_auto_trans($1_lpr_t, lpd_spool_t, $1_lpd_spool_t)
+
+# Read and write shared files in the spool directory.
+allow $1_lpr_t lpd_spool_t:notdevfile_class_set rw_file_perms;
+
+# Connect to lpd.
+allow $1_lpr_t printer_t:sock_file rw_file_perms;
+can_unix_connect($1_lpr_t, lpd_t)
+
+# Send SIGHUP to lpd.
+allow $1_lpr_t lpd_t:process signal;
+
+# Allow lpd to read, rename, and unlink spool files.
+allow lpd_t $1_lpd_spool_t:file r_file_perms;
+allow lpd_t $1_lpd_spool_t:file link_file_perms;
+
+')
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/mail.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,82 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# mail_domain(user_domain)
+#
+# Define a sendmail domain for a user domain.
+#
+define(`mail_domain',`
+
+type $1_mail_t, domain, privlog;
+type $1_mail_tmp_t, file_type, sysadmfile, tmpfile;
+
+# Enter by the sendmail program.
+domain_auto_trans($1_t, sendmail_exec_t, $1_mail_t)
+
+# Use capabilities
+allow $1_mail_t $1_mail_t:capability { setuid setgid net_bind_service chown };
+
+# Use the network.
+can_network($1_mail_t)
+
+# Write to /var/spool/mail and /var/spool/mqueue.
+allow $1_mail_t mail_spool_t:dir rw_dir_perms;
+allow $1_mail_t mail_spool_t:file create_file_perms;
+allow $1_mail_t mqueue_spool_t:dir rw_dir_perms;
+allow $1_mail_t mqueue_spool_t:file create_file_perms;
+
+# Write to /var/log/sendmail.st
+file_type_auto_trans($1_mail_t, var_log_t, sendmail_var_log_t)
+
+# Inherit and use descriptors from login.
+allow $1_mail_t local_login_t:fd inherit_fd_perms;
+allow $1_mail_t remote_login_t:fd inherit_fd_perms;
+
+# Execute procmail.
+can_exec($1_mail_t, bin_t)
+
+# Write to the user domain tty.
+allow $1_mail_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_mail_t $1_devpts_t:chr_file rw_file_perms;
+
+# Inherit and use descriptors from gnome-pty-helper.
+allow $1_mail_t $1_gph_t:fd inherit_fd_perms;
+
+# Read from a user domain pipe.
+allow $1_mail_t $1_t:pipe r_file_perms;
+
+# Read user temporary files.
+allow $1_mail_t $1_tmp_t:file r_file_perms;
+
+# Create dead.letter in user home directories.
+allow $1_mail_t $1_home_t:dir rw_dir_perms;
+allow $1_mail_t $1_home_t:file create_file_perms;
+
+')
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/modutil.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,122 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the module utility domains.
+#
+type modules_dep_t, file_type;
+type modules_conf_t, file_type, sysadmfile;
+type modules_object_t, file_type, sysadmfile;
+
+
+#################################
+#
+# Rules for the modprobe_t domain.
+#
+type modprobe_t, domain, privlog;
+type modprobe_exec_t, file_type, exec_type, sysadmfile;
+
+# Inherit and use descriptors from init.
+allow modprobe_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow modprobe_t initrc_t:pipe rw_file_perms;
+
+# Run insmod in its own domain.
+domain_auto_trans(modprobe_t, insmod_exec_t, insmod_t)
+
+# Read conf.modules.
+allow modprobe_t modules_conf_t:file r_file_perms;
+
+# Run shell commands from conf.modules.
+can_exec_any(modprobe_t)
+
+# Read modules.dep.
+allow modprobe_t modules_dep_t:file r_file_perms;
+
+
+#################################
+#
+# Rules for the depmod_t domain.
+#
+type depmod_t, domain;
+type depmod_exec_t, file_type, exec_type, sysadmfile;
+
+# Inherit and use descriptors from init.
+allow depmod_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow depmod_t initrc_t:pipe rw_file_perms;
+
+# Read conf.modules.
+allow depmod_t modules_conf_t:file r_file_perms;
+
+# Create modules.dep.
+file_type_auto_trans(depmod_t, modules_object_t, modules_dep_t)
+
+# Read module objects.
+allow depmod_t modules_object_t:dir r_dir_perms;
+allow depmod_t modules_object_t:file r_file_perms;
+
+
+#################################
+#
+# Rules for the insmod_t domain.
+#
+type insmod_t, domain;
+type insmod_exec_t, file_type, exec_type, sysadmfile;
+
+# Use the sys_module capability.
+allow insmod_t self:capability { sys_module };
+
+# Inherit and use descriptors from init.
+allow insmod_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow insmod_t initrc_t:pipe rw_file_perms;
+
+# Read module objects.
+allow insmod_t modules_object_t:dir r_dir_perms;
+allow insmod_t modules_object_t:file r_file_perms;
+
+
+#################################
+#
+# Rules for the rmmod_t domain.
+#
+type rmmod_t, domain;
+type rmmod_exec_t, file_type, exec_type, sysadmfile;
+
+# Use the sys_module and setpcap capabilities.
+allow rmmod_t self:capability { sys_module };
+
+# Inherit and use descriptors from init.
+allow rmmod_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow rmmod_t initrc_t:pipe rw_file_perms;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/netscape.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,121 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# netscape_exec_t is the type of the netscape executable.
+#
+type netscape_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+#
+# netscape_domain(user_domain)
+#
+# Define a netscape domain for a user domain.
+#
+define(`netscape_domain',`
+
+type $1_netscape_t, domain, privlog;
+type $1_netscape_rw_t, file_type, sysadmfile, tmpfile;
+type $1_netscape_noread_t, file_type, sysadmfile;
+
+# Enter by the netscape executable.
+domain_auto_trans($1_t, netscape_exec_t, $1_netscape_t)
+
+# Allow the user domain to send any signal to the netscape process.
+allow $1_t $1_netscape_t:process signal_perms;
+
+# Allow the user domain to read the /proc/PID directory for 
+# the netscape process.
+allow $1_t $1_netscape_t:dir r_dir_perms;
+allow $1_t $1_netscape_t:notdevfile_class_set r_file_perms;
+
+# Allow use of /dev/zero by ld.so.
+allow $1_netscape_t zero_device_t:chr_file rw_file_perms;
+allow $1_netscape_t zero_device_t:process execute;
+
+# Create temporary files
+file_type_auto_trans($1_netscape_t, tmp_t, $1_netscape_rw_t)
+
+# Execute system programs.
+can_exec_any($1_netscape_t)
+
+# Execute downloaded programs.
+can_exec($1_netscape_t, $1_netscape_rw_t)
+
+# Use capabilities.
+allow $1_netscape_t self:capability { setuid setgid dac_override };
+
+# Inherit and use descriptors from login.
+allow $1_netscape_t local_login_t:fd inherit_fd_perms;
+allow $1_netscape_t remote_login_t:fd inherit_fd_perms;
+
+# Inherit and use descriptors from gnome-pty-helper.
+allow $1_netscape_t $1_gph_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network($1_netscape_t)
+
+# Allow connections to X server.
+allow $1_netscape_t $1_xserver_tmp_t:dir r_dir_perms;
+allow $1_netscape_t $1_xserver_tmp_t:sock_file rw_file_perms;
+can_unix_connect($1_netscape_t, $1_xserver_t)
+
+# Allow probing of network interfaces.
+allow $1_netscape_t kernel_t:system net_io_control;
+allow $1_netscape_t netif_type:netif getattr;
+
+# Write to the user domain tty.
+allow $1_netscape_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_netscape_t $1_devpts_t:chr_file rw_file_perms;
+
+# Read and write netscape_rw_t.
+allow $1_netscape_t $1_netscape_rw_t:dir create_dir_perms;
+allow $1_netscape_t $1_netscape_rw_t:{ file lnk_file } create_file_perms;
+
+# Allow the user domain to relabel home directory files.
+allow $1_t $1_home_t:{ dir file lnk_file } relabelfrom;
+
+# Allow the user domain to create/relabel files that can be written by
+# the netscape domain.
+allow $1_t $1_netscape_rw_t:dir create_dir_perms;
+allow $1_t $1_netscape_rw_t:{ file lnk_file } create_file_perms;
+allow $1_t $1_netscape_rw_t:{ dir file lnk_file } relabelto;
+allow $1_home_t $1_netscape_rw_t:{ dir file lnk_file } transition;
+
+# Allow the user domain to create/relabel files that cannot be read by
+# by the netscape domain.
+allow $1_t $1_netscape_noread_t:dir create_dir_perms;
+allow $1_t $1_netscape_noread_t:notdevfile_class_set create_file_perms;
+allow $1_t $1_netscape_noread_t:{ dir file lnk_file } relabelto;
+allow $1_home_t $1_netscape_noread_t:{ dir file lnk_file } transition;
+
+# Allow the user domain to relabel downloaded files to its home type.
+allow $1_t $1_netscape_rw_t:{ dir file lnk_file } relabelfrom;
+allow $1_t $1_home_t:{ dir file lnk_file } relabelto;
+allow $1_netscape_rw_t $1_home_t:{ dir file lnk_file } transition;
+
+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/newrole.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,99 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the newrole_t domain.
+#
+# newrole_t is the domain for the newrole program.
+# newrole_exec_t is the type of the newrole executable.
+#
+type newrole_t, domain, privrole, privlog, auth;
+type newrole_exec_t, file_type, exec_type;
+
+# Inherit descriptors from the current session.
+allow newrole_t remote_login_t:fd inherit_fd_perms;
+allow newrole_t local_login_t:fd inherit_fd_perms;
+
+# Execute /sbin/pwdb_chkpwd to check the password.
+can_exec(newrole_t, chkpwd_exec_t)
+
+# Use the network.
+can_network(newrole_t)
+
+# Allow newrole_t to transition to user domains.
+domain_trans(newrole_t, shell_exec_t, userdomain)
+
+# Use capabilities.
+allow newrole_t self:capability { setuid setgid net_bind_service dac_override };
+
+# Read password files
+allow newrole_t etc_auth_t:dir r_dir_perms;
+allow newrole_t etc_auth_t:file r_file_perms;
+
+# Write to utmp
+allow newrole_t initrc_var_run_t:file rw_file_perms;
+
+#
+# Allow sysadm_t to reap a user_t process 
+# created via newrole.
+#
+allow user_t sysadm_t:process { sigchld };
+
+#
+# Allow newrole to relabel TTY's
+#
+allow newrole_t security_t:security { change_sid };
+
+allow newrole_t user_tty_device_t:chr_file { relabelfrom relabelto };
+allow newrole_t sysadm_tty_device_t:chr_file { relabelfrom relabelto };
+
+allow newrole_t sysadm_devpts_t:chr_file { relabelfrom relabelto };
+allow newrole_t user_devpts_t:chr_file { relabelfrom relabelto };
+
+#
+# Allow TTY's types to transition into each other
+#
+allow sysadm_tty_device_t user_tty_device_t:chr_file transition;
+allow user_tty_device_t sysadm_tty_device_t:chr_file transition;
+
+allow sysadm_devpts_t user_devpts_t:chr_file transition;
+allow user_devpts_t sysadm_devpts_t:chr_file transition;
+
+#
+# TTY type transition rules
+#
+type_change sysadm_t user_tty_device_t:chr_file sysadm_tty_device_t;
+type_change user_t sysadm_tty_device_t:chr_file user_tty_device_t;
+
+type_change sysadm_t user_devpts_t:chr_file sysadm_devpts_t;
+type_change user_t sysadm_devpts_t:chr_file user_devpts_t;
+
+#
+# Allow newrole to open descriptors 0..2 (as the appropriate type)
+#
+allow newrole_t sysadm_t:fd create;
+allow newrole_t user_t:fd create;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/passwd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the passwd_t domain.
+#
+# passwd_t is the domain of the passwd program when
+# it is executed through the spasswd wrapper.
+# passwd_exec_t is the type of the spasswd wrapper.
+# This domain and type is also used for wrappers for
+# chfn and chsh.
+#
+type passwd_t, domain, privlog, auth;
+type passwd_exec_t, file_type, sysadmfile, exec_type;
+
+# Use capabilities.
+allow passwd_t passwd_t:capability { chown dac_override fsetid };
+
+# Inherit and use descriptors from login.
+allow passwd_t local_login_t:fd inherit_fd_perms;
+allow passwd_t remote_login_t:fd inherit_fd_perms;
+
+# Execute /usr/bin/{passwd,chfn,chsh}.
+can_exec(passwd_t, bin_t)
+
+# Test for the existence of a shell.
+allow passwd_t shell_exec_t:file access;
+
+# Update /etc/passwd.
+allow passwd_t etc_t:dir rw_dir_perms;
+allow passwd_t etc_t:file create_file_perms;
+
+# Update /etc/auth/shadow.
+allow passwd_t etc_auth_t:dir rw_dir_perms;
+allow passwd_t etc_auth_t:file create_file_perms;
+
+# /usr/bin/passwd asks for w access to utmp, but it will operate
+# correctly without it.  Do not audit write denials to utmp.
+auditdeny passwd_t initrc_var_run_t:file ~write;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/su.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,82 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# su_exec_t is the type of the su executable.
+#
+type su_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+#
+# su_domain(domain_prefix)
+#
+# Define a su domain for a user domain.
+#
+define(`su_domain',`
+
+type $1_su_t, domain, privlog, auth;
+
+# Enter by the su executable.
+domain_auto_trans($1_t, su_exec_t, $1_su_t)
+
+# Revert to the user domain when a shell is executed.
+domain_auto_trans($1_su_t, shell_exec_t, $1_t)
+
+# Execute xauth.
+can_exec($1_su_t, bin_t)
+
+# Use capabilities.
+allow $1_su_t self:capability { setuid setgid net_bind_service };
+
+# Inherit and use descriptors from login.
+allow $1_su_t local_login_t:fd inherit_fd_perms;
+allow $1_su_t remote_login_t:fd inherit_fd_perms;
+
+# Inherit and use descriptors from gnome-pty-helper.
+allow $1_su_t $1_gph_t:fd inherit_fd_perms;
+allow $1_t $1_gph_t:fd inherit_fd_perms;
+
+# Read /etc/auth/shadow.
+allow $1_su_t etc_auth_t:dir r_dir_perms;
+allow $1_su_t etc_auth_t:file r_file_perms;
+
+# Write to utmp.
+allow $1_su_t initrc_var_run_t:file rw_file_perms;
+
+# Use the network.
+can_network($1_su_t)
+
+# Write to the user domain tty.
+allow $1_su_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_su_t $1_devpts_t:chr_file rw_file_perms;
+
+# Modify .Xauthority file (via xauth program).
+allow $1_su_t $1_home_t:dir rw_dir_perms;
+allow $1_su_t $1_home_t:file create_file_perms;
+
+')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/utempter.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the utempter_t domain.
+#
+# This is the domain for the utempter program.  utempter is
+# executed by xterm to update utmp and wtmp.
+# utempter_exec_t is the type of the utempter binary.
+#
+type utempter_t, domain;
+type utempter_exec_t, file_type, sysadmfile, exec_type;
+
+# Use capabilities.
+allow utempter_t utempter_t:capability { setgid };
+
+# Update /var/run/utmp and /var/log/wtmp.
+allow utempter_t initrc_var_run_t:file rw_file_perms;
+allow utempter_t wtmp_t:file rw_file_perms;
+
+# Allow ioctl and getattr /dev/ptmx.
+allow utempter_t ptmx_t:chr_file { ioctl getattr };
+
+# Inherit and use descriptors from login.
+allow utempter_t local_login_t:fd inherit_fd_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/program/xserver.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,100 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# xserver_exec_t is the type of the Xwrapper executable.
+#
+type xserver_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+#
+# xserver_domain(user_domain)
+#
+# Define an X server domain for a user domain.
+# FIXME!  The X server requires far too many privileges.
+#
+define(`xserver_domain',`
+
+type $1_xserver_t, domain, privlog, privmem;
+type $1_xserver_tmp_t, file_type, sysadmfile, tmpfile;
+
+# Enter by the Xwrapper executable.
+domain_auto_trans($1_t, xserver_exec_t, $1_xserver_t)
+
+# Allow the user domain to signal the X server for termination.
+allow $1_t $1_xserver_t:process signal;
+
+# Allow the user domain to connect to the X server.
+can_unix_connect($1_t, $1_xserver_t)
+allow $1_t $1_xserver_tmp_t:sock_file rw_file_perms;
+allow $1_t $1_xserver_tmp_t:dir r_dir_perms;
+
+# Create temporary files.
+file_type_auto_trans($1_xserver_t, tmp_t, $1_xserver_tmp_t)
+
+# Signal the user domain.
+allow $1_xserver_t $1_t:process signal;
+
+# Use capabilities.
+# FIXME!  Should separate the portion of the X server that requires sys_rawio.
+allow $1_xserver_t $1_xserver_t:capability { net_bind_service setuid setgid chown dac_override sys_rawio };
+
+# Use /dev/mem.  Yuck.
+# FIXME!  Should separate the portion of the X server that requires /dev/mem access.
+allow $1_xserver_t memory_device_t:chr_file rw_file_perms;
+
+# Access ttys.
+allow $1_xserver_t $1_tty_device_t:chr_file rw_file_perms;
+allow $1_xserver_t tty_device_t:chr_file rw_file_perms;
+
+# Get network interface configuration.
+allow $1_xserver_t kernel_t:system { net_io_control };
+allow $1_xserver_t netif_type:netif getattr;
+
+# Run helper programs in $1_xserver_t.
+can_exec_any($1_xserver_t)
+
+# Use the network
+can_network($1_xserver_t)
+
+# Connect to xfs.
+can_unix_connect($1_xserver_t, xfs_t)
+allow $1_xserver_t xfs_tmp_t:dir r_dir_perms;
+allow $1_xserver_t xfs_tmp_t:sock_file rw_file_perms;
+
+# Inherit and use descriptors from login.
+allow $1_xserver_t local_login_t:fd inherit_fd_perms;
+
+# Bind to the X server socket in /tmp.
+allow $1_xserver_t $1_xserver_tmp_t:unix_stream_socket name_bind;
+
+# Use /dev/psaux.
+allow $1_xserver_t psaux_t:chr_file rw_file_perms;
+
+')
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/apmd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the apmd_t domain.
+#
+type apmd_t, domain, privlog;
+type apmd_exec_t, file_type, sysadmfile, exec_type;
+type apm_bios_t, file_type;
+
+# Use capabilities.
+allow apmd_t self:capability { sys_admin };
+
+# Inherit and use descriptors from init.
+allow apmd_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow apmd_t initrc_t:pipe rw_file_perms;
+
+# Access /dev/apm_bios.
+allow apmd_t apm_bios_t:chr_file rw_file_perms;
+
+# Create pid file.
+type apmd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(apmd_t, var_run_t, apmd_var_run_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/atd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the atd_t domain.
+#
+type atd_t, domain, privlog;
+type atd_exec_t, file_type, sysadmfile, exec_type;
+
+type atd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(atd_t, tmp_t, atd_tmp_t)
+type atd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(atd_t, var_run_t, atd_var_run_t)
+
+# Use capabilities.
+allow atd_t atd_t:capability { setgid setuid };
+
+# Inherit and use descriptors from init.
+allow atd_t init_t:fd inherit_fd_perms;
+
+# Write to /var/spool/at.
+allow atd_t at_spool_t:dir rw_dir_perms;
+allow atd_t at_spool_t:file create_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/cardmgr.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,74 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the cardmgr_t domain.
+#
+type cardmgr_t, domain, privlog;
+type cardmgr_exec_t, file_type, sysadmfile, exec_type;
+
+# Use capabilities (net_admin for route).
+allow cardmgr_t self:capability { sys_admin net_admin };
+
+# Use system operations (for route).
+allow cardmgr_t kernel_t:system { route_control };
+
+# Inherit and use descriptors from init.
+allow cardmgr_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow cardmgr_t initrc_t:pipe rw_file_perms;
+
+# Create pid file and stab file.
+type cardmgr_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(cardmgr_t, var_run_t, cardmgr_var_run_t)
+
+# Create device files in /tmp.
+type cardmgr_dev_t, file_type, sysadmfile, tmpfile;
+type_transition cardmgr_t tmp_t:chr_file cardmgr_dev_t;
+allow cardmgr_t cardmgr_dev_t:chr_file create_file_perms;
+
+# Create symbolic links in /dev.
+type cardmgr_lnk_t, file_type, sysadmfile;
+type_transition cardmgr_t device_t:lnk_file cardmgr_lnk_t;
+allow cardmgr_t device_t:dir { add_name remove_name search };
+allow cardmgr_t cardmgr_lnk_t:lnk_file create_file_perms;
+
+# Run a shell, normal commands, /etc/pcmcia scripts. 
+can_exec_any(cardmgr_t)
+
+# Run insmod and rmmod. 
+domain_auto_trans(cardmgr_t, insmod_exec_t, insmod_t)
+domain_auto_trans(cardmgr_t, rmmod_exec_t, rmmod_t)
+
+# Run ifconfig.
+domain_auto_trans(cardmgr_t, ifconfig_exec_t, ifconfig_t)
+allow ifconfig_t cardmgr_t:pipe rw_file_perms;
+
+# Read /proc/PID directories for all domains (for fuser).
+allow cardmgr_t domain:notdevfile_class_set r_file_perms;
+allow cardmgr_t domain:dir r_dir_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/crond.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,214 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the crond_t domain, the system_crond_t domain and
+# the crond_domain macro.
+#
+
+type crond_t, domain, privuser, privrole, privlog;
+type crond_exec_t, file_type, sysadmfile, exec_type;
+
+type cron_context_t, file_type, sysadmfile;
+
+type crond_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(crond_t, tmp_t, crond_tmp_t)
+type crond_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(crond_t, var_run_t, crond_var_run_t)
+type cron_log_t, file_type, sysadmfile;
+file_type_auto_trans(crond_t, var_log_t, cron_log_t)
+
+# Use capabilities.
+allow crond_t crond_t:capability { setgid setuid net_bind_service };
+
+# Check entrypoint permission on crontab files.
+allow crond_t security_t:security compute_av;
+
+# Inherit and use descriptors from init.
+allow crond_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow crond_t initrc_t:pipe rw_file_perms;
+
+# Use the network.
+can_network(crond_t)
+
+# Read from /var/spool/cron.
+allow crond_t cron_spool_t:dir r_dir_perms;
+allow crond_t cron_spool_t:file r_file_perms;
+
+# Read system crontabs
+allow crond_t system_crond_script_t:file r_file_perms;
+allow crond_t system_crond_script_t:dir r_dir_perms;
+
+# Read /etc/security/cron_context
+allow crond_t cron_context_t:file r_file_perms;
+
+# Run a shell
+can_exec(crond_t, shell_exec_t)
+
+# Run the sendmail program in the user_mail_t domain.
+domain_auto_trans(crond_t, sendmail_exec_t, user_mail_t)
+
+# Pipe cron job output to sendmail through user_mail_t.
+allow user_mail_t crond_t:pipe rw_file_perms;
+
+# Inherit and use descriptors from init rc.
+allow user_mail_t initrc_t:fd inherit_fd_perms;
+
+# Use pipe from initrc.
+allow user_mail_t initrc_t:pipe rw_file_perms;
+
+
+#########################################
+#
+# system_crond_t domain
+#
+# Used for running system crontabs
+#
+type system_crond_t, domain, privlog;
+type system_crond_script_t, file_type, sysadmfile;
+
+# Enter through crond.
+domain_trans(crond_t, shell_exec_t, system_crond_t)
+
+# Inherit and use descriptors from initrc.
+allow system_crond_t initrc_t:fd inherit_fd_perms;
+
+# Write to a socket from initrc.
+allow system_crond_t initrc_t:udp_socket rw_socket_perms;
+
+# Use capabilities.
+allow system_crond_t system_crond_t:capability { setgid setuid 
+dac_override fowner net_bind_service };
+
+# Use a pipe created by crond_t.
+allow system_crond_t crond_t:pipe rw_file_perms;
+
+# Read the system crontabs.
+allow system_crond_t system_crond_script_t:file r_file_perms;
+
+# 
+# Since crontab files are not directly executed,
+# crond must ensure that the crontab file has
+# a type that is appropriate for the domain of
+# the system cron job.  It performs an entrypoint
+# permission check for this purpose.
+#
+allow system_crond_t system_crond_script_t:process entrypoint;
+
+# Run helper programs in the system_crond_t domain.
+can_exec_any(system_crond_t)
+
+# Read from /var/spool/cron.
+allow system_crond_t cron_spool_t:dir r_dir_perms;
+allow system_crond_t cron_spool_t:file r_file_perms;
+
+# Write to /var/lib/slocate.db.
+allow system_crond_t var_lib_t:dir rw_dir_perms;
+allow system_crond_t var_lib_t:file create_file_perms;
+
+# Update whatis files.
+allow system_crond_t man_t:dir rw_dir_perms;
+allow system_crond_t man_t:file create_file_perms;
+
+# Write /var/lock/makewhatis.lock.
+allow system_crond_t var_lock_t:dir rw_dir_perms;
+allow system_crond_t var_lock_t:file create_file_perms;
+
+# Run rmmod for /etc/cron.d/kmod in the rmmod_t domain.
+domain_auto_trans(system_crond_t, rmmod_exec_t, rmmod_t)
+allow rmmod_t crond_t:fd inherit_fd_perms;
+allow rmmod_t crond_t:process sigchld;
+
+# Run logrotate in the logrotate_t domain.
+domain_auto_trans(system_crond_t, logrotate_exec_t, logrotate_t)
+allow logrotate_t crond_t:fd inherit_fd_perms;
+allow logrotate_t initrc_t:fd inherit_fd_perms;
+#allow logrotate_t crond_t:process sigchld;
+
+# Stat any file and search any directory for find.
+allow system_crond_t file_type:file_class_set getattr;
+allow system_crond_t file_type:dir { read search getattr };
+
+# Create temporary files.
+type system_crond_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(system_crond_t, tmp_t, system_crond_tmp_t)
+
+# Used for /sbin/tmpwatch
+allow system_crond_t tmpfile:dir { read getattr setattr access lock search remove_name rmdir };
+allow system_crond_t tmpfile:notdevfile_class_set link_file_perms;
+allow system_crond_t catman_t:dir { read getattr setattr access lock search remove_name rmdir };
+allow system_crond_t catman_t:notdevfile_class_set link_file_perms;
+
+
+#################################
+#
+# The crond_domain macro.
+#
+define(`crond_domain',`
+
+###########################################
+# $1_crond_t
+#
+# Define a crond domain for a user domain.
+# This is the domain used for user cron jobs.
+#
+type $1_crond_t, domain;
+
+# Use capabilities.
+allow $1_crond_t $1_crond_t:capability dac_override;
+
+# Inherit and use descriptors from initrc.
+allow $1_crond_t initrc_t:fd inherit_fd_perms;
+
+# Enter this domain from crond_t.
+domain_trans(crond_t, shell_exec_t, $1_crond_t)
+
+# 
+# Since crontab files are not directly executed,
+# crond must ensure that the crontab file has
+# a type that is appropriate for the domain of
+# the user cron job.  It performs an entrypoint
+# permission check for this purpose.
+#
+allow $1_crond_t $1_cron_spool_t:process entrypoint;
+
+# Use pipe from crond_t.
+allow $1_crond_t crond_t:pipe rw_file_perms;
+
+# Access user files and dirs.
+allow $1_crond_t $1_home_t:file create_file_perms;
+allow $1_crond_t $1_home_t:dir create_dir_perms;
+
+# Run helper programs.
+can_exec_any($1_crond_t)
+
+# Run scripts in user home directory.
+can_exec($1_crond_t, $1_home_t)
+
+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/ftpd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,130 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the ftpd_t domain and
+# the ftpd_domain macro.
+#
+type ftpd_t, domain, privlog, auth;
+type ftpd_exec_t, file_type, sysadmfile, exec_type;
+type ftpd_stage2_exec_t, file_type, sysadmfile, exec_type;
+type ftpd_var_run_t, file_type, sysadmfile, pidfile;
+
+# Inherit and use descriptors from inetd.
+allow ftpd_t inetd_t:fd inherit_fd_perms;
+
+# Use sockets inherited from inetd.
+allow ftpd_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use capabilities.
+allow ftpd_t ftpd_t:capability { net_bind_service setuid setgid fowner fsetid chown sys_resource };
+
+# Use the network.
+can_network(ftpd_t)
+
+# Connect to inetd.
+can_tcp_connect(ftpd_t,inetd_t)
+
+# Send SIGCHLD to inetd on death.
+allow ftpd_t inetd_t:process sigchld;
+
+# Create pid files.
+file_type_auto_trans(ftpd_t, var_run_t, ftpd_var_run_t)
+
+# Read /etc/auth/shadow.
+allow ftpd_t etc_auth_t:dir r_dir_perms;
+allow ftpd_t etc_auth_t:file r_file_perms;
+
+# Append to /var/log/wtmp.
+allow ftpd_t wtmp_t:file append;
+
+# Append to /var/log/xferlog.
+allow ftpd_t var_log_t:file append;
+
+# Execute /bin/ls.
+# XXX This is unnecessary when using the two-stage modified ftpd,
+# XXX since only the second stage requires this permission.
+can_exec(ftpd_t, ls_exec_t)
+
+
+#################################
+#
+# ftpd_domain(user_domain)
+#
+# Define a ftpd domain for a user domain.
+#
+define(`ftpd_domain',`
+
+type $1_ftpd_t, domain, privlog;
+
+# Enter this domain from ftpd_t.
+# Commented out - modified ftpd removed from distribution for now.
+#domain_trans(ftpd_t, ftpd_stage2_exec_t, $1_ftpd_t)
+
+# Inherit and use descriptors from inetd.
+allow $1_ftpd_t inetd_t:fd inherit_fd_perms;
+
+# Use sockets inherited from inetd.
+allow $1_ftpd_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use capabilities.
+allow $1_ftpd_t $1_ftpd_t:capability { net_bind_service setuid setgid fowner fsetid chown sys_resource dac_override dac_read_search };
+
+# Use the network.
+can_network($1_ftpd_t)
+
+# Connect to inetd.
+can_tcp_connect($1_ftpd_t,inetd_t)
+
+# Connect to ftp client.
+can_tcp_connect($1_ftpd_t,$1_t)
+
+# Send SIGCHLD to inetd on death.
+allow $1_ftpd_t inetd_t:process sigchld;
+
+# Create pid files.
+file_type_auto_trans($1_ftpd_t, var_run_t, ftpd_var_run_t)
+
+# Append to /var/log/wtmp.
+allow $1_ftpd_t wtmp_t:file append;
+
+# Append to /var/log/xferlog.
+allow $1_ftpd_t var_log_t:file append;
+
+# Execute /bin/ls.
+can_exec($1_ftpd_t, ls_exec_t)
+
+# Access user home directories and files.
+allow $1_ftpd_t $1_home_t:file create_file_perms;
+allow $1_ftpd_t $1_home_t:dir create_dir_perms;
+
+')
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/getty.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the getty_t domain.
+#
+type getty_t, domain, privlog;
+type getty_exec_t, file_type, sysadmfile, exec_type;
+
+type getty_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(getty_t, tmp_t, getty_tmp_t)
+
+# Use capabilities.
+allow getty_t getty_t:capability { chown sys_tty_config };
+
+# Inherit and use descriptors from init.
+allow getty_t init_t:fd inherit_fd_perms;
+
+# Run login in local_login_t domain.
+domain_auto_trans(getty_t, login_exec_t, local_login_t)
+
+# Write to /var/run/utmp.
+allow getty_t initrc_var_run_t:file rw_file_perms;
+
+# Write to /var/log/wtmp.
+allow getty_t wtmp_t:file rw_file_perms;
+
+# Read and write ttys.
+allow getty_t tty_device_t:chr_file rw_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/gpm.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,59 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the gpm_t domain.
+#
+# gpm_t is the domain of the console mouse server.
+# gpm_exec_t is the type of the console mouse server program.
+# gpmctl_t is the type of the Unix domain socket created
+# by the console mouse server.
+#
+type gpm_t, domain, privlog;
+type gpm_exec_t, file_type, sysadmfile, exec_type;
+type gpmctl_t, file_type, sysadmfile;
+
+type gpm_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(gpm_t, tmp_t, gpm_tmp_t)
+type gpm_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(gpm_t, var_run_t, gpm_var_run_t)
+
+# Use capabilities.
+allow gpm_t gpm_t:capability { setuid dac_override };
+
+# Inherit and use descriptors from init.
+allow gpm_t init_t:fd inherit_fd_perms;
+
+# Create and bind to /dev/gpmctl.
+file_type_auto_trans(gpm_t, device_t, gpmctl_t)
+allow gpm_t gpmctl_t:unix_stream_socket name_bind;
+
+# Access /dev/psaux.
+allow gpm_t psaux_t:chr_file rw_file_perms;
+
+# Read and write ttys.
+allow gpm_t tty_device_t:chr_file rw_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/inetd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,88 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the inetd_t domain and
+# the inetd_child_t domain.
+#
+
+#################################
+#
+# Rules for the inetd_t domain.
+#
+type inetd_t, domain, privlog;
+type inetd_exec_t, file_type, sysadmfile, exec_type;
+
+type inetd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(inetd_t, tmp_t, inetd_tmp_t)
+type inetd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(inetd_t, var_run_t, inetd_var_run_t)
+
+# Inherit and use descriptors from init.
+allow inetd_t init_t:fd inherit_fd_perms;
+
+# Use capabilities.
+allow inetd_t inetd_t:capability { setgid net_bind_service };
+
+# Use the network.
+can_network(inetd_t)
+
+# Run tcpd in the tcpd_t domain.
+domain_auto_trans(inetd_t, tcpd_exec_t, tcpd_t)
+
+# Run other daemons in the inetd_child_t domain.
+domain_auto_trans(inetd_t, inetd_child_exec_t, inetd_child_t)
+
+# Bind to the telnet, ftp, rlogin and rsh ports.
+allow inetd_t telnet_port_t:tcp_socket name_bind;
+allow inetd_t ftp_port_t:tcp_socket name_bind;
+allow inetd_t rlogin_port_t:tcp_socket name_bind;
+allow inetd_t rsh_port_t:tcp_socket name_bind;
+
+
+#################################
+#
+# Rules for the inetd_child_t domain.
+#
+# inetd_child_t is a general domain for daemons started
+# by inetd that do not have their own individual domains yet.
+# inetd_child_exec_t is the type of the corresponding
+# programs.
+#
+type inetd_child_t, domain, privlog;
+type inetd_child_exec_t, file_type, sysadmfile, exec_type;
+
+type inetd_child_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(inetd_child_t, tmp_t, inetd_child_tmp_t)
+type inetd_child_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(inetd_child_t, var_run_t, inetd_child_var_run_t)
+
+# Use sockets inherited from inetd.
+allow inetd_child_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use the network
+can_network(inetd_child_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/init.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,79 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the init_t domain.
+#
+# init_t is the domain of the init process.
+# init_exec_t is the type of the init program.
+# initctl_t is the type of the named pipe created 
+# by init during initialization.  This pipe is used
+# to communicate with init.
+# sulogin_exec_t is the type of sulogin.
+#
+type init_t, domain, privlog;
+type init_exec_t, file_type, sysadmfile, exec_type;
+type initctl_t, file_type, sysadmfile;
+type sulogin_exec_t, file_type, sysadmfile;
+
+# Use capabilities.
+allow init_t init_t:capability ~sys_module;
+
+# Run /etc/rc.sysinit, /etc/rc, /etc/rc.local in the initrc_t domain.
+domain_auto_trans(init_t, initrc_exec_t, initrc_t)
+
+# Run the shell or sulogin in the sysadm_t domain for single-user mode.
+domain_auto_trans(init_t, shell_exec_t, sysadm_t)
+domain_auto_trans(init_t, sulogin_exec_t, sysadm_t)
+
+# Run mingetty in its own domain.
+domain_auto_trans(init_t, getty_exec_t, getty_t)
+
+# Run /sbin/update in the init_t domain.
+can_exec(init_t, sbin_t)
+
+# Run init.
+can_exec(init_t, init_exec_t)
+
+# Create /dev/initctl.
+file_type_auto_trans(init_t, device_t, initctl_t)
+
+# Create ioctl.save.
+file_type_auto_trans(init_t, etc_t, etc_runtime_t)
+
+# Modify utmp.
+allow init_t var_run_t:file rw_file_perms;
+allow init_t initrc_var_run_t:file rw_file_perms;
+
+# Modify wtmp.
+allow init_t wtmp_t:file rw_file_perms;
+
+# Kill all processes.
+allow init_t domain:process signal_perms;
+
+# Read and write ttys.
+allow init_t tty_device_t:chr_file rw_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/initrc.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,164 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the initrc_t domain.
+#
+# initrc_t is the domain of the init rc scripts.
+# initrc_exec_t is the type of the init program.
+#
+type initrc_t, domain, privlog, privowner;
+type initrc_exec_t, file_type, sysadmfile, exec_type;
+
+type initrc_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(initrc_t, tmp_t, initrc_tmp_t)
+type initrc_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(initrc_t, var_run_t, initrc_var_run_t)
+
+# Use capabilities.
+allow initrc_t initrc_t:capability ~sys_module;
+
+# Use system operations.
+allow initrc_t kernel_t:system *;
+
+# Set values in /proc/sys.
+can_sysctl(initrc_t)
+
+# Use the network.
+can_network(initrc_t)
+
+# Run helper programs in the initrc_t domain.
+can_exec_any(initrc_t)
+
+# Run daemons in their own domains.
+domain_auto_trans(initrc_t, syslogd_exec_t, syslogd_t)
+domain_auto_trans(initrc_t, klogd_exec_t, klogd_t)
+domain_auto_trans(initrc_t, crond_exec_t, crond_t)
+domain_auto_trans(initrc_t, atd_exec_t, atd_t)
+domain_auto_trans(initrc_t, lpd_exec_t, lpd_t)
+domain_auto_trans(initrc_t, inetd_exec_t, inetd_t)
+domain_auto_trans(initrc_t, sendmail_exec_t, sendmail_t)
+domain_auto_trans(initrc_t, ypbind_exec_t, ypbind_t)
+domain_auto_trans(initrc_t, portmap_exec_t, portmap_t)
+domain_auto_trans(initrc_t, rpcd_exec_t, rpcd_t)
+domain_auto_trans(initrc_t, gpm_exec_t, gpm_t)
+domain_auto_trans(initrc_t, xfs_exec_t, xfs_t)
+domain_auto_trans(initrc_t, apmd_exec_t, apmd_t)
+domain_auto_trans(initrc_t, cardmgr_exec_t, cardmgr_t)
+domain_auto_trans(initrc_t, sshd_exec_t, sshd_t)
+
+# Run modules programs in their own domains.
+domain_auto_trans(initrc_t, depmod_exec_t, depmod_t)
+domain_auto_trans(initrc_t, modprobe_exec_t, modprobe_t)
+domain_auto_trans(initrc_t, insmod_exec_t, insmod_t)
+domain_auto_trans(initrc_t, rmmod_exec_t, rmmod_t)
+
+# Read conf.modules.
+allow initrc_t modules_conf_t:file r_file_perms;
+
+# Run fsck and swapon in their own domain.
+domain_auto_trans(initrc_t, fsadm_exec_t, fsadm_t)
+
+# Run ifconfig in its own domain.
+domain_auto_trans(initrc_t, ifconfig_exec_t, ifconfig_t)
+
+# Run other rc scripts in the initrc_t domain.
+allow initrc_t initrc_exec_t:file rx_file_perms;
+
+# Run init (telinit) in the initrc_t domain.
+can_exec(initrc_t, init_exec_t)
+
+# Communicate with the init process.
+allow initrc_t initctl_t:fifo_file rw_file_perms;
+
+# Send messages to portmap and ypbind.
+can_udp_send(initrc_t, portmap_t)
+can_udp_send(initrc_t, ypbind_t)
+
+# Search persistent label mappings.
+allow initrc_t file_labels_t:dir r_dir_perms;
+allow initrc_t file_labels_t:file stat_file_perms;
+
+# Read /proc/PID directories for all domains.
+allow initrc_t domain:notdevfile_class_set r_file_perms;
+allow initrc_t domain:dir r_dir_perms;
+
+# Mount and unmount file systems.
+allow initrc_t fs_type:filesystem mount_fs_perms;
+allow initrc_t file_t:dir mounton;
+
+# Create runtime files in /etc, e.g. /etc/mtab, /etc/HOSTNAME.
+file_type_auto_trans(initrc_t, etc_t, etc_runtime_t)
+
+# Update /etc/mail.
+allow initrc_t etc_mail_t:file rw_file_perms;
+
+# Generate /boot/kernel.h.
+file_type_auto_trans(initrc_t, boot_t, boot_runtime_t)
+
+# Unlink the xfs socket.
+allow initrc_t xfs_tmp_t:dir { read search getattr access remove_name rmdir };
+allow initrc_t xfs_tmp_t:sock_file { read getattr access unlink };
+
+# Update /var/log/wtmp and /var/log/dmesg.
+allow initrc_t wtmp_t:file rw_file_perms;
+allow initrc_t var_log_t:file rw_file_perms;
+
+# Unlink /var/run/random-seed.
+allow initrc_t var_run_t:file unlink;
+
+# Create lock file.
+allow initrc_t var_lock_t:dir create_dir_perms;
+allow initrc_t var_lock_t:file create_file_perms;
+
+# Set the clock.
+allow initrc_t clock_device_t:devfile_class_set rw_file_perms;
+
+# Kill all processes.
+allow initrc_t domain:process signal_perms;
+
+# Read and unlink /var/run/*.pid files.
+allow initrc_t pidfile:file { getattr read unlink };
+
+# Write to /dev/urandom.
+allow initrc_t random_device_t:chr_file rw_file_perms;
+
+# Read /dev/psaux (for kudzu).
+allow initrc_t psaux_t:chr_file r_file_perms;
+
+# Read /dev/cdrom.
+allow initrc_t misc_device_t:lnk_file r_file_perms;
+
+# Stat any file.
+allow initrc_t file_type:file_class_set getattr;
+allow initrc_t file_type:dir { search getattr };
+
+# Read and write ttys.
+allow initrc_t tty_device_t:chr_file rw_file_perms;
+
+# Reset tty labels.
+allow initrc_t tty_device_t:chr_file relabelto;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/kernel.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,51 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the kernel_t domain.
+#
+
+#
+# kernel_t is the domain of process 0 and the kernel
+# threads started by it. It is also the target type
+# when checking permissions in the system class.
+# 
+type kernel_t, domain;
+
+# Use capabilities.
+allow kernel_t self:capability setuid;
+
+# Run init in the init_t domain.
+domain_auto_trans(kernel_t, init_exec_t, init_t)
+
+# Mount and unmount file systems.
+allow kernel_t fs_type:filesystem mount_fs_perms;
+
+# Search the persistent label mapping.
+allow kernel_t file_labels_t:dir search;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/klogd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the klogd_t domain.
+#
+type klogd_t, domain, privlog, privmem;
+type klogd_exec_t, file_type, sysadmfile, exec_type;
+
+type klogd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(klogd_t, tmp_t, klogd_tmp_t)
+type klogd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(klogd_t, var_run_t, klogd_var_run_t)
+
+# Use the sys_admin and sys_rawio capabilities.
+allow klogd_t klogd_t:capability { sys_admin sys_rawio };
+
+# Inherit and use descriptors from init.
+allow klogd_t init_t:fd inherit_fd_perms;
+
+# Read /proc/kmsg and /dev/mem.
+allow klogd_t proc_kmsg_t:file r_file_perms;
+allow klogd_t memory_device_t:chr_file r_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/kmod.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,64 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the kmod_t domain.
+#
+# kmod_t is the domain of the kernel module loader. 
+#
+type kmod_t, domain, privlog;
+
+# Use the sys_module and setpcap capabilities.
+allow kmod_t kmod_t:capability { sys_module setpcap kill };
+
+# Inherit and use descriptors from init.
+allow kmod_t init_t:fd inherit_fd_perms;
+
+# Use a pipe created by initrc_t.
+allow kmod_t initrc_t:pipe rw_file_perms;
+
+# Run modprobe and insmod in the kmod_t domain.
+can_exec(kmod_t,modprobe_exec_t)
+can_exec(kmod_t,insmod_exec_t)
+
+# Read conf.modules.
+allow kmod_t modules_conf_t:file r_file_perms;
+
+# Run shell commands from conf.modules.
+can_exec_any(kmod_t)
+
+# Read modules.dep.
+allow kmod_t modules_dep_t:file r_file_perms;
+
+# Read module objects.
+allow kmod_t modules_object_t:dir r_dir_perms;
+allow kmod_t modules_object_t:file r_file_perms;
+
+# Signal any domain.
+allow kmod_t domain:process signal;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/login.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,141 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+# 
+# Rules for the local_login_t domain
+# and the remote_login_t domain.
+#
+
+#################################
+#
+# Rules for the local_login_t domain.
+#
+# local_login_t is the domain of a login process 
+# spawned by getty.
+# login_exec_t is the type of the login program
+#
+type local_login_t, domain, privuser, privrole, privlog, auth, privowner;
+type login_exec_t, file_type, sysadmfile, exec_type;
+
+type local_login_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(local_login_t, tmp_t, local_login_tmp_t)
+
+# Use capabilities.
+allow local_login_t local_login_t:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override };
+
+# Use the network.
+can_network(local_login_t)
+
+# Run shells in user_t by default.
+domain_auto_trans(local_login_t, shell_exec_t, user_t)
+
+# Allow shells to be created in sysadm_t as well.
+domain_trans(local_login_t, shell_exec_t, sysadm_t)
+
+# Do not audit denied attempts to access devices.
+auditdeny local_login_t fixed_disk_device_t:blk_file ~{ getattr setattr };
+auditdeny local_login_t removable_device_t:blk_file ~{ getattr setattr };
+auditdeny local_login_t device_t:file_class_set ~{ getattr setattr };
+auditdeny local_login_t misc_device_t:file_class_set ~{ getattr setattr };
+
+# Write to /var/run/utmp.
+allow local_login_t initrc_var_run_t:file rw_file_perms;
+
+# Write to /var/log/wtmp.
+allow local_login_t wtmp_t:file rw_file_perms;
+
+# Write to /var/log/lastlog.
+allow local_login_t var_log_t:file rw_file_perms;
+
+# Create lock file.
+allow local_login_t var_lock_t:dir rw_dir_perms;
+allow local_login_t var_lock_t:file create_file_perms;
+
+# Read /etc/auth/shadow.
+allow local_login_t etc_auth_t:dir r_dir_perms;
+allow local_login_t etc_auth_t:file r_file_perms;
+
+# Search for mail spool file.
+allow local_login_t mail_spool_t:dir r_dir_perms;
+allow local_login_t mail_spool_t:file getattr;
+
+# Obtain the SID to use for relabeling terminals.
+allow local_login_t security_t:security change_sid;
+
+# Read and write ttys.
+allow local_login_t tty_device_t:chr_file rw_file_perms;
+
+# Relabel ttys.
+allow local_login_t tty_device_t:chr_file { relabelfrom relabelto };
+
+
+#################################
+#
+# Rules for the remote_login_t domain.
+#
+# remote_login_t is the domain of a login process 
+# spawned by rlogind.
+#
+type remote_login_t, domain, privuser, privrole, privlog, auth, privowner;
+
+type remote_login_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(remote_login_t, tmp_t, remote_login_tmp_t)
+
+# Use capabilities.
+allow remote_login_t remote_login_t:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override };
+
+# Use the network.
+can_network(remote_login_t)
+
+# Run shells in user_t by default.
+domain_auto_trans(remote_login_t, shell_exec_t, user_t)
+
+# Use the pty created by rlogind.
+allow remote_login_t rlogind_devpts_t:chr_file rw_file_perms;
+
+# Write to /var/run/utmp.
+allow remote_login_t initrc_var_run_t:file rw_file_perms;
+
+# Write to /var/log/wtmp.
+allow remote_login_t wtmp_t:file rw_file_perms;
+
+# Write to /var/log/lastlog.
+allow remote_login_t var_log_t:file rw_file_perms;
+
+# Read /etc/auth/shadow.
+allow remote_login_t etc_auth_t:dir r_dir_perms;
+allow remote_login_t etc_auth_t:file r_file_perms;
+
+# Search for mail spool file.
+allow remote_login_t mail_spool_t:dir r_dir_perms;
+allow remote_login_t mail_spool_t:file getattr;
+
+# Obtain the SID to use for relabeling ptys.
+allow remote_login_t security_t:security change_sid;
+
+# Relabel ptys created by rlogind.
+allow remote_login_t rlogind_devpts_t:chr_file { relabelfrom relabelto };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/lpd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,72 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the lpd_t domain.
+#
+# lpd_t is the domain of lpd.
+# lpd_exec_t is the type of the lpd executable.
+# printer_t is the type of the Unix domain socket created
+# by lpd. 
+#
+type lpd_t, domain, privlog;
+type lpd_exec_t, file_type, sysadmfile, exec_type;
+type printer_t, file_type, sysadmfile;
+
+type lpd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(lpd_t, tmp_t, lpd_tmp_t)
+
+# Use capabilities.
+allow lpd_t lpd_t:capability { setgid setuid net_bind_service dac_read_search dac_override };
+
+# Inherit and use descriptors from init.
+allow lpd_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(lpd_t)
+
+# Bind to the printer port.
+allow lpd_t printer_port_t:tcp_socket name_bind;
+
+# Send to portmap.
+can_udp_send(lpd_t, portmap_t)
+
+# Connect to ypbind.
+can_tcp_connect(lpd_t, ypbind_t)
+
+# Create and bind to /dev/printer.
+file_type_auto_trans(lpd_t, device_t, printer_t)
+allow lpd_t printer_t:unix_stream_socket name_bind;
+allow lpd_t printer_t:unix_dgram_socket name_bind;
+
+# Write to /var/spool/lpd.
+allow lpd_t lpd_spool_t:dir rw_dir_perms;
+allow lpd_t lpd_spool_t:file create_file_perms;
+
+# Execute filter scripts.
+can_exec(lpd_t, lpd_spool_t)
+can_exec_any(lpd_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/portmap.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the portmap_t domain.
+#
+type portmap_t, domain, privlog;
+type portmap_exec_t, file_type, sysadmfile, exec_type;
+
+type portmap_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(portmap_t, tmp_t, portmap_tmp_t)
+
+# Inherit and use descriptors from init.
+allow portmap_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(portmap_t)
+
+# Send to ypbind, initrc, lpd.
+can_udp_send(portmap_t, ypbind_t)
+can_udp_send(portmap_t, initrc_t)
+can_udp_send(portmap_t, lpd_t)
+
+# Use capabilitiesl
+allow portmap_t portmap_t:capability { net_bind_service setuid };
+
+# Use net ioctls.
+allow portmap_t kernel_t:system { net_io_control };
+
+# Get network interface configuration.
+allow portmap_t netif_type:netif getattr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/rlogind.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,70 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the rlogind_t domain.
+#
+type rlogind_t, domain, privlog, auth;
+type rlogind_exec_t, file_type, sysadmfile, exec_type;
+
+type rlogind_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(rlogind_t, tmp_t, rlogind_tmp_t)
+
+# Inherit and use descriptors from inetd.
+allow rlogind_t inetd_t:fd inherit_fd_perms;
+
+# Use sockets inherited from inetd.
+allow rlogind_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use capabilities.
+allow rlogind_t rlogind_t:capability { net_bind_service setuid setgid fowner fsetid chown dac_override };
+
+# Perform socket ioctl.
+allow rlogind_t kernel_t:system net_io_control;
+
+# Use the network.
+can_network(rlogind_t)
+
+# Run login in remote_login_t.
+domain_auto_trans(rlogind_t, login_exec_t, remote_login_t)
+
+# Send SIGCHLD to inetd on death.
+allow rlogind_t inetd_t:process sigchld;
+
+# Create ptys.
+can_create_pty(rlogind)
+
+# Modify /var/run/utmp.
+allow rlogind_t initrc_var_run_t:file rw_file_perms;
+
+# Modify /var/log/wtmp.
+allow rlogind_t wtmp_t:file rw_file_perms;
+
+# Read /etc/auth/shadow.
+allow rlogind_t etc_auth_t:dir r_dir_perms;
+allow rlogind_t etc_auth_t:file r_file_perms;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/rpcd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the rpcd_t domain.
+#
+# rpcd_t is the domain of rpc daemons.
+# rpcd_exec_t is the type of rpc daemon programs.
+#
+type rpcd_t, domain, privlog;
+type rpcd_exec_t, file_type, sysadmfile, exec_type;
+
+type rpcd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(rpcd_t, tmp_t, rpcd_tmp_t)
+
+# Inherit and use descriptors from init
+allow rpcd_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(rpcd_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/rshd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,61 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the rshd_t domain.
+#
+type rshd_t, domain, privlog;
+type rshd_exec_t, file_type, sysadmfile, exec_type;
+
+# Inherit and use descriptors from inetd.
+allow rshd_t inetd_t:fd inherit_fd_perms;
+
+# Use sockets inherited from inetd.
+allow rshd_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use capabilities.
+allow rshd_t rshd_t:capability { net_bind_service setuid setgid fowner fsetid chown dac_override};
+
+# Use the network.
+can_network(rshd_t)
+
+# Run shells in user_t.
+# Commented out - modified rshd removed from distribution for now.
+#domain_auto_trans(rshd_t, shell_exec_t, user_t)
+
+# Send SIGCHLD to inetd on death.
+allow rshd_t inetd_t:process sigchld;
+
+# Allow socket ioctls not handled by other, more specific permissions.
+allow rshd_t kernel_t:system net_io_control;
+
+# in.rshd likes to search /etc/auth and read & getattr /etc/auth/shadow.
+# in.rshd will operate correctly without these (dangerous) permissions,
+# so the rshd_t domain does not provide them.  We tell the avc not to
+# log failures for these permissions.
+auditdeny rshd_t etc_auth_t:dir ~search;
+auditdeny rshd_t etc_auth_t:file ~{read getattr};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/sendmail.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,78 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the sendmail_t domain.
+#
+# sendmail_t is the domain for the sendmail 
+# daemon started by the init rc scripts.
+# sendmail_exec_t is the type of the sendmail executable.
+#
+type sendmail_t, domain, privlog;
+type sendmail_exec_t, file_type, sysadmfile, exec_type;
+
+type sendmail_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(sendmail_t, tmp_t, sendmail_tmp_t)
+type sendmail_var_log_t, file_type, sysadmfile;
+file_type_auto_trans(sendmail_t, var_log_t, sendmail_var_log_t)
+type sendmail_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(sendmail_t, var_run_t, sendmail_var_run_t)
+
+# Use capabilities
+allow sendmail_t sendmail_t:capability { setuid setgid net_bind_service sys_nice chown };
+
+# Inherit and use descriptors from init.
+allow sendmail_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(sendmail_t)
+
+# Bind to the SMTP port.
+allow sendmail_t smtp_port_t:tcp_socket name_bind;
+
+# Write to /etc/aliases and /etc/mail.
+allow sendmail_t etc_aliases_t:file rw_file_perms;
+allow sendmail_t etc_mail_t:dir rw_dir_perms;
+allow sendmail_t etc_mail_t:file create_file_perms;
+
+# Write to /var/spool/mail and /var/spool/mqueue.
+allow sendmail_t mail_spool_t:dir rw_dir_perms;
+allow sendmail_t mail_spool_t:file create_file_perms;
+allow sendmail_t mqueue_spool_t:dir rw_dir_perms;
+allow sendmail_t mqueue_spool_t:file create_file_perms;
+
+# Use a pipe inherited from init.
+allow sendmail_t initrc_t:pipe rw_file_perms;
+
+# Execute procmail.
+can_exec(sendmail_t, bin_t)
+
+# /usr/sbin/sendmail asks for w access to utmp, but it will operate
+# correctly without it.  Do not audit write denials to utmp.
+auditdeny sendmail_t initrc_var_run_t:file ~write;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/sshd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,123 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the sshd_t domain, et al.
+#
+# sshd_t is the domain for the sshd program.
+# sshd_login_t is the domain for sshd's login spawn
+# sshd_exec_t is the type of the sshd executable.
+# sshd_key_t is the type of the ssh private key files
+#
+type sshd_t, domain, privlog;
+type sshd_login_t, domain, privuser, privrole, privlog, auth, privowner;
+type sshd_exec_t, file_type, exec_type;
+type sshd_key_t, file_type;
+
+# Inherit and use descriptors from init.
+allow sshd_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(sshd_t)
+
+# Can create pty's
+can_create_pty(sshd)
+
+# Execute Login
+domain_auto_trans(sshd_t, login_exec_t, sshd_login_t)
+
+# Fetch shell attributes
+allow sshd_t shell_exec_t:file { getattr };
+
+# Use capabilities.
+allow sshd_t self:capability { chown fowner fsetid sys_tty_config dac_override net_bind_service };
+
+# Create /var/run/sshd.pid
+type sshd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(sshd_t, var_run_t, sshd_var_run_t)
+
+# Access key files
+allow sshd_t sshd_key_t:file rw_file_perms;
+
+# Append to /var/log/lastlog
+allow sshd_t var_log_t:file append;
+
+# Append to utmp
+allow sshd_t initrc_var_run_t:file append;
+
+# Append to wtmp
+allow sshd_t wtmp_t:file append;
+
+
+#################################
+#
+# Rules for the sshd_login_t domain
+#
+# sshd_login_t is the domain of a login process
+# spawned by sshd
+
+# Use capabilities
+allow sshd_login_t self:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override };
+
+# Use the network
+can_network(sshd_login_t)
+
+# Run shells in user_t by default
+domain_auto_trans(sshd_login_t, shell_exec_t, user_t)
+
+# Use the pty created by sshd
+allow sshd_login_t sshd_devpts_t:chr_file rw_file_perms;
+
+# Write to /var/run/utmp
+allow sshd_login_t initrc_var_run_t:file rw_file_perms;
+
+# Write to /var/log/wtmp
+allow sshd_login_t wtmp_t:file rw_file_perms;
+
+# Write to /var/log/lastlog
+allow sshd_login_t var_log_t:file rw_file_perms;
+
+# Read /etc/auth/shadow
+allow sshd_login_t etc_auth_t:dir r_dir_perms;
+allow sshd_login_t etc_auth_t:file r_file_perms;
+
+# Search for mail spool file
+allow sshd_login_t mail_spool_t:dir r_dir_perms;
+allow sshd_login_t mail_spool_t:file getattr;
+
+# Obtain the SID to use for relabeling ptys
+allow sshd_login_t security_t:security change_sid;
+
+# Relabel ptys created by sshd
+allow sshd_login_t sshd_devpts_t:chr_file { relabelfrom relabelto };
+allow sshd_login_t user_devpts_t:chr_file { relabelto relabelfrom getattr };
+
+allow sshd_devpts_t user_devpts_t:chr_file transition;
+allow user_devpts_t sshd_devpts_t:chr_file transition;
+
+# Tell it how to relabel them
+type_change user_t sshd_devpts_t:chr_file user_devpts_t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/syslogd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the syslogd_t domain.
+#
+# syslogd_t is the domain of syslogd.
+# syslogd_exec_t is the type of the syslogd executable.
+# devlog_t is the type of the Unix domain socket created 
+# by syslogd.
+#
+type syslogd_t, domain;
+type syslogd_exec_t, file_type, sysadmfile, exec_type;
+type devlog_t, file_type, sysadmfile;
+
+type syslogd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(syslogd_t, tmp_t, syslogd_tmp_t)
+type syslogd_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(syslogd_t, var_run_t, syslogd_var_run_t)
+
+# Use the net_bind_service capability.
+allow syslogd_t syslogd_t:capability { net_bind_service };
+
+# Inherit and use descriptors from init.
+allow syslogd_t init_t:fd inherit_fd_perms;
+
+# Modify log files.
+allow syslogd_t var_log_t:file rw_file_perms;
+
+# Create and bind to /dev/log.
+file_type_auto_trans(syslogd_t, device_t, devlog_t)
+allow syslogd_t devlog_t:unix_stream_socket name_bind;
+allow syslogd_t devlog_t:unix_dgram_socket name_bind;
+
+# Domains with the privlog attribute may log to syslogd.
+allow privlog devlog_t:sock_file rw_file_perms;
+can_unix_send(privlog,syslogd_t)
+can_unix_connect(privlog,syslogd_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/tcpd.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the tcpd_t domain.
+#
+type tcpd_t, domain, privlog;
+type tcpd_exec_t, file_type, sysadmfile, exec_type;
+
+type tcpd_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(tcpd_t, tmp_t, tcpd_tmp_t)
+
+# Use sockets inherited from inetd.
+allow tcpd_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Use the network
+can_network(tcpd_t)
+
+# Run rlogind and telnetd in rlogind_t
+domain_auto_trans(tcpd_t, rlogind_exec_t, rlogind_t)
+
+# Run rshd in rshd_t
+domain_auto_trans(tcpd_t, rshd_exec_t, rshd_t)
+
+# Run ftpd in ftpd_t
+domain_auto_trans(tcpd_t, ftpd_exec_t, ftpd_t)
+
+# Run other daemons in the inetd_child_t domain.
+domain_auto_trans(tcpd_t, inetd_child_exec_t, inetd_child_t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/xfs.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the xfs_t domain.
+#
+# xfs_t is the domain of the X font server.
+# xfs_exec_t is the type of the xfs executable.
+#
+type xfs_t, domain, privlog;
+type xfs_exec_t, file_type, sysadmfile, exec_type;
+
+type xfs_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(xfs_t, tmp_t, xfs_tmp_t)
+
+# Use capabilities.
+allow xfs_t xfs_t:capability { setgid setuid };
+
+# Inherit and use descriptors from init.
+allow xfs_t init_t:fd inherit_fd_perms;
+
+# Bind to /tmp/.font-unix/fs-1.
+allow xfs_t xfs_tmp_t:unix_stream_socket name_bind;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/system/ypbind.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,57 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# Rules for the ypbind_t domain.
+#
+type ypbind_t, domain, privlog;
+type ypbind_exec_t, file_type, sysadmfile, exec_type;
+
+type ypbind_tmp_t, file_type, sysadmfile, tmpfile;
+file_type_auto_trans(ypbind_t, tmp_t, ypbind_tmp_t)
+type ypbind_var_run_t, file_type, sysadmfile, pidfile;
+file_type_auto_trans(ypbind_t, var_run_t, ypbind_var_run_t)
+
+# Use capabilities.
+allow ypbind_t ypbind_t:capability net_bind_service;
+
+# Inherit and use descriptors from init.
+allow ypbind_t init_t:fd inherit_fd_perms;
+
+# Use the network.
+can_network(ypbind_t)
+
+# Send to portmap and initrc.
+can_udp_send(ypbind_t, portmap_t)
+can_udp_send(ypbind_t, initrc_t)
+
+# Use net ioctls.
+allow ypbind_t kernel_t:system net_io_control;
+
+# Read and write /var/yp.
+allow ypbind_t var_yp_t:dir rw_dir_perms;
+allow ypbind_t var_yp_t:file create_file_perms;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/domains/user/user.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,216 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#################################
+#
+# The user_domain macro and the 
+# user_t domain.
+#
+
+#
+# shell_exec_t is the type of shell programs.
+#
+type shell_exec_t, file_type, sysadmfile, exec_type;
+
+
+#################################
+# 
+# user_domain(domain_prefix)
+#
+# Rules for all user login domains.
+#
+
+define(`user_domain',`
+
+type $1_home_t, file_type, sysadmfile, home_type;
+type $1_tmp_t, file_type, sysadmfile, tmpfile;
+type $1_tty_device_t, file_type, sysadmfile;
+
+# Allow home directories to be mounted.
+allow $1_home_t file_t:dir mountassociate;
+
+# Use capabilities
+allow $1_t self:capability { net_bind_service dac_override setuid setgid };
+
+# Use the network.
+can_network($1_t)
+
+# Run helper programs.
+can_exec_any($1_t)
+
+# Bind to a Unix domain socket in /tmp.
+allow $1_t $1_tmp_t:unix_stream_socket name_bind;
+
+# Run programs developed by other users in the same domain.
+can_exec($1_t, $1_home_t)
+can_exec($1_t, $1_tmp_t)
+
+# Connect to inetd.
+can_tcp_connect($1_t,inetd_t)
+
+# Connect second port to rshd.
+can_tcp_connect(rshd_t, $1_t)
+
+# Inherit and use sockets from inetd.
+allow $1_t inetd_t:fd inherit_fd_perms;
+allow $1_t inetd_t:tcp_socket rw_stream_socket_perms;
+
+# Connect data port to ftpd.
+can_tcp_connect(ftpd_t, $1_t)
+
+# Create and use files in user home directories.
+allow $1_t $1_home_t:dir create_dir_perms;
+allow $1_t $1_home_t:notdevfile_class_set create_file_perms;
+
+# Create and use polyinstantiated directories.
+allow $1_t poly_t:dir create_dir_perms;
+
+# Redirect processes in this domain when they access
+# a polyinstantiated directory to a member subdirectory 
+# that has the corresponding home directory type.
+type_member $1_t poly_t:dir $1_home_t;
+
+# Read and write /var/catman.
+allow $1_t catman_t:dir rw_dir_perms;
+allow $1_t catman_t:notdevfile_class_set create_file_perms;
+
+# Modify mail spool file.
+allow $1_t mail_spool_t:dir r_dir_perms;
+allow $1_t mail_spool_t:file rw_file_perms;
+
+# Allow ttys to be relabeled during system boot.
+allow initrc_t $1_tty_device_t:chr_file relabelfrom;
+
+# Allow initrc, getty and login to access ttys if they were not relabeled.
+allow initrc_t $1_tty_device_t:chr_file rw_file_perms;
+allow getty_t $1_tty_device_t:chr_file rw_file_perms;
+allow local_login_t $1_tty_device_t:chr_file rw_file_perms;
+
+# Allow login to relabel ttys upon local login.
+type_change $1_t tty_device_t:chr_file $1_tty_device_t;
+allow local_login_t $1_tty_device_t:chr_file { getattr relabelfrom relabelto };
+allow tty_device_t $1_tty_device_t:chr_file transition;
+allow $1_tty_device_t tty_device_t:chr_file transition;
+
+# Allow login to relabel ptys upon remote login.
+type_change $1_t rlogind_devpts_t:chr_file $1_devpts_t;
+allow remote_login_t $1_devpts_t:chr_file { getattr relabelfrom relabelto };
+allow rlogind_devpts_t $1_devpts_t:chr_file transition;
+allow $1_devpts_t rlogind_devpts_t:chr_file transition;
+
+# Use ttys.
+allow $1_t $1_tty_device_t:chr_file rw_file_perms;
+
+# Create and use ptys.
+can_create_pty($1)
+
+# Run the passwd wrapper program in the passwd_t domain.
+domain_auto_trans($1_t, passwd_exec_t, passwd_t)
+allow passwd_t $1_tty_device_t:chr_file rw_file_perms;
+allow passwd_t $1_devpts_t:chr_file rw_file_perms;
+allow passwd_t $1_gph_t:fd inherit_fd_perms;
+
+# Run utempter in the utempter_t domain.
+# Allow utempter_t to inherit and use descriptors from parent user domain.
+domain_auto_trans($1_t, utempter_exec_t, utempter_t)
+allow utempter_t $1_tty_device_t:chr_file getattr;
+allow utempter_t $1_devpts_t:chr_file getattr;
+
+# Run the newrole program in the newrole_t domain.
+domain_auto_trans($1_t, newrole_exec_t, newrole_t)
+allow newrole_t $1_tty_device_t:chr_file rw_file_perms;
+allow newrole_t $1_devpts_t:chr_file rw_file_perms;
+allow newrole_t $1_gph_t:fd inherit_fd_perms;
+
+# Run gnome-pty-helper in a separate domain corresponding to this user domain.
+gph_domain($1)
+
+# Run su in a separate domain.
+su_domain($1)
+
+# Run netscape in a separate domain.
+netscape_domain($1)
+
+# Run the X server, lpr/lpq/lprm, and sendmail in appropriate domains.
+xserver_domain($1)
+lpr_domain($1)
+mail_domain($1)
+
+# Run users cron jobs and crontab in a separate domain.  
+crond_domain($1)
+crontab_domain($1)
+
+# Run user ftp sessions in a separate domain.
+ftpd_domain($1)
+
+# Read /dev/psaux.
+allow $1_t psaux_t:chr_file r_file_perms;
+
+# Access miscellaneous devices.
+allow $1_t misc_device_t:file_class_set rw_file_perms;
+
+# Access System V IPC mechanisms
+# Allows communication within a domain, but not between
+allow $1_t $1_t:sem rw_sem_perms;
+allow $1_t $1_t:msg { send receive };
+allow $1_t $1_t:msgq rw_msgq_perms;
+allow $1_t $1_t:shm rw_shm_perms;
+# Very permissive allowing every domain to see every type
+allow $1_t *:system { ipc_info };
+
+# Create temporary files.
+file_type_auto_trans($1_t, tmp_t, $1_tmp_t)
+
+# When the user domain runs ps, there will be a number of access
+# denials when ps tries to search /proc.  Do not audit these denials.
+auditdeny $1_t domain:dir ~r_dir_perms;
+auditdeny $1_t domain:notdevfile_class_set ~r_file_perms;
+
+# Some shells ask for w access to utmp, but will operate
+# correctly without it.  Do not audit write denials to utmp.
+auditdeny $1_t initrc_var_run_t:file ~write;
+
+#
+# connect_secure and sendmsg_secure calls with a 
+# peer or destination socket SID can be enforced
+# when using the loopback interface.  Enforcement
+# for real network interfaces will be possible when
+# a packet labeling mechanism is integrated.
+#
+allow $1_t node_lo_t:node enforce_dest;
+
+')
+
+
+#################################
+# 
+# Rules for the user_t domain.
+#
+# user_t is the unprivileged users domain.
+#
+type user_t, domain, userdomain;
+
+user_domain(user)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/file_contexts	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,379 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# This file describes the security contexts to be applied to files
+# when the security policy is installed.  The setfiles program
+# reads this file and labels files accordingly.
+#
+# Each specification has the form:
+#       regexp [ -type ] ( context | <<none>> )
+#
+# By default, the regexp is an anchored match on both ends (i.e. a 
+# caret (^) is prepended and a dollar sign ($) is appended automatically).
+# This default may be overridden by using .* at the beginning and/or
+# end of the regular expression.  
+#
+# The optional type field specifies the file type as shown in the mode
+# field by ls, e.g. use -d to match only directories or -- to match only
+# regular files.
+# 
+# The value of <<none> may be used to indicate that matching files
+# should not be relabeled.
+#
+# The last matching specification is used.
+#
+# If there are multiple hard links to a file that match 
+# different specifications and those specifications indicate
+# different security contexts, then a warning is displayed
+# but the file is still labeled based on the last matching
+# specification other than <<none>>.
+#
+# Some of the files listed here get re-created during boot and therefore
+# need type transition rules to retain the correct type. These files are
+# listed here anyway so that if the setfiles program is used on a running
+# system it doesn't relabel them to something we don't want. An example of
+# this is /var/run/utmp.
+#
+
+#
+# The security context for all files not otherwise specified.
+#
+/.*				system_u:object_r:file_t
+
+#
+# The root directory.
+#
+/				system_u:object_r:root_t
+
+#
+# The policy configuration and its sources.
+#
+/etc/security/fmac/ss_policy	system_u:object_r:policy_config_t
+
+# 
+# The superuser home directory.
+#
+/root(|/.*)			system_u:object_r:sysadm_home_t
+/root/\.netscape(|/.*)		system_u:object_r:sysadm_netscape_rw_t
+/root/\.mime\.types		system_u:object_r:sysadm_netscape_rw_t
+/root/\.mailcap			system_u:object_r:sysadm_netscape_rw_t
+
+
+# 
+# Other user home directories.
+#
+/home(|/.*)			system_u:object_r:user_home_t
+/home/.*/\.netscape(|/.*)	system_u:object_r:user_netscape_rw_t
+/home/.*/\.mime\.types		system_u:object_r:user_netscape_rw_t
+/home/.*/\.mailcap		system_u:object_r:user_netscape_rw_t
+
+#
+# /bin
+#
+/bin(|/.*)			system_u:object_r:bin_t
+/bin/login			system_u:object_r:login_exec_t
+/bin/tcsh			system_u:object_r:shell_exec_t
+/bin/bash			system_u:object_r:shell_exec_t
+/bin/ash			system_u:object_r:shell_exec_t
+/bin/su				system_u:object_r:su_exec_t
+/bin/ls				system_u:object_r:ls_exec_t
+
+#
+# /boot
+#
+/boot(|/.*)			system_u:object_r:boot_t
+/boot/kernel.h			system_u:object_r:boot_runtime_t
+
+#
+# /dev
+#
+/dev(|/.*)			system_u:object_r:device_t
+/dev/null			system_u:object_r:null_device_t
+/dev/zero			system_u:object_r:zero_device_t
+/dev/console			system_u:object_r:console_device_t
+/dev/(kmem|mem|port)		system_u:object_r:memory_device_t
+/dev/random			system_u:object_r:random_device_t
+/dev/urandom			system_u:object_r:random_device_t
+/dev/[^/]*tty[^/]*		system_u:object_r:tty_device_t
+/dev/vcs[^/]*			system_u:object_r:tty_device_t
+/dev/tty			system_u:object_r:devtty_t
+/dev/sd[^/]*			system_u:object_r:fixed_disk_device_t
+/dev/hd[^/]*			system_u:object_r:fixed_disk_device_t
+/dev/scd[^/]*			system_u:object_r:removable_device_t
+/dev/fd[^/]*			system_u:object_r:removable_device_t
+/dev/rtc			system_u:object_r:clock_device_t
+/dev/initctl			system_u:object_r:initctl_t
+/dev/log			system_u:object_r:devlog_t
+/dev/printer			system_u:object_r:printer_t
+/dev/psaux			system_u:object_r:psaux_t
+/dev/gpmctl			system_u:object_r:gpmctl_t
+/dev/ptmx			system_u:object_r:ptmx_t
+/dev/sequencer			system_u:object_r:misc_device_t
+/dev/dsp.*			system_u:object_r:misc_device_t
+/dev/audio			system_u:object_r:misc_device_t
+/dev/cdrom			system_u:object_r:misc_device_t
+/dev/fb				system_u:object_r:misc_device_t
+/dev/apm_bios			system_u:object_r:apm_bios_t
+
+#
+# /etc
+#
+/etc(|/.*)			system_u:object_r:etc_t
+/etc/rc.d/rc			system_u:object_r:initrc_exec_t
+/etc/rc.d/rc.sysinit		system_u:object_r:initrc_exec_t
+/etc/rc.d/rc.local		system_u:object_r:initrc_exec_t
+/etc/auth(|/.*)			system_u:object_r:etc_auth_t
+/etc/aliases			system_u:object_r:etc_aliases_t
+/etc/aliases.db			system_u:object_r:etc_aliases_t
+/etc/mail(|/.*)			system_u:object_r:etc_mail_t
+/etc/conf.modules		system_u:object_r:modules_conf_t
+/etc/HOSTNAME			system_u:object_r:etc_runtime_t
+/etc/ioctl.save			system_u:object_r:etc_runtime_t
+/etc/mtab			system_u:object_r:etc_runtime_t
+/etc/issue			system_u:object_r:etc_runtime_t
+/etc/issue.net			system_u:object_r:etc_runtime_t
+/etc/crontab			system_u:object_r:system_crond_script_t
+/etc/cron.d(|/.*)		system_u:object_r:system_crond_script_t
+/etc/security/cron_context.*	system_u:object_r:cron_context_t
+/etc/ssh_host_key               system_u:object_r:sshd_key_t
+/etc/ssh_random_seed            system_u:object_r:sshd_key_t
+
+#
+# /lib
+#
+/lib(|/.*)			system_u:object_r:lib_t
+/lib/ld.*\.so.*			system_u:object_r:ld_so_t
+/lib/lib.*\.so.*		system_u:object_r:shlib_t
+/lib/security/.*\.so.*		system_u:object_r:shlib_t
+/lib/modules(|/.*)		system_u:object_r:modules_object_t
+/lib/modules/[^/]*/modules\.dep system_u:object_r:modules_dep_t
+
+#
+# /sbin
+#
+/sbin(|/.*)			system_u:object_r:sbin_t
+/sbin/ifconfig			system_u:object_r:ifconfig_exec_t
+/sbin/depmod			system_u:object_r:depmod_exec_t
+/sbin/modprobe			system_u:object_r:modprobe_exec_t
+/sbin/insmod			system_u:object_r:insmod_exec_t
+/sbin/insmod.static		system_u:object_r:insmod_exec_t
+/sbin/rmmod			system_u:object_r:rmmod_exec_t
+/sbin/rmmod.static		system_u:object_r:rmmod_exec_t
+/sbin/init		  	system_u:object_r:init_exec_t
+/sbin/sulogin			system_u:object_r:sulogin_exec_t
+/sbin/mingetty			system_u:object_r:getty_exec_t
+/sbin/getty			system_u:object_r:getty_exec_t
+/sbin/uugetty			system_u:object_r:getty_exec_t
+/sbin/syslogd			system_u:object_r:syslogd_exec_t
+/sbin/minilogd			system_u:object_r:syslogd_exec_t
+/sbin/klogd			system_u:object_r:klogd_exec_t
+/sbin/ypbind			system_u:object_r:ypbind_exec_t
+/sbin/portmap			system_u:object_r:portmap_exec_t
+/sbin/rpc\..*			system_u:object_r:rpcd_exec_t
+/sbin/cardmgr			system_u:object_r:cardmgr_exec_t
+/sbin/fsck			system_u:object_r:fsadm_exec_t
+/sbin/fsck\.ext2		system_u:object_r:fsadm_exec_t
+/sbin/e2fsck			system_u:object_r:fsadm_exec_t
+/sbin/e2label			system_u:object_r:fsadm_exec_t
+/sbin/mkfs			system_u:object_r:fsadm_exec_t
+/sbin/mke2fs			system_u:object_r:fsadm_exec_t
+/sbin/mkfs.ext2			system_u:object_r:fsadm_exec_t
+/sbin/mkswap			system_u:object_r:fsadm_exec_t
+/sbin/scsi_info			system_u:object_r:fsadm_exec_t
+/sbin/sfdisk			system_u:object_r:fsadm_exec_t
+/sbin/cfdisk			system_u:object_r:fsadm_exec_t
+/sbin/fdisk			system_u:object_r:fsadm_exec_t
+/sbin/tune2fs			system_u:object_r:fsadm_exec_t
+/sbin/dumpe2fs			system_u:object_r:fsadm_exec_t
+/sbin/swapon			system_u:object_r:fsadm_exec_t
+/sbin/pwdb_chkpwd		system_u:object_r:chkpwd_exec_t
+
+#
+# /tmp
+#
+/tmp(|/.*)			system_u:object_r:tmp_t
+/tmp/orbit.*			system_u:object_r:user_tmp_t
+/tmp/.ICE-unix(|/.*)		system_u:object_r:user_tmp_t
+/tmp/.X11-unix(|/.*)		system_u:object_r:user_xserver_tmp_t
+/tmp/.X0-lock			system_u:object_r:user_xserver_tmp_t
+/tmp/.font-unix(|/.*)		system_u:object_r:xfs_tmp_t
+
+#
+# /usr
+#
+/usr(|/.*)			system_u:object_r:usr_t
+/usr/etc(|/.*)			system_u:object_r:etc_t
+/usr/libexec(|/.*)		system_u:object_r:lib_t
+/usr/src(|/.*)			system_u:object_r:src_t
+/usr/tmp(|/.*)			system_u:object_r:tmp_t
+/usr/man(|/.*)			system_u:object_r:man_t
+
+#
+# /usr/bin
+#
+/usr/bin(|/.*)			system_u:object_r:bin_t
+/usr/bin/lpr			system_u:object_r:lpr_exec_t
+/usr/bin/lpq			system_u:object_r:lpr_exec_t
+/usr/bin/lprm			system_u:object_r:lpr_exec_t
+/usr/bin/makemap		system_u:object_r:sbin_t
+/usr/bin/netscape		system_u:object_r:netscape_exec_t
+/usr/bin/crontab		system_u:object_r:crontab_exec_t
+
+
+#
+# /usr/lib
+#
+/usr/lib(|/.*)			system_u:object_r:lib_t
+/usr/lib/lib.*\.so.*		system_u:object_r:shlib_t
+/usr/lib/perl5/man(|/.*)	system_u:object_r:man_t
+
+#
+# /usr/local
+#
+/usr/local/etc(|/.*)		system_u:object_r:etc_t
+/usr/local/etc/ssh_host_key     system_u:object_r:sshd_key_t
+/usr/local/etc/ssh_host_dsa_key system_u:object_r:sshd_key_t
+/usr/local/src(|/.*)		system_u:object_r:src_t
+/usr/local/sbin(|/.*)		system_u:object_r:sbin_t
+/usr/local/sbin/sshd	        system_u:object_r:sshd_exec_t
+/usr/local/man(|/.*)		system_u:object_r:man_t
+
+#
+# /usr/local/bin
+#
+/usr/local/bin(|/.*)		system_u:object_r:bin_t
+/usr/local/bin/tcsh		system_u:object_r:shell_exec_t
+
+#
+# /usr/local/lib
+#
+/usr/local/lib(|/.*)		system_u:object_r:lib_t
+/usr/local/lib/lib.*\.so.*	system_u:object_r:shlib_t
+
+#
+# /usr/sbin
+#
+/usr/sbin(|/.*)			system_u:object_r:sbin_t
+/usr/sbin/syslogd		system_u:object_r:syslogd_exec_t
+/usr/sbin/klogd			system_u:object_r:klogd_exec_t
+/usr/sbin/apmd			system_u:object_r:apmd_exec_t
+/usr/sbin/crond			system_u:object_r:crond_exec_t
+/usr/sbin/atd			system_u:object_r:atd_exec_t
+/usr/sbin/lpd			system_u:object_r:lpd_exec_t
+/usr/sbin/inetd			system_u:object_r:inetd_exec_t
+/usr/sbin/tcpd			system_u:object_r:tcpd_exec_t
+/usr/sbin/identd		system_u:object_r:inetd_child_exec_t
+/usr/sbin/in\..*d		system_u:object_r:inetd_child_exec_t
+/usr/sbin/in.rlogind		system_u:object_r:rlogind_exec_t
+/usr/sbin/in.telnetd		system_u:object_r:rlogind_exec_t
+/usr/sbin/in.rshd		system_u:object_r:rshd_exec_t
+/usr/sbin/in.ftpd		system_u:object_r:ftpd_exec_t
+/usr/sbin/in.ftpd-stage2	system_u:object_r:ftpd_stage2_exec_t
+/usr/sbin/sendmail		system_u:object_r:sendmail_exec_t
+/usr/sbin/rpc\..*		system_u:object_r:rpcd_exec_t
+/usr/sbin/gpm			system_u:object_r:gpm_exec_t
+/usr/sbin/makemap		system_u:object_r:sbin_t
+/usr/sbin/utempter		system_u:object_r:utempter_exec_t
+/usr/sbin/gnome-pty-helper	system_u:object_r:gph_exec_t
+/usr/sbin/logrotate		system_u:object_r:logrotate_exec_t
+
+#
+# /usr/X11R6/bin
+#
+/usr/X11R6/bin(|/.*)		system_u:object_r:bin_t
+/usr/X11R6/bin/xfs		system_u:object_r:xfs_exec_t
+/usr/X11R6/bin/Xwrapper		system_u:object_r:xserver_exec_t
+
+#
+# /usr/X11R6/lib
+#
+/usr/X11R6/lib(|/.*)		system_u:object_r:lib_t
+/usr/X11R6/lib/lib.*\.so.*	system_u:object_r:shlib_t
+
+#
+# /usr/X11R6/man
+#
+/usr/X11R6/man(|/.*)		system_u:object_r:man_t
+
+#
+# /usr/flask
+#
+/usr/flask/bin(|/.*)		system_u:object_r:bin_t
+/usr/flask/sbin(|/.*)		system_u:object_r:bin_t
+/usr/flask/libexec(|/.*)	system_u:object_r:lib_t
+/usr/flask/bin/spasswd		system_u:object_r:passwd_exec_t
+/usr/flask/bin/schsh		system_u:object_r:passwd_exec_t
+/usr/flask/bin/schfn		system_u:object_r:passwd_exec_t
+/usr/flask/bin/newrole		system_u:object_r:newrole_exec_t
+
+#
+# /var
+#
+/var(|/.*)			system_u:object_r:var_t
+/var/catman(|/.*)		system_u:object_r:catman_t
+/var/yp(|/.*)			system_u:object_r:var_yp_t
+/var/lib(|/.*)			system_u:object_r:var_lib_t
+/var/lock(|/.*)			system_u:object_r:var_lock_t
+/var/tmp(|/.*)			system_u:object_r:tmp_t
+
+#
+# /var/run
+#
+/var/run(|/.*)			system_u:object_r:var_run_t
+/var/run/utmp			system_u:object_r:initrc_var_run_t
+/var/run/runlevel.dir		system_u:object_r:initrc_var_run_t
+/var/run/random-seed		system_u:object_r:initrc_var_run_t
+/var/run/.*\.*pid		<<none>>
+
+#
+# /var/spool
+#
+/var/spool(|/.*)		system_u:object_r:var_spool_t
+/var/spool/at(|/.*)		system_u:object_r:at_spool_t
+/var/spool/cron(|/.*)		system_u:object_r:cron_spool_t
+/var/spool/lpd(|/.*)		system_u:object_r:lpd_spool_t
+/var/spool/mail(|/.*)		system_u:object_r:mail_spool_t
+/var/spool/mqueue(|/.*)		system_u:object_r:mqueue_spool_t
+
+# 
+# /var/log
+#
+/var/log(|/.*)			system_u:object_r:var_log_t
+/var/log/wtmp			system_u:object_r:wtmp_t
+/var/log/sendmail.st		system_u:object_r:sendmail_var_log_t
+/var/log/cron			system_u:object_r:cron_log_t
+
+#
+# Persistent label mappings.
+#
+.*/\.\.\.security(|/.*)		system_u:object_r:file_labels_t
+
+#
+# Lost and found directories.
+#
+.*/lost\+found(|/.*)		system_u:object_r:lost_found_t
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/fs_use	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define the labeling behavior for inodes in particular filesystem types.
+
+# Use extended attributes for the following filesystem types, e.g.
+# conventional filesystems that support attributes.
+fs_use_xattr ufs system_u:object_r:fs_t;
+fs_use_xattr zfs system_u:object_r:fs_t;
+
+# Other options:
+# fs_use_task - label inodes from the creating task.
+# fs_use_trans - label inodes based on a type transition.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/init.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,140 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Extensions to the Type Enforcement configuration
+# for the initial boot and relabeling of the system.
+#
+
+
+#
+# Define a new domain for all descendants of init.
+#
+type initial_boot_t, domain, privuser, privrole, privowner;
+
+#
+# Include the normal policy configuration so
+# that all types will be defined for the relabeling
+# and so that all rules that apply to all domains
+# will be applied.
+#
+include(all.te)
+
+#
+# Extend the kernel_t domain.
+#
+allow kernel_t file_t:dir_file_class_set *;
+
+#
+# Extend the init_t domain.
+#
+allow init_t file_t:dir_file_class_set *;
+allow init_t file_t:process { entrypoint execute };
+domain_auto_trans(init_t, file_t, initial_boot_t)
+can_unix_connect(init_t, initial_boot_t)
+
+#
+# Extend the initrc_t domain (for reboot after relabel).
+#
+can_unix_send(initrc_t, initial_boot_t)
+allow initrc_t file_t:file unlink;
+
+#
+# Extend the kmod_t domain.
+#
+allow kmod_t file_t:dir_file_class_set *;
+allow kmod_t file_t:process execute;
+can_unix_connect(kmod_t, initial_boot_t)
+
+#
+# Extend the sysadm_t domain.
+#
+allow sysadm_t file_t:dir_file_class_set *;
+allow sysadm_t file_t:process execute;
+can_exec(sysadm_t, user_home_t)
+allow sysadm_t tty_device_t:chr_file rw_file_perms;
+allow sysadm_t file_t:unix_stream_socket name_bind;
+allow sysadm_t file_t:unix_dgram_socket name_bind;
+can_unix_send(sysadm_t, initial_boot_t)
+can_unix_connect(sysadm_t, initial_boot_t)
+can_udp_send(sysadm_t, initial_boot_t)
+
+#
+# Rules for the initial_boot_t domain.
+#
+
+# Use security server calls.
+allow initial_boot_t security_t:security { compute_av change_sid };
+
+# Perform any privileged operation.
+allow initial_boot_t kernel_t:system *;
+allow initial_boot_t self:capability *;
+
+# Change sysctl variables.
+can_sysctl(initial_boot_t)
+
+# Read /proc/kmsg (for klogd).
+allow initial_boot_t proc_kmsg_t:file r_file_perms;
+
+# Use the network and configure network interfaces.
+can_network(initial_boot_t)
+allow initial_boot_t netif_type:netif { getattr setattr };
+
+# Bind to any network port.
+allow initial_boot_t port_type:tcp_socket name_bind;
+allow initial_boot_t port_type:udp_socket name_bind;
+
+# Perform any operation on any process.
+allow initial_boot_t domain:process ~{ entrypoint execute };
+allow initial_boot_t domain:dir_file_class_set *;
+
+# Execute code from any program.
+allow initial_boot_t file_type:process { entrypoint execute };
+
+# Perform any operation on any file system.
+allow initial_boot_t fs_type:filesystem *;
+
+# Perform any operation on any file.
+allow initial_boot_t file_type:dir_file_class_set *;
+
+# Bind to a file_t Unix domain socket file.
+allow initial_boot_t file_t:unix_stream_socket name_bind;
+allow initial_boot_t file_t:unix_dgram_socket name_bind;
+
+# Send to sysadm_t.
+can_udp_send(initial_boot_t, sysadm_t)
+
+# Can transition to sysadm_t for login.
+domain_trans(initial_boot_t, file_t, sysadm_t)
+
+# Transition to proper domain when executing module programs after relabel.
+domain_auto_trans(initial_boot_t, modprobe_exec_t, modprobe_t)
+domain_auto_trans(initial_boot_t, insmod_exec_t, insmod_t)
+domain_auto_trans(initial_boot_t, rmmod_exec_t, rmmod_t)
+
+# Add initial_boot_t to the system_r role.
+role system_r types initial_boot_t;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/initial_sid_contexts	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,59 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define the security context for each initial SID
+# sid sidname   context
+
+sid kernel	system_u:system_r:kernel_t
+sid security	system_u:object_r:security_t
+sid unlabeled	system_u:object_r:unlabeled_t
+sid fs		system_u:object_r:fs_t
+sid file	system_u:object_r:file_t
+sid file_labels	system_u:object_r:file_labels_t
+sid init	system_u:system_r:init_t
+sid proc	system_u:object_r:proc_t
+sid any_socket 	system_u:system_r:any_socket_t
+sid port	system_u:object_r:port_t
+sid netif	system_u:object_r:netif_t
+sid netmsg	system_u:object_r:netmsg_t
+sid node	system_u:object_r:node_t
+sid icmp_socket system_u:system_r:icmp_socket_t
+sid tcp_socket  system_u:system_r:tcp_socket_t
+sid proc_kmsg	system_u:object_r:proc_kmsg_t
+sid proc_kcore	system_u:object_r:proc_kcore_t
+sid sysctl_modprobe	system_u:object_r:sysctl_modprobe_t
+sid sysctl	system_u:object_r:sysctl_t
+sid sysctl_fs	system_u:object_r:sysctl_fs_t
+sid sysctl_kernel	system_u:object_r:sysctl_kernel_t
+sid sysctl_net	system_u:object_r:sysctl_net_t
+sid sysctl_vm	system_u:object_r:sysctl_vm_t
+sid sysctl_dev	system_u:object_r:sysctl_dev_t
+sid kmod	system_u:system_r:kmod_t
+sid devpts	system_u:object_r:devpts_t
+sid nfs		system_u:object_r:nfs_t
+sid policy	system_u:object_r:policy_config_t
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/macros.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,469 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+##############################
+#
+# Global macros for the type enforcement (TE) configuration.
+#
+
+
+#################################
+# 
+# Macros for groups of classes and 
+# groups of permissions.
+#
+
+#
+# All directory and file classes
+#
+define(`dir_file_class_set', `{ dir file lnk_file sock_file fifo_file 
+			      chr_file blk_file }')
+
+#
+# All non-directory file classes.
+#
+define(`file_class_set', `{ file lnk_file sock_file fifo_file 
+			    chr_file blk_file }')
+
+#
+# Non-device file classes.
+#
+define(`notdevfile_class_set', `{ file lnk_file sock_file fifo_file }')
+
+#
+# Device file classes.
+#
+define(`devfile_class_set', `{ chr_file blk_file }')
+
+#
+# All socket classes.
+#
+define(`socket_class_set', `{ tcp_socket udp_socket rawip_socket
+	netlink_socket packet_socket unix_stream_socket
+	unix_dgram_socket }')
+
+# 
+# Permissions for getting file attributes.
+#
+define(`stat_file_perms', `{ getattr access }')
+
+# 
+# Permissions for executing files.
+#
+define(`x_file_perms', `{ getattr access execute }')
+
+# 
+# Permissions for reading files and their attributes.
+#
+define(`r_file_perms', `{ read getattr access lock poll }')
+
+# 
+# Permissions for reading and executing files.
+#
+define(`rx_file_perms', `{ read getattr access lock poll execute }')
+
+# 
+# Permissions for reading and writing files and their attributes.
+#
+define(`rw_file_perms', `{ ioctl read getattr access lock poll write setattr append }')
+
+# 
+# Permissions for reading and appending to files.
+#
+define(`ra_file_perms', `{ ioctl read getattr access lock poll append }')
+
+#
+# Permissions for linking, unlinking and renaming files.
+# 
+define(`link_file_perms', `{ getattr access link unlink rename }')
+
+#
+# Permissions for creating and using files.
+# 
+define(`create_file_perms', `{ create ioctl read getattr access lock poll write setattr append link unlink rename }')
+
+# 
+# Permissions for reading directories and their attributes.
+#
+define(`r_dir_perms', `{ read getattr access lock poll search }')
+
+# 
+# Permissions for reading and writing directories and their attributes.
+#
+define(`rw_dir_perms', `{ read getattr access lock poll setattr search add_name remove_name }')
+
+# 
+# Permissions for reading and adding names to directories.
+#
+define(`ra_dir_perms', `{ read getattr access lock poll setattr search add_name }')
+
+
+#
+# Permissions for creating and using directories.
+# 
+define(`create_dir_perms', `{ create read getattr access poll setattr link unlink rename search add_name remove_name reparent rmdir }')
+
+#
+# Permissions to inherit and use file descriptions.
+#
+define(`inherit_fd_perms', `{ inherit getattr setattr }')
+
+#
+# Permissions to receive fds via a socket and use them.
+#
+define(`receive_fd_perms', `{ receive getattr setattr }')
+
+#
+# Permissions to mount and unmount file systems.
+#
+define(`mount_fs_perms', `{ mount remount unmount getattr }')
+
+#
+# Permissions for using sockets.
+# 
+define(`rw_socket_perms', `{ ioctl read getattr poll write setattr append bind connect getopt setopt shutdown }')
+
+#
+# Permissions for creating and using sockets.
+# 
+define(`create_socket_perms', `{ create ioctl read getattr poll write setattr append bind connect getopt setopt shutdown }')
+
+#
+# Permissions for using stream sockets.
+# 
+define(`rw_stream_socket_perms', `{ ioctl read getattr poll write setattr append bind connect getopt setopt shutdown listen accept }')
+
+#
+# Permissions for creating and using stream sockets.
+# 
+define(`create_stream_socket_perms', `{ create ioctl read getattr poll write setattr append bind connect getopt setopt shutdown listen accept }')
+
+
+#
+# Permissions for sending all signals.
+#
+define(`signal_perms', `{ sigkill sigstop sigchld signal }')
+
+#
+# Permissions for sending and receiving network packets.
+#
+define(`packet_perms', `{ tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send }')
+
+#
+# Permissions for using System V IPC
+#
+define(`r_sem_perms', `{ associate getattr read }')
+define(`rw_sem_perms', `{ associate getattr setattr create destroy read write }')
+define(`r_msgq_perms', `{ associate getattr read }')
+define(`rw_msgq_perms', `{ associate getattr setattr create destroy read write enqueue }')
+define(`r_shm_perms', `{ associate getattr read }')
+define(`rw_shm_perms', `{ associate getattr setattr create destroy read write lock }')
+
+#################################
+# 
+# Macros for type transition rules and
+# access vector rules.
+#
+
+#################################
+#
+# domain_trans(parent_domain, program_type, child_domain)
+#
+# Permissions for transitioning to a new domain.
+#
+
+define(`domain_trans',`
+
+#
+# Allow the process to transition to the new domain.
+#
+allow $1 $3:process transition;
+
+#
+# Allow the process to execute the program.
+# 
+allow $1 $2:file x_file_perms;
+
+#
+# Allow the process to reap the new domain.
+#
+allow $3 $1:process sigchld;
+
+#
+# Allow the new domain to inherit and use file 
+# descriptions from the creating process.
+#
+allow $3 $1:fd inherit_fd_perms;
+
+#
+# Allow the new domain to read the program.
+#
+allow $3 $2:file r_file_perms;
+
+#
+# Allow the new domain to execute from the program.
+#
+allow $3 $2:process execute;
+
+#
+# Allow the new domain to be entered by the program.
+#
+allow $3 $2:process entrypoint;
+')
+
+#################################
+#
+# domain_auto_trans(parent_domain, program_type, child_domain)
+#
+# Define a default domain transition and allow it.
+#
+define(`domain_auto_trans',`
+domain_trans($1,$2,$3)
+type_transition $1 $2:process $3;
+')
+
+
+#################################
+#
+# uses_shlib(domain)
+#
+# Permissions for using shared libraries.
+#
+define(`uses_shlib',`
+allow $1 ld_so_t:file rx_file_perms;
+allow $1 ld_so_t:process execute;
+allow $1 shlib_t:file r_file_perms;
+allow $1 shlib_t:process execute;
+')
+
+#################################
+#
+# can_exec(domain, type)
+#
+# Permissions for executing programs with
+# a specified type without changing domains.
+#
+define(`can_exec',`
+allow $1 $2:file rx_file_perms;
+allow $1 $2:process execute;
+')
+
+#################################
+#
+# can_exec_any(domain)
+#
+# Permissions for executing a variety
+# of executable types.
+#
+define(`can_exec_any',`
+can_exec($1, etc_t)
+can_exec($1, lib_t)
+can_exec($1, bin_t)
+can_exec($1, sbin_t)
+can_exec($1, exec_type)
+')
+
+
+#################################
+#
+# file_type_trans(domain, dir_type, file_type)
+#
+# Permissions for transitioning to a new file type.
+#
+
+define(`file_type_trans',`
+
+#
+# Allow the process to modify the directory.
+#
+allow $1 $2:dir rw_dir_perms;
+
+#
+# Allow the process to create the file.
+#
+allow $1 $3:notdevfile_class_set create_file_perms;
+allow $1 $3:dir create_dir_perms;
+')
+
+#################################
+#
+# file_type_auto_trans(creator_domain, parent_directory_type, file_type)
+#
+# Define a default file type transition and allow it.
+#
+define(`file_type_auto_trans',`
+file_type_trans($1,$2,$3)
+type_transition $1 $2:dir $3;
+type_transition $1 $2:notdevfile_class_set $3;
+')
+
+#################################
+#
+# can_network(domain)
+#
+# Permissions for accessing the network.
+#
+define(`can_network',`
+#
+# Allow the process to send UDP traffic.
+#
+allow $1 any_socket_t:udp_socket sendto;
+
+#
+# Allow the process to receive unlabeled
+# UDP traffic from any network interface.
+#
+allow $1 netmsg_type:udp_socket { recvfrom };
+
+#
+# Allow the process to initiate or accept 
+# unlabeled TCP connections on any network interface.
+#
+allow $1 netmsg_type:tcp_socket { connectto acceptfrom };
+
+#
+# Allow the process to send or receive on any
+# network interface and from or to any node.
+#
+allow $1 netif_type:netif packet_perms; 
+allow $1 node_type:node packet_perms;
+
+#
+# Allow the process to send NFS client requests.
+#
+allow $1 initrc_t:udp_socket rw_socket_perms;
+')
+
+#################################
+#
+# can_unix_connect(client, server)
+#
+# Permissions for establishing a Unix stream connection.
+#
+define(`can_unix_connect',`
+allow $1 $2:unix_stream_socket connectto;
+allow $2 $1:unix_stream_socket acceptfrom;
+')
+
+#################################
+#
+# can_unix_send(sender, receiver)
+#
+# Permissions for sending Unix datagrams.
+#
+define(`can_unix_send',`
+allow $1 $2:unix_dgram_socket sendto;
+allow $2 $1:unix_dgram_socket recvfrom;
+')
+
+#################################
+#
+# can_tcp_connect(client, server)
+#
+# Permissions for establishing a TCP connection.
+#
+define(`can_tcp_connect',`
+allow $1 $2:tcp_socket connectto;
+allow $2 $1:tcp_socket acceptfrom;
+')
+
+#################################
+#
+# can_udp_send(sender, receiver)
+#
+# Permissions for sending UDP datagrams.
+#
+define(`can_udp_send',`
+allow $1 $2:udp_socket sendto;
+allow $2 $1:udp_socket recvfrom;
+')
+
+#################################
+#
+# can_sysctl(domain)
+#
+# Permissions for modifying sysctl parameters.
+#
+define(`can_sysctl',`
+allow $1 sysctl_t:dir r_dir_perms;
+allow $1 sysctl_t:file rw_file_perms;
+allow $1 sysctl_fs_t:dir r_dir_perms;
+allow $1 sysctl_fs_t:file rw_file_perms;
+allow $1 sysctl_kernel_t:dir r_dir_perms;
+allow $1 sysctl_kernel_t:file rw_file_perms;
+allow $1 sysctl_net_t:dir r_dir_perms;
+allow $1 sysctl_net_t:file rw_file_perms;
+allow $1 sysctl_vm_t:dir r_dir_perms;
+allow $1 sysctl_vm_t:file rw_file_perms;
+allow $1 sysctl_dev_t:dir r_dir_perms;
+allow $1 sysctl_dev_t:file rw_file_perms;
+allow $1 sysctl_modprobe_t:file rw_file_perms;
+')
+
+
+##################################
+#
+# can_create_pty(domain_prefix)
+#
+# Permissions for creating ptys.
+#
+define(`can_create_pty',`
+
+type $1_devpts_t, file_type, sysadmfile;
+
+# Allow the pty to be associated with the file system.
+allow $1_devpts_t devpts_t:filesystem associate;
+
+# Access the pty master multiplexer.
+allow $1_t ptmx_t:chr_file rw_file_perms;
+
+# Label pty files with a derived type.
+type_transition $1_t devpts_t:chr_file $1_devpts_t;
+
+# Read and write my pty files.
+allow $1_t $1_devpts_t:chr_file rw_file_perms;
+')
+
+
+##################################
+#
+# can_create_other_pty(domain_prefix,other_domain)
+#
+# Permissions for creating ptys for another domain.
+#
+define(`can_create_other_pty',`
+
+# Access the pty master multiplexer.
+allow $1_t ptmx_t:chr_file rw_file_perms;
+
+# Label pty files with a derived type.
+type_transition $1_t devpts_t:chr_file $2_devpts_t;
+
+# Read and write pty files.
+allow $1_t $2_devpts_t:chr_file rw_file_perms;
+')
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/mls	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,306 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+# Define sensitivities 
+#
+# Each sensitivity has a name and zero or more aliases.
+
+sensitivity unclassified alias u;
+sensitivity confidential alias c;
+sensitivity secret alias s;
+sensitivity top_secret alias ts;
+
+# Define the ordering of the sensitivity levels (least to greatest)
+dominance { u c s ts }
+
+# Define the categories
+#
+# Each category has a name and zero or more aliases.
+#
+
+category nocon;
+category noforn;
+category nato;
+category usuk;
+
+# Identify which categories may be associated with which sensitivities
+#
+# Each MLS level specifies a sensitivity and zero or more categories which may
+# be associated with that sensitivity.
+
+level u; 
+level c;
+level s:nocon, noforn;
+level ts:nocon, noforn, nato, usuk;
+
+#
+# Map each permission to a set of MLS base permissions.
+#
+
+common file
+{
+	poll		:	none
+	ioctl		:	none
+	read		:	read
+	write		:	write
+	create		:	write
+	getattr		:	read
+	setattr		:	write
+	lock		:	none
+	relabelfrom	:	{ read write }
+	relabelto	:	write
+	transition	:	write
+	append		:	write
+	access		:	none
+	unlink		:	write
+	link		:	write
+	rename		:	write
+	execute		:	read
+}
+
+common socket
+{
+	poll		:	none
+	ioctl		:	none
+	read		:	none
+	write		:	none
+	create		:	write
+	getattr		:	none
+	setattr		:	none
+	lock		:	none
+	relabelfrom	:	{ read write }
+	relabelto	:	write
+	transition	:	write
+	append		:	none
+	bind		:	write
+	connect		:	write
+	getopt		:	none
+	setopt		:	none
+	shutdown	:	none
+	recvfrom	:	read
+	sendto		:	none
+	recv_msg	:	read
+	send_msg	:	write
+	name_bind	:	none
+}	
+
+common ipc
+{
+	create		:	write
+	destroy		:	{ read write }
+	getattr		:	read
+	setattr		:	{ read write }
+	read		:	{ read write }
+	write		:	write
+	associate	:	none
+}
+
+class filesystem
+{
+	mount		:	none
+	remount		:	none
+	unmount		:	none
+	getattr		:	none
+	relabelfrom	:	none
+	relabelto	:	none
+	transition	:	none
+	associate	:	readby
+}
+
+class dir
+{
+	add_name	:	write	
+	remove_name	:	write
+	reparent	:	write
+	search		:	read
+	rmdir		:	{ read write }
+	mounton		:	none
+	mountassociate	:	none
+}
+
+class file
+class lnk_file
+class chr_file
+class blk_file
+class sock_file
+class fifo_file
+class pipe
+
+class fd
+{
+	create		:	write
+	getattr		:	none
+	setattr		:	none
+	inherit		: 	none
+	receive		:	none
+}
+
+class socket
+
+class tcp_socket
+{
+	connectto 	:	none
+	listen		:	write
+	accept		:	read
+	newconn 	:	write
+        acceptfrom 	:	read
+}
+
+class udp_socket
+class rawip_socket
+
+class node 
+{
+	tcp_recv 	:	readby
+	tcp_send	:	writeby
+	udp_recv 	:	readby
+	udp_send	:	writeby
+	rawip_recv	:	readby
+	rawip_send	:	writeby
+	enforce_dest	:	none
+}
+
+class netif
+{
+	getattr		:	none
+	setattr		:	write
+	tcp_recv 	:	readby
+	tcp_send	:	writeby
+	udp_recv 	:	readby
+	udp_send	:	writeby
+	rawip_recv 	:	readby
+	rawip_send	:	writeby
+}
+
+class netlink_socket
+class packet_socket
+class unix_dgram_socket
+
+class unix_stream_socket
+{
+	connectto 	:	none
+	listen		:	write
+	accept		:	read
+	newconn 	:	write
+        acceptfrom 	:	read
+}
+
+
+class process
+{
+	execute		: 	read
+	fork		:	none
+	transition	:	write
+	sigchld		:	readby
+	sigkill		:	write
+	sigstop		:	write
+	signal		:	write
+	ptrace		:	{ read write }
+	getsched	:	read
+	setsched	:	write
+	getsession	:	read
+	getpgid		:	read
+	setpgid		:	write
+	getcap		:	read
+	setcap		:	write
+	entrypoint	:	read
+}
+
+class sem
+
+class msgq
+{
+	enqueue		:	write
+}
+
+class msg
+{
+	send		:	{ write }
+	receive		:	{ read }
+}
+
+class shm
+{
+	lock		:	{ write }
+}
+
+class security
+{
+	compute_av		:	none
+	notify_perm		:	none
+	transition_sid		:	none
+	member_sid		:	none
+	sid_to_context		:	none
+	context_to_sid		:	none
+	load_policy		:	none
+	register_avc		:	none
+	change_sid		:	none
+}
+
+class system
+{
+	net_io_control		:	none
+	route_control		:	none
+	arp_control		: 	none
+	rarp_control		: 	none
+	ipc_info		:	read
+	avc_toggle		:	none
+}
+
+class capability
+{
+
+	# This will be converted to privilege at a later time.
+	# (Order matters)
+
+	chown           	: 	none
+	dac_override    	: 	none
+	dac_read_search 	: 	none
+	fowner          	: 	none
+	fsetid          	: 	none
+	kill            	: 	none
+	setgid          	: 	none 
+	setuid          	: 	none 
+	setpcap         	: 	none 
+	linux_immutable 	: 	none 
+	net_bind_service	: 	none 
+	net_broadcast   	: 	none 
+	net_admin       	: 	none 
+	net_raw         	: 	none 
+	ipc_lock        	: 	none 
+	ipc_owner       	: 	none 
+	sys_module      	: 	none 
+	sys_rawio       	: 	none 
+	sys_chroot      	: 	none 
+	sys_ptrace      	: 	none 
+	sys_pacct       	: 	none 
+	sys_admin       	: 	none 
+	sys_boot        	: 	none 
+	sys_nice        	: 	none 
+	sys_resource    	: 	none 
+	sys_time        	: 	none 
+	sys_tty_config  	: 	none
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/net_contexts	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,66 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Security contexts for network entities
+# If no context is specified, then a default initial SID is used.
+#
+
+#
+# Port numbers (default = initial SID 'port')
+# 
+# protocol number context
+# protocol low-high context
+#
+portcon tcp 21 system_u:object_r:ftp_port_t
+portcon tcp 23 system_u:object_r:telnet_port_t
+portcon tcp 25 system_u:object_r:smtp_port_t
+portcon tcp 80  system_u:object_r:http_port_t
+portcon tcp 513 system_u:object_r:rlogin_port_t
+portcon tcp 514 system_u:object_r:rsh_port_t
+portcon tcp 515 system_u:object_r:printer_port_t
+portcon tcp 8080  system_u:object_r:http_port_t
+
+
+# Network interfaces (default = initial SID 'netif' and 'netmsg')
+#
+# interface netif_context default_msg_context
+#
+netifcon lo system_u:object_r:netif_lo_t system_u:object_r:netmsg_lo_t
+netifcon eth0 system_u:object_r:netif_eth0_t system_u:object_r:netmsg_eth0_t
+netifcon eth1 system_u:object_r:netif_eth1_t system_u:object_r:netmsg_eth1_t
+
+
+# Nodes (default = initial SID 'node')
+#
+# address mask context
+#
+# The first matching entry is used.
+#
+nodecon 127.0.0.1 255.255.255.255 system_u:object_r:node_lo_t
+nodecon 144.51.25.0 255.255.255.0 system_u:object_r:node_internal_t
+
+# FLASK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/rbac	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,187 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+################################################
+#
+# Role-based access control (RBAC) configuration.
+#
+
+#
+#
+
+########################################
+#
+# Role declarations.
+#
+# Each role has a set of types (domains) that may
+# be entered by processes in the role.
+# The syntax of a role declaration is:
+# 	role rolename types type_set ;
+#
+
+#
+# system_r is the role of system processes.
+#
+role system_r types {
+	kernel_t
+	kmod_t
+	any_socket_t
+	tcp_socket_t
+	icmp_socket_t
+	init_t
+	initrc_t
+	getty_t
+	syslogd_t
+	klogd_t
+	crond_t
+	system_crond_t
+	atd_t 
+	lpd_t 
+	inetd_t 
+	tcpd_t 
+	rlogind_t
+	sshd_t
+	rshd_t
+	ftpd_t
+	inetd_child_t
+        sendmail_t
+	cardmgr_t
+	apmd_t
+	ypbind_t
+	gpm_t
+	portmap_t
+	rpcd_t 
+	xfs_t
+	local_login_t
+	remote_login_t
+	sshd_login_t
+	depmod_t
+	modprobe_t
+	insmod_t
+	rmmod_t
+        fsadm_t
+	ifconfig_t
+	logrotate_t
+	sysadm_t	# single-user mode
+	user_mail_t	# mail sent by crond
+};
+
+#
+# user_r is the role for unprivileged users.
+#
+role user_r types {
+	user_t 
+	passwd_t	
+	utempter_t
+	newrole_t
+	user_lpr_t
+        user_mail_t
+	user_xserver_t
+	user_gph_t
+	user_su_t
+	user_netscape_t
+	user_crontab_t
+	user_crond_t
+	user_ftpd_t
+};
+
+#
+# sysadm_r is the role for the system administrator.
+#
+role sysadm_r types { 
+	sysadm_t
+	ifconfig_t
+	fsadm_t
+	depmod_t
+	modprobe_t
+	insmod_t
+	rmmod_t
+	passwd_t
+	utempter_t
+	logrotate_t
+	newrole_t
+	sysadm_lpr_t
+        sysadm_mail_t
+	sysadm_xserver_t
+	sysadm_gph_t
+	sysadm_su_t
+	sysadm_netscape_t
+	sysadm_crontab_t
+        sysadm_crond_t
+	sysadm_ftpd_t
+};
+
+
+########################################
+#
+# Role transition rules and role allow rules.
+#
+# A role transition rule specifies the default
+# role of a transformed process based on its prior
+# role and the type of the program executable.
+# If no rule is specified, then the default role
+# of a process is the same as its role prior to
+# the execve call.
+#
+# The syntax of a role transition is:
+# 	role_transition current_role program_type new_role ;
+#
+# A role allow rule specifies the allowable
+# transitions between roles on an execve.
+# If no rule is specified, then the change in
+# roles will not be permitted.  Additional
+# controls over role transitions based on the
+# type of the process may be specified through
+# the constraints file.
+#
+# The syntax of a role allow rule is:
+# 	allow current_role new_role ;
+#
+
+#############################
+#
+# role_auto_trans(current_role, program_type, new_role)
+#
+# Define a default role transition and allow it.
+#
+define(`role_auto_trans', `
+role_transition $1 $2 $3;
+allow $1 $3;
+')
+
+#
+# Allow the system_r role to transition 
+# into any of the user roles.
+#
+allow system_r user_r;
+allow system_r sysadm_r;
+
+#
+# Allow the user roles to transition
+# into each other.
+#
+allow user_r sysadm_r;
+allow sysadm_r user_r;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/device.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,103 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+############################################
+#
+# Device types
+#
+
+#
+# device_t is the type of /dev.
+#
+type device_t, file_type;
+
+#
+# null_device_t is the type of /dev/null.
+#
+type null_device_t, file_type;
+
+#
+# zero_device_t is the type of /dev/zero.
+#
+type zero_device_t, file_type;
+
+#
+# console_device_t is the type of /dev/console.
+#
+type console_device_t, file_type;
+
+#
+# memory_device_t is the type of /dev/kmem,
+# /dev/mem, and /dev/port.
+#
+type memory_device_t, file_type;
+
+#
+# random_device_t is the type of /dev/urandom
+# and /dev/random.
+#
+type random_device_t, file_type;
+
+#
+# devtty_t is the type of /dev/tty.
+#
+type devtty_t, file_type;
+
+#
+# tty_device_t is the type of /dev/*tty*
+#
+type tty_device_t, file_type;
+
+#
+# fixed_disk_device_t is the type of 
+# /dev/hd* and /dev/sd*.
+#
+type fixed_disk_device_t, file_type;
+
+#
+# removable_device_t is the type of
+# /dev/scd* and /dev/fd*.
+#
+type removable_device_t, file_type;
+
+#
+# clock_device_t is the type of
+# /dev/rtc.
+#
+type clock_device_t, file_type;
+
+#
+# misc_device_t is the type of miscellaneous devices.
+# XXX:  FIXME!  Appropriate access to these devices need to be identified.
+#
+type misc_device_t, file_type;
+
+#
+# psaux_t is the type of the /dev/psaux mouse device.
+#
+type psaux_t, file_type;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/devpts.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+############################################
+#
+# Devpts types
+#
+
+#
+# ptmx_t is the type for /dev/ptmx.
+#
+type ptmx_t, file_type, sysadmfile;
+
+#
+# devpts_t is the type of the devpts file system and 
+# the type of the root directory of the file system.
+#
+type devpts_t, fs_type, root_dir_type;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/file.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,236 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#######################################
+#
+# General file-related types
+#
+
+#
+# unlabeled_t is the type of unlabeled objects.
+# Eventually, once all objects are labeled and 
+# controlled by the security policy, unlabeled_t 
+# will not be used.
+#
+type unlabeled_t, fs_type, root_dir_type;
+
+#
+# fs_t is the default type of an unlabeled
+# file system.  When an unlabeled file system is
+# mounted read-write, the file system is labeled
+# with this type.  Except for the root file system,
+# other types may be specified using the fs_contexts
+# or fs_contexts.mls file.
+#
+type fs_t, fs_type;
+
+#
+# file_t is the default type of an unlabeled
+# file.  When an unlabeled file system is mounted
+# read-write, all files in the file system are labeled
+# with this type.   Except for the root file system,
+# other types may be specified using the fs_contexts
+# or fs_contexts.mls file.
+#
+type file_t, file_type, root_dir_type, sysadmfile;
+
+#
+# root_t is the type for the root directory.
+#
+type root_t, file_type, sysadmfile;
+
+#
+# lost_found_t is the type for the lost+found directories.
+#
+type lost_found_t, file_type, sysadmfile;
+
+#
+# boot_t is the type for files in /boot,
+# including the kernel.
+#
+type boot_t, file_type, root_dir_type, sysadmfile;
+
+#
+# boot_runtime_t is the type for /boot/kernel.h,
+# which is automatically generated at boot time.
+#
+type boot_runtime_t, file_type, sysadmfile;
+
+#
+# tmp_t is the type of /tmp and /var/tmp.
+#
+type tmp_t, file_type, sysadmfile, tmpfile;
+
+#
+# etc_t is the type of the system etc directories.
+#
+type etc_t, file_type, sysadmfile;
+
+#
+# etc_runtime_t is the type of various
+# files in /etc that are automatically
+# generated during initialization.
+#
+type etc_runtime_t, file_type, sysadmfile;
+
+#
+# etc_auth_t is the type of /etc/auth,
+# which contains the shadow password file.
+#
+type etc_auth_t, file_type, sysadmfile;
+
+#
+# etc_aliases_t is the type of the aliases database.
+# etc_mail_t is the type of /etc/mail.
+# sendmail needs write access to these files.
+#
+type etc_aliases_t, file_type, sysadmfile;
+type etc_mail_t, file_type, sysadmfile;
+
+#
+# lib_t is the type of files in the system lib directories.
+#
+type lib_t, file_type, sysadmfile;
+
+#
+# shlib_t is the type of shared objects in the system lib
+# directories.
+#
+type shlib_t, file_type, sysadmfile;
+
+#
+# ld_so_t is the type of the system dynamic loaders.
+#
+type ld_so_t, file_type, sysadmfile;
+
+#
+# bin_t is the type of files in the system bin directories.
+#
+type bin_t, file_type, sysadmfile;
+
+#
+# ls_exec_t is the type of the ls program.
+#
+type ls_exec_t, file_type, exec_type, sysadmfile;
+
+#
+# chkpwd_exec_t is the type of the pwdb_chkpwd program.
+#
+type chkpwd_exec_t, file_type, exec_type, sysadmfile;
+
+#
+# sbin_t is the type of files in the system sbin directories.
+#
+type sbin_t, file_type, sysadmfile;
+
+#
+# usr_t is the type for /usr.
+#
+type usr_t, file_type, sysadmfile;
+
+#
+# src_t is the type of files in the system src directories.
+#
+type src_t, file_type, sysadmfile;
+
+#
+# var_t is the type for /var.
+#
+type var_t, file_type, sysadmfile;
+
+#
+# Types for subdirectories of /var.
+#
+type var_run_t, file_type, sysadmfile;
+type var_log_t, file_type, sysadmfile;
+type var_lock_t, file_type, sysadmfile;
+type var_lib_t, file_type, sysadmfile;
+type var_spool_t, file_type, sysadmfile;
+type var_yp_t, file_type, sysadmfile;
+
+#
+# wtmp_t is the type of /var/log/wtmp.
+#
+type wtmp_t, file_type, sysadmfile;
+
+#
+# catman_t is the type for /var/catman.
+#
+type catman_t, file_type, sysadmfile;
+
+#
+# at_spool_t is the type for /var/spool/at.
+#
+type at_spool_t, file_type, sysadmfile;
+
+#
+# cron_spool_t is the type for /var/spool/cron.
+#
+type cron_spool_t, file_type, sysadmfile;
+
+#
+# lpd_spool_t is the type for /var/spool/lpd.
+#
+type lpd_spool_t, file_type, sysadmfile;
+
+#
+# mail_spool_t is the type for /var/spool/mail.
+#
+type mail_spool_t, file_type, sysadmfile;
+
+#
+# mqueue_spool_t is the type for /var/spool/mqueue.
+#
+type mqueue_spool_t, file_type, sysadmfile;
+
+#
+# man_t is the type for the man directories.
+#
+type man_t, file_type, sysadmfile;
+
+#
+# poly_t is the type for the polyinstantiated directories.
+#
+type poly_t, file_type, sysadmfile;
+
+#
+# Allow each file type to be associated with 
+# the default file system type.
+#
+allow file_type fs_t:filesystem associate;
+
+#
+# Allow each file type to be mounted on a directory
+# with the same type.
+#
+allow file_type self:dir mountassociate;
+
+#
+# Allow each root directory to be mounted
+# on a directory with the default file type.
+#
+allow root_dir_type file_t:dir mountassociate;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/network.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,117 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+############################################
+#
+# Network types
+#
+
+# 
+# any_socket_t is the default destination
+# socket type for UDP traffic.  Unless a 
+# destination socket type is explicitly specified
+# using sendto_secure/sendmsg_secure, this type
+# is used for the udp_socket sendto permission check.
+#
+type any_socket_t, socket_type;
+
+#
+# icmp_socket_t is the type of the kernel socket
+# used to send ICMP messages.
+# tcp_socket_t is the type of the kernel socket
+# used to send TCP resets.
+#
+type icmp_socket_t, socket_type;
+type tcp_socket_t, socket_type;
+
+#
+# port_t is the default type of INET port numbers.
+# The *_port_t types are used for specific port
+# numbers in net_contexts or net_contexts.mls.
+#
+type port_t, port_type;
+type ftp_port_t, port_type;
+type telnet_port_t, port_type;
+type smtp_port_t, port_type;
+type http_port_t, port_type;
+type rlogin_port_t, port_type;
+type rsh_port_t, port_type;
+type printer_port_t, port_type;
+
+#
+# netif_t is the default type of network interfaces.
+# The netif_*_t types are used for specific network
+# interfaces in net_contexts or net_contexts.mls.
+#
+type netif_t, netif_type;
+type netif_eth0_t, netif_type;
+type netif_eth1_t, netif_type;
+type netif_lo_t, netif_type;
+
+#
+# netmsg_t is the default type of unlabeled received messages.
+# The netmsg_*_t types are used for specific network
+# interfaces in net_contexts or net_contexts.mls.
+#
+type netmsg_t, netmsg_type;
+type netmsg_eth0_t, netmsg_type;
+type netmsg_eth1_t, netmsg_type;
+type netmsg_lo_t, netmsg_type;
+
+#
+# node_t is the default type of network nodes.
+# The node_*_t types are used for specific network
+# nodes in net_contexts or net_contexts.mls.
+#
+type node_t, node_type;
+type node_lo_t, node_type;
+type node_internal_t, node_type;
+
+
+#
+# Allow the ICMP socket to send and receive.
+#
+allow icmp_socket_t netif_type:netif { rawip_recv rawip_send };
+allow icmp_socket_t node_type:node { rawip_recv rawip_send };
+
+#
+# Allow the TCP reset socket to send and receive.
+#
+allow tcp_socket_t netif_type:netif { tcp_send tcp_recv };
+allow tcp_socket_t node_type:node { tcp_send tcp_recv };
+
+#
+# Allow unlabeled network messages to be received.
+#
+allow netmsg_t netif_t:netif { tcp_recv udp_recv rawip_recv };
+allow netmsg_t node_t:node { tcp_recv udp_recv rawip_recv };
+allow netmsg_eth0_t netif_eth0_t:netif { tcp_recv udp_recv rawip_recv };
+allow netmsg_eth0_t node_internal_t:node { tcp_recv udp_recv rawip_recv };
+allow netmsg_eth0_t node_t:node { tcp_recv udp_recv rawip_recv };
+allow netmsg_eth1_t netif_eth1_t:netif { tcp_recv udp_recv rawip_recv };
+allow netmsg_eth1_t node_t:node { tcp_recv udp_recv rawip_recv };
+allow netmsg_lo_t netif_lo_t:netif { tcp_recv udp_recv rawip_recv };
+allow netmsg_lo_t node_lo_t:node { tcp_recv udp_recv rawip_recv };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/nfs.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#############################################
+#
+# NFS types
+#
+
+#
+# nfs_t is the default type for NFS file systems 
+# and their files.  
+# The nfs_*_t types are used for specific NFS
+# servers in net_contexts or net_contexts.mls.
+#
+type nfs_t, fs_type, root_dir_type;
+type nfs_clipper_t, fs_type, root_dir_type;
+
+#
+# Allow NFS files to be associated with an NFS file system.
+#
+allow nfs_t nfs_t:filesystem associate;
+allow nfs_clipper_t nfs_clipper_t:filesystem associate;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/procfs.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,61 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+############################################
+#
+# Procfs types
+#
+
+#
+# proc_t is the type of /proc.
+# proc_kmsg_t is the type of /proc/kmsg.
+# proc_kcore_t is the type of /proc/kcore.
+#
+type proc_t, fs_type, root_dir_type;
+type proc_kmsg_t;
+type proc_kcore_t;
+
+#
+# sysctl_t is the type of /proc/sys.
+# sysctl_fs_t is the type of /proc/sys/fs.
+# sysctl_kernel_t is the type of /proc/sys/kernel.
+# sysctl_modprobe_t is the type of /proc/sys/kernel/modprobe.
+# sysctl_net_t is the type of /proc/sys/net.
+# sysctl_vm_t is the type of /proc/sys/vm.
+# sysctl_dev_t is the type of /proc/sys/dev.
+#
+# These types are applied to both the entries in
+# /proc/sys and the corresponding sysctl parameters.
+#
+type sysctl_t;
+type sysctl_fs_t;
+type sysctl_kernel_t;
+type sysctl_modprobe_t;
+type sysctl_net_t;
+type sysctl_vm_t;
+type sysctl_dev_t;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/types/security.te	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,68 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+############################################
+#
+# Security types
+#
+
+# 
+# security_t is the target type when checking
+# most of the permissions in the security class.
+# The two exceptions are sid_to_context and load_policy.
+# The sid_to_context permission uses the type attribute
+# of the SID parameter, and the load_policy permission
+# uses the type of the policy file.
+#
+type security_t;
+
+#
+# policy_config_t is the type of /ss_policy,
+# the security server policy configuration.
+#
+type policy_config_t, file_type, sysadmfile;
+
+#
+# policy_src_t is the type of the policy source
+# files.
+#
+type policy_src_t, file_type, sysadmfile;
+
+#
+# file_labels_t is the type of the persistent
+# label mapping stored in each file system.
+# The mapping files are in the ...security
+# subdirectory at the root of each file system.
+#
+type file_labels_t, file_type, sysadmfile;
+
+#
+# no_access_t is the type for objects that should
+# only be accessed administratively. 
+#
+type no_access_t, file_type, sysadmfile;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/policy/users	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+##################################
+#
+# User configuration.
+#
+# This file defines each user recognized by the system security policy
+# if MLS is not enabled.
+# Only the user identities defined in this file may be used as the
+# user attribute in a security context.
+#
+# Each user has a set of roles that may be entered by processes
+# with the user's identity.  The syntax of a user declaration is:
+#
+# 	user username roles role_set ;
+#
+
+#
+# system_u is the user identity for system processes and objects.
+# There should be no corresponding Unix user identity for system_u,
+# and a user process should never be assigned the system_u user
+# identity.
+#
+user system_u roles system_r;
+
+#
+# The following users correspond to Unix identities.
+# These identities are typically assigned as the user attribute
+# when login starts the user shell.
+#
+
+user root roles { user_r sysadm_r };
+
+user jadmin roles { user_r sysadm_r };
+
+user jdoe roles { user_r };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/setfiles/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+# Installation directories.
+
+PROG = setfiles
+
+include ../../Makefile.cmd
+
+C99MODE = -xc99=%all
+C99LMODE = -Xc99=%all
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTSBINPROG)
+
+clean:
+
+lint:	lint_PROG
+
+#relabel: install
+#	setfilecon system_u:object_r:setfiles_exec_t $(SBINDIR)/setfiles
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fmac/setfiles/setfiles.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,882 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author:  Stephen Smalley <sds@epoch.ncsc.mil>
+ */
+
+/*
+ * setfiles
+ *
+ * PURPOSE:
+ * This program reads a set of file security context specifications
+ * based on pathname regular expressions and labels files
+ * accordingly, traversing a set of file systems specified by
+ * the user.  The program does not cross file system boundaries.
+ *
+ * USAGE:
+ * setfiles [-dnpqsvW] spec_file pathname...
+ *
+ * -d   Show what specification matched each file.
+ * -n	Do not change any file labels.
+ * -q   Be quiet (suppress non-error output).
+ * -v	Show changes in file labels.
+ * -W   Warn about entries that have no matching file.
+ *
+ * spec_file	The specification file.
+ * pathname...	The file systems to label (omit if using -s).
+ *
+ * EXAMPLE USAGE:
+ * ./setfiles -v file_contexts `mount | awk '/ext3/{print $3}'`
+ *
+ * SPECIFICATION FILE:
+ * Each specification has the form:
+ *       regexp [ -type ] ( context | <<none>> )
+ *
+ * By default, the regexp is an anchored match on both ends (i.e. a
+ * caret (^) is prepended and a dollar sign ($) is appended automatically).
+ * This default may be overridden by using .* at the beginning and/or
+ * end of the regular expression.
+ *
+ * The optional type field specifies the file type as shown in the mode
+ * field by ls, e.g. use -d to match only directories or -- to match only
+ * regular files.
+ *
+ * The value of <<none> may be used to indicate that matching files
+ * should not be relabeled.
+ *
+ * The last matching specification is used.
+ *
+ * If there are multiple hard links to a file that match
+ * different specifications and those specifications indicate
+ * different security contexts, then a warning is displayed
+ * but the file is still labeled based on the last matching
+ * specification other than <<none>>.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <sys/vfs.h>
+#include <ftw.h>
+#include <limits.h>
+#ifdef jweeks
+#include <fmac/fmac.h>
+#endif
+
+/* jweeks - until we have library support */
+int
+lgetfilecon(const char *c, char **context)
+{
+	*context = strdup("system_u:object_r:file_t");
+	return (0);
+}
+
+int
+lsetfilecon(const char *c, const char *context)
+{
+	return (0);
+}
+
+void
+freecon(char *context)
+{
+	if (context != NULL)
+		free(context);
+}
+
+int
+security_check_context(const char *context)
+{
+	return (0);
+}
+/* jweeks - until we have library support  */
+
+static int add_assoc = 1;
+
+/*
+ * Command-line options.
+ */
+static int debug = 0;
+static int change = 1;
+static int quiet = 0;
+#define	QPRINTF(args...) do { if (!quiet) printf(args); } while (0)
+static int verbose = 0;
+static int warn_no_match = 0;
+
+/*
+ * Program name and error message buffer.
+ */
+static char *progname;
+static char errbuf[255 + 1];
+
+/*
+ * A file security context specification.
+ */
+typedef struct spec {
+	char	*regex_str;	/* regular expession string for diagnostic */
+				/* messages */
+	char	*type_str;	/* type string for diagnostic messages */
+	char	*context;	/* context string */
+	regex_t	regex;		/* compiled regular expression */
+	mode_t	mode;		/* mode format value */
+	int	matches;	/* number of matching pathnames */
+	int	hasMetaChars;	/* indicates whether the RE has */
+				/* any meta characters. */
+				/* 0 = no meta chars */
+				/* 1 = has one or more meta chars */
+} spec_t;
+
+/*
+ * The array of specifications, initially in the
+ * same order as in the specification file.
+ * Sorting occurs based on hasMetaChars
+ */
+static spec_t *spec;
+static int nspec;
+
+/*
+ * An association between an inode and a
+ * specification.
+ */
+typedef struct file_spec {
+	ino_t ino;		/* inode number */
+	int specind;		/* index of specification in spec */
+	char *file;		/* full pathname for diagnostic messages */
+				/* about conflicts */
+	struct file_spec *next;	/* next association in hash bucket chain */
+} file_spec_t;
+
+/*
+ * The hash table of associations, hashed by inode number.
+ * Chaining is used for collisions, with elements ordered
+ * by inode number in each bucket.  Each hash bucket has a dummy
+ * header.
+ */
+#define	HASH_BITS 16
+#define	HASH_BUCKETS (1 << HASH_BITS)
+#define	HASH_MASK (HASH_BUCKETS-1)
+static file_spec_t fl_head[HASH_BUCKETS];
+
+/*
+ * Try to add an association between an inode and
+ * a specification.  If there is already an association
+ * for the inode and it conflicts with this specification,
+ * then use the specification that occurs later in the
+ * specification array.
+ */
+static file_spec_t *
+file_spec_add(ino_t ino, int specind, const char *file)
+{
+	file_spec_t *prevfl, *fl;
+	int h, no_conflict, ret;
+	struct stat sb;
+
+	h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
+	for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
+		prevfl = fl, fl = fl->next) {
+		if (ino == fl->ino) {
+			ret = lstat(fl->file, &sb);
+			if (ret < 0 || sb.st_ino != ino) {
+				fl->specind = specind;
+				free(fl->file);
+				fl->file = malloc(strlen(file) + 1);
+				if (!fl->file) {
+					fprintf(stderr,
+					    "%s:  insufficient memory for "
+					    "file label entry for %s\n",
+					    progname, file);
+					return (NULL);
+				}
+				strcpy(fl->file, file);
+				return (fl);
+			}
+
+			no_conflict = (strcmp(spec[fl->specind].context,
+			    spec[specind].context) == 0);
+			if (no_conflict)
+				return (fl);
+
+			fprintf(stderr, "%s:  conflicting specifications "
+			    "for %s and %s, using %s.\n",
+			    progname, file, fl->file,
+			    ((specind > fl->specind) ? spec[specind].context :
+			    spec[fl->specind].context));
+			fl->specind =
+			    (specind > fl->specind) ? specind : fl->specind;
+			free(fl->file);
+			fl->file = malloc(strlen(file) + 1);
+			if (!fl->file) {
+				fprintf(stderr,
+				    "%s:  insufficient memory for file "
+				    "label entry for %s\n",
+				    progname, file);
+				return (NULL);
+			}
+			strcpy(fl->file, file);
+			return (fl);
+		}
+
+		if (ino > fl->ino)
+			break;
+	}
+
+	fl = malloc(sizeof (file_spec_t));
+	if (!fl) {
+		fprintf(stderr,
+		    "%s:  insufficient memory for file label entry for %s\n",
+		    progname, file);
+		return (NULL);
+	}
+	fl->ino = ino;
+	fl->specind = specind;
+	fl->file = malloc(strlen(file) + 1);
+	if (!fl->file) {
+		fprintf(stderr,
+		    "%s:  insufficient memory for file label entry for %s\n",
+		    progname, file);
+		return (NULL);
+	}
+	strcpy(fl->file, file);
+	fl->next = prevfl->next;
+	prevfl->next = fl;
+	return (fl);
+}
+
+/*
+ * Evaluate the association hash table distribution.
+ */
+static void
+file_spec_eval(void)
+{
+	file_spec_t *fl;
+	int h, used, nel, len, longest;
+
+	used = 0;
+	longest = 0;
+	nel = 0;
+	for (h = 0; h < HASH_BUCKETS; h++) {
+		len = 0;
+		for (fl = fl_head[h].next; fl; fl = fl->next) {
+			len++;
+		}
+		if (len)
+			used++;
+		if (len > longest)
+			longest = len;
+		nel += len;
+	}
+
+	QPRINTF("%s:  hash table stats: %d elements, %d/%d buckets used, "
+	    "longest chain length %d\n",
+	    progname, nel, used, HASH_BUCKETS, longest);
+}
+
+
+/*
+ * Destroy the association hash table.
+ */
+static void
+file_spec_destroy(void)
+{
+	file_spec_t *fl, *tmp;
+	int h;
+
+	for (h = 0; h < HASH_BUCKETS; h++) {
+		fl = fl_head[h].next;
+		while (fl) {
+			tmp = fl;
+			fl = fl->next;
+			free(tmp->file);
+			free(tmp);
+		}
+		fl_head[h].next = NULL;
+	}
+}
+
+
+int
+match(const char *name, struct stat *sb)
+{
+	int i, ret;
+
+	ret = lstat(name, sb);
+	if (ret) {
+		fprintf(stderr, "%s:  unable to stat file %s\n", progname,
+			name);
+		return (-1);
+	}
+
+	/*
+	 * Check for matching specifications in reverse order, so that
+	 * the last matching specification is used.
+	 */
+	for (i = nspec - 1; i >= 0; i--) {
+		ret = regexec(&spec[i].regex, name, 0, NULL, 0);
+		if (ret == 0 && (!spec[i].mode ||
+		    (sb->st_mode & S_IFMT) == spec[i].mode))
+			break;
+		if (ret) {
+			if (ret == REG_NOMATCH)
+				continue;
+			regerror(ret, &spec[i].regex, errbuf, sizeof (errbuf));
+			fprintf(stderr,
+			    "%s:  unable to match %s against %s:  %s\n",
+			    progname, name, spec[i].regex_str, errbuf);
+			return (-1);
+		}
+	}
+
+	if (i < 0)
+		/* No matching specification. */
+		return (-1);
+
+	spec[i].matches++;
+
+	return (i);
+}
+
+/* Used with qsort to sort specs from lowest to highest hasMetaChars value */
+int
+spec_compare(const void* specA, const void* specB)
+{
+	return (((struct spec *)specB)->hasMetaChars -
+	    ((struct spec *)specA)->hasMetaChars);
+}
+
+/*
+ * Check for duplicate specifications. If a duplicate specification is found
+ * and the context is the same, give a warning to the user. If a duplicate
+ * specification is found and the context is different, give a warning
+ * to the user (This could be changed to error). Return of non-zero is
+ * an error.
+ */
+int
+nodups_specs()
+{
+	int ii, jj;
+	struct spec *curr_spec;
+
+	for (ii = 0; ii < nspec; ii++) {
+		curr_spec = &spec[ii];
+		for (jj = ii + 1; jj < nspec; jj++) {
+			/* Check if same RE string */
+			if ((strcmp(spec[jj].regex_str,
+			    curr_spec->regex_str) == 0) &&
+			    (!spec[jj].mode || !curr_spec->mode ||
+			    spec[jj].mode == curr_spec->mode)) {
+				/* Same RE string found */
+				if (strcmp(spec[jj].context,
+				    curr_spec->context)) {
+					/*
+					 * If different contexts, give
+					 * warning
+					 */
+					fprintf(stderr,
+					    "ERROR: Multiple different "
+					    "specifications for %s  "
+					    "(%s and %s).\n",
+					    curr_spec->regex_str,
+					    spec[jj].context,
+					    curr_spec->context);
+				} else {
+					/* If same contexts give warning */
+					fprintf(stderr,
+					    "WARNING: Multiple same "
+					    "specifications for %s.\n",
+					    curr_spec->regex_str);
+				}
+			}
+		}
+	}
+	return (0);
+}
+
+
+/*
+ * Determine if the regular expression specification has any meta characters.
+ */
+void
+spec_hasMetaChars(struct spec *spec)
+{
+	char *c;
+	int len;
+	char *end;
+
+	c = spec->regex_str;
+	len = strlen(spec->regex_str);
+	end = c + len;
+
+	spec->hasMetaChars = 0;
+
+	/*
+	 * Look at each character in the RE specification string for a
+	 * meta character. Return when any meta character reached.
+	 */
+	while (c != end) {
+		switch (*c) {
+			case '.':
+			case '^':
+			case '$':
+			case '?':
+			case '*':
+			case '+':
+			case '|':
+			case '[':
+			case '(':
+			case '{':
+				spec->hasMetaChars = 1;
+				return;
+			case '\\':		// skip the next character
+				c++;
+				break;
+			default:
+				break;
+
+		}
+		c++;
+	}
+}
+
+#define	SZ 255
+
+/*
+ * Apply the last matching specification to a file.
+ * This function is called by nftw on each file during
+ * the directory traversal.
+ */
+static int
+apply_spec(const char *file, const struct stat *sb, int flag, struct FTW *s)
+{
+	const char	*my_file;
+	file_spec_t	*fl;
+	struct stat	my_sb;
+	int		i;
+	int		ret;
+	char		*context;
+
+	/* Skip the extra slash at the beginning, if present. */
+	if (file[0] == '/' && file[1] == '/')
+		my_file = &file[1];
+	else
+		my_file = file;
+
+	if (flag == FTW_DNR) {
+		fprintf(stderr, "%s:  unable to read directory %s\n",
+			progname, my_file);
+		return (0);
+	}
+
+	i = match(my_file, &my_sb);
+	if (i < 0)
+		/* No matching specification. */
+		return (0);
+
+	/*
+	 * Try to add an association between this inode and
+	 * this specification.  If there is already an association
+	 * for this inode and it conflicts with this specification,
+	 * then use the last matching specification.
+	 */
+	if (add_assoc) {
+		fl = file_spec_add(my_sb.st_ino, i, my_file);
+		if (!fl)
+			/* Insufficient memory to proceed. */
+			return (1);
+
+		if (fl->specind != i)
+			/*
+			 * There was already an association and it
+			 * took precedence.
+			 */
+			return (0);
+	}
+
+	if (debug) {
+		if (spec[i].type_str) {
+			printf("%s:  %s matched by (%s,%s,%s)\n",
+			    progname, my_file, spec[i].regex_str,
+			    spec[i].type_str, spec[i].context);
+		} else {
+			printf("%s:  %s matched by (%s,%s)\n",
+			    progname, my_file, spec[i].regex_str,
+			    spec[i].context);
+		}
+	}
+
+	/* Get the current context of the file. */
+	ret = lgetfilecon(my_file, &context);
+	if (ret < 0) {
+		if (errno == ENODATA) {
+			context = malloc(10);
+			strcpy(context, "<<none>>");
+		} else {
+			perror(my_file);
+			fprintf(stderr, "%s:  unable to obtain attribute for "
+			    "file %s\n",
+			    progname, my_file);
+			return (-1);
+		}
+	}
+
+	/*
+	 * Do not relabel the file if the matching specification is
+	 * <<none>> or the file is already labeled according to the
+	 * specification.
+	 */
+	if ((strcmp(spec[i].context, "<<none>>") == 0) ||
+	    (strcmp(context, spec[i].context) == 0)) {
+		freecon(context);
+		return (0);
+	}
+
+	if (verbose) {
+		printf("%s:  relabeling %s from %s to %s\n", progname, my_file,
+		    context, spec[i].context);
+	}
+
+	freecon(context);
+
+	/*
+	 * Do not relabel the file if -n was used.
+	 */
+	if (!change)
+		return (0);
+
+	/*
+	 * Relabel the file to the specified context.
+	 */
+	ret = lsetfilecon(my_file, spec[i].context);
+	if (ret) {
+		perror(my_file);
+		fprintf(stderr, "%s:  unable to relabel %s to %s\n",
+			progname, my_file, spec[i].context);
+		return (1);
+	}
+
+	return (0);
+}
+
+
+int
+main(int argc, char **argv)
+{
+	FILE *fp;
+	char buf[255 + 1], *buf_p;
+	char regex[256], type[256], context[256];
+	char *anchored_regex;
+	int opt, items, len, lineno, pass, nerr, regerr, i;
+
+	/* Process any options. */
+	while ((opt = getopt(argc, argv, "dnpqvxW")) > 0) {
+		switch (opt) {
+		case 'd':
+			debug = 1;
+			break;
+		case 'n':
+			change = 0;
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'x':
+			/* now the default */
+			break;
+		case 'W':
+			warn_no_match = 1;
+			break;
+		case '?':
+			fprintf(stderr,
+			    "usage:  %s [-dnpqsvW] spec_file pathname...\n",
+			    argv[0]);
+			exit(1);
+		}
+	}
+
+	if (optind > (argc - 2)) {
+		fprintf(stderr,
+			"usage:  %s [-dnpqvW] spec_file pathname...\n",
+			argv[0]);
+		exit(1);
+	}
+
+	/* Open the specification file. */
+	if ((fp = fopen(argv[optind], "r")) == NULL) {
+		perror(argv[optind]);
+		exit(1);
+	}
+	optind++;
+
+	/*
+	 * Perform two passes over the specification file.
+	 * The first pass counts the number of specifications and
+	 * performs simple validation of the input.  At the end
+	 * of the first pass, the spec array is allocated.
+	 * The second pass performs detailed validation of the input
+	 * and fills in the spec array.
+	 */
+	for (pass = 0; pass < 2; pass++) {
+		lineno = 0;
+		nspec = 0;
+		nerr = 0;
+		while (fgets(buf, sizeof (buf), fp)) {
+			lineno++;
+			len = strlen(buf);
+			if (buf[len - 1] != '\n') {
+				fprintf(stderr,
+				    "%s:  no newline on line number %d "
+				    "(only read %s)\n",
+				    argv[0], lineno, buf);
+				nerr++;
+				continue;
+			}
+			buf[len - 1] = 0;
+			buf_p = buf;
+			while (isspace(*buf_p))
+				buf_p++;
+			/* Skip comment lines and empty lines. */
+			if (*buf_p == '#' || *buf_p == 0)
+				continue;
+			items = sscanf(buf, "%255s %255s %255s",
+					regex,
+					type,
+					context);
+			if (items < 2) {
+				fprintf(stderr,
+				    "%s:  line number %d is missing fields "
+				    "(only read %s)\n",
+				    argv[0], lineno, buf);
+				nerr++;
+				continue;
+			} else if (items == 2) {
+				/* The type field is optional. */
+				strncpy(context, type, sizeof (context));
+				type[0] = 0;
+			}
+
+			if (pass == 1) {
+				/*
+				 * On the second pass, compile and store
+				 * the specification in spec.
+				 */
+				spec[nspec].regex_str = strdup(regex);
+
+				/* Anchor the regular expression. */
+				len = strlen(regex);
+				anchored_regex = malloc(len + 3);
+				if (!anchored_regex) {
+					fprintf(stderr,
+					    "%s:  insufficient memory for "
+					    "anchored regexp on line %d\n",
+					    argv[0], lineno);
+					exit(1);
+				}
+				sprintf(anchored_regex, "^%s$", regex);
+
+				/* Compile the regular expression. */
+				regerr = regcomp(&spec[nspec].regex,
+				    anchored_regex, REG_EXTENDED | REG_NOSUB);
+				if (regerr < 0) {
+					regerror(regerr, &spec[nspec].regex,
+					    errbuf, sizeof (errbuf));
+					fprintf(stderr,
+					    "%s:  unable to compile regular "
+					    "expression %s on line number "
+					    "%d:  %s\n",
+						argv[0], regex, lineno, errbuf);
+					nerr++;
+				}
+				free(anchored_regex);
+
+				/* Convert the type string to a mode format */
+				if (type[0] != 0)
+					spec[nspec].type_str = strdup(type);
+				else
+					spec[nspec].type_str = NULL;
+				spec[nspec].mode = 0;
+				if (strlen(type) == 0)
+					goto skip_type;
+				len = strlen(type);
+				if (type[0] != '-' || len != 2) {
+					fprintf(stderr,
+					    "%s:  invalid type specifier %s "
+					    "on line number %d\n",
+					    argv[0], type, lineno);
+					nerr++;
+					goto skip_type;
+				}
+				switch (type[1]) {
+				case 'b':
+					spec[nspec].mode = S_IFBLK;
+					break;
+				case 'c':
+					spec[nspec].mode = S_IFCHR;
+					break;
+				case 'd':
+					spec[nspec].mode = S_IFDIR;
+					break;
+				case 'p':
+					spec[nspec].mode = S_IFIFO;
+					break;
+				case 'l':
+					spec[nspec].mode = S_IFLNK;
+					break;
+				case 's':
+					spec[nspec].mode = S_IFSOCK;
+					break;
+				case '-':
+					spec[nspec].mode = S_IFREG;
+					break;
+				default:
+					fprintf(stderr,
+					    "%s:  invalid type specifier %s "
+					    "on line number %d\n",
+						argv[0], type, lineno);
+					nerr++;
+				}
+
+skip_type:
+
+				spec[nspec].context = strdup(context);
+
+				if (strcmp(context, "<<none>>")) {
+					if (security_check_context(context) <
+					    0) {
+						fprintf(stderr,
+						    "%s:  invalid context %s "
+						    "on line number %d\n",
+						    argv[0], context, lineno);
+						nerr++;
+					}
+				}
+
+				/*
+				 * Determine if specification has
+				 * any meta characters in the RE
+				 */
+				spec_hasMetaChars(&spec[nspec]);
+			}
+
+			nspec++;
+		}
+
+		if (nerr)
+			exit(1);
+
+		if (pass == 0) {
+			QPRINTF("%s:  read %d specifications\n", argv[0],
+			    nspec);
+			if (nspec == 0)
+				exit(0);
+			if ((spec = malloc(sizeof (spec_t) * nspec)) ==
+			    NULL) {
+				fprintf(stderr,
+				    "%s:  insufficient memory for "
+				    "specifications\n",
+				    argv[0]);
+				exit(1);
+			}
+			memset(spec, 0, sizeof (spec_t) * nspec);
+			rewind(fp);
+		}
+	}
+	fclose(fp);
+
+	/* Sort the specifications with most general first */
+	qsort(spec, nspec, sizeof (struct spec), spec_compare);
+
+	/* Verify no exact duplicates */
+	if (nodups_specs() != 0) {
+		exit(1);
+	}
+
+	/*
+	 * Apply the specifications to the file systems.
+	 */
+	progname = argv[0];
+	for (; optind < argc; optind++) {
+
+		QPRINTF("%s:  labeling files under %s\n", argv[0],
+			argv[optind]);
+
+		/* Walk the file tree, calling apply_spec on each file. */
+		if (nftw(argv[optind], apply_spec, 1024,
+		    FTW_PHYS | FTW_MOUNT)) {
+			fprintf(stderr,
+				"%s:  error while labeling files under %s\n",
+				argv[0], argv[optind]);
+			exit(1);
+		}
+
+		/*
+		 * Evaluate the association hash table distribution for the
+		 * directory tree just traversed.
+		 */
+		file_spec_eval();
+
+		/*
+		 * Reset the association hash table for the next
+		 * directory tree.
+		 */
+		file_spec_destroy();
+	}
+
+	if (warn_no_match) {
+		for (i = 0; i < nspec; i++) {
+			if (spec[i].matches == 0) {
+				if (spec[i].type_str) {
+					printf("%s:  Warning!  No matches for "
+					    "(%s, %s, %s)\n",
+					    argv[0], spec[i].regex_str,
+					    spec[i].type_str, spec[i].context);
+				} else {
+					printf("%s:  Warning!  No matches for "
+					    "(%s, %s)\n",
+					    argv[0], spec[i].regex_str,
+					    spec[i].context);
+				}
+			}
+		}
+	}
+
+	QPRINTF("%s:  Done.\n", argv[0]);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/policy/flask/access_vectors	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,361 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define common prefixes for access vectors
+#
+# common common_name { permission_name ... }
+
+
+#
+# Define a common prefix for file access vectors.
+#
+
+common file
+{
+	poll
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	transition
+	append
+	access
+	unlink
+	link
+	rename
+	execute
+}
+
+
+#
+# Define a common prefix for socket access vectors.
+#
+
+common socket
+{
+# inherited from file
+	poll
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	transition
+	append
+# socket-specific
+	bind
+	connect
+	getopt
+	setopt
+	shutdown
+	recvfrom
+	sendto
+	recv_msg
+	send_msg
+	name_bind
+}	
+
+#
+# Define a common prefix for ipc access vectors.
+#
+
+common ipc
+{
+	create
+	destroy
+	getattr
+	setattr
+	read
+	write
+	associate
+}
+
+#
+# Define the access vectors.
+#
+# class class_name [ inherits common_name ] { permission_name ... }
+
+
+#
+# Define the access vector interpretation for file-related objects.
+#
+
+class filesystem
+{
+	mount
+	remount
+	unmount
+	getattr
+	relabelfrom
+	relabelto
+	transition
+	associate
+}
+
+class dir
+inherits file
+{
+	add_name
+	remove_name
+	reparent
+	search
+	rmdir
+	mounton
+	mountassociate
+}
+
+class file
+inherits file
+
+class lnk_file
+inherits file
+
+class chr_file
+inherits file
+
+class blk_file
+inherits file
+
+class sock_file
+inherits file
+
+class fifo_file
+inherits file
+
+class pipe
+inherits file
+
+
+class fd
+{
+	create
+	getattr
+	setattr
+	inherit
+	receive
+}
+
+
+#
+# Define the access vector interpretation for network-related objects.
+#
+
+class socket
+inherits socket
+
+class tcp_socket
+inherits socket
+{
+	connectto
+	listen
+	accept
+	newconn
+	acceptfrom
+}
+
+class udp_socket
+inherits socket
+
+class rawip_socket
+inherits socket
+
+class node 
+{
+	tcp_recv
+	tcp_send
+	udp_recv
+	udp_send
+	rawip_recv
+	rawip_send
+	enforce_dest
+}
+
+class netif
+{
+	getattr
+	setattr
+	tcp_recv
+	tcp_send
+	udp_recv
+	udp_send
+	rawip_recv
+	rawip_send
+}
+
+class netlink_socket
+inherits socket
+
+class packet_socket
+inherits socket
+
+class unix_stream_socket
+inherits socket
+{
+	connectto
+	listen
+	accept
+	newconn
+	acceptfrom
+}
+
+class unix_dgram_socket
+inherits socket
+
+
+#
+# Define the access vector interpretation for process-related objects
+#
+
+class process
+{
+	execute
+	fork
+	transition
+	sigchld
+	sigkill
+	sigstop
+	signal
+	ptrace
+	getsched
+	setsched
+	getsession
+	getpgid
+	setpgid
+	getcap
+	setcap
+	entrypoint
+}
+
+
+#
+# Define the access vector interpretation for ipc-related objects
+#
+
+class sem
+inherits ipc
+
+class msgq
+inherits ipc
+{
+	enqueue
+}
+
+class msg
+{
+	send
+	receive
+}
+
+class shm
+inherits ipc
+{
+	lock
+}
+
+
+#
+# Define the access vector interpretation for the security server. 
+#
+
+class security
+{
+	compute_av
+	notify_perm
+	transition_sid
+	member_sid
+	sid_to_context
+	context_to_sid
+	load_policy
+	get_sids
+	register_avc
+	change_sid
+	get_user_sids
+}
+
+
+#
+# Define the access vector interpretation for system operations.
+#
+
+class system
+{
+	net_io_control
+	route_control
+	arp_control
+	rarp_control
+	ipc_info
+	avc_toggle
+}
+
+#
+# Define the access vector interpretation for controling privileges
+#
+
+class capability
+{
+	# This will be converted to privilege at a later time.
+        # (Order matters)
+
+	chown           
+	dac_override    
+	dac_read_search 
+	fowner          
+	fsetid          
+	kill            
+	setgid           
+	setuid           
+	setpcap          
+	linux_immutable  
+	net_bind_service 
+	net_broadcast    
+	net_admin        
+	net_raw          
+	ipc_lock         
+	ipc_owner        
+	sys_module       
+	sys_rawio        
+	sys_chroot       
+	sys_ptrace       
+	sys_pacct        
+	sys_admin        
+	sys_boot         
+	sys_nice         
+	sys_resource     
+	sys_time         
+	sys_tty_config  
+	mknod
+	lease
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/policy/flask/initial_sids	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,58 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define initial security identifiers 
+#
+
+sid kernel
+sid security
+sid unlabeled
+sid fs
+sid file
+sid file_labels
+sid init
+sid proc
+sid any_socket
+sid port
+sid netif
+sid netmsg
+sid node
+sid icmp_socket
+sid tcp_socket
+sid proc_kmsg
+sid proc_kcore
+sid sysctl_modprobe
+sid sysctl
+sid sysctl_fs
+sid sysctl_kernel
+sid sysctl_net
+sid sysctl_vm
+sid sysctl_dev
+sid kmod
+sid devpts
+sid nfs
+sid policy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/policy/flask/security_classes	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,64 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+#
+# Define the security object classes 
+#
+
+class security
+class process
+class system
+class capability
+
+# file-related classes
+class filesystem
+class file
+class dir
+class fd
+class lnk_file
+class chr_file
+class blk_file
+class sock_file
+class fifo_file
+class pipe
+
+# network-related classes
+class socket
+class tcp_socket
+class udp_socket
+class rawip_socket
+class node
+class netif
+class netlink_socket
+class packet_socket
+class unix_stream_socket
+class unix_dgram_socket
+
+# sysv-ipc-related clases
+class sem
+class msg
+class msgq
+class shm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/avtab.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,332 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the access vector table type.
+ */
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "avtab.h"
+#include "policydb.h"
+
+#define	AVTAB_HASH(keyp)						\
+	((keyp->target_class +						\
+	    (keyp->target_type << 2) + (keyp->source_type << 9)) &	\
+	    AVTAB_HASH_MASK)
+
+int
+avtab_insert(avtab_t *h, avtab_key_t *key, avtab_datum_t *datum)
+{
+	int hvalue;
+	avtab_ptr_t prev, cur, newnode;
+
+	if (!h)
+		return (ENOMEM);
+
+	hvalue = AVTAB_HASH(key);
+	for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur,
+		cur = cur->next) {
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class == cur->key.target_class &&
+		    (datum->specified & cur->datum.specified))
+			return (EEXIST);
+		if (key->source_type < cur->key.source_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type < cur->key.target_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class < cur->key.target_class)
+			break;
+	}
+
+	newnode = (avtab_ptr_t) SS_ALLOC_SLEEP(sizeof (struct avtab_node));
+	if (newnode == NULL)
+		return (ENOMEM);
+	(void) memset(newnode, 0, sizeof (struct avtab_node));
+	newnode->key = *key;
+	newnode->datum = *datum;
+	if (prev) {
+		newnode->next = prev->next;
+		prev->next = newnode;
+	} else {
+		newnode->next = h->htable[hvalue];
+		h->htable[hvalue] = newnode;
+	}
+
+	h->nel++;
+	return (0);
+}
+
+
+avtab_datum_t *
+avtab_search(avtab_t *h, avtab_key_t *key, int specified)
+{
+	int hvalue;
+	avtab_ptr_t cur;
+
+
+	if (!h)
+		return (NULL);
+
+	hvalue = AVTAB_HASH(key);
+	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class == cur->key.target_class &&
+		    (specified & cur->datum.specified))
+			return (&cur->datum);
+
+		if (key->source_type < cur->key.source_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type < cur->key.target_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class < cur->key.target_class)
+			break;
+	}
+
+	return (NULL);
+}
+
+
+void
+avtab_destroy(avtab_t *h)
+{
+	int i;
+	avtab_ptr_t cur, temp;
+
+
+	if (!h)
+		return;
+
+	for (i = 0; i < AVTAB_SIZE; i++) {
+		cur = h->htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur->next;
+			SS_FREE(temp, sizeof (struct avtab_node));
+		}
+		h->htable[i] = NULL;
+	}
+	SS_FREE(h->htable, sizeof (avtab_ptr_t)*AVTAB_SIZE);
+}
+
+
+int
+avtab_map(avtab_t *h, int (*apply) (avtab_key_t *k, avtab_datum_t *d,
+    void *args), void *args)
+{
+	int i, ret;
+	avtab_ptr_t cur;
+
+
+	if (!h)
+		return (0);
+
+	for (i = 0; i < AVTAB_SIZE; i++) {
+		cur = h->htable[i];
+		while (cur != NULL) {
+			ret = apply(&cur->key, &cur->datum, args);
+			if (ret)
+				return (ret);
+			cur = cur->next;
+		}
+	}
+	return (0);
+}
+
+int
+avtab_init(avtab_t *h)
+{
+	int i;
+
+	h->htable = SS_ALLOC_SLEEP(sizeof (avtab_ptr_t)*AVTAB_SIZE);
+	if (!h->htable)
+		return (-1);
+	for (i = 0; i < AVTAB_SIZE; i++)
+		h->htable[i] = (avtab_ptr_t) NULL;
+	h->nel = 0;
+	return (0);
+}
+
+
+void
+avtab_hash_eval(avtab_t *h, char *tag)
+{
+	int i, chain_len, slots_used, max_chain_len;
+	avtab_ptr_t cur;
+
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i < AVTAB_SIZE; i++) {
+		cur = h->htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur->next;
+			}
+
+			if (chain_len > max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	(void) printf("%s:  %d entries and %d/%d buckets used, longest "
+		"chain length %d\n",
+		tag,
+		h->nel,
+		slots_used,
+		AVTAB_SIZE,
+		max_chain_len);
+}
+
+/*ARGSUSED*/
+int
+avtab_read(avtab_t *a, void *fp, uint32_t config)
+{
+	int i, rc;
+	avtab_key_t avkey;
+	avtab_datum_t avdatum;
+	uint32_t buf[7];
+	uint32_t nel;
+	size_t items, items2;
+
+
+	items = next_entry(&nel, sizeof (uint32_t), 1, fp);
+	if (items != 1) {
+		(void) printf("security: avtab: truncated table\n");
+		goto bad;
+	}
+	nel = SS_LE32_TO_CPU(nel);
+	if (!nel) {
+		(void) printf("security: avtab: table is empty\n");
+		goto bad;
+	}
+	for (i = 0; i < nel; i++) {
+		(void) memset(&avkey, 0, sizeof (avtab_key_t));
+		(void) memset(&avdatum, 0, sizeof (avtab_datum_t));
+
+		items = next_entry(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1) {
+			(void) printf("security: avtab: truncated entry\n");
+			goto bad;
+		}
+		items2 = SS_LE32_TO_CPU(buf[0]);
+		if (items2 > (sizeof (buf) / sizeof (uint32_t))) {
+			(void) printf("security: avtab: entry too large\n");
+			goto bad;
+		}
+		items = next_entry(buf, sizeof (uint32_t), items2, fp);
+		if (items != items2) {
+			(void) printf("security: avtab: truncated entry\n");
+			goto bad;
+		}
+		items = 0;
+		avkey.source_type = SS_LE32_TO_CPU(buf[items++]);
+		avkey.target_type = SS_LE32_TO_CPU(buf[items++]);
+		avkey.target_class = SS_LE32_TO_CPU(buf[items++]);
+		avdatum.specified = SS_LE32_TO_CPU(buf[items++]);
+		if (!(avdatum.specified & (AVTAB_AV | AVTAB_TYPE))) {
+			(void) printf("security: avtab: null entry\n");
+			goto bad;
+		}
+		if ((avdatum.specified & AVTAB_AV) &&
+		    (avdatum.specified & AVTAB_TYPE)) {
+			(void) printf("security: avtab: entry has both "
+				"access vectors and types\n");
+			goto bad;
+		}
+		if (avdatum.specified & AVTAB_AV) {
+			if (avdatum.specified & AVTAB_ALLOWED)
+				avtab_allowed(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+			if (avdatum.specified & AVTAB_AUDITDENY)
+				avtab_auditdeny(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+			if (avdatum.specified & AVTAB_AUDITALLOW)
+				avtab_auditallow(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+		} else {
+			if (avdatum.specified & AVTAB_TRANSITION)
+				avtab_transition(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+			if (avdatum.specified & AVTAB_CHANGE)
+				avtab_change(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+			if (avdatum.specified & AVTAB_MEMBER)
+				avtab_member(&avdatum) =
+				    SS_LE32_TO_CPU(buf[items++]);
+		}
+		if (items != items2) {
+			(void) printf("security: avtab: entry only had %lu "
+			    "items, expected %lu\n", items2, items);
+			goto bad;
+		}
+		rc = avtab_insert(a, &avkey, &avdatum);
+		if (rc) {
+			if (rc == ENOMEM)
+				(void) printf("security: avtab: out of "
+				    "memory\n");
+			if (rc == EEXIST)
+				(void) printf("security: avtab: duplicate "
+				    "entry\n");
+			goto bad;
+		}
+	}
+
+	return (0);
+
+bad:
+	avtab_destroy(a);
+	return (-1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/avtab.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,105 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * An access vector table (avtab) is a hash table
+ * of access vectors and transition types indexed
+ * by a type pair and a class.  An access vector
+ * table is used to represent the type enforcement
+ * tables.
+ */
+
+#ifndef _AVTAB_H
+#define	_AVTAB_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+typedef struct avtab_key {
+	uint32_t source_type;	/* source type */
+	uint32_t target_type;	/* target type */
+	uint32_t target_class;	/* target object class */
+} avtab_key_t;
+
+typedef struct avtab_datum {
+#define	AVTAB_ALLOWED		1
+#define	AVTAB_AUDITALLOW	2
+#define	AVTAB_AUDITDENY		4
+#define	AVTAB_AV	(AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
+#define	AVTAB_TRANSITION	16
+#define	AVTAB_MEMBER		32
+#define	AVTAB_CHANGE		64
+#define	AVTAB_TYPE		(AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
+	uint32_t specified;	/* what fields are specified */
+	uint32_t data[3];	/* access vectors or types */
+#define	avtab_allowed(x) (x)->data[0]
+#define	avtab_auditdeny(x) (x)->data[1]
+#define	avtab_auditallow(x) (x)->data[2]
+#define	avtab_transition(x) (x)->data[0]
+#define	avtab_change(x) (x)->data[1]
+#define	avtab_member(x) (x)->data[2]
+} avtab_datum_t;
+
+typedef struct avtab_node *avtab_ptr_t;
+
+struct avtab_node {
+	avtab_key_t key;
+	avtab_datum_t datum;
+	avtab_ptr_t next;
+};
+
+typedef struct avtab {
+	avtab_ptr_t *htable;
+	uint32_t nel;	/* number of elements */
+} avtab_t;
+
+int avtab_init(avtab_t *);
+
+int avtab_insert(avtab_t * h, avtab_key_t * k, avtab_datum_t * d);
+
+avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k, int specified);
+
+void avtab_destroy(avtab_t * h);
+
+int avtab_map(avtab_t * h, int (*apply) (avtab_key_t *k, avtab_datum_t *d,
+    void *args), void *args);
+
+void avtab_hash_eval(avtab_t * h, char *tag);
+
+int avtab_read(avtab_t *a, void *fp, uint32_t config);
+
+#define	AVTAB_HASH_BITS		15
+#define	AVTAB_HASH_BUCKETS	(1 << AVTAB_HASH_BITS)
+#define	AVTAB_HASH_MASK		(AVTAB_HASH_BUCKETS-1)
+
+#define	AVTAB_SIZE		AVTAB_HASH_BUCKETS
+
+#endif	/* _AVTAB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/constraint.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A constraint is a condition that must be satisfied in
+ * order for one or more permissions to be granted.
+ * Constraints are used to impose additional restrictions
+ * beyond the type-based rules in `te' or the role-based
+ * transition rules in `rbac'.  Constraints are typically
+ * used to prevent a process from transitioning to a new user
+ * identity or role unless it is in a privileged type.
+ * Constraints are likewise typically used to prevent a
+ * process from labeling an object with a different user
+ * identity.
+ */
+
+#ifndef _CONSTRAINT_H
+#define	_CONSTRAINT_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+#include "ebitmap.h"
+
+#define	CEXPR_MAXDEPTH		5
+
+typedef struct constraint_expr {
+#define	CEXPR_NOT		1	/* not expr */
+#define	CEXPR_AND		2 	/* expr and expr */
+#define	CEXPR_OR		3 	/* expr or expr */
+#define	CEXPR_ATTR		4	/* attr op attr */
+#define	CEXPR_NAMES		5 	/* attr op names */
+	uint32_t expr_type;		/* expression type */
+
+#define	CEXPR_USER		 1	/* user */
+#define	CEXPR_ROLE		 2	/* role */
+#define	CEXPR_TYPE		 4	/* type */
+#define	CEXPR_TARGET		 8	/* target if set, source otherwise */
+	uint32_t attr;			/* attribute */
+
+#define	CEXPR_EQ		1	/* == or eq */
+#define	CEXPR_NEQ		2	/* != */
+#define	CEXPR_DOM		3	/* dom */
+#define	CEXPR_DOMBY		4	/* domby  */
+#define	CEXPR_INCOMP		5	/* incomp */
+	uint32_t op;			/* operator */
+	ebitmap_t names;		/* names */
+	struct constraint_expr *next;   /* next expression */
+} constraint_expr_t;
+
+
+typedef struct constraint_node {
+	access_vector_t permissions;	/* constrained permissions */
+	constraint_expr_t *expr;	/* constraint on permissions */
+	struct constraint_node *next;	/* next constraint */
+} constraint_node_t;
+
+#endif	/* _CONSTRAINT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/context.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,144 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A security context is a set of security attributes
+ * associated with each subject and object controlled
+ * by the security policy.  Security contexts are
+ * externally represented as variable-length strings
+ * that can be interpreted by a user or application
+ * with an understanding of the security policy.
+ * Internally, the security server uses a simple
+ * structure.  This structure is private to the
+ * security server and can be changed without affecting
+ * clients of the security server.
+ */
+
+#ifndef _CONTEXT_H
+#define	_CONTEXT_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#else
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "ebitmap.h"
+#include "mls_types.h"
+
+/*
+ * A security context consists of an authenticated user
+ * identity, a role, a type and a MLS range.
+ */
+typedef struct context_struct {
+	uint32_t user;
+	uint32_t role;
+	uint32_t type;
+#ifdef CONFIG_FLASK_MLS
+	mls_range_t range;
+#endif
+} context_struct_t;
+
+
+#ifdef CONFIG_FLASK_MLS
+
+#define	mls_context_init(c) (void) memset(c, 0, sizeof (mls_range_t))
+
+static inline int mls_context_cpy(context_struct_t *dst, context_struct_t *src)
+{
+	(dst)->range.level[0].sens = (src)->range.level[0].sens;
+	if (!ebitmap_cpy(&(dst)->range.level[0].cat,
+	    &(src)->range.level[0].cat))
+		return (ENOMEM);
+	(dst)->range.level[1].sens = (src)->range.level[1].sens;
+	if (!ebitmap_cpy(&(dst)->range.level[1].cat,
+	    &(src)->range.level[1].cat)) {
+		ebitmap_destroy(&(dst)->range.level[0].cat);
+		return (ENOMEM);
+	}
+	return (0);
+}
+
+#define	mls_context_cmp(c1, c2)						\
+	(((c1)->range.level[0].sens == (c2)->range.level[0].sens) &&	\
+	ebitmap_cmp(&(c1)->range.level[0].cat,				\
+	    &(c2)->range.level[0].cat) &&				\
+	((c1)->range.level[1].sens == (c2)->range.level[1].sens) &&	\
+	ebitmap_cmp(&(c1)->range.level[1].cat, &(c2)->range.level[1].cat))
+
+#define	mls_context_destroy(c)						\
+	{								\
+		ebitmap_destroy(&(c)->range.level[0].cat);		\
+		ebitmap_destroy(&(c)->range.level[1].cat);		\
+		(void) memset(c, 0, sizeof (mls_range_t));		\
+	}
+#else
+
+#define	mls_context_init(c)
+#define	mls_context_cpy(dst, src)	0
+#define	mls_context_destroy(c)
+#define	mls_context_cmp(c1, c2)		1
+
+#endif
+
+
+#define	context_init(c)	(void) memset(c, 0, sizeof (context_struct_t))
+
+static inline int
+context_cpy(context_struct_t *dst, context_struct_t *src)
+{
+	(dst)->user = (src)->user;
+	(dst)->role = (src)->role;
+	(dst)->type = (src)->type;
+	return (mls_context_cpy(dst, src));
+}
+
+
+#define	context_destroy(c)						\
+	{								\
+		(c)->user = 0;						\
+		(c)->role = 0;						\
+		(c)->type = 0;						\
+		mls_context_destroy(c);					\
+	}
+
+static inline int
+context_cmp(context_struct_t *c1, context_struct_t *c2)
+{
+	return (((c1)->user == (c2)->user) &&
+		((c1)->role == (c2)->role) &&
+		((c1)->type == (c2)->type) &&
+		mls_context_cmp(c1, c2));
+}
+
+#endif	/* _CONTEXT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/ebitmap.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,388 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the extensible bitmap type.
+ */
+
+#if defined(_KERNEL)
+#include <sys/types.h>
+#include <sys/inttypes.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "ebitmap.h"
+#include "policydb.h"
+
+int
+ebitmap_or(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+{
+	ebitmap_node_t *n1, *n2, *new, *prev;
+
+	ebitmap_init(dst);
+
+	n1 = e1->node;
+	n2 = e2->node;
+	prev = 0;
+	while (n1 || n2) {
+		new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP(
+		    sizeof (ebitmap_node_t));
+		if (!new) {
+			ebitmap_destroy(dst);
+			return (FALSE);
+		}
+		(void) memset(new, 0, sizeof (ebitmap_node_t));
+		if (n1 && n2 && n1->startbit == n2->startbit) {
+			new->startbit = n1->startbit;
+			new->map = n1->map | n2->map;
+			n1 = n1->next;
+			n2 = n2->next;
+		} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
+			new->startbit = n1->startbit;
+			new->map = n1->map;
+			n1 = n1->next;
+		} else {
+			new->startbit = n2->startbit;
+			new->map = n2->map;
+			n2 = n2->next;
+		}
+
+		new->next = 0;
+		if (prev)
+			prev->next = new;
+		else
+			dst->node = new;
+		prev = new;
+	}
+
+	dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
+	return (TRUE);
+}
+
+int
+ebitmap_cmp(ebitmap_t *e1, ebitmap_t *e2)
+{
+	ebitmap_node_t *n1, *n2;
+
+
+	if (e1->highbit != e2->highbit)
+		return (FALSE);
+
+	n1 = e1->node;
+	n2 = e2->node;
+	while (n1 && n2 && (n1->startbit == n2->startbit) &&
+	    (n1->map == n2->map)) {
+		n1 = n1->next;
+		n2 = n2->next;
+	}
+
+	if (n1 || n2)
+		return (FALSE);
+
+	return (TRUE);
+}
+
+int
+ebitmap_cpy(ebitmap_t *dst, ebitmap_t *src)
+{
+	ebitmap_node_t *n, *new, *prev;
+
+
+	ebitmap_init(dst);
+	n = src->node;
+	prev = 0;
+	while (n) {
+		new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP(
+		    sizeof (ebitmap_node_t));
+		if (!new) {
+			ebitmap_destroy(dst);
+			return (FALSE);
+		}
+		(void) memset(new, 0, sizeof (ebitmap_node_t));
+		new->startbit = n->startbit;
+		new->map = n->map;
+		new->next = 0;
+		if (prev)
+			prev->next = new;
+		else
+			dst->node = new;
+		prev = new;
+		n = n->next;
+	}
+
+	dst->highbit = src->highbit;
+	return (TRUE);
+}
+
+int
+ebitmap_contains(ebitmap_t *e1, ebitmap_t *e2)
+{
+	ebitmap_node_t *n1, *n2;
+
+
+	if (e1->highbit < e2->highbit)
+		return (FALSE);
+
+	n1 = e1->node;
+	n2 = e2->node;
+	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
+		if (n1->startbit < n2->startbit) {
+			n1 = n1->next;
+			continue;
+		}
+		if ((n1->map & n2->map) != n2->map)
+			return (FALSE);
+
+		n1 = n1->next;
+		n2 = n2->next;
+	}
+
+	if (n2)
+		return (FALSE);
+
+	return (TRUE);
+}
+
+int
+ebitmap_get_bit(ebitmap_t *e, unsigned long bit)
+{
+	ebitmap_node_t *n;
+
+	if (e->highbit < bit)
+		return (FALSE);
+
+	n = e->node;
+	while (n && (n->startbit <= bit)) {
+		if ((n->startbit + MAPSIZE) > bit) {
+			if (n->map & (MAPBIT << (bit - n->startbit)))
+				return (TRUE);
+			else
+				return (FALSE);
+		}
+		n = n->next;
+	}
+
+	return (FALSE);
+}
+
+int
+ebitmap_set_bit(ebitmap_t *e, unsigned long bit, int value)
+{
+	ebitmap_node_t *n, *prev, *new;
+
+
+	prev = 0;
+	n = e->node;
+	while (n && n->startbit <= bit) {
+		if ((n->startbit + MAPSIZE) > bit) {
+			if (value) {
+				n->map |= (MAPBIT << (bit - n->startbit));
+			} else {
+				n->map &= ~(MAPBIT << (bit - n->startbit));
+				if (!n->map) {
+					/* drop this node from the bitmap */
+
+					if (!n->next) {
+						/*
+						 * this was the highest map
+						 * within the bitmap
+						 */
+						if (prev)
+							e->highbit =
+							    prev->startbit +
+							    MAPSIZE;
+						else
+							e->highbit = 0;
+					}
+					if (prev)
+						prev->next = n->next;
+					else
+						e->node = n->next;
+
+					SS_FREE(n, sizeof (ebitmap_node_t));
+				}
+			}
+			return (TRUE);
+		}
+		prev = n;
+		n = n->next;
+	}
+
+	if (!value)
+		return (TRUE);
+
+	new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP(sizeof (ebitmap_node_t));
+	if (!new)
+		return (FALSE);
+	(void) memset(new, 0, sizeof (ebitmap_node_t));
+
+	new->startbit = bit & ~(MAPSIZE - 1);
+	new->map = (MAPBIT << (bit - new->startbit));
+
+	if (!n)
+		/* this node will be the highest map within the bitmap */
+		e->highbit = new->startbit + MAPSIZE;
+
+	if (prev) {
+		new->next = prev->next;
+		prev->next = new;
+	} else {
+		new->next = e->node;
+		e->node = new;
+	}
+
+	return (TRUE);
+}
+
+void
+ebitmap_destroy(ebitmap_t *e)
+{
+	ebitmap_node_t *n, *temp;
+
+	if (!e)
+		return;
+
+	n = e->node;
+	while (n) {
+		temp = n;
+		n = n->next;
+		SS_FREE(temp, sizeof (ebitmap_node_t));
+	}
+
+	e->highbit = 0;
+	e->node = 0;
+}
+
+int
+ebitmap_read(ebitmap_t *e, void *fp)
+{
+	ebitmap_node_t *n, *l;
+	uint32_t buf[3], mapsize, count, i;
+	uint64_t map;
+	size_t items;
+
+	ebitmap_init(e);
+
+	items = next_entry(buf, sizeof (uint32_t), 3, fp);
+	if (items != 3)
+		return (FALSE);
+	mapsize = SS_LE32_TO_CPU(buf[0]);
+	e->highbit = SS_LE32_TO_CPU(buf[1]);
+	count = SS_LE32_TO_CPU(buf[2]);
+
+	if (mapsize != MAPSIZE) {
+		(void) printf("security: ebitmap: map size %u does not match "
+		    "my size %u (high bit was %u)\n", mapsize,
+		    (uint32_t)MAPSIZE, e->highbit);
+		return (FALSE);
+	}
+	if (!e->highbit) {
+		e->node = NULL;
+		return (TRUE);
+	}
+	if (e->highbit & (MAPSIZE - 1)) {
+		(void) printf("security: ebitmap: high bit (%u) is not "
+		    "a multiple of the map size (%u)\n",
+		    e->highbit, (uint32_t)MAPSIZE);
+		goto bad;
+	}
+	l = NULL;
+	for (i = 0; i < count; i++) {
+		items = next_entry(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1) {
+			(void) printf("security: ebitmap: truncated map\n");
+			goto bad;
+		}
+		n = (ebitmap_node_t *) SS_ALLOC_NOSLEEP(
+		    sizeof (ebitmap_node_t));
+		if (!n) {
+			(void) printf("security: ebitmap: out of memory\n");
+			goto bad;
+		}
+		(void) memset(n, 0, sizeof (ebitmap_node_t));
+
+		n->startbit = SS_LE32_TO_CPU(buf[0]);
+
+		if (n->startbit & (MAPSIZE - 1)) {
+			(void) printf("security: ebitmap start bit (%u) is "
+			    "not a multiple of the map size (%u)\n",
+			    n->startbit, (uint32_t)MAPSIZE);
+			goto bad_free;
+		}
+		if (n->startbit > (e->highbit - MAPSIZE)) {
+			(void) printf("security: ebitmap start bit (%u) is "
+			    "beyond the end of the bitmap (%u)\n",
+			    n->startbit, (uint32_t)(e->highbit - MAPSIZE));
+			goto bad_free;
+		}
+		items = next_entry(&map, sizeof (uint64_t), 1, fp);
+		if (items != 1) {
+			(void) printf("security: ebitmap: truncated map\n");
+			goto bad_free;
+		}
+		n->map = SS_LE64_TO_CPU(map);
+
+		if (!n->map) {
+			(void) printf("security: ebitmap: null map in ebitmap "
+			    "(startbit %d)\n",
+			    n->startbit);
+			goto bad_free;
+		}
+		if (l) {
+			if (n->startbit <= l->startbit) {
+				(void) printf("security: ebitmap: start bit "
+				    "%d comes after start bit %d\n",
+				    n->startbit, l->startbit);
+				goto bad_free;
+			}
+			l->next = n;
+		} else
+			e->node = n;
+
+		l = n;
+	}
+
+	return (TRUE);
+
+bad_free:
+	SS_FREE(n, sizeof (ebitmap_node_t));
+bad:
+	ebitmap_destroy(e);
+	return (FALSE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/ebitmap.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,92 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * An extensible bitmap is a bitmap that supports an
+ * arbitrary number of bits.  Extensible bitmaps are
+ * used to represent sets of values, such as types,
+ * roles, categories, and classes.
+ *
+ * Each extensible bitmap is implemented as a linked
+ * list of bitmap nodes, where each bitmap node has
+ * an explicitly specified starting bit position within
+ * the total bitmap.
+ */
+
+#ifndef _EBITMAP_H
+#define	_EBITMAP_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/systm.h>
+#else
+#include <inttypes.h>
+#include <string.h>
+#endif /* defined(_KERNEL) */
+
+#define	MAPTYPE uint64_t		/* portion of bitmap in each node */
+#define	MAPSIZE (sizeof (MAPTYPE) * 8)	/* number of bits in node bitmap */
+#define	MAPBIT  1ULL			/* a bit in the node bitmap */
+
+typedef struct ebitmap_node {
+	uint32_t startbit;	/* starting position in the total bitmap */
+	MAPTYPE map;		/* this node's portion of the bitmap */
+	struct ebitmap_node *next;
+} ebitmap_node_t;
+
+typedef struct ebitmap {
+	ebitmap_node_t *node;	/* first node in the bitmap */
+	uint32_t highbit;	/* highest position in the total bitmap */
+} ebitmap_t;
+
+
+#define	ebitmap_length(e) ((e)->highbit)
+#define	ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
+
+#define	ebitmap_init(e) (void) memset(e, 0, sizeof (ebitmap_t))
+
+/*
+ * All of the non-void functions return TRUE or FALSE.
+ * Contrary to typical usage, nonzero (TRUE) is returned
+ * on success and zero (FALSE) is returned on failure.
+ * These functions should be changed to use more conventional
+ * return codes.  TBD.
+ */
+#define	FALSE	0
+#define	TRUE	1
+
+int ebitmap_cmp(ebitmap_t *e1, ebitmap_t *e2);
+int ebitmap_or(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
+int ebitmap_cpy(ebitmap_t *dst, ebitmap_t *src);
+int ebitmap_contains(ebitmap_t *e1, ebitmap_t *e2);
+int ebitmap_get_bit(ebitmap_t *e, unsigned long bit);
+int ebitmap_set_bit(ebitmap_t *e, unsigned long bit, int value);
+void ebitmap_destroy(ebitmap_t *e);
+int ebitmap_read(ebitmap_t *e, void *fp);
+
+#endif	/* _EBITMAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/hashtab.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,348 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the hash table type.
+ */
+
+
+#if defined(_KERNEL)
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/systm.h>
+#else
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "hashtab.h"
+
+hashtab_t
+hashtab_create(unsigned int (*hash_value) (hashtab_t h, hashtab_key_t key),
+    int (*keycmp) (hashtab_t h, hashtab_key_t key1, hashtab_key_t key2),
+    unsigned int size)
+{
+	hashtab_t p;
+	int i;
+
+
+	p = (hashtab_t) SS_ALLOC_SLEEP(sizeof (hashtab_val_t));
+	if (p == NULL)
+		return (p);
+
+	(void) memset(p, 0, sizeof (hashtab_val_t));
+	p->size = size;
+	p->nel = 0;
+	p->hash_value = hash_value;
+	p->keycmp = keycmp;
+	p->htable =
+	    (hashtab_ptr_t *) SS_ALLOC_SLEEP(sizeof (hashtab_ptr_t) * size);
+	if (p->htable == NULL) {
+		SS_FREE(p, sizeof (hashtab_val_t));
+		return (NULL);
+	}
+	for (i = 0; i < size; i++)
+		p->htable[i] = (hashtab_ptr_t) NULL;
+
+	return (p);
+}
+
+int
+hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
+{
+	int hvalue;
+	hashtab_ptr_t prev, cur, newnode;
+
+
+	if (!h)
+		return (HASHTAB_OVERFLOW);
+
+	hvalue = h->hash_value(h, key);
+	prev = NULL;
+	cur = h->htable[hvalue];
+	while (cur && h->keycmp(h, key, cur->key) > 0) {
+		prev = cur;
+		cur = cur->next;
+	}
+
+	if (cur && (h->keycmp(h, key, cur->key) == 0))
+		return (HASHTAB_PRESENT);
+
+	newnode = (hashtab_ptr_t) SS_ALLOC_SLEEP(sizeof (hashtab_node_t));
+	if (newnode == NULL)
+		return (HASHTAB_OVERFLOW);
+	(void) memset(newnode, 0, sizeof (struct hashtab_node));
+	newnode->key = key;
+	newnode->datum = datum;
+	if (prev) {
+		newnode->next = prev->next;
+		prev->next = newnode;
+	} else {
+		newnode->next = h->htable[hvalue];
+		h->htable[hvalue] = newnode;
+	}
+
+	h->nel++;
+	return (HASHTAB_SUCCESS);
+}
+
+int
+hashtab_remove(hashtab_t h, hashtab_key_t key,
+    void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args),
+    void *args)
+{
+	int hvalue;
+	hashtab_ptr_t cur, last;
+
+
+	if (!h)
+		return (HASHTAB_MISSING);
+
+	hvalue = h->hash_value(h, key);
+	last = NULL;
+	cur = h->htable[hvalue];
+	while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
+		last = cur;
+		cur = cur->next;
+	}
+
+	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
+		return (HASHTAB_MISSING);
+
+	if (last == NULL)
+		h->htable[hvalue] = cur->next;
+	else
+		last->next = cur->next;
+
+	if (destroy)
+		destroy(cur->key, cur->datum, args);
+	SS_FREE(cur, sizeof (struct hashtab_node));
+	h->nel--;
+	return (HASHTAB_SUCCESS);
+}
+
+int
+hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum,
+    void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args),
+    void *args)
+{
+	int hvalue;
+	hashtab_ptr_t prev, cur, newnode;
+
+
+	if (!h)
+		return (HASHTAB_OVERFLOW);
+
+	hvalue = h->hash_value(h, key);
+	prev = NULL;
+	cur = h->htable[hvalue];
+	while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
+		prev = cur;
+		cur = cur->next;
+	}
+
+	if (cur && (h->keycmp(h, key, cur->key) == 0)) {
+		if (destroy)
+			destroy(cur->key, cur->datum, args);
+		cur->key = key;
+		cur->datum = datum;
+	} else {
+		newnode =
+		    (hashtab_ptr_t) SS_ALLOC_SLEEP(sizeof (hashtab_node_t));
+		if (newnode == NULL)
+			return (HASHTAB_OVERFLOW);
+		(void) memset(newnode, 0, sizeof (struct hashtab_node));
+		newnode->key = key;
+		newnode->datum = datum;
+		if (prev) {
+			newnode->next = prev->next;
+			prev->next = newnode;
+		} else {
+			newnode->next = h->htable[hvalue];
+			h->htable[hvalue] = newnode;
+		}
+	}
+
+	return (HASHTAB_SUCCESS);
+}
+
+hashtab_datum_t
+hashtab_search(hashtab_t h, hashtab_key_t key)
+{
+	int hvalue;
+	hashtab_ptr_t cur;
+
+
+	if (!h)
+		return (NULL);
+
+	hvalue = h->hash_value(h, key);
+	cur = h->htable[hvalue];
+	while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
+		cur = cur->next;
+
+	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
+		return (NULL);
+
+	return (cur->datum);
+}
+
+void
+hashtab_destroy(hashtab_t h)
+{
+	int i;
+	hashtab_ptr_t cur, temp;
+
+
+	if (!h)
+		return;
+
+	for (i = 0; i < h->size; i++) {
+		cur = h->htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur->next;
+			SS_FREE(temp, sizeof (hashtab_node_t));
+		}
+		h->htable[i] = NULL;
+	}
+
+	SS_FREE(h->htable, sizeof (hashtab_ptr_t) * h->size);
+	h->htable = NULL;
+
+	SS_FREE(h, sizeof (hashtab_val_t));
+}
+
+int
+hashtab_map(
+	hashtab_t h,
+	int (*apply) (
+		hashtab_key_t k,
+		hashtab_datum_t d,
+		void *args),
+	void *args)
+{
+	int i, ret;
+	hashtab_ptr_t cur;
+
+
+	if (!h)
+		return (HASHTAB_SUCCESS);
+
+	for (i = 0; i < h->size; i++) {
+		cur = h->htable[i];
+		while (cur != NULL) {
+			ret = apply(cur->key, cur->datum, args);
+			if (ret)
+				return (ret);
+			cur = cur->next;
+		}
+	}
+	return (HASHTAB_SUCCESS);
+}
+
+void
+hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k,
+    hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k,
+    hashtab_datum_t d, void *args), void *args)
+{
+	int i, ret;
+	hashtab_ptr_t last, cur, temp;
+
+
+	if (!h)
+		return;
+
+	for (i = 0; i < h->size; i++) {
+		last = NULL;
+		cur = h->htable[i];
+		while (cur != NULL) {
+			ret = apply(cur->key, cur->datum, args);
+			if (ret) {
+				if (last) {
+					last->next = cur->next;
+				} else {
+					h->htable[i] = cur->next;
+				}
+
+				temp = cur;
+				cur = cur->next;
+				if (destroy)
+					destroy(temp->key, temp->datum, args);
+				SS_FREE(temp, sizeof (hashtab_node_t));
+				h->nel--;
+			} else {
+				last = cur;
+				cur = cur->next;
+			}
+		}
+	}
+}
+
+void
+hashtab_hash_eval(hashtab_t h, char *tag)
+{
+	int i, chain_len, slots_used, max_chain_len;
+	hashtab_ptr_t cur;
+
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i < h->size; i++) {
+		cur = h->htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur->next;
+			}
+
+			if (chain_len > max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	(void) printf("%s:  %d entries and %d/%d buckets used, longest "
+		"chain length %d\n",
+		tag,
+		h->nel,
+		slots_used,
+		h->size,
+		max_chain_len);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/hashtab.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,166 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A hash table (hashtab) maintains associations between
+ * key values and datum values.  The type of the key values
+ * and the type of the datum values is arbitrary.  The
+ * functions for hash computation and key comparison are
+ * provided by the creator of the table.
+ */
+
+#ifndef _HASHTAB_H
+#define	_HASHTAB_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+typedef char *hashtab_key_t;	/* generic key type */
+typedef void *hashtab_datum_t;	/* generic datum type */
+
+typedef struct hashtab_node *hashtab_ptr_t;
+
+typedef struct hashtab_node {
+	hashtab_key_t	key;
+	hashtab_datum_t	datum;
+	hashtab_ptr_t	next;
+} hashtab_node_t;
+
+typedef struct hashtab_val {
+	hashtab_ptr_t *htable;	/* hash table */
+	unsigned int size;	/* number of slots in hash table */
+	uint32_t nel;		/* number of elements in hash table */
+	unsigned int (*hash_value) (
+		struct hashtab_val *h,
+		hashtab_key_t key); /* hash function */
+	int (*keycmp) (
+		struct hashtab_val *h,
+		hashtab_key_t key1,
+		hashtab_key_t key2); /* key comparison function */
+} hashtab_val_t;
+
+
+typedef hashtab_val_t *hashtab_t;
+
+/* Define status codes for hash table functions */
+#define	HASHTAB_SUCCESS		0
+#define	HASHTAB_OVERFLOW	ENOMEM
+#define	HASHTAB_PRESENT		EEXIST
+#define	HASHTAB_MISSING		ENOENT
+
+/*
+ * Creates a new hash table with the specified characteristics.
+ *
+ * Returns NULL if insufficent space is available or
+ * the new hash table otherwise.
+ */
+hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
+    hashtab_key_t key), int (*keycmp) (hashtab_t h, hashtab_key_t key1,
+    hashtab_key_t key2), unsigned int size);
+
+/*
+ * Inserts the specified (key, datum) pair into the specified hash table.
+ *
+ * Returns HASHTAB_OVERFLOW if insufficient space is available or
+ * HASHTAB_PRESENT  if there is already an entry with the same key or
+ * HASHTAB_SUCCESS otherwise.
+ */
+int hashtab_insert(hashtab_t h, hashtab_key_t k, hashtab_datum_t d);
+
+/*
+ * Removes the entry with the specified key from the hash table.
+ * Applies the specified destroy function to (key,datum,args) for
+ * the entry.
+ *
+ * Returns HASHTAB_MISSING if no entry has the specified key or
+ * HASHTAB_SUCCESS otherwise.
+ */
+int hashtab_remove(
+	hashtab_t h,
+	hashtab_key_t k,
+	void (*destroy) (hashtab_key_t k,
+		hashtab_datum_t d,
+		void *args),
+	void *args);
+
+/*
+ * Insert or replace the specified (key, datum) pair in the specified
+ * hash table.  If an entry for the specified key already exists,
+ * then the specified destroy function is applied to (key,datum,args)
+ * for the entry prior to replacing the entry's contents.
+ *
+ * Returns HASHTAB_OVERFLOW if insufficient space is available or
+ * HASHTAB_SUCCESS otherwise.
+ */
+int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d,
+    void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args),
+    void *args);
+
+/*
+ * Searches for the entry with the specified key in the hash table.
+ *
+ * Returns NULL if no entry has the specified key or
+ * the datum of the entry otherwise.
+ */
+hashtab_datum_t hashtab_search(hashtab_t h, hashtab_key_t k);
+
+/*
+ * Destroys the specified hash table.
+ */
+void hashtab_destroy(hashtab_t h);
+
+/*
+ * Applies the specified apply function to (key,datum,args)
+ * for each entry in the specified hash table.
+ *
+ * The order in which the function is applied to the entries
+ * is dependent upon the internal structure of the hash table.
+ *
+ * If apply returns a non-zero status, then hashtab_map will cease
+ * iterating through the hash table and will propagate the error
+ * return to its caller.
+ */
+int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d,
+    void *args), void *args);
+
+/*
+ * Same as hashtab_map, except that if apply returns a non-zero status,
+ * then the (key,datum) pair will be removed from the hashtab and the
+ * destroy function will be applied to (key,datum,args).
+ */
+void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k,
+    hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k,
+    hashtab_datum_t d, void *args), void *args);
+
+void hashtab_hash_eval(hashtab_t h, char *tag);
+
+
+#endif /* _HASHTAB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/mls.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,859 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the multi-level security (MLS) policy.
+ */
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#include <strings.h>
+#endif /* defined(_KERNEL) */
+
+#include <sys/types.h>
+#include "ss_impl.h"
+#include "mls.h"
+#include "policydb.h"
+#include "services.h"
+
+/*
+ * Remove any permissions from `allowed' that are
+ * denied by the MLS policy.
+ */
+void
+mls_compute_av(context_struct_t *scontext, context_struct_t *tcontext,
+    class_datum_t *tclass, access_vector_t *allowed)
+{
+	unsigned int rel[2];
+	int l;
+
+	for (l = 0; l < 2; l++)
+		rel[l] = mls_level_relation(scontext->range.level[l],
+					    tcontext->range.level[l]);
+
+	if (rel[1] != MLS_RELATION_EQ) {
+		if (rel[1] != MLS_RELATION_DOM &&
+		    !ebitmap_get_bit(&policydb.trustedreaders,
+			scontext->type - 1) &&
+		    !ebitmap_get_bit(&policydb.trustedobjects,
+			tcontext->type - 1)) {
+			/* read(s,t) = (s.high >= t.high) = False */
+			*allowed = (*allowed) & ~(tclass->mlsperms.read);
+		}
+		if (rel[1] != MLS_RELATION_DOMBY &&
+		    !ebitmap_get_bit(&policydb.trustedreaders,
+			tcontext->type - 1) &&
+		    !ebitmap_get_bit(&policydb.trustedobjects,
+			scontext->type - 1)) {
+			/* readby(s,t) = read(t,s) = False */
+			*allowed = (*allowed) & ~(tclass->mlsperms.readby);
+		}
+	}
+	if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
+	    ((!mls_level_eq(tcontext->range.level[0],
+			    tcontext->range.level[1])) &&
+	    (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
+	    !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
+	    !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
+		/*
+		 * write(s,t) = ((s.low <= t.low = t.high) or (s.low
+		 * <= t.low <= t.high <= s.high)) = False
+		 */
+		*allowed = (*allowed) & ~(tclass->mlsperms.write);
+	}
+
+	if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
+	    ((!mls_level_eq(scontext->range.level[0],
+			    scontext->range.level[1])) &&
+	    (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
+	    !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
+	    !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
+		/* writeby(s,t) = write(t,s) = False */
+		*allowed = (*allowed) & ~(tclass->mlsperms.writeby);
+	}
+}
+
+/*
+ * Return the length in bytes for the MLS fields of the
+ * security context string representation of `context'.
+ */
+int
+mls_compute_context_len(context_struct_t *context)
+{
+	int categories;
+	int i;
+	int l;
+	int len;
+
+	len = 0;
+
+	/* Scan through sensitivities */
+	for (l = 0; l < 2; l++) {
+		/* Add sensitivity size */
+		len += strlen(
+		    policydb.p_sens_val_to_name[context->range.level[l].sens
+		    - 1]);
+
+		/* Scan through categories */
+		for (i = 1; i <= ebitmap_length(&context->range.level[l].cat);
+		    i++) {
+
+			/* Add category size */
+			if (ebitmap_get_bit(&context->range.level[l].cat,
+			    i - 1)) {
+
+				/*
+				 * This is either the first category or
+				 * the next, so adjust for the separators
+				 * ":" or ",".
+				 */
+				len++;
+
+				len +=
+				    strlen(policydb.p_cat_val_to_name[i - 1]);
+			}
+		}
+		if (mls_level_relation(context->range.level[0],
+		    context->range.level[1]) != MLS_RELATION_EQ) {
+			/*
+			 * If the first sensitivity was written and there
+			 * is a range, then add the separator.
+			 */
+			if (l == 0) {
+				/* Add range separator "-" size */
+				len++;
+			}
+		} else {
+			break;
+		}
+	}
+
+	return (len);
+}
+
+/*
+ * Write the security context string representation of
+ * the MLS fields of `context' into the string `*scontext'.
+ * Update `*scontext' to point to the end of the MLS fields.
+ *
+ * Format: sensitivity[:category,...][-sensitivity[:category,...]]
+ */
+int
+mls_sid_to_context(context_struct_t *context, char *scontextp)
+{
+	int categories;
+	int i;
+	int l;
+
+	/* Scan through sensitivities */
+	for (l = 0; l < 2; l++) {
+		/* Add sensitivity value */
+		(void) strcpy(scontextp,
+		    policydb.p_sens_val_to_name[context->range.level[l].sens
+		    - 1]);
+		scontextp += strlen(
+		    policydb.p_sens_val_to_name[context->range.level[l].sens
+		    - 1]);
+		/* Scan through categories */
+		for (i = 1, categories = 0;
+		    i <= ebitmap_length(&context->range.level[l].cat); i++) {
+
+			/* Add category value */
+			if (ebitmap_get_bit(&context->range.level[l].cat,
+			    i - 1)) {
+
+				/* First category, add separator ":" */
+				if (categories == 0) {
+					*scontextp = ':';
+					scontextp++;
+				} else {
+					/* Otherwise add add separator "," */
+					*scontextp = ',';
+					scontextp++;
+				}
+
+				(void) strcpy(scontextp,
+				    policydb.p_cat_val_to_name[i - 1]);
+
+				scontextp += strlen(
+					policydb.p_cat_val_to_name[i - 1]);
+
+				categories++;
+			}
+		}
+
+		if (mls_level_relation(context->range.level[0],
+		    context->range.level[1]) != MLS_RELATION_EQ) {
+			/*
+			 * If the first sensitivity was written and there
+			 * is a range, then add the separator.
+			 */
+			if (l == 0) {
+				/* Add range separator */
+				*scontextp = '-';
+				scontextp++;
+			}
+		} else {
+			break;
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Return TRUE if the MLS fields in the security context
+ * structure `c' are valid.  Return FALSE otherwise.
+ */
+int
+mls_context_isvalid(policydb_t *p, context_struct_t *c)
+{
+	unsigned int		relation;
+	level_datum_t		*levdatum;
+	user_datum_t		*usrdatum;
+	mls_range_list_t	*rnode;
+	int			i;
+	int			l;
+
+	/*
+	 * MLS range validity checks: high must dominate low, low level must
+	 * be valid (category set <-> sensitivity check), and high level must
+	 * be valid (category set <-> sensitivity check)
+	 */
+	relation = mls_level_relation(c->range.level[1], c->range.level[0]);
+	if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
+		/* High does not dominate low. */
+		return (FALSE);
+
+	for (l = 0; l < 2; l++) {
+		if (!c->range.level[l].sens || c->range.level[l].sens >
+		    p->p_levels.nprim)
+			return (FALSE);
+		levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
+		    p->p_sens_val_to_name[c->range.level[l].sens - 1]);
+		if (!levdatum)
+			return (FALSE);
+
+		for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
+			if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
+				if (i > p->p_cats.nprim)
+					return (FALSE);
+				if (!ebitmap_get_bit(&levdatum->level->cat,
+				    i - 1)) {
+					/*
+					 * Category may not be associated with
+					 * sensitivity in low level.
+					 */
+					return (FALSE);
+				}
+			}
+		}
+	}
+
+	if (c->role == OBJECT_R_VAL)
+		return (TRUE);
+
+	/*
+	 * User must be authorized for the MLS range.
+	 */
+	if (!c->user || c->user > p->p_users.nprim)
+		return (FALSE);
+	usrdatum = p->user_val_to_struct[c->user - 1];
+	for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
+		if (mls_range_contains(rnode->range, c->range))
+			break;
+	}
+	if (!rnode)
+		/* user may not be associated with range */
+		return (FALSE);
+
+	return (TRUE);
+}
+
+/*
+ * Set the MLS fields in the security context structure
+ * `context' based on the string representation in
+ * the string `*scontext'.  Update `*scontext' to
+ * point to the end of the string representation of
+ * the MLS fields.
+ *
+ * This function modifies the string in place, inserting
+ * NULL characters to terminate the MLS fields.
+ */
+int
+mls_context_to_sid(char oldc, char **scontext, context_struct_t *context)
+{
+
+	char		delim;
+	char		*scontextp, *p;
+	level_datum_t	*levdatum;
+	cat_datum_t	*catdatum;
+	int		l;
+
+	if (!oldc) {
+		/*
+		 * No MLS component to the security context.  Try
+		 * to use a default 'unclassified' value.
+		 */
+		levdatum =
+		    (level_datum_t *) hashtab_search(policydb.p_levels.table,
+		    (hashtab_key_t) "unclassified");
+
+		if (!levdatum)
+			return (EINVAL);
+		context->range.level[0].sens = levdatum->level->sens;
+		context->range.level[1].sens = context->range.level[0].sens;
+		return (0);
+	}
+
+	/* Extract low sensitivity. */
+	scontextp = p = *scontext;
+	while (*p && *p != ':' && *p != '-')
+		p++;
+
+	delim = *p;
+	if (delim != 0)
+		*p++ = 0;
+
+	for (l = 0; l < 2; l++) {
+		levdatum =
+		    (level_datum_t *) hashtab_search(policydb.p_levels.table,
+			(hashtab_key_t) scontextp);
+
+		if (!levdatum)
+			return (EINVAL);
+
+		context->range.level[l].sens = levdatum->level->sens;
+
+		if (delim == ':') {
+			/* Extract low category set. */
+			for (;;) {
+				scontextp = p;
+				while (*p && *p != ',' && *p != '-')
+					p++;
+				delim = *p;
+				if (delim != 0)
+					*p++ = 0;
+
+				catdatum =
+				    (cat_datum_t *) hashtab_search(
+				    policydb.p_cats.table,
+				    (hashtab_key_t) scontextp);
+
+				if (!catdatum)
+					return (EINVAL);
+
+				if (!ebitmap_set_bit(
+				    &context->range.level[l].cat,
+				    catdatum->value - 1, TRUE))
+					return (ENOMEM);
+				if (delim != ',')
+					break;
+			}
+		}
+		if (delim == '-') {
+			/* Extract high sensitivity. */
+			scontextp = p;
+			while (*p && *p != ':')
+				p++;
+
+			delim = *p;
+			if (delim != 0)
+				*p++ = 0;
+		} else
+			break;
+	}
+
+	if (l == 0) {
+		context->range.level[1].sens = context->range.level[0].sens;
+		ebitmap_cpy(&context->range.level[1].cat,
+		    &context->range.level[0].cat);
+	}
+	*scontext = ++p;
+	return (0);
+}
+
+/*
+ * Copies the MLS range from `src' into `dst'.
+ */
+static inline int
+mls_copy_context(context_struct_t *dst, context_struct_t *src)
+{
+	int l;
+
+	/* Copy the MLS range from the source context */
+	for (l = 0; l < 2; l++) {
+		dst->range.level[l].sens = src->range.level[l].sens;
+		if (!ebitmap_cpy(&dst->range.level[l].cat,
+		    &src->range.level[l].cat))
+			return (ENOMEM);
+	}
+
+	return (0);
+}
+
+/*
+ * Convert the MLS fields in the security context
+ * structure `c' from the values specified in the
+ * policy `oldp' to the values specified in the policy `newp'.
+ */
+int
+mls_convert_context(policydb_t *oldp, policydb_t *newp, context_struct_t *c)
+{
+	level_datum_t	*levdatum;
+	cat_datum_t	*catdatum;
+	ebitmap_t	bitmap;
+	int		l;
+	int		i;
+
+	for (l = 0; l < 2; l++) {
+		levdatum = (level_datum_t *) hashtab_search(
+						    newp->p_levels.table,
+		    oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
+
+		if (!levdatum)
+			return (EINVAL);
+		c->range.level[l].sens = levdatum->level->sens;
+
+		ebitmap_init(&bitmap);
+		for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
+			if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
+				catdatum =
+				    (cat_datum_t *) hashtab_search(
+				    newp->p_cats.table,
+				    oldp->p_cat_val_to_name[i - 1]);
+				if (!catdatum)
+					return (EINVAL);
+				if (!ebitmap_set_bit(
+				    &bitmap, catdatum->value - 1, TRUE))
+					return (ENOMEM);
+			}
+		}
+		ebitmap_destroy(&c->range.level[l].cat);
+		c->range.level[l].cat = bitmap;
+	}
+
+	return (0);
+}
+
+/*ARGSUSED*/
+int
+mls_compute_sid(context_struct_t *scontext, context_struct_t *tcontext,
+    security_class_t tclass, uint32_t specified, context_struct_t *newcontext)
+{
+	switch (specified) {
+	case AVTAB_TRANSITION:
+	case AVTAB_CHANGE:
+		/* Use the process MLS attributes. */
+		return (mls_copy_context(newcontext, scontext));
+	case AVTAB_MEMBER:
+		/*
+		 * Only polyinstantiate the MLS attributes if
+		 * the type is being polyinstantiated
+		 */
+		if (newcontext->type != tcontext->type) {
+			/* Use the process MLS attributes. */
+			return (mls_copy_context(newcontext, scontext));
+		} else {
+			/* Use the related object MLS attributes. */
+			return (mls_copy_context(newcontext, tcontext));
+		}
+	default:
+		break;
+	}
+	return (EINVAL);
+}
+
+void
+mls_user_destroy(user_datum_t *usrdatum)
+{
+	mls_range_list_t *rnode, *rtmp;
+
+	rnode = usrdatum->ranges;
+
+	while (rnode) {
+		rtmp = rnode;
+		rnode = rnode->next;
+		ebitmap_destroy(&rtmp->range.level[0].cat);
+		ebitmap_destroy(&rtmp->range.level[1].cat);
+		SS_FREE(rtmp, sizeof (mls_range_list_t));
+	}
+}
+
+int
+mls_read_perm(perm_datum_t *perdatum, void *fp)
+{
+	uint32_t buf[1];
+	int items;
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+	perdatum->base_perms = SS_LE32_TO_CPU(buf[0]);
+	return (0);
+}
+
+/*
+ * Read a MLS level structure from a policydb binary
+ * representation file.
+ */
+mls_level_t
+*mls_read_level(void *fp)
+{
+	mls_level_t *l;
+	uint32_t sens;
+	int items;
+
+	l = SS_ALLOC_NOSLEEP(sizeof (mls_level_t));
+	if (!l) {
+		(void) printf("security: mls: out of memory\n");
+		return (NULL);
+	}
+	(void) memset(l, 0, sizeof (mls_level_t));
+
+	items = next_entry(&sens, sizeof (uint32_t), 1, fp);
+	if (items != 1) {
+		(void) printf("security: mls: truncated level\n");
+		goto bad;
+	}
+	l->sens = cpu_to_le32(sens);
+
+	if (!ebitmap_read(&l->cat, fp)) {
+		(void) printf("security: mls:  error reading level "
+		    "categories\n");
+		goto bad;
+	}
+	return (l);
+
+bad:
+	SS_FREE(l, sizeof (mls_level_t));
+	return (NULL);
+}
+
+
+/*
+ * Read a MLS range structure from a policydb binary
+ * representation file.
+ */
+
+static int
+mls_read_range_helper(mls_range_t *r, void *fp)
+{
+	uint32_t buf[3];
+	int items, items2;
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		return (-1);
+
+	items2 = SS_LE32_TO_CPU(buf[0]);
+	if (items2 > (sizeof (buf) / sizeof (uint32_t))) {
+		(void) printf("security: mls:  range too large\n");
+		return (-1);
+	}
+	items = next_entry(buf, sizeof (uint32_t), items2, fp);
+	if (items != items2) {
+		(void) printf("security: mls:  truncated range\n");
+		return (-1);
+	}
+	r->level[0].sens = SS_LE32_TO_CPU(buf[0]);
+	if (items > 1) {
+		r->level[1].sens = SS_LE32_TO_CPU(buf[1]);
+	} else {
+		r->level[1].sens = r->level[0].sens;
+	}
+
+	if (!ebitmap_read(&r->level[0].cat, fp)) {
+		(void) printf("security: mls:  error reading low categories\n");
+		return (-1);
+	}
+	if (items > 1) {
+		if (!ebitmap_read(&r->level[1].cat, fp)) {
+			(void) printf("security: mls:  error reading high "
+			    "categories\n");
+			goto bad_high;
+		}
+	} else {
+		if (!ebitmap_cpy(&r->level[1].cat, &r->level[0].cat)) {
+			(void) printf("security: mls:  out of memory\n");
+			goto bad_high;
+		}
+	}
+
+	return (0);
+
+bad_high:
+	ebitmap_destroy(&r->level[0].cat);
+	return (-1);
+}
+
+int
+mls_read_range(context_struct_t *c, void *fp)
+{
+	return (mls_read_range_helper(&c->range, fp));
+}
+
+
+/*
+ * Read a MLS perms structure from a policydb binary
+ * representation file.
+ */
+int
+mls_read_class(class_datum_t *cladatum, void *fp)
+{
+	mls_perms_t * p = &cladatum->mlsperms;
+	uint32_t buf[4];
+	int items;
+
+	items = next_entry(buf, sizeof (uint32_t), 4, fp);
+	if (items != 4) {
+		(void) printf("security: mls:  truncated mls permissions\n");
+		return (-1);
+	}
+	p->read = SS_LE32_TO_CPU(buf[0]);
+	p->readby = SS_LE32_TO_CPU(buf[1]);
+	p->write = SS_LE32_TO_CPU(buf[2]);
+	p->writeby = SS_LE32_TO_CPU(buf[3]);
+	return (0);
+}
+
+int
+mls_read_user(user_datum_t *usrdatum, void *fp)
+{
+	mls_range_list_t	*r, *l;
+	uint32_t		nel, i;
+	uint32_t		buf[1];
+	int			items;
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		goto bad;
+	nel = SS_LE32_TO_CPU(buf[0]);
+	l = NULL;
+	for (i = 0; i < nel; i++) {
+		r = SS_ALLOC_NOSLEEP(sizeof (mls_range_list_t));
+		if (!r)
+			goto bad;
+		(void) memset(r, 0, sizeof (mls_range_list_t));
+
+		if (mls_read_range_helper(&r->range, fp))
+			goto bad;
+
+		if (l)
+			l->next = r;
+		else
+			usrdatum->ranges = r;
+		l = r;
+	}
+	return (0);
+bad:
+	return (-1);
+}
+
+int
+mls_read_nlevels(policydb_t *p, void *fp)
+{
+	uint32_t buf[2];
+	int items;
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1) {
+		return (-1);
+	}
+	p->nlevels = SS_LE32_TO_CPU(buf[0]);
+	return (0);
+}
+
+int
+mls_read_trusted(policydb_t *p, void *fp)
+{
+	if (!ebitmap_read(&p->trustedreaders, fp))
+		return (-1);
+	if (!ebitmap_read(&p->trustedwriters, fp))
+		return (-1);
+	if (!ebitmap_read(&p->trustedobjects, fp))
+		return (-1);
+	return (0);
+}
+
+int
+sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	level_datum_t *levdatum;
+
+
+	levdatum = (level_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	if (!levdatum->isalias)
+		p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *) key;
+
+	return (0);
+}
+
+int
+cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	cat_datum_t *catdatum;
+
+
+	catdatum = (cat_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+
+	if (!catdatum->isalias)
+		p->p_cat_val_to_name[catdatum->value - 1] = (char *) key;
+
+	return (0);
+}
+
+/*ARGSUSED*/
+int
+sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	level_datum_t *levdatum;
+
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	levdatum = (level_datum_t *) datum;
+	if (!levdatum->isalias) {
+		ebitmap_destroy(&levdatum->level->cat);
+		SS_FREE(levdatum->level, sizeof (mls_level_t));
+	}
+	SS_FREE(datum, sizeof (level_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+int
+cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	SS_FREE(datum, sizeof (cat_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+int
+sens_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char		*key = 0;
+	level_datum_t	*levdatum;
+	uint32_t	buf[2], len;
+	int		items;
+
+	levdatum = SS_ALLOC_NOSLEEP(sizeof (level_datum_t));
+	if (!levdatum)
+		return (-1);
+	(void) memset(levdatum, 0, sizeof (level_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 2, fp);
+	if (items != 2)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	levdatum->isalias = SS_LE32_TO_CPU(buf[1]);
+
+	key = SS_ALLOC_NOSLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	levdatum->level = mls_read_level(fp);
+	if (!levdatum->level)
+		goto bad;
+
+	if (hashtab_insert(h, key, levdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	sens_destroy(key, levdatum, NULL);
+	return (-1);
+}
+
+
+/*ARGSUSED*/
+int
+cat_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char		*key = 0;
+	cat_datum_t	*catdatum;
+	uint32_t	buf[3], len;
+	int		items;
+
+	catdatum = SS_ALLOC_NOSLEEP(sizeof (cat_datum_t));
+	if (!catdatum)
+		return (-1);
+	(void) memset(catdatum, 0, sizeof (cat_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 3, fp);
+	if (items != 3)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	catdatum->value = SS_LE32_TO_CPU(buf[1]);
+	catdatum->isalias = SS_LE32_TO_CPU(buf[2]);
+
+	key = SS_ALLOC_NOSLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (hashtab_insert(h, key, catdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	cat_destroy(key, catdatum, NULL);
+	return (-1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/mls.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,126 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Multi-level security (MLS) policy operations.
+ */
+
+#ifndef _MLS_H
+#define	_MLS_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "context.h"
+#include "policydb.h"
+
+#ifdef CONFIG_FLASK_MLS
+
+void mls_compute_av(context_struct_t *scontext, context_struct_t *tcontext,
+    class_datum_t *tclass, access_vector_t *allowed);
+
+int mls_compute_context_len(context_struct_t * context);
+
+int mls_sid_to_context(context_struct_t *context, char *scontext);
+
+int mls_context_isvalid(policydb_t *p, context_struct_t * c);
+
+int mls_context_to_sid(char oldc, char **scontext, context_struct_t *context);
+
+int mls_convert_context(policydb_t *oldp, policydb_t *newp,
+    context_struct_t *context);
+
+int mls_compute_sid(context_struct_t *scontext, context_struct_t *tcontext,
+    security_class_t tclass, uint32_t specified, context_struct_t *newcontext);
+
+int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap);
+int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap);
+int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
+int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
+int sens_read(policydb_t * p, hashtab_t h, void * fp);
+int cat_read(policydb_t * p, hashtab_t h, void * fp);
+
+#define	mls_for_user_ranges(user, usercon) {				\
+	mls_range_list_t *ranges;					\
+	for (ranges = user->ranges; ranges; ranges = ranges->next) {	\
+		usercon.range = ranges->range;
+
+#define	mls_end_user_ranges } }
+
+#define	mls_symtab_names , "levels", "categories"
+#define	mls_symtab_sizes , 16, 16
+#define	mls_index_f , sens_index, cat_index
+#define	mls_destroy_f , sens_destroy, cat_destroy
+#define	mls_read_f , sens_read, cat_read
+#define	mls_write_f , sens_write, cat_write
+#define	mls_policydb_index_others(p) printf(", %d levels", p->nlevels);
+
+#define	mls_set_config(config) config |= POLICYDB_CONFIG_MLS
+
+void mls_user_destroy(user_datum_t *usrdatum);
+int mls_read_range(context_struct_t *c, void * fp);
+int mls_read_perm(perm_datum_t *perdatum, void *fp);
+int mls_read_class(class_datum_t *cladatum,  void * fp);
+int mls_read_user(user_datum_t *usrdatum, void *fp);
+int mls_read_nlevels(policydb_t *p, void *fp);
+int mls_read_trusted(policydb_t *p, void *fp);
+
+#else /* CONFIG_FLASK_MLS */
+
+#define	mls_compute_av(scontext, tcontext, tclass_datum, allowed)
+#define	mls_compute_context_len(context) 0
+#define	mls_sid_to_context(context, scontextp)
+#define	mls_context_isvalid(p, c) TRUE
+#define	mls_context_to_sid(oldc, context_str, context) 0
+#define	mls_convert_context(oldp, newp, c) 0
+#define	mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0
+#define	mls_for_user_ranges(user, usercon)
+#define	mls_end_user_ranges
+#define	mls_symtab_names
+#define	mls_symtab_sizes
+#define	mls_index_f
+#define	mls_destroy_f
+#define	mls_read_f
+#define	mls_write_f
+#define	mls_policydb_index_others(p)
+#define	mls_set_config(config)
+#define	mls_user_destroy(usrdatum)
+#define	mls_read_range(c, fp) 0
+#define	mls_read_perm(p, fp) 0
+#define	mls_read_class(c, fp) 0
+#define	mls_read_user(u, fp) 0
+#define	mls_read_nlevels(p, fp) 0
+#define	mls_read_trusted(p, fp) 0
+
+#endif /* CONFIG_FLASK_MLS */
+
+#endif /* _MLS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/mls_types.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,92 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Type definitions for the multi-level security (MLS) policy.
+ */
+
+#ifndef _MLS_TYPES_H
+#define	_MLS_TYPES_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+#include <sys/fmac/flask_types.h>
+
+typedef struct mls_level {
+	uint32_t sens;	/* sensitivity */
+	ebitmap_t cat;	/* category set */
+} mls_level_t;
+
+typedef struct mls_range {
+	mls_level_t level[2]; /* low == level[0], high == level[1] */
+} mls_range_t;
+
+typedef struct mls_range_list {
+	mls_range_t range;
+	struct mls_range_list *next;
+} mls_range_list_t;
+
+#define	MLS_RELATION_DOM	1 /* source dominates */
+#define	MLS_RELATION_DOMBY	2 /* target dominates */
+#define	MLS_RELATION_EQ		4 /* source and target are equivalent */
+#define	MLS_RELATION_INCOMP	8 /* source and target are incomparable */
+
+#define	mls_level_eq(l1, l2)						\
+	(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat, &(l2).cat))	\
+
+#define	mls_level_relation(l1, l2) (					\
+	(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,		\
+	    &(l2).cat)) ? MLS_RELATION_EQ :				\
+	    (((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat,	\
+	    &(l2).cat)) ? MLS_RELATION_DOM :				\
+	    (((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat,	\
+	    &(l1).cat)) ? MLS_RELATION_DOMBY : MLS_RELATION_INCOMP)
+
+#define	mls_range_contains(r1, r2) \
+	((mls_level_relation((r1).level[0], (r2).level[0]) &		\
+	    (MLS_RELATION_EQ | MLS_RELATION_DOMBY)) &&			\
+	    (mls_level_relation((r1).level[1], (r2).level[1]) &		\
+	    (MLS_RELATION_EQ | MLS_RELATION_DOM)))
+
+/*
+ * Every access vector permission is mapped to a set of MLS base
+ * permissions, based on the flow properties of the corresponding
+ * operation.
+ */
+typedef struct mls_perms {
+	access_vector_t read;		/* permissions that map to `read' */
+	access_vector_t readby;		/* permissions that map to `readby' */
+	access_vector_t write;		/* permissions that map to `write' */
+	access_vector_t writeby;	/* permissions that map to `writeby' */
+} mls_perms_t;
+
+#endif /* _MLS_TYPES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/policydb.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,1366 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the policy database.
+ */
+
+#include <sys/types.h>
+
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/systm.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include "policydb.h"
+#include "mls.h"
+
+#if 0
+static char *symtab_name[SYM_NUM] = {
+	"common prefixes",
+	"classes",
+	"roles",
+	"types",
+	"users"
+	mls_symtab_names
+};
+#endif
+
+static unsigned int symtab_sizes[SYM_NUM] = {
+	2,
+	32,
+	16,
+	512,
+	128
+	mls_symtab_sizes
+};
+
+/*
+ * Initialize the role table.
+ */
+int
+roles_init(policydb_t *p)
+{
+	char *key = 0;
+	role_datum_t *role;
+
+	role = SS_ALLOC_SLEEP(sizeof (role_datum_t));
+	if (!role)
+		return (-1);
+	(void) memset(role, 0, sizeof (role_datum_t));
+	role->value = ++p->p_roles.nprim;
+	if (role->value != OBJECT_R_VAL)
+		return (-1);
+	key = SS_ALLOC_SLEEP(strlen(OBJECT_R)+1);
+	if (!key)
+		return (-1);
+	(void) strcpy(key, OBJECT_R);
+
+	if (hashtab_insert(p->p_roles.table, key, role))
+		return (-1);
+
+	return (0);
+}
+
+/*
+ * Initialize a policy database structure.
+ */
+int
+policydb_init(policydb_t *p)
+{
+	int i;
+
+	(void) memset(p, 0, sizeof (policydb_t));
+
+	for (i = 0; i < SYM_NUM; i++) {
+		if (symtab_init(&p->symtab[i], symtab_sizes[i]))
+			return (-1);
+	}
+
+	if (avtab_init(&p->te_avtab))
+		return (-1);
+
+	if (roles_init(p))
+		return (-1);
+
+	return (0);
+}
+
+/*
+ * The following *_index functions are used to
+ * define the val_to_name and val_to_struct arrays
+ * in a policy database structure.  The val_to_name
+ * arrays are used when converting security context
+ * structures into string representations.  The
+ * val_to_struct arrays are used when the attributes
+ * of a class, role, or user are needed.
+ */
+static int
+common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	common_datum_t *comdatum;
+
+
+	comdatum = (common_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	p->p_common_val_to_name[comdatum->value - 1] = (char *) key;
+
+	return (0);
+}
+
+static int
+class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	class_datum_t *cladatum;
+
+
+	cladatum = (class_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	p->p_class_val_to_name[cladatum->value - 1] = (char *) key;
+	p->class_val_to_struct[cladatum->value - 1] = cladatum;
+
+	return (0);
+}
+
+static int
+role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	role_datum_t *role;
+
+
+	role = (role_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	p->p_role_val_to_name[role->value - 1] = (char *) key;
+	p->role_val_to_struct[role->value - 1] = role;
+
+	return (0);
+}
+
+static int
+type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	type_datum_t *typdatum;
+
+
+	typdatum = (type_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	if (typdatum->primary)
+		p->p_type_val_to_name[typdatum->value - 1] = (char *) key;
+
+	return (0);
+}
+
+static int
+user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
+{
+	policydb_t *p;
+	user_datum_t *usrdatum;
+
+
+	usrdatum = (user_datum_t *) datum;
+	p = (policydb_t *) datap;
+
+	p->p_user_val_to_name[usrdatum->value - 1] = (char *) key;
+	p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
+
+	return (0);
+}
+
+static int
+(*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) =
+{
+	common_index,
+	class_index,
+	role_index,
+	type_index,
+	user_index
+	mls_index_f
+};
+
+/*
+ * Define the common val_to_name array and the class
+ * val_to_name and val_to_struct arrays in a policy
+ * database structure.
+ */
+int
+policydb_index_classes(policydb_t *p)
+{
+	p->p_common_val_to_name = (char **)
+	    SS_ALLOC_SLEEP(p->p_commons.nprim * sizeof (char *));
+	if (!p->p_common_val_to_name)
+		return (-1);
+
+	if (hashtab_map(p->p_commons.table, common_index, p))
+		return (-1);
+
+	p->class_val_to_struct = (class_datum_t **)
+	    SS_ALLOC_SLEEP(p->p_classes.nprim * sizeof (class_datum_t *));
+	if (!p->class_val_to_struct)
+		return (-1);
+
+	p->p_class_val_to_name = (char **)
+	    SS_ALLOC_SLEEP(p->p_classes.nprim * sizeof (char *));
+	if (!p->p_class_val_to_name)
+		return (-1);
+
+	if (hashtab_map(p->p_classes.table, class_index, p))
+		return (-1);
+	return (0);
+}
+
+/*
+ * Define the other val_to_name and val_to_struct arrays
+ * in a policy database structure.
+ */
+int
+policydb_index_others(policydb_t *p)
+{
+	int i;
+
+
+	(void) printf("security:  %d users, %d roles, %d types",
+	    p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim);
+	mls_policydb_index_others(p);
+	(void) printf("\n");
+
+	(void) printf("security:  %d classes, %d rules\n",
+	    p->p_classes.nprim, p->te_avtab.nel);
+
+#if 0
+	avtab_hash_eval(&p->te_avtab, "rules");
+	for (i = 0; i < SYM_NUM; i++)
+		hashtab_hash_eval(p->symtab[i].table, symtab_name[i]);
+#endif
+
+	p->role_val_to_struct = (role_datum_t **)
+	    SS_ALLOC_SLEEP(p->p_roles.nprim * sizeof (role_datum_t *));
+	if (!p->role_val_to_struct)
+		return (-1);
+
+	p->user_val_to_struct = (user_datum_t **)
+	    SS_ALLOC_SLEEP(p->p_users.nprim * sizeof (user_datum_t *));
+	if (!p->user_val_to_struct)
+		return (-1);
+
+	for (i = SYM_ROLES; i < SYM_NUM; i++) {
+		p->sym_val_to_name[i] = (char **)
+		    SS_ALLOC_SLEEP(p->symtab[i].nprim * sizeof (char *));
+		if (!p->sym_val_to_name[i])
+			return (-1);
+		if (hashtab_map(p->symtab[i].table, index_f[i], p))
+			return (-1);
+	}
+
+	return (0);
+}
+
+/*
+ * The following *_destroy functions are used to
+ * free any memory allocated for each kind of
+ * symbol data in the policy database.
+ */
+
+/*ARGSUSED*/
+static int
+perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	SS_FREE(datum, sizeof (perm_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	common_datum_t *comdatum;
+
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	comdatum = (common_datum_t *) datum;
+	(void) hashtab_map(comdatum->permissions.table, perm_destroy, 0);
+	hashtab_destroy(comdatum->permissions.table);
+	SS_FREE(datum, sizeof (common_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	class_datum_t *cladatum;
+	constraint_node_t *constraint, *ctemp;
+	constraint_expr_t *e, *etmp;
+
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	cladatum = (class_datum_t *) datum;
+	(void) hashtab_map(cladatum->permissions.table, perm_destroy, 0);
+	hashtab_destroy(cladatum->permissions.table);
+	constraint = cladatum->constraints;
+	while (constraint) {
+		e = constraint->expr;
+		while (e) {
+			ebitmap_destroy(&e->names);
+			etmp = e;
+			e = e->next;
+			SS_FREE(etmp, sizeof (constraint_expr_t));
+		}
+		ctemp = constraint;
+		constraint = constraint->next;
+		SS_FREE(ctemp, sizeof (constraint_node_t));
+	}
+	if (cladatum->comkey)
+		SS_FREE(cladatum->comkey, strlen(cladatum->comkey) + 1);
+	SS_FREE(datum, sizeof (class_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	role_datum_t *role;
+
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	role = (role_datum_t *) datum;
+	ebitmap_destroy(&role->dominates);
+	ebitmap_destroy(&role->types);
+	SS_FREE(datum, sizeof (role_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	SS_FREE(datum, sizeof (type_datum_t));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	user_datum_t *usrdatum;
+
+	if (key)
+		SS_FREE(key, strlen(key) + 1);
+	usrdatum = (user_datum_t *) datum;
+	ebitmap_destroy(&usrdatum->roles);
+	mls_user_destroy(usrdatum);
+	SS_FREE(datum, sizeof (user_datum_t));
+	return (0);
+}
+
+static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
+    void *datap) =
+{
+	common_destroy,
+	class_destroy,
+	role_destroy,
+	type_destroy,
+	user_destroy
+	mls_destroy_f
+};
+
+/*
+ * Free any memory allocated by a policy database structure.
+ */
+void
+policydb_destroy(policydb_t *p)
+{
+	ocontext_t *c, *ctmp;
+	genfs_t *g, *gtmp;
+	int i;
+
+	for (i = 0; i < SYM_NUM; i++) {
+		(void) hashtab_map(p->symtab[i].table, destroy_f[i], 0);
+		hashtab_destroy(p->symtab[i].table);
+	}
+
+	for (i = 0; i < SYM_NUM; i++) {
+		if (p->sym_val_to_name[i])
+			SS_FREE(p->sym_val_to_name[i],
+				p->symtab[i].nprim * sizeof (char *));
+	}
+
+	if (p->class_val_to_struct)
+		SS_FREE(p->class_val_to_struct,
+			p->p_classes.nprim * sizeof (class_datum_t *));
+	if (p->role_val_to_struct)
+		SS_FREE(p->role_val_to_struct,
+			p->p_roles.nprim * sizeof (role_datum_t *));
+	if (p->user_val_to_struct)
+		SS_FREE(p->user_val_to_struct,
+			p->p_users.nprim * sizeof (user_datum_t *));
+
+	avtab_destroy(&p->te_avtab);
+
+	for (i = 0; i < OCON_NUM; i++) {
+		c = p->ocontexts[i];
+		while (c) {
+			ctmp = c;
+			c = c->next;
+			context_destroy(&ctmp->context[0]);
+			context_destroy(&ctmp->context[1]);
+			if ((i == OCON_ISID || i == OCON_FS ||
+			    i == OCON_NETIF || i == OCON_FSUSE) &&
+			    ctmp->u.name)
+				SS_FREE(ctmp->u.name, strlen(ctmp->u.name) + 1);
+			SS_FREE(ctmp, sizeof (ocontext_t));
+		}
+	}
+
+	g = p->genfs;
+	while (g) {
+		SS_FREE(g->fstype, strlen(g->fstype) + 1);
+		c = g->head;
+		while (c) {
+			ctmp = c;
+			c = c->next;
+			context_destroy(&ctmp->context[0]);
+			SS_FREE(ctmp->u.name, strlen(ctmp->u.name) + 1);
+			SS_FREE(ctmp, sizeof (ocontext_t));
+		}
+		gtmp = g;
+		g = g->next;
+		SS_FREE(gtmp, sizeof (genfs_t));
+	}
+}
+
+
+/*
+ * Load the initial SIDs specified in a policy database
+ * structure into a SID table.
+ */
+int
+policydb_load_isids(policydb_t *p, sidtab_t *s)
+{
+	ocontext_t *head, *c;
+
+	if (sidtab_init(s)) {
+		(void) printf("security:  out of memory on SID table init\n");
+		return (-1);
+	}
+
+	head = p->ocontexts[OCON_ISID];
+	for (c = head; c; c = c->next) {
+		if (!c->context[0].user) {
+			(void) printf("security:  SID %s was never defined.\n",
+			    c->u.name);
+			return (-1);
+		}
+		if (sidtab_insert(s, c->sid[0], &c->context[0])) {
+			(void) printf("security:  unable to load initial "
+			    "SID %s.\n",
+			    c->u.name);
+			return (-1);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Return TRUE if the fields in the security context
+ * structure `c' are valid.  Return FALSE otherwise.
+ */
+int
+policydb_context_isvalid(policydb_t *p, context_struct_t *c)
+{
+	role_datum_t *role;
+	user_datum_t *usrdatum;
+
+
+	/*
+	 * Role must be authorized for the type.
+	 */
+	if (!c->role || c->role > p->p_roles.nprim)
+		return (FALSE);
+
+	if (c->role != OBJECT_R_VAL) {
+		role = p->role_val_to_struct[c->role - 1];
+		if (!ebitmap_get_bit(&role->types,
+		    c->type - 1))
+			/* role may not be associated with type */
+			return (FALSE);
+
+		/*
+		 * User must be authorized for the role.
+		 */
+		if (!c->user || c->user > p->p_users.nprim)
+			return (FALSE);
+		usrdatum = p->user_val_to_struct[c->user - 1];
+		if (!usrdatum)
+			return (FALSE);
+
+		if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1))
+			/* user may not be associated with role */
+			return (FALSE);
+	}
+
+	if (mls_context_isvalid(p, c) != TRUE)
+		return (FALSE);
+
+	return (TRUE);
+}
+
+/*
+ * Read and validate a security context structure
+ * from a policydb binary representation file.
+ */
+static int
+context_read_and_validate(context_struct_t *c, policydb_t *p, void *fp)
+{
+	uint32_t buf[3];
+	size_t items;
+
+	items = next_entry(buf, sizeof (uint32_t), 3, fp);
+	if (items != 3) {
+		(void) printf("security: context truncated\n");
+		return (-1);
+	}
+	c->user = SS_LE32_TO_CPU(buf[0]);
+	c->role = SS_LE32_TO_CPU(buf[1]);
+	c->type = SS_LE32_TO_CPU(buf[2]);
+	if (mls_read_range(c, fp)) {
+		(void) printf("security: error reading MLS range of context\n");
+		return (-1);
+	}
+
+	if (!policydb_context_isvalid(p, c)) {
+		(void) printf("security:  invalid security context\n");
+		context_destroy(c);
+		return (-1);
+	}
+	return (0);
+}
+
+/*
+ * The following *_read functions are used to
+ * read the symbol data from a policy database
+ * binary representation file.
+ */
+
+/*ARGSUSED*/
+static int
+perm_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char		*key = 0;
+	perm_datum_t	*perdatum;
+	uint32_t	buf[2], len;
+	int		items, items2;
+
+	perdatum = SS_ALLOC_SLEEP(sizeof (perm_datum_t));
+	if (!perdatum)
+		return (-1);
+	(void) memset(perdatum, 0, sizeof (perm_datum_t));
+
+	items = 2;
+	items2 = next_entry(buf, sizeof (uint32_t), items, fp);
+	if (items != items2)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	perdatum->value = SS_LE32_TO_CPU(buf[1]);
+	if (mls_read_perm(perdatum, fp))
+		goto bad;
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (hashtab_insert(h, key, perdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) perm_destroy(key, perdatum, NULL);
+	return (-1);
+}
+
+static int
+common_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char *key = 0;
+	common_datum_t *comdatum;
+	uint32_t buf[4], len, nel;
+	int items, i;
+
+	comdatum = SS_ALLOC_SLEEP(sizeof (common_datum_t));
+	if (!comdatum)
+		return (-1);
+	(void) memset(comdatum, 0, sizeof (common_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 4, fp);
+	if (items != 4)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	comdatum->value = SS_LE32_TO_CPU(buf[1]);
+
+	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE))
+		goto bad;
+	comdatum->permissions.nprim = SS_LE32_TO_CPU(buf[2]);
+	nel = SS_LE32_TO_CPU(buf[3]);
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	for (i = 0; i < nel; i++) {
+		if (perm_read(p, comdatum->permissions.table, fp))
+			goto bad;
+	}
+
+	if (hashtab_insert(h, key, comdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) common_destroy(key, comdatum, NULL);
+	return (-1);
+}
+
+static int
+class_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char *key = 0;
+	class_datum_t *cladatum;
+	constraint_node_t *c, *lc;
+	constraint_expr_t *e, *le;
+	uint32_t buf[6], len, len2, ncons, nexpr, nel;
+	int items, i, j, depth;
+
+	cladatum = (class_datum_t *) SS_ALLOC_SLEEP(sizeof (class_datum_t));
+	if (!cladatum)
+		return (-1);
+	(void) memset(cladatum, 0, sizeof (class_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 6, fp);
+	if (items != 6)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	len2 = SS_LE32_TO_CPU(buf[1]);
+	cladatum->value = SS_LE32_TO_CPU(buf[2]);
+
+	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE))
+		goto bad;
+	cladatum->permissions.nprim = SS_LE32_TO_CPU(buf[3]);
+	nel = SS_LE32_TO_CPU(buf[4]);
+
+	ncons = SS_LE32_TO_CPU(buf[5]);
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (len2) {
+		cladatum->comkey = SS_ALLOC_SLEEP(len2 + 1);
+		if (!cladatum->comkey)
+			goto bad;
+		items = next_entry(cladatum->comkey, 1, len2, fp);
+		if (items != len2)
+			goto bad;
+		cladatum->comkey[len2] = 0;
+
+		cladatum->comdatum = hashtab_search(p->p_commons.table,
+						    cladatum->comkey);
+		if (!cladatum->comdatum) {
+			(void) printf("security:  unknown common %s\n",
+			    cladatum->comkey);
+			goto bad;
+		}
+	}
+	for (i = 0; i < nel; i++) {
+		if (perm_read(p, cladatum->permissions.table, fp))
+			goto bad;
+	}
+
+	lc = NULL;
+	for (i = 0; i < ncons; i++) {
+		c = SS_ALLOC_SLEEP(sizeof (constraint_node_t));
+		if (!c)
+			goto bad;
+		(void) memset(c, 0, sizeof (constraint_node_t));
+		items = next_entry(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			goto bad;
+		c->permissions = SS_LE32_TO_CPU(buf[0]);
+		nexpr = SS_LE32_TO_CPU(buf[1]);
+		le = NULL;
+		depth = -1;
+		for (j = 0; j < nexpr; j++) {
+			e = SS_ALLOC_SLEEP(sizeof (constraint_expr_t));
+			if (!e)
+				goto bad;
+			(void) memset(e, 0, sizeof (constraint_expr_t));
+			items = next_entry(buf, sizeof (uint32_t), 3, fp);
+			if (items != 3) {
+				SS_FREE(e, sizeof (constraint_expr_t));
+				goto bad;
+			}
+			e->expr_type = SS_LE32_TO_CPU(buf[0]);
+			e->attr = SS_LE32_TO_CPU(buf[1]);
+			e->op = SS_LE32_TO_CPU(buf[2]);
+
+			switch (e->expr_type) {
+			case CEXPR_NOT:
+				if (depth < 0) {
+					SS_FREE(e,
+						sizeof (constraint_expr_t));
+					goto bad;
+				}
+				break;
+			case CEXPR_AND:
+			case CEXPR_OR:
+				if (depth < 1) {
+					SS_FREE(e,
+						sizeof (constraint_expr_t));
+					goto bad;
+				}
+				depth--;
+				break;
+			case CEXPR_ATTR:
+				if (depth == (CEXPR_MAXDEPTH-1)) {
+					SS_FREE(e,
+						sizeof (constraint_expr_t));
+					goto bad;
+				}
+				depth++;
+				break;
+			case CEXPR_NAMES:
+				if (depth == (CEXPR_MAXDEPTH-1)) {
+					SS_FREE(e,
+						sizeof (constraint_expr_t));
+					goto bad;
+				}
+				depth++;
+				if (!ebitmap_read(&e->names, fp)) {
+					SS_FREE(e,
+						sizeof (constraint_expr_t));
+					goto bad;
+				}
+				break;
+			default:
+				SS_FREE(e, sizeof (constraint_expr_t));
+				goto bad;
+			}
+			if (le) {
+				le->next = e;
+			} else {
+				c->expr = e;
+			}
+			le = e;
+		}
+		if (depth != 0)
+			goto bad;
+		if (lc) {
+			lc->next = c;
+		} else {
+			cladatum->constraints = c;
+		}
+		lc = c;
+	}
+
+	if (mls_read_class(cladatum, fp))
+		goto bad;
+
+	if (hashtab_insert(h, key, cladatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) class_destroy(key, cladatum, NULL);
+	return (-1);
+}
+
+/*ARGSUSED*/
+static int
+role_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char *key = 0;
+	role_datum_t *role;
+	uint32_t buf[2], len;
+	int items;
+
+	role = SS_ALLOC_SLEEP(sizeof (role_datum_t));
+	if (!role)
+		return (-1);
+	(void) memset(role, 0, sizeof (role_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 2, fp);
+	if (items != 2)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	role->value = SS_LE32_TO_CPU(buf[1]);
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (!ebitmap_read(&role->dominates, fp))
+		goto bad;
+
+	if (!ebitmap_read(&role->types, fp))
+		goto bad;
+
+	if (strcmp(key, OBJECT_R) == 0) {
+		if (role->value != OBJECT_R_VAL) {
+			(void) printf("Role %s has wrong value %d\n",
+			    OBJECT_R, role->value);
+			(void) role_destroy(key, role, NULL);
+			return (-1);
+		}
+		(void) role_destroy(key, role, NULL);
+		return (0);
+	}
+
+	if (hashtab_insert(h, key, role))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) role_destroy(key, role, NULL);
+	return (-1);
+}
+
+/*ARGSUSED*/
+static int
+type_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char *key = 0;
+	type_datum_t *typdatum;
+	uint32_t buf[3], len;
+	int items;
+
+	typdatum = SS_ALLOC_SLEEP(sizeof (type_datum_t));
+	if (!typdatum)
+		return (-1);
+	(void) memset(typdatum, 0, sizeof (type_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 3, fp);
+	if (items != 3)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	typdatum->value = SS_LE32_TO_CPU(buf[1]);
+	typdatum->primary = SS_LE32_TO_CPU(buf[2]);
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (hashtab_insert(h, key, typdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) type_destroy(key, typdatum, NULL);
+	return (-1);
+}
+
+/*ARGSUSED*/
+static int
+user_read(policydb_t *p, hashtab_t h, void *fp)
+{
+	char *key = 0;
+	user_datum_t *usrdatum;
+	uint32_t buf[2], len;
+	int items;
+
+
+	usrdatum = SS_ALLOC_SLEEP(sizeof (user_datum_t));
+	if (!usrdatum)
+		return (-1);
+	(void) memset(usrdatum, 0, sizeof (user_datum_t));
+
+	items = next_entry(buf, sizeof (uint32_t), 2, fp);
+	if (items != 2)
+		goto bad;
+
+	len = SS_LE32_TO_CPU(buf[0]);
+	usrdatum->value = SS_LE32_TO_CPU(buf[1]);
+
+	key = SS_ALLOC_SLEEP(len + 1);
+	if (!key)
+		goto bad;
+	items = next_entry(key, 1, len, fp);
+	if (items != len)
+		goto bad;
+	key[len] = 0;
+
+	if (!ebitmap_read(&usrdatum->roles, fp))
+		goto bad;
+
+	if (mls_read_user(usrdatum, fp))
+		goto bad;
+
+	if (hashtab_insert(h, key, usrdatum))
+		goto bad;
+
+	return (0);
+
+bad:
+	(void) user_destroy(key, usrdatum, NULL);
+	return (-1);
+}
+
+static int (*read_f[SYM_NUM]) (policydb_t *p, hashtab_t h, void *fp) =
+{
+	common_read,
+	class_read,
+	role_read,
+	type_read,
+	user_read
+	mls_read_f
+};
+
+#define	mls_config(x)	((x) & POLICYDB_CONFIG_MLS) ? "mls" : "no_mls"
+
+/*
+ * Read the configuration data from a policy database binary
+ * representation file into a policy database structure.
+ */
+int
+policydb_read(policydb_t *p, void *fp)
+{
+	struct role_allow *ra, *lra;
+	struct role_trans *tr, *ltr;
+	ocontext_t *l, *c, *newc;
+	genfs_t *genfs_p, *genfs, *newgenfs;
+	int i, j;
+	uint32_t buf[4], len, len2, config, nprim, nel, nel2;
+	size_t items;
+	char *policydb_str;
+
+	config = 0;
+	mls_set_config(config);
+
+	if (policydb_init(p))
+		return (-1);
+
+	/* Read the magic number and string length. */
+	items = next_entry(buf, sizeof (uint32_t), 2, fp);
+	if (items != 2)
+		goto bad;
+	for (i = 0; i < 2; i++)
+		buf[i] = SS_LE32_TO_CPU(buf[i]);
+
+	if (buf[0] != POLICYDB_MAGIC) {
+		(void) printf("security:  policydb magic number 0x%x does "
+			"not match expected magic number 0x%x\n",
+			buf[0],
+			POLICYDB_MAGIC);
+		goto bad;
+	}
+
+	len = buf[1];
+	if (len != strlen(POLICYDB_STRING)) {
+		(void) printf("security:  policydb string length %u does "
+			"not match expected length %lu\n",
+			len,
+			strlen(POLICYDB_STRING));
+		goto bad;
+	}
+	policydb_str = SS_ALLOC_SLEEP(len + 1);
+	if (!policydb_str) {
+		(void) printf("security:  unable to allocate memory for "
+			"policydb string of length %d\n",
+			len);
+		goto bad;
+	}
+	items = next_entry(policydb_str, 1, len, fp);
+	if (items != len) {
+		(void) printf("security:  truncated policydb string "
+		    "identifier\n");
+		goto bad;
+	}
+	policydb_str[len] = 0;
+	if (strcmp(policydb_str, POLICYDB_STRING)) {
+		(void) printf("security:  policydb string %s does not match "
+			"my string %s\n",
+			policydb_str,
+			POLICYDB_STRING);
+		SS_FREE(policydb_str, len + 1);
+		goto bad;
+	}
+	/* Done with policydb_str. */
+	SS_FREE(policydb_str, len + 1);
+	policydb_str = NULL;
+
+	/* Read the version, config, and table sizes. */
+	items = next_entry(buf, sizeof (uint32_t), 4, fp);
+	if (items != 4)
+		goto bad;
+	for (i = 0; i < 4; i++)
+		buf[i] = SS_LE32_TO_CPU(buf[i]);
+
+	if (buf[0] != POLICYDB_VERSION) {
+		(void) printf("security:  policydb version %d does not "
+			"match my version %d\n",
+			buf[0],
+			POLICYDB_VERSION);
+		goto bad;
+	}
+	if (buf[1] != config) {
+		(void) printf("security:  policydb configuration (%s) does "
+			"not match my configuration (%s)\n",
+			mls_config(buf[1]),
+			mls_config(config));
+		goto bad;
+	}
+	if (buf[2] != SYM_NUM || buf[3] != OCON_NUM) {
+		(void) printf("security:  policydb table sizes (%d,%d) do not "
+			"match mine (%d,%d)\n",
+			buf[2],
+			buf[3],
+			SYM_NUM, OCON_NUM);
+		goto bad;
+	}
+
+	if (mls_read_nlevels(p, fp))
+		goto bad;
+
+	for (i = 0; i < SYM_NUM; i++) {
+		items = next_entry(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			goto bad;
+		nprim = SS_LE32_TO_CPU(buf[0]);
+		nel = SS_LE32_TO_CPU(buf[1]);
+		for (j = 0; j < nel; j++) {
+			if (read_f[i] (p, p->symtab[i].table, fp))
+				goto bad;
+		}
+
+		p->symtab[i].nprim = nprim;
+	}
+
+	if (avtab_read(&p->te_avtab, fp, config))
+		goto bad;
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		goto bad;
+	nel = SS_LE32_TO_CPU(buf[0]);
+	ltr = NULL;
+	for (i = 0; i < nel; i++) {
+		tr = SS_ALLOC_SLEEP(sizeof (struct role_trans));
+		if (!tr) {
+			goto bad;
+		}
+		(void) memset(tr, 0, sizeof (struct role_trans));
+		if (ltr) {
+			ltr->next = tr;
+		} else {
+			p->role_tr = tr;
+		}
+		items = next_entry(buf, sizeof (uint32_t), 3, fp);
+		if (items != 3)
+			goto bad;
+		tr->role = SS_LE32_TO_CPU(buf[0]);
+		tr->type = SS_LE32_TO_CPU(buf[1]);
+		tr->new_role = SS_LE32_TO_CPU(buf[2]);
+		ltr = tr;
+	}
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		goto bad;
+	nel = SS_LE32_TO_CPU(buf[0]);
+	lra = NULL;
+	for (i = 0; i < nel; i++) {
+		ra = SS_ALLOC_SLEEP(sizeof (struct role_allow));
+		if (!ra) {
+			goto bad;
+		}
+		(void) memset(ra, 0, sizeof (struct role_allow));
+		if (lra) {
+			lra->next = ra;
+		} else {
+			p->role_allow = ra;
+		}
+		items = next_entry(buf, sizeof (uint32_t), 2, fp);
+		if (items != 2)
+			goto bad;
+		ra->role = SS_LE32_TO_CPU(buf[0]);
+		ra->new_role = SS_LE32_TO_CPU(buf[1]);
+		lra = ra;
+	}
+
+	if (policydb_index_classes(p))
+		goto bad;
+
+	if (policydb_index_others(p))
+		goto bad;
+
+	for (i = 0; i < OCON_NUM; i++) {
+		items = next_entry(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			goto bad;
+		nel = SS_LE32_TO_CPU(buf[0]);
+		l = NULL;
+		for (j = 0; j < nel; j++) {
+			c = SS_ALLOC_SLEEP(sizeof (ocontext_t));
+			if (!c) {
+				goto bad;
+			}
+			(void) memset(c, 0, sizeof (ocontext_t));
+			if (l) {
+				l->next = c;
+			} else {
+				p->ocontexts[i] = c;
+			}
+			l = c;
+			switch (i) {
+			case OCON_ISID:
+				items = next_entry(buf, sizeof (uint32_t), 1,
+				    fp);
+				if (items != 1)
+					goto bad;
+				c->sid[0] = SS_LE32_TO_CPU(buf[0]);
+				if (context_read_and_validate(&c->context[0],
+				    p, fp))
+					goto bad;
+				break;
+			case OCON_FS:
+			case OCON_NETIF:
+				items = next_entry(buf, sizeof (uint32_t), 1,
+				    fp);
+				if (items != 1)
+					goto bad;
+				len = SS_LE32_TO_CPU(buf[0]);
+				c->u.name = SS_ALLOC_SLEEP(len + 1);
+				if (!c->u.name) {
+					goto bad;
+				}
+				items = next_entry(c->u.name, 1, len, fp);
+				if (items != len)
+					goto bad;
+				c->u.name[len] = 0;
+				if (context_read_and_validate(&c->context[0],
+				    p, fp))
+					goto bad;
+				if (context_read_and_validate(&c->context[1],
+				    p, fp))
+					goto bad;
+				break;
+			case OCON_PORT:
+				items = next_entry(buf, sizeof (uint32_t), 3,
+				    fp);
+				if (items != 3)
+					goto bad;
+				c->u.port.protocol = SS_LE32_TO_CPU(buf[0]);
+				c->u.port.low_port = SS_LE32_TO_CPU(buf[1]);
+				c->u.port.high_port = SS_LE32_TO_CPU(buf[2]);
+				if (context_read_and_validate(&c->context[0],
+				    p, fp))
+					goto bad;
+				break;
+			case OCON_NODE:
+				items = next_entry(buf, sizeof (uint32_t), 2,
+				    fp);
+				if (items != 2)
+					goto bad;
+				c->u.node.addr = SS_LE32_TO_CPU(buf[0]);
+				c->u.node.mask = SS_LE32_TO_CPU(buf[1]);
+				if (context_read_and_validate(&c->context[0],
+				    p, fp))
+					goto bad;
+				break;
+			case OCON_FSUSE:
+				items = next_entry(buf, sizeof (uint32_t), 2,
+				    fp);
+				if (items != 2)
+					goto bad;
+				c->v.behavior = SS_LE32_TO_CPU(buf[0]);
+				len = SS_LE32_TO_CPU(buf[1]);
+				c->u.name = SS_ALLOC_SLEEP(len + 1);
+				if (!c->u.name) {
+					goto bad;
+				}
+				items = next_entry(c->u.name, 1, len, fp);
+				if (items != len)
+					goto bad;
+				c->u.name[len] = 0;
+				if (context_read_and_validate(&c->context[0],
+				    p, fp))
+					goto bad;
+				break;
+			}
+		}
+	}
+
+	items = next_entry(buf, sizeof (uint32_t), 1, fp);
+	if (items != 1)
+		goto bad;
+	nel = SS_LE32_TO_CPU(buf[0]);
+	genfs_p = NULL;
+	for (i = 0; i < nel; i++) {
+		newgenfs = SS_ALLOC_SLEEP(sizeof (genfs_t));
+		if (!newgenfs) {
+			goto bad;
+		}
+		(void) memset(newgenfs, 0, sizeof (genfs_t));
+		items = next_entry(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			goto bad;
+		len = SS_LE32_TO_CPU(buf[0]);
+		newgenfs->fstype = SS_ALLOC_SLEEP(len + 1);
+		if (!newgenfs->fstype) {
+			goto bad;
+		}
+		items = next_entry(newgenfs->fstype, 1, len, fp);
+		if (items != len)
+			goto bad;
+		newgenfs->fstype[len] = 0;
+		for (genfs_p = NULL, genfs = p->genfs; genfs;
+		    genfs_p = genfs, genfs = genfs->next) {
+			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
+				(void) printf("security:  dup genfs "
+				    "fstype %s\n",
+				    newgenfs->fstype);
+				goto bad;
+			}
+			if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
+				break;
+		}
+		newgenfs->next = genfs;
+		if (genfs_p)
+			genfs_p->next = newgenfs;
+		else
+			p->genfs = newgenfs;
+		items = next_entry(buf, sizeof (uint32_t), 1, fp);
+		if (items != 1)
+			goto bad;
+		nel2 = SS_LE32_TO_CPU(buf[0]);
+		for (j = 0; j < nel2; j++) {
+			newc = SS_ALLOC_SLEEP(sizeof (ocontext_t));
+			if (!newc) {
+				goto bad;
+			}
+			(void) memset(newc, 0, sizeof (ocontext_t));
+			items = next_entry(buf, sizeof (uint32_t), 1, fp);
+			if (items != 1)
+				goto bad;
+			len = SS_LE32_TO_CPU(buf[0]);
+			newc->u.name = SS_ALLOC_SLEEP(len + 1);
+			if (!newc->u.name) {
+				goto bad;
+			}
+			items = next_entry(newc->u.name, 1, len, fp);
+			if (items != len)
+				goto bad;
+			newc->u.name[len] = 0;
+			items = next_entry(buf, sizeof (uint32_t), 1, fp);
+			if (items != 1)
+				goto bad;
+			newc->v.sclass = SS_LE32_TO_CPU(buf[0]);
+			if (context_read_and_validate(&newc->context[0], p, fp))
+				goto bad;
+			for (l = NULL, c = newgenfs->head; c; l = c,
+			    c = c->next) {
+				if (strcmp(newc->u.name, c->u.name) == 0 &&
+				    (!c->v.sclass || !newc->v.sclass ||
+				    newc->v.sclass == c->v.sclass)) {
+					(void) printf("security:  dup genfs "
+					    "entry (%s,%s)\n",
+					    newgenfs->fstype, c->u.name);
+					goto bad;
+				}
+				len = strlen(newc->u.name);
+				len2 = strlen(c->u.name);
+				if (len > len2)
+					break;
+			}
+			newc->next = c;
+			if (l)
+				l->next = newc;
+			else
+				newgenfs->head = newc;
+		}
+	}
+
+	if (mls_read_trusted(p, fp))
+		goto bad;
+
+	return (0);
+bad:
+	policydb_destroy(p);
+	return (-1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/policydb.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,333 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A policy database (policydb) specifies the
+ * configuration data for the security policy.
+ */
+
+#ifndef _POLICYDB_H
+#define	_POLICYDB_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/kobj.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+#include <sys/types.h>
+#include "ss_impl.h"
+#include "symtab.h"
+#include "avtab.h"
+#include "sidtab.h"
+#include "context.h"
+#include "constraint.h"
+
+/*
+ * A datum type is defined for each kind of symbol
+ * in the configuration data:  individual permissions,
+ * common prefixes for access vectors, classes,
+ * users, roles, types, sensitivities, categories, etc.
+ */
+
+/* Permission attributes */
+typedef struct perm_datum {
+	uint32_t value;		/* permission bit + 1 */
+#ifdef CONFIG_FLASK_MLS
+#define	MLS_BASE_READ    1	/* MLS base permission `read' */
+#define	MLS_BASE_WRITE   2	/* MLS base permission `write' */
+#define	MLS_BASE_READBY  4	/* MLS base permission `readby' */
+#define	MLS_BASE_WRITEBY 8	/* MLS base permission `writeby' */
+	uint32_t base_perms;	/* MLS base permission mask */
+#endif
+} perm_datum_t;
+
+/* Attributes of a common prefix for access vectors */
+typedef struct common_datum {
+	uint32_t value;		/* internal common value */
+	symtab_t permissions;	/* common permissions */
+} common_datum_t;
+
+/* Class attributes */
+typedef struct class_datum {
+	uint32_t value;		/* class value */
+	char *comkey;		/* common name */
+	common_datum_t *comdatum;	/* common datum */
+	symtab_t permissions;	/* class-specific permission symbol table */
+	constraint_node_t *constraints;	/* constraints on class permissions */
+#ifdef CONFIG_FLASK_MLS
+	mls_perms_t mlsperms;	/* MLS base permission masks */
+#endif
+} class_datum_t;
+
+/* Role attributes */
+typedef struct role_datum {
+	uint32_t value;		/* internal role value */
+	ebitmap_t dominates;	/* set of roles dominated by this role */
+	ebitmap_t types;	/* set of authorized types for role */
+} role_datum_t;
+
+typedef struct role_trans {
+	uint32_t role;		/* current role */
+	uint32_t type;		/* program executable type */
+	uint32_t new_role;	/* new role */
+	struct role_trans *next;
+} role_trans_t;
+
+typedef struct role_allow {
+	uint32_t role;		/* current role */
+	uint32_t new_role;	/* new role */
+	struct role_allow *next;
+} role_allow_t;
+
+/* Type attributes */
+typedef struct type_datum {
+	uint32_t value;		/* internal type value */
+	unsigned char primary;	/* primary name? */
+#ifndef _KERNEL
+	unsigned char isattr;   /* is this a type attribute? */
+	ebitmap_t types;	/* types with this attribute */
+#endif /* _KERNEL */
+} type_datum_t;
+
+/* User attributes */
+typedef struct user_datum {
+	uint32_t value;			/* internal user value */
+	ebitmap_t roles;		/* set of authorized roles for user */
+#ifdef CONFIG_FLASK_MLS
+	mls_range_list_t *ranges;	/* list of authorized MLS ranges */
+					/* for user */
+#endif
+} user_datum_t;
+
+
+#ifdef CONFIG_FLASK_MLS
+/* Sensitivity attributes */
+typedef struct level_datum {
+	mls_level_t *level;	/* sensitivity and associated categories */
+	unsigned char isalias;  /* is this sensitivity an alias for another? */
+} level_datum_t;
+
+/* Category attributes */
+typedef struct cat_datum {
+	uint32_t value;		/* internal category bit + 1 */
+	unsigned char isalias;  /* is this category an alias for another? */
+} cat_datum_t;
+#endif
+
+
+/*
+ * The configuration data includes security contexts for
+ * initial SIDs, unlabeled file systems, TCP and UDP port numbers,
+ * network interfaces, and nodes.  This structure stores the
+ * relevant data for one such entry.  Entries of the same kind
+ * (e.g. all initial SIDs) are linked together into a list.
+ */
+typedef struct ocontext {
+	union {
+		char *name;	/* name of initial SID, fs, netif, fstype, */
+				/* path */
+		struct {
+			uint8_t protocol;
+			uint16_t low_port;
+			uint16_t high_port;
+		} port;		/* TCP or UDP port information */
+		struct {
+			uint32_t addr;
+			uint32_t mask;
+		} node;		/* node information */
+	} u;
+	union {
+		uint32_t sclass;  /* security class for genfs */
+		uint32_t behavior;  /* labeling behavior for fs_use */
+	} v;
+	context_struct_t context[2];	/* security context(s) */
+	security_id_t sid[2];	/* SID(s) */
+	struct ocontext *next;
+} ocontext_t;
+
+typedef struct genfs {
+	char *fstype;
+	struct ocontext *head;
+	struct genfs *next;
+} genfs_t;
+
+/* symbol table array indices */
+#define	SYM_COMMONS	0
+#define	SYM_CLASSES	1
+#define	SYM_ROLES	2
+#define	SYM_TYPES	3
+#define	SYM_USERS	4
+#ifdef CONFIG_FLASK_MLS
+#define	SYM_LEVELS	5
+#define	SYM_CATS	6
+#define	SYM_NUM		7
+#else
+#define	SYM_NUM		5
+#endif
+
+/* object context array indices */
+#define	OCON_ISID  0	/* initial SIDs */
+#define	OCON_FS    1	/* unlabeled file systems */
+#define	OCON_PORT  2	/* TCP and UDP port numbers */
+#define	OCON_NETIF 3	/* network interfaces */
+#define	OCON_NODE  4	/* nodes */
+#define	OCON_FSUSE 5	/* fs_use */
+#define	OCON_NUM   6
+
+/* The policy database */
+typedef struct policydb {
+	/* symbol tables */
+	symtab_t symtab[SYM_NUM];
+#define	p_commons symtab[SYM_COMMONS]
+#define	p_classes symtab[SYM_CLASSES]
+#define	p_roles symtab[SYM_ROLES]
+#define	p_types symtab[SYM_TYPES]
+#define	p_users symtab[SYM_USERS]
+#define	p_levels symtab[SYM_LEVELS]
+#define	p_cats symtab[SYM_CATS]
+
+	/* symbol names indexed by (value - 1) */
+	char **sym_val_to_name[SYM_NUM];
+#define	p_common_val_to_name sym_val_to_name[SYM_COMMONS]
+#define	p_class_val_to_name sym_val_to_name[SYM_CLASSES]
+#define	p_role_val_to_name sym_val_to_name[SYM_ROLES]
+#define	p_type_val_to_name sym_val_to_name[SYM_TYPES]
+#define	p_user_val_to_name sym_val_to_name[SYM_USERS]
+#define	p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
+#define	p_cat_val_to_name sym_val_to_name[SYM_CATS]
+
+	/* class, role, and user attributes indexed by (value - 1) */
+	class_datum_t **class_val_to_struct;
+	role_datum_t **role_val_to_struct;
+	user_datum_t **user_val_to_struct;
+
+	/* type enforcement access vectors and transitions */
+	avtab_t te_avtab;
+
+	/* role transitions */
+	role_trans_t *role_tr;
+
+	/* role allows */
+	role_allow_t *role_allow;
+
+	/*
+	 * security contexts of initial SIDs, unlabeled file systems,
+	 * TCP or UDP port numbers, network interfaces and nodes
+	 */
+	ocontext_t *ocontexts[OCON_NUM];
+
+	/*
+	 * security contexts for files in filesystems that cannot support
+	 * a persistent label mapping or use another
+	 * fixed labeling behavior.
+	 */
+	genfs_t *genfs;
+
+#ifdef CONFIG_FLASK_MLS
+	/* number of legitimate MLS levels */
+	uint32_t nlevels;
+
+	ebitmap_t trustedreaders;
+	ebitmap_t trustedwriters;
+	ebitmap_t trustedobjects;
+#endif
+} policydb_t;
+
+extern int policydb_init(policydb_t * p);
+
+extern int policydb_index_classes(policydb_t * p);
+
+extern int policydb_index_others(policydb_t * p);
+
+extern int constraint_expr_destroy(constraint_expr_t * expr);
+
+extern void policydb_destroy(policydb_t * p);
+
+extern int policydb_load_isids(policydb_t *p, sidtab_t *s);
+
+extern int policydb_context_isvalid(policydb_t *p, context_struct_t *c);
+
+extern int policydb_read(policydb_t * p, void * fp);
+
+#define	PERM_SYMTAB_SIZE 32
+
+#define	POLICYDB_VERSION 15
+#define	POLICYDB_CONFIG_MLS    1
+
+#define	OBJECT_R "object_r"
+#define	OBJECT_R_VAL 1
+
+#define	POLICYDB_MAGIC SEMAGIC
+#define	POLICYDB_STRING "Flask"
+
+struct policy_file {
+	char *data;
+	size_t len;
+};
+
+#if defined(_KERNEL)
+static inline
+ssize_t next_entry(void *buf, size_t size, size_t nitems,
+    struct policy_file *fp)
+{
+	struct _buf *policy_handle = (struct _buf *)fp->data;
+	unsigned long bytes = nitems * size;
+	unchar *cptr = (unchar *)buf;
+	int ch;
+
+	while (bytes-- && (ch = kobj_getc(policy_handle)) != -1) {
+		*cptr++ = (unchar)ch;
+	}
+
+	return ((cptr-(unchar *)buf) / size);
+}
+#else
+static inline
+ssize_t next_entry(void *buf, size_t size, size_t nitems,
+    struct policy_file *fp)
+{
+	unsigned long bytes = nitems * size;
+
+	if (bytes > fp->len)
+		bytes = fp->len;
+
+	memcpy(buf, fp->data, bytes);
+	fp->data += bytes;
+	fp->len -= bytes;
+	return (bytes / size);
+}
+#endif /* defined(_KERNEL) */
+
+#endif	/* _POLICYDB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/services.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,1509 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+/*
+ * Implementation of the security services.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/fmac/avc_ss.h>
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/systm.h>
+#include <sys/ksynch.h>
+#include <sys/debug.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#include <synch.h>
+#include <assert.h>
+#endif
+
+#include "ss_impl.h"
+#include <sys/fmac/fmac.h>
+#include <sys/fmac/flask.h>
+#include <sys/fmac/security.h>
+#include <sys/fmac/av_permissions.h>
+#include "context.h"
+#include "policydb.h"
+#include "sidtab.h"
+#include "services.h"
+#include "mls.h"
+
+#if defined(_KERNEL)
+static krwlock_t policy_rwlock;
+#define	POLICY_RDLOCK rw_enter(&policy_rwlock, RW_READER)
+#define	POLICY_WRLOCK rw_enter(&policy_rwlock, RW_WRITER)
+#define	POLICY_RDUNLOCK rw_exit(&policy_rwlock)
+#define	POLICY_WRUNLOCK rw_exit(&policy_rwlock)
+static kmutex_t policy_load_lock;
+#define	LOAD_LOCK mutex_enter(&policy_load_lock)
+#define	LOAD_UNLOCK mutex_exit(&policy_load_lock)
+#else
+static rwlock_t policy_rwlock;
+#define	POLICY_RDLOCK rw_rdlock(&policy_rwlock)
+#define	POLICY_WRLOCK rw_wrlock(&policy_rwlock)
+#define	POLICY_RDUNLOCK rw_unlock(&policy_rwlock)
+#define	POLICY_WRUNLOCK rw_unlock(&policy_rwlock)
+static mutex_t policy_load_lock = DEFAULTMUTEX;
+#define	LOAD_LOCK mutex_lock(&policy_load_lock)
+#define	LOAD_UNLOCK mutex_unlock(&policy_load_lock)
+#endif
+
+#if !defined(_KERNEL)
+#define	ASSERT	assert
+#endif
+
+sidtab_t sidtab;
+policydb_t policydb;
+int ss_initialized = 0;
+
+/*
+ * The largest sequence number that has been used when
+ * providing an access decision to the access vector cache.
+ * The sequence number only changes when a policy change
+ * occurs.
+ */
+static uint32_t latest_granting = 0;
+
+
+/*
+ * Return the boolean value of a constraint expression
+ * when it is applied to the specified source and target
+ * security contexts.
+ */
+static int
+constraint_expr_eval(context_struct_t *scontext, context_struct_t *tcontext,
+    constraint_expr_t *cexpr)
+{
+	uint32_t val1, val2;
+	context_struct_t *c;
+	role_datum_t *r1, *r2;
+	constraint_expr_t *e;
+	int s[CEXPR_MAXDEPTH];
+	int sp = -1;
+
+	for (e = cexpr; e; e = e->next) {
+		switch (e->expr_type) {
+		case CEXPR_NOT:
+			ASSERT(sp >= 0);
+			s[sp] = !s[sp];
+			break;
+		case CEXPR_AND:
+			ASSERT(sp >= 1);
+			sp--;
+			s[sp] &= s[sp+1];
+			break;
+		case CEXPR_OR:
+			ASSERT(sp >= 1);
+			sp--;
+			s[sp] |= s[sp+1];
+			break;
+		case CEXPR_ATTR:
+			if (sp == (CEXPR_MAXDEPTH-1))
+				return (0);
+			switch (e->attr) {
+			case CEXPR_USER:
+				val1 = scontext->user;
+				val2 = tcontext->user;
+				break;
+			case CEXPR_TYPE:
+				val1 = scontext->type;
+				val2 = tcontext->type;
+				break;
+			case CEXPR_ROLE:
+				val1 = scontext->role;
+				val2 = tcontext->role;
+				r1 = policydb.role_val_to_struct[val1 - 1];
+				r2 = policydb.role_val_to_struct[val2 - 1];
+				switch (e->op) {
+				case CEXPR_DOM:
+					s[++sp] =
+					    ebitmap_get_bit(&r1->dominates,
+					    val2 - 1);
+					continue;
+				case CEXPR_DOMBY:
+					s[++sp] =
+					    ebitmap_get_bit(&r2->dominates,
+					    val1 - 1);
+					continue;
+				case CEXPR_INCOMP:
+					s[++sp] =
+					    (!ebitmap_get_bit(&r1->dominates,
+					    val2 - 1) &&
+					    !ebitmap_get_bit(&r2->dominates,
+						val1 - 1));
+					continue;
+				default:
+					break;
+				}
+				break;
+			default:
+				ASSERT(0);
+				return (0);
+			}
+
+			switch (e->op) {
+			case CEXPR_EQ:
+				s[++sp] = (val1 == val2);
+				break;
+			case CEXPR_NEQ:
+				s[++sp] = (val1 != val2);
+				break;
+			default:
+				ASSERT(0);
+				return (0);
+			}
+			break;
+		case CEXPR_NAMES:
+			if (sp == (CEXPR_MAXDEPTH-1))
+				return (0);
+			c = scontext;
+			if (e->attr & CEXPR_TARGET)
+				c = tcontext;
+			if (e->attr & CEXPR_USER)
+				val1 = c->user;
+			else if (e->attr & CEXPR_ROLE)
+				val1 = c->role;
+			else if (e->attr & CEXPR_TYPE)
+				val1 = c->type;
+			else {
+				ASSERT(0);
+				return (0);
+			}
+
+			switch (e->op) {
+			case CEXPR_EQ:
+				s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
+				break;
+			case CEXPR_NEQ:
+				s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
+				break;
+			default:
+				ASSERT(0);
+				return (0);
+			}
+			break;
+		default:
+			ASSERT(0);
+			return (0);
+		}
+	}
+
+	ASSERT(sp == 0);
+	return (s[0]);
+}
+
+
+/*
+ * Compute access vectors based on a context structure pair for
+ * the permissions in a particular class.
+ */
+static int
+context_struct_compute_av(context_struct_t *scontext,
+    context_struct_t *tcontext, security_class_t tclass,
+    access_vector_t requested, struct av_decision *avd)
+{
+	constraint_node_t *constraint;
+	struct role_allow *ra;
+	avtab_key_t avkey;
+	avtab_datum_t *avdatum;
+	class_datum_t *tclass_datum;
+
+	if (!tclass || tclass > policydb.p_classes.nprim) {
+		(void) printf("security_compute_av:  unrecognized class %d\n",
+		tclass);
+		return (EINVAL);
+	}
+	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
+	/*
+	 * Initialize the access vectors to the default values.
+	 */
+	avd->allowed = 0;
+	avd->decided = 0xffffffff;
+	avd->auditallow = 0;
+	avd->auditdeny = 0xffffffff;
+	avd->seqno = latest_granting;
+
+	/*
+	 * If a specific type enforcement rule was defined for
+	 * this permission check, then use it.
+	 */
+	avkey.source_type = scontext->type;
+	avkey.target_type = tcontext->type;
+	avkey.target_class = tclass;
+	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
+	if (avdatum) {
+		if (avdatum->specified & AVTAB_ALLOWED)
+			avd->allowed = avtab_allowed(avdatum);
+		if (avdatum->specified & AVTAB_AUDITDENY)
+			avd->auditdeny = avtab_auditdeny(avdatum);
+		if (avdatum->specified & AVTAB_AUDITALLOW)
+			avd->auditallow = avtab_auditallow(avdatum);
+	}
+
+	/*
+	 * Remove any permissions prohibited by the MLS policy.
+	 */
+	mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed);
+
+	/*
+	 * Remove any permissions prohibited by a constraint.
+	 */
+	constraint = tclass_datum->constraints;
+	while (constraint) {
+		if ((constraint->permissions & (avd->allowed)) &&
+		    !constraint_expr_eval(scontext, tcontext,
+			constraint->expr)) {
+			avd->allowed =
+			    (avd->allowed) & ~(constraint->permissions);
+		}
+		constraint = constraint->next;
+	}
+
+	/*
+	 * If checking process transition permission and the
+	 * role is changing, then check the (current_role, new_role)
+	 * pair.
+	 */
+	if (tclass == SECCLASS_PROCESS &&
+	    (avd->allowed & PROCESS__TRANSITION) &&
+	    scontext->role != tcontext->role) {
+		for (ra = policydb.role_allow; ra; ra = ra->next) {
+			if (scontext->role == ra->role &&
+			    tcontext->role == ra->new_role)
+				break;
+		}
+		if (!ra)
+			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION);
+	}
+
+	return (0);
+}
+
+
+int
+security_compute_av(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, access_vector_t requested,
+    struct av_decision *avd)
+{
+	context_struct_t *scontext = 0, *tcontext = 0;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		avd->allowed = requested;
+		avd->decided = requested;
+		avd->auditallow = 0;
+		avd->auditdeny = 0xffffffff;
+		avd->seqno = latest_granting;
+		return (0);
+	}
+
+	POLICY_RDLOCK;
+
+	scontext = sidtab_search(&sidtab, ssid);
+	if (!scontext) {
+		(void) printf("security_compute_av:  unrecognized SID %d\n",
+		    ssid);
+		rc = EINVAL;
+		goto out;
+	}
+	tcontext = sidtab_search(&sidtab, tsid);
+	if (!tcontext) {
+		(void) printf("security_compute_av:  unrecognized SID %d\n",
+		    tsid);
+		rc = EINVAL;
+		goto out;
+	}
+
+	rc = context_struct_compute_av(scontext, tcontext, tclass, requested,
+	    avd);
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+
+/*
+ * Write the security context string representation of
+ * the context structure `context' into a dynamically
+ * allocated string of the correct size.  Set `*scontext'
+ * to point to this string and set `*scontext_len' to
+ * the length of the string including the terminating null character.
+ */
+int
+context_struct_to_string(context_struct_t *context,
+    security_context_t *scontext, uint32_t *scontext_len)
+{
+	int user_len;
+	int role_len;
+	int type_len;
+	int mls_len;
+	char *scontextp;
+
+	*scontext = 0;
+	*scontext_len = 0;
+
+	/* Compute the size of the context. */
+	user_len = strlen(policydb.p_user_val_to_name[context->user - 1]);
+	role_len = strlen(policydb.p_role_val_to_name[context->role - 1]);
+	type_len = strlen(policydb.p_type_val_to_name[context->type - 1]);
+	mls_len = mls_compute_context_len(context);
+
+	/* "user:role:type" */
+	*scontext_len += user_len + 1 + role_len + 1 + type_len;
+
+	if (mls_len != 0) {
+		/* ":mls" */
+		*scontext_len += 1 + mls_len;
+	}
+
+	/* context length should include terminating null character */
+	*scontext_len += 1;
+
+	/*
+	 * Allocate space for the context; caller must
+	 * free this space.
+	 */
+	scontextp = (security_context_t)SS_ALLOC_NOSLEEP(*scontext_len);
+	if (!scontextp) {
+		return (ENOMEM);
+	}
+	*scontext = (security_context_t) scontextp;
+
+	/*
+	 * Copy the user name, role name and type name into the context.
+	 */
+	(void) sprintf(scontextp, "%s:%s:%s",
+	    policydb.p_user_val_to_name[context->user - 1],
+	    policydb.p_role_val_to_name[context->role - 1],
+	    policydb.p_type_val_to_name[context->type - 1]);
+
+
+	scontextp += user_len + 1 + role_len + 1 + type_len;
+
+	if (mls_len) {
+		/* Add MLS separator */
+		*scontextp = ':';
+		scontextp++;
+	}
+
+	mls_sid_to_context(context, scontextp);
+
+	return (0);
+}
+
+#include <sys/fmac/initial_sid_to_string.h>
+
+/*
+ * Write the security context string representation of
+ * the context associated with `sid' into a dynamically
+ * allocated string of the correct size.  Set `*scontext'
+ * to point to this string and set `*scontext_len' to
+ * the length of the string (note: length does not include the
+ * NULL at the end of the string).
+ */
+int
+security_sid_to_context(security_id_t sid, security_context_t *scontext,
+    uint32_t *scontext_len)
+{
+	context_struct_t *context;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		if (sid <= SECINITSID_NUM) {
+			char *scontextp;
+
+			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+			scontextp = SS_ALLOC_NOSLEEP(*scontext_len);
+			(void) strcpy(scontextp, initial_sid_to_string[sid]);
+			*scontext = (security_context_t) scontextp;
+			return (0);
+		}
+		(void) printf("security_sid_to_context:  called before initial "
+		    "load_policy on unknown SID %d\n",
+		    sid);
+		return (EINVAL);
+	}
+	POLICY_RDLOCK;
+	context = sidtab_search(&sidtab, sid);
+	if (!context) {
+		(void) printf("security_sid_to_context:  unrecognized SID %d\n",
+		    sid);
+		rc = (EINVAL);
+		goto out;
+	}
+	rc = context_struct_to_string(context, scontext, scontext_len);
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+/*
+ * Return a SID associated with the security context that
+ * has the string representation specified by `scontext'.
+ */
+int
+security_context_to_sid(security_context_t scontext, uint32_t scontext_len,
+    security_id_t *sid)
+{
+	security_context_t scontext2;
+	context_struct_t context;
+	role_datum_t *role;
+	type_datum_t *typdatum;
+	user_datum_t *usrdatum;
+	char *scontextp, *p, oldc;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		int i;
+
+		for (i = 1; i < SECINITSID_NUM; i++) {
+			if (strcmp(initial_sid_to_string[i], scontext) == 0) {
+				*sid = i;
+				return (0);
+			}
+		}
+		(void) printf("security_context_to_sid: called before initial "
+		    "load_policy on unknown context %s\n",
+		    scontext);
+		return (EINVAL);
+	}
+	*sid = SECSID_NULL;
+
+	/* Copy the string so that we can modify the copy as we parse it. */
+	scontext2 = SS_ALLOC_NOSLEEP(scontext_len+1);
+	if (!scontext2) {
+		return (ENOMEM);
+	}
+	(void) memcpy(scontext2, scontext, scontext_len);
+	scontext2[scontext_len] = 0;
+
+	context_init(&context);
+	*sid = SECSID_NULL;
+
+	POLICY_RDLOCK;
+
+	/* Parse the security context. */
+
+	rc = (EINVAL);
+	scontextp = (char *) scontext2;
+
+	/* Extract the user. */
+	p = scontextp;
+	while (*p && *p != ':')
+		p++;
+
+	if (*p == 0)
+		goto out;
+
+	*p++ = 0;
+
+	usrdatum = (user_datum_t *) hashtab_search(policydb.p_users.table,
+	    (hashtab_key_t) scontextp);
+	if (!usrdatum)
+		goto out;
+
+	context.user = usrdatum->value;
+
+	/* Extract role. */
+	scontextp = p;
+	while (*p && *p != ':')
+		p++;
+
+	if (*p == 0)
+		goto out;
+
+	*p++ = 0;
+
+	role = (role_datum_t *) hashtab_search(policydb.p_roles.table,
+	    (hashtab_key_t) scontextp);
+	if (!role)
+		goto out;
+	context.role = role->value;
+
+	/* Extract type. */
+	scontextp = p;
+	while (*p && *p != ':')
+		p++;
+	oldc = *p;
+	*p++ = 0;
+
+	typdatum = (type_datum_t *) hashtab_search(policydb.p_types.table,
+	    (hashtab_key_t) scontextp);
+
+	if (!typdatum)
+		goto out;
+
+	context.type = typdatum->value;
+
+	rc = mls_context_to_sid(oldc, &p, &context);
+	if (rc)
+		goto out;
+
+	if ((p - scontext2) < scontext_len) {
+		rc = (EINVAL);
+		goto out;
+	}
+
+	/* Check the validity of the new context. */
+	if (!policydb_context_isvalid(&policydb, &context)) {
+		rc = (EINVAL);
+		goto out;
+	}
+	/* Obtain the new sid. */
+	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+out:
+	POLICY_RDUNLOCK;
+	context_destroy(&context);
+	SS_FREE(scontext2, scontext_len + 1);
+	return (rc);
+}
+
+void
+security_context_free(security_context_t scontext)
+{
+	ASSERT(scontext != NULL);
+
+	SS_FREE(scontext, strlen(scontext) + 1);
+}
+
+static inline int
+compute_sid_handle_invalid_context(context_struct_t *scontext,
+    context_struct_t *tcontext, security_class_t tclass,
+    context_struct_t *newcontext)
+{
+	if (flask_enforcing) {
+		return (EACCES);
+	} else {
+		security_context_t s, t, n;
+		uint32_t slen, tlen, nlen;
+
+		(void) context_struct_to_string(scontext, &s, &slen);
+		(void) context_struct_to_string(tcontext, &t, &tlen);
+		(void) context_struct_to_string(newcontext, &n, &nlen);
+		(void) printf("security_compute_sid:  invalid context %s", n);
+		(void) printf(" for scontext=%s", s);
+		(void) printf(" tcontext=%s", t);
+		(void) printf(" tclass=%s\n",
+		    policydb.p_class_val_to_name[tclass-1]);
+		SS_FREE(s, slen);
+		SS_FREE(t, tlen);
+		SS_FREE(n, nlen);
+		return (0);
+	}
+}
+
+static int
+security_compute_sid(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, uint32_t specified, security_id_t *out_sid)
+{
+	context_struct_t *scontext = 0, *tcontext = 0, newcontext;
+	struct role_trans *roletr = 0;
+	avtab_key_t avkey;
+	avtab_datum_t *avdatum;
+	unsigned int type_change = 0;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		switch (tclass) {
+		case SECCLASS_PROCESS:
+			*out_sid = ssid;
+			break;
+		default:
+			*out_sid = tsid;
+			break;
+		}
+		return (0);
+	}
+
+	POLICY_RDLOCK;
+
+	scontext = sidtab_search(&sidtab, ssid);
+	if (!scontext) {
+		(void) printf("security_compute_sid:  unrecognized SID %d\n",
+		    ssid);
+		rc = EINVAL;
+		goto out;
+	}
+	tcontext = sidtab_search(&sidtab, tsid);
+	if (!tcontext) {
+		(void) printf("security_compute_sid:  unrecognized SID %d\n",
+		    tsid);
+		rc = EINVAL;
+		goto out;
+	}
+
+	context_init(&newcontext);
+
+	/* Set the user identity. */
+	switch (specified) {
+	case AVTAB_TRANSITION:
+	case AVTAB_CHANGE:
+		/* Use the process user identity. */
+		newcontext.user = scontext->user;
+		break;
+	case AVTAB_MEMBER:
+		/* Use the related object owner. */
+		newcontext.user = tcontext->user;
+		break;
+	}
+
+	/* Set the role and type to default values. */
+	switch (tclass) {
+	case SECCLASS_PROCESS:
+		/* Use the current role and type of process. */
+		newcontext.role = scontext->role;
+		newcontext.type = scontext->type;
+		break;
+	default:
+		/* Use the well-defined object role. */
+		newcontext.role = OBJECT_R_VAL;
+		/* Use the type of the related object. */
+		newcontext.type = tcontext->type;
+	}
+
+	/* Look for a type transition/member/change rule. */
+	avkey.source_type = scontext->type;
+	avkey.target_type = tcontext->type;
+	avkey.target_class = tclass;
+	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
+	type_change = (avdatum && (avdatum->specified & specified));
+	if (type_change) {
+		/* Use the type from the type transition/member/change rule. */
+		switch (specified) {
+		case AVTAB_TRANSITION:
+			newcontext.type = avtab_transition(avdatum);
+			break;
+		case AVTAB_MEMBER:
+			newcontext.type = avtab_member(avdatum);
+			break;
+		case AVTAB_CHANGE:
+			newcontext.type = avtab_change(avdatum);
+			break;
+		}
+	}
+
+	/* Check for class-specific changes. */
+	switch (tclass) {
+	case SECCLASS_PROCESS:
+		if (specified & AVTAB_TRANSITION) {
+			/* Look for a role transition rule. */
+			for (roletr = policydb.role_tr; roletr;
+			    roletr = roletr->next) {
+				if (roletr->role == scontext->role &&
+				    roletr->type == tcontext->type) {
+					/* Use the role transition rule. */
+					newcontext.role = roletr->new_role;
+					break;
+				}
+			}
+		}
+
+		if (!type_change && !roletr) {
+			/* No change in process role or type. */
+			*out_sid = ssid;
+			goto out;
+
+		}
+		break;
+	default:
+		if (!type_change && (newcontext.user == tcontext->user) &&
+		    mls_context_cmp(scontext, tcontext)) {
+			/*
+			 * No change in object type, owner, or MLS attributes.
+			 */
+			*out_sid = tsid;
+			goto out;
+		}
+		break;
+	}
+
+	/*
+	 * Set the MLS attributes.
+	 * This is done last because it may allocate memory.
+	 */
+	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+	    &newcontext);
+	if (rc)
+		goto out;
+
+	/* Check the validity of the context. */
+	if (!policydb_context_isvalid(&policydb, &newcontext)) {
+		rc = compute_sid_handle_invalid_context(scontext, tcontext,
+		    tclass, &newcontext);
+		if (rc)
+			goto out;
+	}
+	/* Obtain the sid for the context. */
+	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+out:
+	POLICY_RDUNLOCK;
+	context_destroy(&newcontext);
+	return (rc);
+}
+
+/*
+ * Compute a SID to use for labeling a new object in the
+ * class `tclass' based on a SID pair.
+ */
+int
+security_transition_sid(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, security_id_t *out_sid)
+{
+	return (security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
+	    out_sid));
+}
+
+
+/*
+ * Compute a SID to use when selecting a member of a
+ * polyinstantiated object of class `tclass' based on
+ * a SID pair.
+ */
+int
+security_member_sid(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, security_id_t *out_sid)
+{
+	return (security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER,
+	    out_sid));
+}
+
+
+/*
+ * Compute a SID to use for relabeling an object in the
+ * class `tclass' based on a SID pair.
+ */
+int
+security_change_sid(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, security_id_t *out_sid)
+{
+	return (security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE,
+	    out_sid));
+}
+
+
+/*
+ * Verify that each permission that is defined under the
+ * existing policy is still defined with the same value
+ * in the new policy.
+ */
+static int
+validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	hashtab_t h;
+	perm_datum_t *perdatum, *perdatum2;
+
+
+	h = (hashtab_t) p;
+	perdatum = (perm_datum_t *) datum;
+
+	perdatum2 = (perm_datum_t *) hashtab_search(h, key);
+	if (!perdatum2) {
+		(void) printf("security:  permission %s disappeared", key);
+		return (-1);
+	}
+	if (perdatum->value != perdatum2->value) {
+		(void) printf("security:  the value of permission %s changed",
+		    key);
+		return (-1);
+	}
+	return (0);
+}
+
+/*
+ * Verify that each class that is defined under the
+ * existing policy is still defined with the same
+ * attributes in the new policy.
+ */
+static int
+validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+	policydb_t *newp;
+	class_datum_t *cladatum, *cladatum2;
+
+	newp = (policydb_t *) p;
+	cladatum = (class_datum_t *) datum;
+
+	cladatum2 =
+	    (class_datum_t *) hashtab_search(newp->p_classes.table, key);
+	if (!cladatum2) {
+		(void) printf("security:  class %s disappeared\n", key);
+		return (-1);
+	}
+	if (cladatum->value != cladatum2->value) {
+		(void) printf("security:  the value of class %s changed\n",
+		    key);
+		return (-1);
+	}
+	if ((cladatum->comdatum && !cladatum2->comdatum) ||
+	    (!cladatum->comdatum && cladatum2->comdatum)) {
+		(void) printf("security:  the inherits clause for the access "
+		    "vector definition for class %s changed\n",
+		    key);
+		return (-1);
+	}
+	if (cladatum->comdatum) {
+		if (hashtab_map(cladatum->comdatum->permissions.table,
+		    validate_perm,
+		    cladatum2->comdatum->permissions.table)) {
+			(void) printf(" in the access vector definition for "
+			    "class %s\n",
+			    key);
+			return (-1);
+		}
+	}
+	if (hashtab_map(cladatum->permissions.table, validate_perm,
+			cladatum2->permissions.table)) {
+		(void) printf(" in access vector definition for class %s\n",
+		    key);
+		return (-1);
+	}
+	return (0);
+}
+
+/* Clone the SID into the new SID table. */
+static int
+clone_sid(security_id_t sid, context_struct_t *context, void *arg)
+{
+	sidtab_t *s = arg;
+
+	return (sidtab_insert(s, sid, context));
+}
+
+static inline int
+convert_context_handle_invalid_context(context_struct_t *context)
+{
+	if (flask_enforcing) {
+		return (EINVAL);
+	} else {
+		security_context_t s;
+		uint32_t len;
+
+		(void) context_struct_to_string(context, &s, &len);
+		(void) printf("security:  context %s is invalid\n", s);
+		SS_FREE(s, len);
+		return (0);
+	}
+}
+
+typedef struct {
+	policydb_t *oldp;
+	policydb_t *newp;
+} convert_context_args_t;
+
+/*
+ * Convert the values in the security context
+ * structure `c' from the values specified
+ * in the policy `p->oldp' to the values specified
+ * in the policy `p->newp'.  Verify that the
+ * context is valid under the new policy.
+ */
+
+/*ARGSUSED*/
+static int
+convert_context(security_id_t key, context_struct_t *c, void *p)
+{
+	convert_context_args_t *args;
+	context_struct_t oldc;
+	role_datum_t *role;
+	type_datum_t *typdatum;
+	user_datum_t *usrdatum;
+	security_context_t s;
+	uint32_t len;
+	int rc = EINVAL;
+
+	args = (convert_context_args_t *) p;
+
+	if (context_cpy(&oldc, c))
+		return (ENOMEM);
+
+	/* Convert the user. */
+	usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table,
+			    args->oldp->p_user_val_to_name[c->user - 1]);
+
+	if (!usrdatum) {
+		goto bad;
+	}
+	c->user = usrdatum->value;
+
+	/* Convert the role. */
+	role = (role_datum_t *) hashtab_search(args->newp->p_roles.table,
+			    args->oldp->p_role_val_to_name[c->role - 1]);
+	if (!role) {
+		goto bad;
+	}
+	c->role = role->value;
+
+	/* Convert the type. */
+	typdatum = (type_datum_t *) hashtab_search(args->newp->p_types.table,
+	    args->oldp->p_type_val_to_name[c->type - 1]);
+	if (!typdatum) {
+		goto bad;
+	}
+	c->type = typdatum->value;
+
+	rc = mls_convert_context(args->oldp, args->newp, c);
+	if (rc)
+		goto bad;
+
+	/* Check the validity of the new context. */
+	if (!policydb_context_isvalid(args->newp, c)) {
+		rc = convert_context_handle_invalid_context(&oldc);
+		if (rc)
+			goto bad;
+	}
+
+	context_destroy(&oldc);
+	return (0);
+
+bad:
+	(void) context_struct_to_string(&oldc, &s, &len);
+	context_destroy(&oldc);
+	(void) printf("security:  invalidating context %s\n", s);
+	SS_FREE(s, len);
+	return (rc);
+}
+
+/*
+ * Read a new set of configuration data from
+ * a policy database binary representation file.
+ *
+ * Verify that each class that is defined under the
+ * existing policy is still defined with the same
+ * attributes in the new policy.
+ *
+ * Convert the context structures in the SID table to the
+ * new representation and verify that all entries
+ * in the SID table are valid under the new policy.
+ *
+ * Change the active policy database to use the new
+ * configuration data.
+ *
+ * Reset the access vector cache.
+ */
+int
+security_load_policy(void *data, size_t len)
+{
+	policydb_t oldpolicydb, newpolicydb;
+	sidtab_t oldsidtab, newsidtab;
+	convert_context_args_t args;
+	uint32_t seqno;
+	int rc = 0;
+	struct policy_file file = { data, len }, *fp = &file;
+
+	LOAD_LOCK;
+
+	if (!ss_initialized) {
+		if (policydb_read(&policydb, fp)) {
+			LOAD_UNLOCK;
+			return (EINVAL);
+		}
+		if (policydb_load_isids(&policydb, &sidtab)) {
+			LOAD_UNLOCK;
+			policydb_destroy(&policydb);
+			return (EINVAL);
+		}
+		ss_initialized = 1;
+		LOAD_UNLOCK;
+		return (0);
+	}
+
+#if 0
+	sidtab_hash_eval(&sidtab, "sids");
+#endif
+
+	if (policydb_read(&newpolicydb, fp)) {
+		LOAD_UNLOCK;
+		return (EINVAL);
+	}
+
+	(void) sidtab_init(&newsidtab);
+
+	/* Verify that the existing classes did not change. */
+	if (hashtab_map(policydb.p_classes.table, validate_class,
+	    &newpolicydb)) {
+		(void) printf("security:  the definition of an existing class "
+		    "changed\n");
+		rc = EINVAL;
+		goto err;
+	}
+
+	/* Clone the SID table. */
+	sidtab_shutdown(&sidtab);
+	if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
+		rc = ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * Convert the internal representations of contexts
+	 * in the new SID table and remove invalid SIDs.
+	 */
+	args.oldp = &policydb;
+	args.newp = &newpolicydb;
+	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
+
+	/* Save the old policydb and SID table to free later. */
+	(void) memcpy(&oldpolicydb, &policydb, sizeof (policydb));
+	sidtab_set(&oldsidtab, &sidtab);
+
+	/* Install the new policydb and SID table. */
+	POLICY_WRLOCK;
+	(void) memcpy(&policydb, &newpolicydb, sizeof (policydb));
+	sidtab_set(&sidtab, &newsidtab);
+	seqno = ++latest_granting;
+	POLICY_WRUNLOCK;
+	LOAD_UNLOCK;
+
+	/* Free the old policydb and SID table. */
+	policydb_destroy(&oldpolicydb);
+	sidtab_destroy(&oldsidtab);
+
+	(void) avc_ss_reset(seqno);
+
+	return (0);
+
+err:
+	LOAD_UNLOCK;
+	sidtab_destroy(&newsidtab);
+	policydb_destroy(&newpolicydb);
+	return (rc);
+
+}
+
+/*
+ * Return the SIDs to use for an unlabeled file system
+ * that is being mounted from the device with the
+ * the kdevname `name'.  The `fs_sid' SID is returned for
+ * the file system and the `file_sid' SID is returned
+ * for all files within that file system.
+ */
+int
+security_fs_sid(char *name, security_id_t *fs_sid, security_id_t *file_sid)
+{
+	int rc = 0;
+	ocontext_t *c;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_FS];
+	while (c) {
+		if (strcmp(c->u.name, name) == 0)
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0] || !c->sid[1]) {
+			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			    &c->sid[0]);
+			if (rc)
+				goto out;
+			rc = sidtab_context_to_sid(&sidtab, &c->context[1],
+			    &c->sid[1]);
+			if (rc)
+				goto out;
+		}
+		*fs_sid = c->sid[0];
+		*file_sid = c->sid[1];
+	} else {
+		*fs_sid = SECINITSID_FS;
+		*file_sid = SECINITSID_FILE;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+
+/*
+ * Return the SID of the port specified by
+ * `domain', `type', `protocol', and `port'.
+ */
+
+/*ARGSUSED*/
+int
+security_port_sid(uint16_t domain, uint16_t type, uint8_t protocol,
+    uint16_t port, security_id_t *out_sid)
+{
+	ocontext_t *c;
+	int rc = 0;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_PORT];
+	while (c) {
+		if (c->u.port.protocol == protocol &&
+		    c->u.port.low_port <= port &&
+		    c->u.port.high_port >= port)
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0]) {
+			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			    &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c->sid[0];
+	} else {
+		*out_sid = SECINITSID_PORT;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+
+/*
+ * Return the SIDs to use for a network interface
+ * with the name `name'.  The `if_sid' SID is returned for
+ * the interface and the `msg_sid' SID is returned as
+ * the default SID for messages received on the
+ * interface.
+ */
+int
+security_netif_sid(char *name, security_id_t *if_sid, security_id_t *msg_sid)
+{
+	int rc = 0;
+	ocontext_t *c;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_NETIF];
+	while (c) {
+		if (strcmp(name, c->u.name) == 0)
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0] || !c->sid[1]) {
+			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			    &c->sid[0]);
+			if (rc)
+				goto out;
+			rc = sidtab_context_to_sid(&sidtab, &c->context[1],
+			    &c->sid[1]);
+			if (rc)
+				goto out;
+		}
+		*if_sid = c->sid[0];
+		*msg_sid = c->sid[1];
+	} else {
+		*if_sid = SECINITSID_NETIF;
+		*msg_sid = SECINITSID_NETMSG;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+
+/*
+ * Return the SID of the node specified by the address
+ * `addrp' where `addrlen' is the length of the address
+ * in bytes and `domain' is the communications domain or
+ * address family in which the address should be interpreted.
+ */
+int
+security_node_sid(uint16_t domain, void *addrp, uint32_t addrlen,
+    security_id_t *out_sid)
+{
+	int rc = 0;
+	uint32_t addr;
+	ocontext_t *c;
+
+	POLICY_RDLOCK;
+
+	if (domain != AF_INET || addrlen != sizeof (uint32_t)) {
+		*out_sid = SECINITSID_NODE;
+		goto out;
+	}
+	addr = *((uint32_t *)addrp);
+
+	c = policydb.ocontexts[OCON_NODE];
+	while (c) {
+		if (c->u.node.addr == (addr & c->u.node.mask))
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		if (!c->sid[0]) {
+			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			    &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c->sid[0];
+	} else {
+		*out_sid = SECINITSID_NODE;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+/*
+ * Generate the set of active SIDs.
+ * Set `*sids' to point to a dynamically allocated
+ * array containing the set of SIDs.  Set `*nel' to the
+ * number of elements in the array.
+ */
+int
+security_get_sids(security_id_t **sids, uint32_t *nel)
+{
+	int rc;
+	POLICY_RDLOCK;
+	rc = sidtab_get_sids(&sidtab, sids, nel);
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+/*
+ * Generate the set of SIDs for legal security contexts
+ * for a given user that can be reached by `fromsid'.
+ * Set `*sids' to point to a dynamically allocated
+ * array containing the set of SIDs.  Set `*nel' to the
+ * number of elements in the array.
+ */
+#define	SIDS_NEL 25
+
+int
+security_get_user_sids(security_id_t fromsid, char *username,
+    security_id_t **sids, uint32_t *nel)
+{
+	context_struct_t *fromcon, usercon;
+	security_id_t *mysids, *mysids2, sid;
+	uint32_t mynel = 0, maxnel = SIDS_NEL;
+	user_datum_t *user;
+	role_datum_t *role;
+	struct av_decision avd;
+	int rc = 0, i, j;
+
+	if (!ss_initialized) {
+		*nel = 0;
+		return (0);
+	}
+
+	POLICY_RDLOCK;
+
+	fromcon = sidtab_search(&sidtab, fromsid);
+	if (!fromcon) {
+		rc = EINVAL;
+		goto out;
+	}
+
+	user = (user_datum_t *) hashtab_search(policydb.p_users.table,
+	    username);
+	if (!user) {
+		rc = EINVAL;
+		goto out;
+	}
+	usercon.user = user->value;
+
+	mysids = SS_ALLOC_NOSLEEP(maxnel*sizeof (security_id_t));
+	if (!mysids) {
+		rc = ENOMEM;
+		goto out;
+	}
+	(void) memset(mysids, 0, maxnel*sizeof (security_id_t));
+
+	for (i = ebitmap_startbit(&user->roles);
+	    i < ebitmap_length(&user->roles); i++) {
+		if (!ebitmap_get_bit(&user->roles, i))
+			continue;
+		role = policydb.role_val_to_struct[i];
+		usercon.role = i+1;
+		for (j = ebitmap_startbit(&role->types);
+		    j < ebitmap_length(&role->types); j++) {
+			if (!ebitmap_get_bit(&role->types, j))
+				continue;
+			usercon.type = j+1;
+			if (usercon.type == fromcon->type)
+				continue;
+			mls_for_user_ranges(user, usercon) {
+				rc = context_struct_compute_av(fromcon,
+				    &usercon, SECCLASS_PROCESS,
+				    PROCESS__TRANSITION, &avd);
+				if (rc || !(avd.allowed & PROCESS__TRANSITION))
+					continue;
+				rc = sidtab_context_to_sid(&sidtab, &usercon,
+				    &sid);
+				if (rc) {
+					SS_FREE(mysids,
+						maxnel*sizeof (security_id_t));
+					goto out;
+				}
+				if (mynel < maxnel) {
+					mysids[mynel++] = sid;
+				} else {
+					uint32_t oldmaxnel = maxnel;
+
+					maxnel += SIDS_NEL;
+					mysids2 = SS_ALLOC_NOSLEEP(
+					    maxnel*sizeof (security_id_t));
+					if (!mysids2) {
+						rc = ENOMEM;
+						SS_FREE(mysids, oldmaxnel *
+						    sizeof (security_id_t));
+						goto out;
+					}
+					(void) memset(mysids2, 0,
+					    maxnel*sizeof (security_id_t));
+					(void) memcpy(mysids2, mysids,
+					    mynel * sizeof (security_id_t));
+					SS_FREE(mysids,
+					    oldmaxnel*sizeof (security_id_t));
+					mysids = mysids2;
+					mysids[mynel++] = sid;
+				}
+			}
+			mls_end_user_ranges;
+		}
+	}
+
+	*sids = mysids;
+	*nel = mynel;
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+/*
+ * Return the SID to use for a file in a filesystem
+ * that cannot support a persistent label mapping or use another
+ * fixed labeling behavior like transition SIDs or task SIDs.
+ */
+int
+security_genfs_sid(const char *fstype, char *path, security_class_t sclass,
+    security_id_t *sid)
+{
+	int len;
+	genfs_t *genfs;
+	ocontext_t *c;
+	int rc = 0, cmp = 0;
+
+	POLICY_RDLOCK;
+
+	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+		cmp = strcmp(fstype, genfs->fstype);
+		if (cmp <= 0)
+			break;
+	}
+
+	if (!genfs || cmp) {
+		*sid = SECINITSID_UNLABELED;
+		rc = ENOENT;
+		goto out;
+	}
+
+	for (c = genfs->head; c; c = c->next) {
+		len = strlen(c->u.name);
+		if ((!c->v.sclass || sclass == c->v.sclass) &&
+		    (strncmp(c->u.name, path, len) == 0))
+			break;
+	}
+
+	if (!c) {
+		*sid = SECINITSID_UNLABELED;
+		rc = ENOENT;
+		goto out;
+	}
+
+	if (!c->sid[0]) {
+		rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+		    &c->sid[0]);
+		if (rc)
+			goto out;
+	}
+
+	*sid = c->sid[0];
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
+
+int
+security_fs_use(const char *fstype, unsigned int *behavior,
+    security_id_t *sid)
+{
+	int rc = 0;
+	ocontext_t *c;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_FSUSE];
+	while (c) {
+		if (strcmp(fstype, c->u.name) == 0)
+			break;
+		c = c->next;
+	}
+
+	if (c) {
+		*behavior = c->v.behavior;
+		if (!c->sid[0]) {
+			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			    &c->sid[0]);
+			if (rc)
+				goto out;
+		}
+		*sid = c->sid[0];
+	} else {
+		rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+		if (rc) {
+			*behavior = SECURITY_FS_USE_NONE;
+			rc = 0;
+		} else {
+			*behavior = SECURITY_FS_USE_GENFS;
+		}
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return (rc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/services.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,43 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+#ifndef _SERVICES_H
+#define	_SERVICES_H
+
+#include "policydb.h"
+#include "sidtab.h"
+
+/*
+ * The security server uses two global data structures
+ * when providing its services:  the SID table (sidtab)
+ * and the policy database (policydb).
+ */
+extern sidtab_t sidtab;
+extern policydb_t policydb;
+
+#endif	/* SERVICES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/sidtab.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,406 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the SID table type.
+ */
+
+#include <sys/types.h>
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/ksynch.h>
+#else
+#include <inttypes.h>
+#include <thread.h>
+#include <synch.h>
+#include <limits.h>
+#endif /* defined(_KERNEL) */
+
+#include "ss_impl.h"
+#include <sys/fmac/flask.h>
+#include "sidtab.h"
+
+#define	SIDTAB_HASH(sid)	(sid & SIDTAB_HASH_MASK)
+
+#if defined(_KERNEL)
+#define	INIT_SIDTAB_LOCK(s) mutex_init(&s->lock, NULL, MUTEX_DEFAULT, NULL)
+#define	SIDTAB_LOCK(s) mutex_enter(&s->lock)
+#define	SIDTAB_UNLOCK(s) mutex_exit(&s->lock)
+#else
+#define	INIT_SIDTAB_LOCK(s) mutex_init(&s->lock, USYNC_THREAD, NULL)
+#define	SIDTAB_LOCK(s) mutex_lock(&s->lock)
+#define	SIDTAB_UNLOCK(s) mutex_unlock(&s->lock)
+#endif
+
+int
+sidtab_init(sidtab_t *s)
+{
+	int i;
+
+	s->htable = SS_ALLOC_NOSLEEP(sizeof (sidtab_ptr_t)*SIDTAB_SIZE);
+	if (!s->htable)
+		return (ENOMEM);
+	for (i = 0; i < SIDTAB_SIZE; i++)
+		s->htable[i] = (sidtab_ptr_t) NULL;
+	s->nel = 0;
+	s->next_sid = 1;
+	s->shutdown = 0;
+	INIT_SIDTAB_LOCK(s);
+	return (0);
+}
+
+int
+sidtab_insert(sidtab_t *s, security_id_t sid, context_struct_t *context)
+{
+	int hvalue;
+	sidtab_node_t *prev, *cur, *newnode;
+
+
+	if (!s)
+		return (ENOMEM);
+
+	hvalue = SIDTAB_HASH(sid);
+	prev = NULL;
+	cur = s->htable[hvalue];
+	while (cur != NULL && sid > cur->sid) {
+		prev = cur;
+		cur = cur->next;
+	}
+
+	if (cur && sid == cur->sid)
+		return (EEXIST);
+
+	newnode = (sidtab_node_t *) SS_ALLOC_NOSLEEP(sizeof (sidtab_node_t));
+	if (newnode == NULL)
+		return (ENOMEM);
+	newnode->sid = sid;
+	if (context_cpy(&newnode->context, context)) {
+		SS_FREE(newnode, sizeof (sidtab_node_t));
+		return (ENOMEM);
+	}
+
+	if (prev) {
+		newnode->next = prev->next;
+		prev->next = newnode;
+	} else {
+		newnode->next = s->htable[hvalue];
+		s->htable[hvalue] = newnode;
+	}
+
+	s->nel++;
+	if (sid >= s->next_sid)
+		s->next_sid = sid + 1;
+	return (0);
+}
+
+int
+sidtab_remove(sidtab_t *s, security_id_t sid)
+{
+	int hvalue;
+	sidtab_node_t *cur, *last;
+
+
+	if (!s)
+		return (ENOENT);
+
+	hvalue = SIDTAB_HASH(sid);
+	last = NULL;
+	cur = s->htable[hvalue];
+	while (cur != NULL && sid > cur->sid) {
+		last = cur;
+		cur = cur->next;
+	}
+
+	if (cur == NULL || sid != cur->sid)
+		return (ENOENT);
+
+	if (last == NULL)
+		s->htable[hvalue] = cur->next;
+	else
+		last->next = cur->next;
+
+	context_destroy(&cur->context);
+
+	SS_FREE(cur, sizeof (sidtab_node_t));
+	s->nel--;
+	return (0);
+}
+
+context_struct_t *
+sidtab_search(sidtab_t *s, security_id_t sid)
+{
+	int hvalue;
+	sidtab_node_t *cur;
+
+	if (!s)
+		return (NULL);
+
+	hvalue = SIDTAB_HASH(sid);
+	cur = s->htable[hvalue];
+	while (cur != NULL && sid > cur->sid)
+		cur = cur->next;
+
+	if (cur == NULL || sid != cur->sid) {
+		/* Remap invalid SIDs to the unlabeled SID. */
+		sid = SECINITSID_UNLABELED;
+		hvalue = SIDTAB_HASH(sid);
+		cur = s->htable[hvalue];
+		while (cur != NULL && sid > cur->sid)
+			cur = cur->next;
+		if (!cur || sid != cur->sid)
+			return (NULL);
+	}
+
+	return (&cur->context);
+}
+
+int
+sidtab_map(sidtab_t *s, int (*apply) (security_id_t sid,
+    context_struct_t *context, void *args), void *args)
+{
+	int i, ret;
+	sidtab_node_t *cur;
+
+
+	if (!s)
+		return (0);
+
+	for (i = 0; i < SIDTAB_SIZE; i++) {
+		cur = s->htable[i];
+		while (cur != NULL) {
+			ret = apply(cur->sid, &cur->context, args);
+			if (ret)
+				return (ret);
+			cur = cur->next;
+		}
+	}
+	return (0);
+}
+
+void
+sidtab_map_remove_on_error(sidtab_t *s, int (*apply) (security_id_t sid,
+    context_struct_t *context, void *args), void *args)
+{
+	int i, ret;
+	sidtab_node_t *last, *cur, *temp;
+
+
+	if (!s)
+		return;
+
+	for (i = 0; i < SIDTAB_SIZE; i++) {
+		last = NULL;
+		cur = s->htable[i];
+		while (cur != NULL) {
+			ret = apply(cur->sid, &cur->context, args);
+			if (ret) {
+				if (last) {
+					last->next = cur->next;
+				} else {
+					s->htable[i] = cur->next;
+				}
+
+				temp = cur;
+				cur = cur->next;
+				context_destroy(&temp->context);
+				SS_FREE(temp, sizeof (sidtab_node_t));
+				s->nel--;
+			} else {
+				last = cur;
+				cur = cur->next;
+			}
+		}
+	}
+}
+
+static inline security_id_t
+sidtab_search_context(sidtab_t *s, context_struct_t *context)
+{
+	int i;
+	sidtab_node_t *cur;
+
+	for (i = 0; i < SIDTAB_SIZE; i++) {
+		cur = s->htable[i];
+		while (cur != NULL) {
+			if (context_cmp(&cur->context, context))
+				return (cur->sid);
+			cur = cur->next;
+		}
+	}
+	return (0);
+}
+
+int
+sidtab_context_to_sid(sidtab_t *s, context_struct_t *context,
+    security_id_t *out_sid)
+{
+	security_id_t sid;
+	int ret = 0;
+
+	*out_sid = SECSID_NULL;
+
+	sid = sidtab_search_context(s, context);
+	if (!sid) {
+		SIDTAB_LOCK(s);
+		/* Rescan now that we hold the lock. */
+		sid = sidtab_search_context(s, context);
+		if (sid)
+			goto unlock_out;
+		/* No SID exists for the context.  Allocate a new one. */
+		if (s->next_sid == UINT_MAX || s->shutdown) {
+			ret = ENOMEM;
+			goto unlock_out;
+		}
+		sid = s->next_sid++;
+		ret = sidtab_insert(s, sid, context);
+		if (ret)
+			s->next_sid--;
+unlock_out:
+		SIDTAB_UNLOCK(s);
+	}
+
+	if (ret)
+		return (ret);
+
+	*out_sid = sid;
+	return (0);
+}
+
+void
+sidtab_hash_eval(sidtab_t *h, char *tag)
+{
+	int i, chain_len, slots_used, max_chain_len;
+	sidtab_node_t *cur;
+
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i < SIDTAB_SIZE; i++) {
+		cur = h->htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur->next;
+			}
+
+			if (chain_len > max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	(void) printf("%s:  %d entries and %d/%d buckets used, longest chain "
+	    "length %d\n",
+	    tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len);
+}
+
+void
+sidtab_destroy(sidtab_t *s)
+{
+	int i;
+	sidtab_ptr_t cur, temp;
+
+
+	if (!s)
+		return;
+
+	for (i = 0; i < SIDTAB_SIZE; i++) {
+		cur = s->htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur->next;
+			context_destroy(&temp->context);
+			SS_FREE(temp, sizeof (sidtab_node_t));
+		}
+		s->htable[i] = NULL;
+	}
+	SS_FREE(s->htable, sizeof (sidtab_ptr_t) * SIDTAB_SIZE);
+	s->htable = NULL;
+	s->nel = 0;
+	s->next_sid = 1;
+}
+
+void
+sidtab_set(sidtab_t *dst, sidtab_t *src)
+{
+	SIDTAB_LOCK(src);
+	dst->htable = src->htable;
+	dst->nel = src->nel;
+	dst->next_sid = src->next_sid;
+	dst->shutdown = 0;
+	SIDTAB_UNLOCK(src);
+}
+
+void
+sidtab_shutdown(sidtab_t *s)
+{
+	SIDTAB_LOCK(s);
+	s->shutdown = 1;
+	SIDTAB_UNLOCK(s);
+}
+
+int
+sidtab_get_sids(sidtab_t *s,
+		    security_id_t **sids,
+		    uint32_t *nel)
+{
+	int rc = 0;
+	security_id_t *mysids;
+	uint32_t mynel;
+	int i, j;
+	sidtab_node_t *cur;
+
+	SIDTAB_LOCK(s);
+	mynel = s->nel;
+	mysids = SS_ALLOC_NOSLEEP(sizeof (security_id_t)*mynel);
+	if (!mysids) {
+		rc = ENOMEM;
+		goto out;
+	}
+	j = 0;
+	for (i = 0; i < SIDTAB_SIZE && j < mynel; i++) {
+		cur = s->htable[i];
+		while (cur != NULL && j < mynel) {
+			mysids[j++] = cur->sid;
+			cur = cur->next;
+		}
+	}
+	*nel = mynel;
+	*sids = mysids;
+
+out:
+	SIDTAB_UNLOCK(s);
+	return (rc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/sidtab.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,100 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A security identifier table (sidtab) is a hash table
+ * of security context structures indexed by SID value.
+ */
+
+#ifndef _SIDTAB_H
+#define	_SIDTAB_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/ksynch.h>
+#else
+#include <inttypes.h>
+#include <synch.h>
+#endif /* defined(_KERNEL) */
+
+#include "context.h"
+
+typedef struct sidtab_node {
+	security_id_t sid;		/* security identifier */
+	context_struct_t context;	/* security context structure */
+	struct sidtab_node *next;
+} sidtab_node_t;
+
+typedef struct sidtab_node *sidtab_ptr_t;
+
+#define	SIDTAB_HASH_BITS 7
+#define	SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
+#define	SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1)
+
+#define	SIDTAB_SIZE SIDTAB_HASH_BUCKETS
+
+typedef struct {
+	sidtab_ptr_t *htable;
+	unsigned int nel;	/* number of elements */
+	unsigned int next_sid;	/* next SID to allocate */
+	unsigned char shutdown;
+#if defined(_KERNEL)
+	kmutex_t lock;
+#else
+	mutex_t lock;
+#endif
+} sidtab_t;
+
+int sidtab_init(sidtab_t *s);
+
+int sidtab_insert(sidtab_t * s, security_id_t sid, context_struct_t * context);
+
+context_struct_t *sidtab_search(sidtab_t * s, security_id_t sid);
+
+int sidtab_map(sidtab_t *s, int (*apply) (security_id_t sid,
+    context_struct_t *context, void *args), void *args);
+
+void sidtab_map_remove_on_error(sidtab_t *s, int (*apply) (security_id_t sid,
+    context_struct_t *context, void *args), void *args);
+
+int sidtab_context_to_sid(
+	sidtab_t *s,			/* IN */
+	context_struct_t *context,	/* IN */
+	security_id_t *sid);		/* OUT */
+
+void sidtab_hash_eval(sidtab_t *h, char *tag);
+
+void sidtab_destroy(sidtab_t *s);
+
+void sidtab_set(sidtab_t *dst, sidtab_t *src);
+
+void sidtab_shutdown(sidtab_t *s);
+
+int sidtab_get_sids(sidtab_t *s, security_id_t **sids, uint32_t *nel);
+
+#endif	/* _SIDTAB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/ss_impl.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,108 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Global definitions that are included at the beginning
+ * of every file using the -include directive.
+ *
+ * These definitions are used to permit the same
+ * source code to be used to build both the security
+ * server component of the kernel and the checkpolicy
+ * program.
+ */
+
+#ifndef _SS_IMPL_H
+#define	_SS_IMPL_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/kmem.h>
+#else
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include <sys/byteorder.h>
+
+/*
+ * Comment out the line below if you want to build
+ * the security server with MLS.
+ */
+/* #DEFine	CONFIG_FLASK_MLS */
+
+#define	SS_CPU_TO_LE32(x)	cpu_to_le32(x)
+#define	SS_LE32_TO_CPU(x)	le32_to_cpu(x)
+#define	SS_CPU_TO_LE64(x)	cpu_to_le64(x)
+#define	SS_LE64_TO_CPU(x)	le64_to_cpu(x)
+
+static uint32_t
+cpu_to_le32(uint32_t x)
+{
+	return (LE_32(x));
+}
+#pragma inline(cpu_to_le32)
+
+static uint32_t
+le32_to_cpu(uint32_t x)
+{
+	return (LE_32(x));
+}
+#pragma inline(le32_to_cpu)
+
+static uint64_t
+le64_to_cpu(uint64_t x)
+{
+	return (LE_64(x));
+}
+#pragma inline(le64_to_cpu)
+
+static uint64_t
+cpu_to_le64(uint64_t x)
+{
+	return (LE_64(x));
+}
+#pragma inline(cpu_to_le64)
+
+#if defined(_KERNEL)
+#define	SS_ALLOC_SLEEP(s)	kmem_alloc((s), KM_SLEEP)
+#define	SS_ALLOC_NOSLEEP(s)	kmem_alloc((s), KM_NOSLEEP)
+#define	SS_FREE(p, s)		kmem_free((p), (s))
+#else
+#define	SS_ALLOC_SLEEP(s)	malloc((s))
+#define	SS_ALLOC_NOSLEEP(s)	malloc((s))
+#define	SS_FREE(p, s)		free((p))
+#endif
+
+#endif /* _SS_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/symtab.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * Implementation of the symbol table type.
+ */
+
+#if defined(_KERNEL)
+#include <sys/systm.h>
+#else
+#include <strings.h>
+#endif /* defined(_KERNEL) */
+
+#include "symtab.h"
+
+static unsigned int
+symhash(hashtab_t h, hashtab_key_t key)
+{
+	char *p, *keyp;
+	unsigned int size;
+	unsigned int val;
+
+
+	val = 0;
+	keyp = (char *) key;
+	size = strlen(keyp);
+	for (p = keyp; (p - keyp) < size; p++)
+		val = (val << 4 | (val >> (8*sizeof (unsigned int)-4))) ^ (*p);
+	return (val & (h->size - 1));
+}
+
+/*ARGSUSED*/
+static int
+symcmp(hashtab_t h, hashtab_key_t key1, hashtab_key_t key2)
+{
+	char *keyp1, *keyp2;
+
+	keyp1 = (char *) key1;
+	keyp2 = (char *) key2;
+	return (strcmp(keyp1, keyp2));
+}
+
+int
+symtab_init(symtab_t *s, unsigned int size)
+{
+	s->table = hashtab_create(symhash, symcmp, size);
+	if (!s->table)
+		return (-1);
+	s->nprim = 0;
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fmac/ss/symtab.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
+
+/*
+ * A symbol table (symtab) maintains associations between symbol
+ * strings and datum values.  The type of the datum values
+ * is arbitrary.  The symbol table type is implemented
+ * using the hash table type (hashtab).
+ */
+
+#ifndef _SYMTAB_H
+#define	_SYMTAB_H
+
+#if defined(_KERNEL)
+#include <sys/inttypes.h>
+#else
+#include <inttypes.h>
+#endif /* defined(_KERNEL) */
+
+#include "hashtab.h"
+
+typedef struct {
+	hashtab_t table;	/* hash table (keyed on a string) */
+	uint32_t nprim;		/* number of primary names in table */
+} symtab_t;
+
+int symtab_init(symtab_t *, unsigned int size);
+
+#endif	/* _SYMTAB_H */
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/pkgdefs/SUNWcsr/prototype_com	Thu May 01 16:48:12 2008 -0700
@@ -285,6 +285,8 @@
 f none etc/security/dev/sr0 400 root bin
 f none etc/security/dev/st0 400 root bin
 f none etc/security/dev/st1 400 root bin
+d none etc/security/fmac 755 root bin
+f none etc/security/fmac/ss_policy 644 root sys
 f none etc/security/kmfpolicy.xml 644 root bin
 d none etc/security/lib 755 root sys
 f none etc/security/lib/audio_clean 555 root sys
@@ -395,6 +397,7 @@
 d none sbin 755 root sys
 f none sbin/autopush 555 root bin
 f none sbin/bootadm 555 root bin
+f none sbin/checkpolicy 555 root bin
 f none sbin/devprop 555 root bin
 f none sbin/dhcpagent 555 root bin
 f none sbin/dhcpinfo 555 root bin
@@ -420,6 +423,7 @@
 f none sbin/rcS 744 root sys
 f none sbin/route 555 root bin
 f none sbin/routeadm 555 root bin
+f none sbin/setfiles 555 root root
 f none sbin/sh 555 root root
 f none sbin/sulogin 555 root bin
 f none sbin/su.static 555 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_com	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com	Thu May 01 16:48:12 2008 -0700
@@ -824,6 +824,19 @@
 f none usr/include/sys/fm/io/pci.h 644 root bin
 f none usr/include/sys/fm/io/scsi.h 644 root bin
 f none usr/include/sys/fm/io/sun4upci.h 644 root bin
+d none usr/include/sys/fmac 755 root bin
+f none usr/include/sys/fmac/av_inherit.h 644 root bin
+f none usr/include/sys/fmac/av_perm_to_string.h 644 root bin
+f none usr/include/sys/fmac/av_permissions.h 644 root bin
+f none usr/include/sys/fmac/avc.h 644 root bin
+f none usr/include/sys/fmac/avc_ss.h 644 root bin
+f none usr/include/sys/fmac/class_to_string.h 644 root bin
+f none usr/include/sys/fmac/common_perm_to_string.h 644 root bin
+f none usr/include/sys/fmac/flask.h 644 root bin
+f none usr/include/sys/fmac/flask_types.h 644 root bin
+f none usr/include/sys/fmac/fmac.h 644 root bin
+f none usr/include/sys/fmac/initial_sid_to_string.h 644 root bin
+f none usr/include/sys/fmac/security.h 644 root bin
 f none usr/include/sys/fork.h 644 root bin
 f none usr/include/sys/frame.h 644 root bin
 f none usr/include/sys/fss.h 644 root bin
--- a/usr/src/uts/common/Makefile.files	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/uts/common/Makefile.files	Thu May 01 16:48:12 2008 -0700
@@ -85,7 +85,9 @@
 		aio_subr.o	\
 		auditsys.o	\
 		autoconf.o	\
+		avc.o		\
 		avl.o		\
+		avtab.o		\
 		bdev_dsort.o	\
 		bio.o		\
 		bitmap.o	\
@@ -135,6 +137,7 @@
 		dumpsubr.o	\
 		driver_lyr.o	\
 		dtrace_subr.o	\
+		ebitmap.o	\
 		errorq.o	\
 		etheraddr.o	\
 		evchannels.o	\
@@ -151,6 +154,8 @@
 		fio.o		\
 		flock.o		\
 		fm.o		\
+		fmac.o		\
+		$(FMAC_MLS_OBJS)	\
 		fork.o		\
 		vpm.o		\
 		fsat.o		\
@@ -167,6 +172,7 @@
 		gid.o		\
 		groups.o	\
 		grow.o		\
+		hashtab.o	\
 		hat.o		\
 		hat_refmod.o	\
 		id32.o		\
@@ -222,6 +228,7 @@
 		pathconf.o	\
 		pathname.o	\
 		pause.o		\
+		policydb.o	\
 		serializer.o	\
 		pci_intr_lib.o	\
 		pci_cap.o	\
@@ -262,6 +269,7 @@
 		sad_conf.o	\
 		sid.o		\
 		sidsys.o	\
+		sidtab.o	\
 		sched.o		\
 		schedctl.o	\
 		seg_dev.o	\
@@ -272,6 +280,7 @@
 		seg_spt.o	\
 		semaphore.o	\
 		sendfile.o	\
+		services.o	\
 		session.o	\
 		share.o		\
 		shuttle.o	\
@@ -310,6 +319,7 @@
 		swap_subr.o	\
 		swap_vnops.o	\
 		symlink.o	\
+		symtab.o	\
 		sync.o		\
 		sysclass.o	\
 		sysconfig.o	\
--- a/usr/src/uts/common/Makefile.rules	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/uts/common/Makefile.rules	Thu May 01 16:48:12 2008 -0700
@@ -174,6 +174,23 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/common/fmac/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
+CHECK_FOR_MLS =		if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS'	\
+				$(SRC)/common/fmac/ss/ss_impl.h ; then	\
+				echo "mls.o" ;				\
+			else						\
+				echo "" ;				\
+			fi ;
+
+FMAC_MLS_OBJS =		$(CHECK_FOR_MLS:sh)
+
+$(OBJS_DIR)/%.o:		$(COMMONBASE)/fmac/ss/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/fs/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -1195,6 +1212,12 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/fs/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/fmac/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+$(LINTS_DIR)/%.ln:		$(COMMONBASE)/fmac/ss/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/fs/autofs/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/fmac/avc.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,953 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author:  Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+/*
+ * Implementation of the kernel access vector cache (AVC).
+ */
+
+/* include system headers from the OS here */
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/ksynch.h>
+#include <sys/inttypes.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/systm.h>
+#include <sys/fmac/fmac.h>
+#include <sys/fmac/avc.h>
+#include <sys/fmac/avc_ss.h>
+#include <sys/fmac/class_to_string.h>
+#include <sys/fmac/common_perm_to_string.h>
+#include <sys/fmac/av_inherit.h>
+#include <sys/fmac/av_perm_to_string.h>
+
+static kmutex_t avc_lock;
+
+typedef struct avc_node {
+	struct avc_entry ae;
+	struct avc_node *next;
+} avc_node_t;
+
+static struct avc_node *avc_node_freelist = NULL;
+
+#define	AVC_CACHE_SLOTS		512
+#define	AVC_CACHE_MAXNODES	410
+
+typedef struct {
+	avc_node_t	*slots[AVC_CACHE_SLOTS];
+	uint32_t	lru_hint;	/* LRU hint for reclaim scan */
+	uint32_t	activeNodes;
+	uint32_t	latest_notif;	/* latest revocation notification */
+} avc_cache_t;
+
+static avc_cache_t avc_cache;
+
+
+#define	AVC_HASH(ssid, tsid, tclass) \
+		((ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1))
+
+static char *avc_audit_buffer = NULL;
+
+unsigned avc_cache_stats[AVC_NSTATS];
+
+#ifdef AVC_CACHE_STATS
+#define	avc_cache_stats_incr(x) avc_cache_stats[(x)]++
+#define	avc_cache_stats_add(x, y) avc_cache_stats[(x)] += (y)
+#else
+#define	avc_cache_stats_incr(x)
+#define	avc_cache_stats_add(x, y)
+#endif /* AVC_CACHE_STATS */
+
+/*
+ * Display the cache statistics
+ */
+void
+avc_dump_stats(char *tag)
+{
+	printf("%s avc:  entry:  %d lookups == %d hits + %d misses "
+	    "(%d discards)\n",
+	    tag, avc_cache_stats[AVC_ENTRY_LOOKUPS],
+	    avc_cache_stats[AVC_ENTRY_HITS], avc_cache_stats[AVC_ENTRY_MISSES],
+	    avc_cache_stats[AVC_ENTRY_DISCARDS]);
+
+	printf("%s avc:  cav:  %d lookups == %d hits + %d misses\n",
+	    tag, avc_cache_stats[AVC_CAV_LOOKUPS],
+	    avc_cache_stats[AVC_CAV_HITS], avc_cache_stats[AVC_CAV_MISSES]);
+
+	printf("%s avc:  cav:  %d/%d probe/hit ratio\n",
+	    tag, avc_cache_stats[AVC_CAV_PROBES],
+	    avc_cache_stats[AVC_CAV_HITS]);
+}
+
+/*
+ * Display an access vector in human-readable form.
+ */
+void
+avc_dump_av(security_class_t tclass, access_vector_t av)
+{
+	char		**common_pts = 0;
+	access_vector_t	common_base = 0;
+	int		i;
+	int		i2;
+	int		perm;
+
+	if (av == 0) {
+		printf(" null");
+		return;
+	}
+
+	for (i = 0; i < AV_INHERIT_SIZE; i++) {
+		if (av_inherit[i].tclass == tclass) {
+			common_pts = av_inherit[i].common_pts;
+			common_base = av_inherit[i].common_base;
+			break;
+		}
+	}
+
+	printf(" {");
+	i = 0;
+	perm = 1;
+	while (perm < common_base) {
+		if (perm & av)
+			printf(" %s", common_pts[i]);
+		i++;
+		perm <<= 1;
+	}
+
+	while (i < sizeof (access_vector_t) * 8) {
+		if (perm & av) {
+			for (i2 = 0; i2 < AV_PERM_TO_STRING_SIZE; i2++) {
+				if ((av_perm_to_string[i2].tclass == tclass) &&
+				    (av_perm_to_string[i2].value == perm))
+					break;
+			}
+			if (i2 < AV_PERM_TO_STRING_SIZE)
+				printf(" %s", av_perm_to_string[i2].name);
+		}
+		i++;
+		perm <<= 1;
+	}
+
+	printf(" }");
+}
+
+/*
+ * Display a SID pair and a class in human-readable form.
+ */
+void
+avc_dump_query(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass)	/* IN */
+{
+	int			rc;
+	security_context_t	scontext;
+	uint32_t		scontext_len;
+
+	rc = security_sid_to_context(ssid, &scontext, &scontext_len);
+	if (rc)
+		printf("ssid=%d", ssid);
+	else {
+		printf("scontext=%s", scontext);
+		security_context_free(scontext);
+	}
+
+	rc = security_sid_to_context(tsid, &scontext, &scontext_len);
+	if (rc)
+		printf(" tsid=%d", tsid);
+	else {
+		printf(" tcontext=%s", scontext);
+		security_context_free(scontext);
+	}
+	printf(" tclass=%s", class_to_string[tclass]);
+}
+
+/*
+ * Initialize the cache.
+ */
+void
+avc_init(void)
+{
+	avc_node_t	*new;
+	int		i;
+
+	for (i = 0; i < AVC_NSTATS; i++)
+		avc_cache_stats[i] = 0;
+
+	for (i = 0; i < AVC_CACHE_SLOTS; i++)
+		avc_cache.slots[i] = 0;
+	avc_cache.lru_hint = 0;
+	avc_cache.activeNodes = 0;
+	avc_cache.latest_notif = 0;
+
+	for (i = 0; i < AVC_CACHE_MAXNODES; i++) {
+		new = (avc_node_t *) kmem_zalloc(sizeof (avc_node_t), KM_SLEEP);
+		if (!new) {
+			cmn_err(CE_WARN,
+			    "avc:  only able to allocate %d entries\n", i);
+			break;
+		}
+		new->next = avc_node_freelist;
+		avc_node_freelist = new;
+	}
+
+	avc_audit_buffer = (char *)kmem_zalloc(PAGESIZE, KM_SLEEP);
+	if (!avc_audit_buffer)
+		cmn_err(CE_WARN, "AVC:  unable to allocate audit buffer\n");
+
+	cmn_err(CE_CONT, "AVC: Initialized\n");
+}
+
+#if 0
+static void
+avc_hash_eval(char *tag)
+{
+	int		i;
+	int		chain_len;
+	int		max_chain_len;
+	int		slots_used;
+	avc_node_t	*node;
+
+	mutex_enter(&avc_lock);
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+		node = avc_cache.slots[i];
+		if (node) {
+			slots_used++;
+			chain_len = 0;
+			while (node) {
+				chain_len++;
+				node = node->next;
+			}
+			if (chain_len > max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	mutex_exit(&avc_lock);
+
+	printf("\n%s avc:  %d entries and %d/%d buckets used, longest "
+	    "chain length %d\n",
+	    tag, avc_cache.activeNodes, slots_used, AVC_CACHE_SLOTS,
+	    max_chain_len);
+}
+#else
+#define	avc_hash_eval(t)
+#endif
+
+/*
+ * Display the contents of the cache in human-readable form.
+ */
+void
+avc_dump_cache(char *tag)
+{
+	int		i;
+	int		chain_len;
+	int		max_chain_len;
+	int		slots_used;
+	avc_node_t	*node;
+
+	avc_dump_stats(tag);
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+		node = avc_cache.slots[i];
+		if (node) {
+			printf("\n%s avc:  slot %d:\n", tag, i);
+			slots_used++;
+			chain_len = 0;
+			while (node) {
+				avc_dump_query(node->ae.ssid, node->ae.tsid,
+				    node->ae.tclass);
+				printf(" allowed");
+				avc_dump_av(node->ae.tclass,
+				    node->ae.avd.allowed);
+				printf("\n");
+
+				chain_len++;
+				node = node->next;
+			}
+
+			if (chain_len > max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	printf("\n%s avc:  %d entries and %d/%d buckets used, longest "
+	    "chain length %d\n",
+	    tag, avc_cache.activeNodes, slots_used, AVC_CACHE_SLOTS,
+	    max_chain_len);
+
+	printf("%s avc:  latest_notif=%d\n", tag, avc_cache.latest_notif);
+}
+
+/*
+ * Reclaim a node from the cache for use.
+ */
+static inline avc_node_t *
+avc_reclaim_node(void)
+{
+	avc_node_t	*prev;
+	avc_node_t	*cur;
+	int		hvalue;
+	int		try;
+
+	hvalue = avc_cache.lru_hint;
+	for (try = 0; try < 2; try++) {
+		do {
+			prev = NULL;
+			cur = avc_cache.slots[hvalue];
+			while (cur) {
+				if (!cur->ae.used)
+					goto found;
+
+				cur->ae.used = 0;
+
+				prev = cur;
+				cur = cur->next;
+			}
+			hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1);
+		} while (hvalue != avc_cache.lru_hint);
+	}
+
+	panic("avc_reclaim_node");
+
+found:
+	avc_cache.lru_hint = hvalue;
+
+	if (prev == NULL)
+		avc_cache.slots[hvalue] = cur->next;
+	else
+		prev->next = cur->next;
+
+	return (cur);
+}
+
+/*
+ * Claim a node for use for a particular
+ * SID pair and class.
+ */
+static inline avc_node_t *
+avc_claim_node(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass)
+{
+	avc_node_t	*new;
+	int		hvalue;
+
+	hvalue = AVC_HASH(ssid, tsid, tclass);
+	if (avc_node_freelist) {
+		new = avc_node_freelist;
+		avc_node_freelist = avc_node_freelist->next;
+		avc_cache.activeNodes++;
+	} else {
+		new = avc_reclaim_node();
+		if (!new)
+			return (NULL);
+	}
+
+	new->ae.used = 1;
+	new->ae.ssid = ssid;
+	new->ae.tsid = tsid;
+	new->ae.tclass = tclass;
+	new->next = avc_cache.slots[hvalue];
+	avc_cache.slots[hvalue] = new;
+
+	return (new);
+}
+
+/*
+ * Search for a node that has the specified
+ * SID pair and class.
+ */
+static inline avc_node_t *
+avc_search_node(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, int *probes)
+{
+	avc_node_t	*cur;
+	int		hvalue;
+	int		tprobes = 1;
+
+	hvalue = AVC_HASH(ssid, tsid, tclass);
+	cur = avc_cache.slots[hvalue];
+	while (cur != NULL &&
+	    (ssid != cur->ae.ssid ||
+	    tclass != cur->ae.tclass ||
+	    tsid != cur->ae.tsid)) {
+		tprobes++;
+		cur = cur->next;
+	}
+
+	if (cur == NULL) {
+		/* cache miss */
+		return (NULL);
+	}
+
+	/* cache hit */
+	if (probes)
+		*probes = tprobes;
+
+	cur->ae.used = 1;
+
+	return (cur);
+}
+
+/*
+ * Look up an AVC entry that is valid for the
+ * `requested' permissions between the SID pair
+ * (`ssid', `tsid'), interpreting the permissions
+ * based on `tclass'.  If a valid AVC entry exists,
+ * then this function updates `aeref' to refer to the
+ * entry and returns 0. Otherwise, this function
+ * returns ENOENT.
+ */
+int
+avc_lookup(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested,	/* IN */
+	avc_entry_ref_t *aeref)	/* OUT */
+{
+	avc_node_t	*node;
+	int		probes;
+
+	avc_cache_stats_incr(AVC_CAV_LOOKUPS);
+	node = avc_search_node(ssid, tsid, tclass, &probes);
+
+	if (node && ((node->ae.avd.decided & requested) == requested)) {
+		avc_cache_stats_incr(AVC_CAV_HITS);
+		avc_cache_stats_add(AVC_CAV_PROBES, probes);
+		aeref->ae = &node->ae;
+		return (0);
+	}
+
+	avc_cache_stats_incr(AVC_CAV_MISSES);
+	return (ENOENT);
+}
+
+/*
+ * Insert an AVC entry for the SID pair
+ * (`ssid', `tsid') and class `tclass'.
+ * The access vectors and the sequence number are
+ * normally provided by the security server in
+ * response to a security_compute_av call.  If the
+ * sequence number `ae->avd.seqno' is not less than the latest
+ * revocation notification, then the function copies
+ * the access vectors into a cache entry, updates
+ * `aeref' to refer to the entry, and returns 0.
+ * Otherwise, this function returns EAGAIN.
+ */
+int
+avc_insert(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	struct avc_entry *ae,		/* IN */
+	avc_entry_ref_t *aeref)		/* OUT */
+{
+	avc_node_t	*node;
+
+	if (ae->avd.seqno < avc_cache.latest_notif) {
+		printf("avc:  seqno %d < latest_notif %d\n", ae->avd.seqno,
+		    avc_cache.latest_notif);
+		return (EAGAIN);
+	}
+
+	node = avc_claim_node(ssid, tsid, tclass);
+	if (!node) {
+		return (ENOMEM);
+	}
+
+	node->ae.avd.allowed = ae->avd.allowed;
+	node->ae.avd.decided = ae->avd.decided;
+	node->ae.avd.auditallow = ae->avd.auditallow;
+	node->ae.avd.auditdeny = ae->avd.auditdeny;
+	node->ae.avd.seqno = ae->avd.seqno;
+	aeref->ae = &node->ae;
+	return (0);
+}
+
+/*
+ * Audit the granting or denial of permissions.
+ */
+void
+avc_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t audited,	/* IN */
+	struct avc_entry *ae,		/* IN */
+	uint32_t denied,		/* IN */
+	avc_audit_data_t *a)		/* IN */
+{
+	if (a && a->type == AVC_AUDIT_DATA_DONTAUDIT)
+		return;
+
+	printf("\navc:  %s ", denied ? "denied" : "granted");
+	avc_dump_av(tclass, audited);
+	printf(" for ");
+	avc_dump_query(ssid, tsid, tclass);
+	printf("\n");
+}
+
+typedef struct avc_callback_node
+{
+	int (*callback)(uint32_t event,
+	    security_id_t ssid,
+	    security_id_t tsid,
+	    security_class_t tclass,
+	    access_vector_t perms,
+	    access_vector_t *out_retained);
+	uint32_t events;
+	security_id_t ssid;
+	security_id_t tsid;
+	security_class_t tclass;
+	access_vector_t perms;
+	struct avc_callback_node *next;
+} avc_callback_node_t;
+
+static avc_callback_node_t *avc_callbacks = NULL;
+
+/*
+ * Register a callback for events in the set `events'
+ * related to the SID pair (`ssid', `tsid') and
+ * and the permissions `perms', interpreting
+ * `perms' based on `tclass'.
+ */
+
+int
+avc_add_callback(int (*callback)(uint32_t event, security_id_t ssid,
+    security_id_t tsid, security_class_t tclass, access_vector_t perms,
+    access_vector_t *out_retained), uint32_t events, security_id_t ssid,
+    security_id_t tsid, security_class_t tclass, access_vector_t perms)
+{
+	avc_callback_node_t *c;
+
+	c = (avc_callback_node_t *) kmem_alloc(sizeof (avc_callback_node_t),
+	    KM_SLEEP);
+	if (!c)
+		return (ENOMEM);
+
+	c->callback = callback;
+	c->events = events;
+	c->ssid = ssid;
+	c->tsid = tsid;
+	c->perms = perms;
+	c->next = avc_callbacks;
+	avc_callbacks = c;
+
+	return (0);
+}
+
+
+#define	AVC_SIDCMP(x, y) \
+		((x) == (y) || (x) == SECSID_WILD || (y) == SECSID_WILD)
+
+/*
+ * Update the cache entry `node' based on the
+ * event `event' and permissions `perms'.
+ */
+static inline void
+avc_update_node(uint32_t event, avc_node_t *node, access_vector_t perms)
+{
+	switch (event) {
+	case AVC_CALLBACK_GRANT:
+		node->ae.avd.allowed |= perms;
+		break;
+	case AVC_CALLBACK_TRY_REVOKE:
+	case AVC_CALLBACK_REVOKE:
+		node->ae.avd.allowed &= ~perms;
+		break;
+	case AVC_CALLBACK_AUDITALLOW_ENABLE:
+		node->ae.avd.auditallow |= perms;
+		break;
+	case AVC_CALLBACK_AUDITALLOW_DISABLE:
+		node->ae.avd.auditallow &= ~perms;
+		break;
+	case AVC_CALLBACK_AUDITDENY_ENABLE:
+		node->ae.avd.auditdeny |= perms;
+		break;
+	case AVC_CALLBACK_AUDITDENY_DISABLE:
+		node->ae.avd.auditdeny &= ~perms;
+		break;
+	}
+}
+
+/*
+ * Update any cache entries that match the
+ * SID pair (`ssid', `tsid') and class `tclass'
+ * based on the event `event' and permissions
+ * `perms'.
+ */
+static int
+avc_update_cache(
+	uint32_t event, 		/* IN */
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms)		/* IN */
+{
+	avc_node_t	*node;
+	int		i;
+
+	mutex_enter(&avc_lock);
+
+	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
+		/* apply to all matching nodes */
+		for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+			for (node = avc_cache.slots[i]; node;
+			    node = node->next) {
+				if (AVC_SIDCMP(ssid, node->ae.ssid) &&
+				    AVC_SIDCMP(tsid, node->ae.tsid) &&
+				    tclass == node->ae.tclass) {
+					avc_update_node(event, node, perms);
+				}
+			}
+		}
+	} else {
+		/* apply to one node */
+		node = avc_search_node(ssid, tsid, tclass, 0);
+		if (node) {
+			avc_update_node(event, node, perms);
+		}
+	}
+
+	mutex_exit(&avc_lock);
+
+	return (0);
+}
+
+/*
+ * Update the cache state and invoke any
+ * registered callbacks that match the
+ * SID pair (`ssid', `tsid') and class `tclass'
+ * based on the event `event' and permissions
+ * `perms'.  Increase the latest revocation
+ * notification sequence number if appropriate.
+ */
+static int
+avc_control(
+	uint32_t event,			/* IN */
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	access_vector_t *out_retained)	/* OUT */
+{
+	avc_callback_node_t *c;
+	access_vector_t tretained = 0, cretained = 0;
+	int rc;
+
+	/*
+	 * try_revoke only removes permissions from the cache
+	 * state if they are not retained by the object manager.
+	 * Hence, try_revoke must wait until after the callbacks have
+	 * been invoked to update the cache state.
+	 */
+	if (event != AVC_CALLBACK_TRY_REVOKE)
+		(void) avc_update_cache(event, ssid, tsid, tclass, perms);
+
+	for (c = avc_callbacks; c; c = c->next) {
+		if ((c->events & event) &&
+		    AVC_SIDCMP(c->ssid, ssid) &&
+		    AVC_SIDCMP(c->tsid, tsid) &&
+		    c->tclass == tclass &&
+		    (c->perms & perms)) {
+			cretained = 0;
+			rc = c->callback(event, ssid, tsid, tclass,
+			    (c->perms & perms), &cretained);
+			if (rc)
+				return (rc);
+			tretained |= cretained;
+		}
+	}
+
+	if (event == AVC_CALLBACK_TRY_REVOKE) {
+		/* revoke any unretained permissions */
+		perms &= ~tretained;
+		(void) avc_update_cache(event, ssid, tsid, tclass, perms);
+		*out_retained = tretained;
+	}
+
+	mutex_enter(&avc_lock);
+	if (seqno > avc_cache.latest_notif)
+		avc_cache.latest_notif = seqno;
+	mutex_exit(&avc_lock);
+
+	return (0);
+}
+
+/* Grant previously denied permissions */
+int
+avc_ss_grant(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno)			/* IN */
+{
+	return avc_control(AVC_CALLBACK_GRANT, ssid, tsid, tclass, perms,
+	    seqno, 0);
+}
+
+/*
+ * Try to revoke previously granted permissions, but
+ * only if they are not retained as migrated permissions.
+ * Return the subset of permissions that are retained.
+ */
+int
+avc_ss_try_revoke(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	access_vector_t *out_retained)	/* OUT */
+{
+	return avc_control(AVC_CALLBACK_TRY_REVOKE, ssid, tsid, tclass, perms,
+	    seqno, out_retained);
+}
+
+/*
+ * Revoke previously granted permissions, even if
+ * they are retained as migrated permissions.
+ */
+int
+avc_ss_revoke(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno)			/* IN */
+{
+	return avc_control(AVC_CALLBACK_REVOKE,
+	    ssid, tsid, tclass, perms, seqno, 0);
+}
+
+/*
+ * Flush the cache and revalidate all migrated permissions.
+ */
+int
+avc_ss_reset(uint32_t seqno)
+{
+	avc_callback_node_t	*c;
+	int			rc;
+	avc_node_t		*node;
+	avc_node_t		*tmp;
+	int			i;
+
+	avc_hash_eval("reset");
+
+	mutex_enter(&avc_lock);
+
+	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+		node = avc_cache.slots[i];
+		while (node) {
+			tmp = node;
+			node = node->next;
+			tmp->ae.ssid = tmp->ae.tsid = SECSID_NULL;
+			tmp->ae.tclass = SECCLASS_NULL;
+			tmp->ae.avd.allowed = tmp->ae.avd.decided = 0;
+			tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = 0;
+			tmp->ae.used = 0;
+			tmp->next = avc_node_freelist;
+			avc_node_freelist = tmp;
+			avc_cache.activeNodes--;
+		}
+		avc_cache.slots[i] = 0;
+	}
+	avc_cache.lru_hint = 0;
+
+	mutex_exit(&avc_lock);
+
+	for (i = 0; i < AVC_NSTATS; i++)
+		avc_cache_stats[i] = 0;
+
+	for (c = avc_callbacks; c; c = c->next) {
+		if (c->events & AVC_CALLBACK_RESET) {
+			rc = c->callback(AVC_CALLBACK_RESET,
+				0, 0, 0, 0, 0);
+			if (rc)
+				return (rc);
+		}
+	}
+
+	mutex_enter(&avc_lock);
+	if (seqno > avc_cache.latest_notif)
+		avc_cache.latest_notif = seqno;
+	mutex_exit(&avc_lock);
+
+	return (0);
+}
+
+/* Enable or disable auditing of granted permissions */
+int
+avc_ss_set_auditallow(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	uint32_t enable)
+{
+	if (enable)
+		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
+			ssid, tsid, tclass, perms, seqno, 0);
+	else
+		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
+			ssid, tsid, tclass, perms, seqno, 0);
+}
+
+/* Enable or disable auditing of denied permissions */
+int
+avc_ss_set_auditdeny(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	uint32_t enable)
+{
+	if (enable)
+		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
+			ssid, tsid, tclass, perms, seqno, 0);
+	else
+		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
+			ssid, tsid, tclass, perms, seqno, 0);
+}
+
+/*
+ * Check permissions using an AVC entry ref.
+ *
+ * If the ref is null or the underlying AVC entry has been invalidated
+ * or the underlying AVC entry does not contain all the requested
+ * decisions, then this code falls through to avc_lookup.  In
+ * this case, the AVC entry ref will be updated appropriately.
+ */
+int
+avc_has_perm_ref_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested,	/* IN */
+	avc_entry_ref_t *aeref,		/* IN */
+	avc_audit_data_t *auditdata)	/* IN */
+{
+	struct avc_entry	*ae;
+	int			rc;
+	struct avc_entry	entry;
+	access_vector_t		denied;
+
+	mutex_enter(&avc_lock);
+	avc_cache_stats_incr(AVC_ENTRY_LOOKUPS);
+	ae = aeref->ae;
+	if (ae) {
+		if (ae->ssid == ssid &&
+		    ae->tsid == tsid &&
+		    ae->tclass == tclass &&
+		    ((ae->avd.decided & requested) == requested)) {
+			avc_cache_stats_incr(AVC_ENTRY_HITS);
+			ae->used = 1;
+		} else {
+			avc_cache_stats_incr(AVC_ENTRY_DISCARDS);
+			ae = 0;
+		}
+	}
+
+	if (!ae) {
+		avc_cache_stats_incr(AVC_ENTRY_MISSES);
+		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
+		if (rc) {
+			mutex_exit(&avc_lock);
+			rc = security_compute_av(ssid, tsid, tclass, requested,
+			    &entry.avd);
+			if (rc)
+				return (rc);
+			mutex_enter(&avc_lock);
+			rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
+			if (rc) {
+				mutex_exit(&avc_lock);
+				return (rc);
+			}
+		}
+		ae = aeref->ae;
+	}
+
+	denied = requested & ~(ae->avd.allowed);
+
+	if (!requested || denied) {
+		if (!requested || (denied & ae->avd.auditdeny))
+			avc_audit(ssid, tsid, tclass, denied, ae, AVC_AUDITDENY,
+			    auditdata);
+		if (flask_enforcing) {
+			mutex_exit(&avc_lock);
+			return (EACCES);
+		} else {
+			ae->avd.allowed |= requested;
+			mutex_exit(&avc_lock);
+			return (0);
+		}
+	}
+
+	if (requested & ae->avd.auditallow)
+		avc_audit(ssid, tsid, tclass, requested, ae, AVC_AUDITALLOW,
+		    auditdata);
+
+	mutex_exit(&avc_lock);
+	return (0);
+}
+
+/* Check permissions */
+int
+avc_has_perm_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested, 	/* IN */
+	avc_audit_data_t *auditdata)	/* IN */
+{
+	avc_entry_ref_t ref;
+	AVC_ENTRY_REF_INIT(&ref);
+	return (avc_has_perm_ref_audit(ssid, tsid, tclass, requested, &ref,
+	    auditdata));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/fmac/fmac.c	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,77 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * FMAC
+ */
+
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/kobj.h>
+#include <sys/fmac/security.h>
+#include <sys/fmac/fmac.h>
+
+char *fmac_default_policy_file = FMAC_POLICY_FILE;
+
+
+#ifdef DEBUG
+int flask_enforcing = 1;
+#endif /* DEBUG */
+
+void
+fmac_init()
+{
+	(void) fmac_load_policy(fmac_default_policy_file);
+}
+
+int
+fmac_load_policy(char *file)
+{
+	struct _buf *policy_handle;
+	int ret;
+
+	cmn_err(CE_CONT, "security: Loading policy %s\n", file);
+
+	if ((policy_handle = kobj_open_file(file)) ==
+	    (struct _buf *)-1) {
+		cmn_err(CE_WARN, "security: Unable to open %s\n", file);
+		return (ENOENT);
+	}
+
+	if ((ret = security_load_policy(policy_handle, 0)) < 0) {
+		cmn_err(CE_WARN, "security: Policy load failed %s\n", file);
+		kobj_close_file(policy_handle);
+		return (ret);
+	}
+
+	kobj_close_file(policy_handle);
+
+	cmn_err(CE_CONT, "security: Policy loaded from %s\n", file);
+
+	return (0);
+}
--- a/usr/src/uts/common/os/main.c	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/uts/common/os/main.c	Thu May 01 16:48:12 2008 -0700
@@ -79,6 +79,10 @@
 
 #include <c2/audit.h>
 
+#include <sys/fmac/fmac.h>
+#include <sys/fmac/security.h>
+#include <sys/fmac/avc.h>
+
 /* well known processes */
 proc_t *proc_sched;		/* memory scheduler */
 proc_t *proc_init;		/* init */
@@ -420,6 +424,11 @@
 	lgrp_plat_probe();
 
 	/*
+	 * Initialize the Access Vector Cache
+	 */
+	avc_init();
+
+	/*
 	 * Call all system initialization functions.
 	 */
 	for (initptr = &init_tbl[0]; *initptr; initptr++)
@@ -560,6 +569,11 @@
 #endif
 
 	/*
+	 * Load and initialize seurity policy
+	 */
+	fmac_init();
+
+	/*
 	 * Make init process; enter scheduling loop with system process.
 	 */
 
--- a/usr/src/uts/common/sys/Makefile	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/uts/common/sys/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -732,6 +732,26 @@
 	$(LVMHDRS)		\
 	$(DERIVED_LVMHDRS)
 
+DERIVED_FMACHDRS=		\
+	class_to_string.h	\
+	flask.h			\
+	initial_sid_to_string.h	\
+	av_inherit.h		\
+	common_perm_to_string.h	\
+	av_perm_to_string.h	\
+	av_permissions.h
+
+FMACHDRS=			\
+	avc.h			\
+	avc_ss.h		\
+	flask_types.h		\
+	fmac.h			\
+	security.h
+
+ALL_FMACHDRS=			\
+	$(FMACHDRS)		\
+	$(DERIVED_FMACHDRS)
+
 FMHDRS=				\
 	protocol.h		\
 	util.h
@@ -1039,6 +1059,7 @@
 	$(IBMFHDRS:%.h=ib/mgt/ibmf/%.check)		\
 	$(TAVORHDRS:%.h=ib/adapters/tavor/%.check)	\
 	$(ISOHDRS:%.h=iso/%.check)			\
+	$(FMACHDRS:%.h=fmac/%.check)			\
 	$(FMHDRS:%.h=fm/%.check)			\
 	$(FMFSHDRS:%.h=fm/fs/%.check)			\
 	$(FMIOHDRS:%.h=fm/io/%.check)			\
@@ -1119,6 +1140,7 @@
 
 install_h:			\
 	$(ROOTDIRS)		\
+	FMACDERIVED_H		\
 	LVMDERIVED_H		\
 	.WAIT			\
 	$(ROOTHDRS)		\
@@ -1126,6 +1148,7 @@
 	$(ROOTCRYPTOHDRS)	\
 	$(ROOTDCAMHDRS)		\
 	$(ROOTISOHDRS)		\
+	$(ROOTFMACHDRS)		\
 	$(ROOTFMHDRS)		\
 	$(ROOTFMFSHDRS)		\
 	$(ROOTFMIOHDRS)		\
@@ -1175,6 +1198,9 @@
 LVMDERIVED_H:
 	cd $(SRC)/uts/common/sys/lvm; pwd; $(MAKE)
 
+FMACDERIVED_H:
+	cd $(SRC)/uts/common/sys/fmac; pwd; $(MAKE)
+
 check:	$(CHECKHDRS)
 
 FRC:
--- a/usr/src/uts/common/sys/Makefile.syshdrs	Thu May 01 16:11:45 2008 -0700
+++ b/usr/src/uts/common/sys/Makefile.syshdrs	Thu May 01 16:48:12 2008 -0700
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -46,6 +46,9 @@
 fm/io/%.check:	fm/io/%.h
 	$(DOT_H_CHECK)
 
+fmac/%.check:   fmac/%.h
+	$(DOT_H_CHECK)
+
 fs/%.check:	fs/%.h
 	$(DOT_H_CHECK)
 
@@ -162,6 +165,7 @@
 	$(ROOTDIR)/fm/cpu	\
 	$(ROOTDIR)/fm/fs	\
 	$(ROOTDIR)/fm/io	\
+	$(ROOTDIR)/fmac		\
 	$(ROOTDIR)/fs		\
 	$(ROOTDIR)/ib		\
 	$(ROOTDIR)/ib/adapters/tavor	\
@@ -219,6 +223,8 @@
 
 ROOTISOHDRS= $(ISOHDRS:%=$(ROOTDIR)/iso/%)
 
+ROOTFMACHDRS= $(ALL_FMACHDRS:%=$(ROOTDIR)/fmac/%)
+
 ROOTFMHDRS= $(FMHDRS:%=$(ROOTDIR)/fm/%)
 ROOTFMCPUHDRS= $(FMCPUHDRS:%=$(ROOTDIR)/fm/cpu/%)
 ROOTFMIOHDRS= $(FMIOHDRS:%=$(ROOTDIR)/fm/io/%)
@@ -295,6 +301,9 @@
 $(ROOTDIR)/fm/io/%:                fm/io/%
 	$(INS.file)
 
+$(ROOTDIR)/fmac/%: fmac/%
+	$(INS.file)
+
 $(ROOTDIR)/fs/%: fs/%
 	$(INS.file)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/Makefile	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,69 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+UTSBASE = ../../..
+
+include $(UTSBASE)/../Makefile.master
+
+.KEEP_STATE:
+
+COMMONBASE = $(SRC)/common
+
+FMAC_MKFLASK_AWK = mkflask.awk
+FMAC_MKACCESSVECTOR_AWK = mkaccess_vector.awk
+
+DERIVED_FLASK_DEFS =						\
+	$(COMMONBASE)/fmac/policy/flask/security_classes	\
+	$(COMMONBASE)/fmac/policy/flask/initial_sids
+
+DERIVED_FLASK_FILES =						\
+	class_to_string.h					\
+	flask.h							\
+	initial_sid_to_string.h
+
+DERIVED_ACCESSVECTOR_DEFS =					\
+	$(COMMONBASE)/fmac/policy/flask/access_vectors
+
+DERIVED_ACCESSVECTOR_FILES =					\
+	av_inherit.h						\
+	common_perm_to_string.h					\
+	av_perm_to_string.h					\
+	av_permissions.h
+
+DERIVED_FILES =							\
+	$(DERIVED_FLASK_FILES)					\
+	$(DERIVED_ACCESSVECTOR_FILES)
+
+all install lint clean.lint:	$(DERIVED_FILES)
+
+clean clobber:
+	$(RM) $(DERIVED_FILES)
+
+$(DERIVED_FLASK_FILES): $(FMAC_MKFLASK_AWK) $(DERIVED_FLASK_DEFS)
+	$(NAWK) -f $(FMAC_MKFLASK_AWK) $(DERIVED_FLASK_DEFS)
+
+$(DERIVED_ACCESSVECTOR_FILES): $(FMAC_MKACCESSVECTOR_AWK) $(DERIVED_ACCESSVECTOR_DEFS)
+	$(NAWK) -f $(FMAC_MKACCESSVECTOR_AWK) $(DERIVED_ACCESSVECTOR_DEFS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/avc.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,244 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+#ifndef _SYS_FMAC_AVC_H
+#define	_SYS_FMAC_AVC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Access vector cache interface for object managers
+ */
+
+#include <sys/systm.h>
+#include <sys/fmac/flask_types.h>
+#include <sys/fmac/flask.h>
+#include <sys/fmac/av_permissions.h>
+#include <sys/fmac/security.h>
+
+/*
+ * An entry in the AVC.
+ */
+typedef struct avc_entry {
+	security_id_t		ssid;
+	security_id_t		tsid;
+	security_class_t	tclass;
+	struct av_decision	avd;
+	int			used;	 /* used recently */
+} avc_entry_t;
+
+
+/*
+ * A reference to an AVC entry.
+ */
+typedef struct avc_entry_ref {
+	avc_entry_t *ae;
+} avc_entry_ref_t;
+
+#define	AVC_ENTRY_REF_NULL { NULL }
+
+/* Initialize an AVC entry reference before first use. */
+#define	AVC_ENTRY_REF_INIT(h) { (h)->ae = NULL; }
+
+#define	AVC_ENTRY_REF_CPY(dst, src) (dst)->ae = (src)->ae
+
+
+typedef struct avc_audit_data {
+	char    type;
+#define	AVC_AUDIT_DATA_FS   1
+#define	AVC_AUDIT_DATA_NET  2
+#define	AVC_AUDIT_DATA_CAP  3
+#define	AVC_AUDIT_DATA_IPC  4
+#define	AVC_AUDIT_DATA_DONTAUDIT 5 /* never audit this permission check */
+	union 	{
+		/* add ancillary audit data here for your OS */
+		int fill;
+	} u;
+
+} avc_audit_data_t;
+
+/* Initialize an AVC audit data structure. */
+#define	AVC_AUDIT_DATA_INIT(_d, _t) {					\
+	memset((_d), 0, sizeof (struct avc_audit_data));		\
+	(_d)->type = AVC_AUDIT_DATA_##_t;				\
+}
+
+/*
+ * AVC statistics
+ */
+#define	AVC_ENTRY_LOOKUPS	0
+#define	AVC_ENTRY_HITS		1
+#define	AVC_ENTRY_MISSES	2
+#define	AVC_ENTRY_DISCARDS	3
+#define	AVC_CAV_LOOKUPS		4
+#define	AVC_CAV_HITS		5
+#define	AVC_CAV_PROBES		6
+#define	AVC_CAV_MISSES		7
+#define	AVC_NSTATS		8
+extern unsigned avc_cache_stats[AVC_NSTATS];
+void avc_dump_stats(char *tag);
+
+/*
+ * AVC display support
+ */
+void avc_dump_av(
+	security_class_t tclass,	/* IN */
+	access_vector_t av);		/* IN */
+
+void avc_dump_query(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass);	/* IN */
+
+void avc_dump_cache(char *tag);
+
+
+/*
+ * AVC operations
+ */
+
+/* Initialize the AVC */
+void avc_init(void);
+
+/*
+ * Look up an AVC entry that is valid for the
+ * `requested' permissions between the SID pair
+ * (`ssid', `tsid'), interpreting the permissions
+ * based on `tclass'.  If a valid AVC entry exists,
+ * then this function updates `aeref' to refer to the
+ * entry and returns 0. Otherwise, this function
+ * returns -ENOENT.
+ */
+int avc_lookup(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested,	/* IN */
+	avc_entry_ref_t *aeref);	/* OUT */
+
+/*
+ * Insert an AVC entry for the SID pair
+ * (`ssid', `tsid') and class `tclass'.
+ * The access vectors and the sequence number are
+ * normally provided by the security server in
+ * response to a security_compute_av call.  If the
+ * sequence number `ae->avd.seqno' is not less than the latest
+ * revocation notification, then the function copies
+ * the access vectors into a cache entry, updates
+ * `aeref' to refer to the entry, and returns 0.
+ * Otherwise, this function returns -EAGAIN.
+ */
+int avc_insert(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	struct avc_entry *ae,		/* IN */
+	avc_entry_ref_t *out_aeref);	/* OUT */
+
+
+/* Audit the checking of permissions */
+#define	AVC_AUDITALLOW	0
+#define	AVC_AUDITDENY	1
+void avc_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	struct avc_entry *ae,		/* IN */
+	uint32_t denied,		/* IN */
+	avc_audit_data_t *auditdata);   /* IN */
+
+/*
+ * Check permissions using an AVC entry ref.
+ *
+ * If the ref is null or the underlying AVC entry has been invalidated
+ * or the underlying AVC entry does not contain all the requested
+ * decisions, then this code falls through to avc_lookup.  In
+ * this case, the AVC entry ref will be updated appropriately.
+ */
+int avc_has_perm_ref_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested, 	/* IN */
+	avc_entry_ref_t *aeref,		/* IN */
+	avc_audit_data_t *auditdata);	/* IN */
+
+#define	avc_has_perm_ref(ssid, tsid, tclass, requested, aeref)		\
+	avc_has_perm_ref_audit(ssid, tsid, tclass, requested, aeref, 0)
+
+
+/* Check permissions */
+int
+avc_has_perm_audit(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t requested,	/* IN */
+	avc_audit_data_t *auditdata);	/* IN */
+
+#define	avc_has_perm(ssid, tsid, tclass, requested) \
+	avc_has_perm_audit(ssid, tsid, tclass, requested, 0)
+
+#define	AVC_CALLBACK_GRANT		1
+#define	AVC_CALLBACK_TRY_REVOKE		2
+#define	AVC_CALLBACK_REVOKE		4
+#define	AVC_CALLBACK_RESET		8
+#define	AVC_CALLBACK_AUDITALLOW_ENABLE	16
+#define	AVC_CALLBACK_AUDITALLOW_DISABLE	32
+#define	AVC_CALLBACK_AUDITDENY_ENABLE	64
+#define	AVC_CALLBACK_AUDITDENY_DISABLE	128
+
+/*
+ * Register a callback for events in the set `events'
+ * related to the SID pair (`ssid', `tsid') and
+ * and the permissions `perms', interpreting
+ * `perms' based on `tclass'.
+ */
+int avc_add_callback(int (*callback)(
+	    uint32_t event,
+	    security_id_t ssid,
+	    security_id_t tsid,
+	    security_class_t tclass,
+	    access_vector_t perms,
+	    access_vector_t *out_retained),
+	uint32_t events,
+	security_id_t ssid,
+	security_id_t tsid,
+	security_class_t tclass,
+	access_vector_t perms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FMAC_AVC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/avc_ss.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,111 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+#ifndef _SYS_FMAC_AVC_SS_H
+#define	_SYS_FMAC_AVC_SS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Access vector cache interface for the security server
+ */
+
+#include <sys/fmac/flask_types.h>
+#include <sys/fmac/flask.h>
+
+/*
+ * Any of the SID parameters may be wildcarded,
+ * in which case the operation is applied to all
+ * matching entries in the AVC.
+ */
+
+/* Grant previously denied permissions */
+int avc_ss_grant(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno);		/* IN */
+
+/*
+ * Try to revoke previously granted permissions, but
+ * only if they are not retained as migrated permissions.
+ * Return the subset of permissions that are retained.
+ */
+int avc_ss_try_revoke(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	access_vector_t *out_retained);	/* OUT */
+
+/*
+ * Revoke previously granted permissions, even if
+ * they are retained as migrated permissions.
+ */
+int avc_ss_revoke(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno);		/* IN */
+
+/*
+ * Flush the cache and revalidate all migrated permissions.
+ */
+int avc_ss_reset(uint32_t seqno);
+
+
+/* Enable or disable auditing of granted permissions */
+int avc_ss_set_auditallow(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	uint32_t enable);
+
+/* Enable or disable auditing of denied permissions */
+int avc_ss_set_auditdeny(
+	security_id_t ssid,		/* IN */
+	security_id_t tsid,		/* IN */
+	security_class_t tclass,	/* IN */
+	access_vector_t perms,		/* IN */
+	uint32_t seqno,			/* IN */
+	uint32_t enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FMAC_AVC_SS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/flask_types.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,96 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+#ifndef _SYS_FMAC_FLASK_TYPES_H
+#define	_SYS_FMAC_FLASK_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * The basic Flask types and constants.
+ */
+
+/*
+ * A security context is a set of security attributes
+ * associated with each subject and object controlled
+ * by the security policy.  The security context type
+ * is defined as a variable-length string that can be
+ * interpreted by any application or user with an
+ * understanding of the security policy.
+ */
+typedef char *security_context_t;
+
+/*
+ * An access vector (AV) is a collection of related permissions
+ * for a pair of SIDs.  The bits within an access vector
+ * are interpreted differently depending on the class of
+ * the object.  The access vector interpretations are specified
+ * in flask/access_vectors, and the corresponding constants
+ * for permissions are defined in the automatically generated
+ * header file av_permissions.h.
+ */
+typedef uint32_t access_vector_t;
+
+/*
+ * Each object class is identified by a fixed-size value.
+ * The set of security classes is specified in flask/security_classes,
+ * with the corresponding constants defined in the automatically
+ * generated header file flask.h.
+ */
+typedef uint16_t security_class_t;
+#define	SECCLASS_NULL			0x0000 /* no class */
+
+/* Private kernel definitions */
+
+/*
+ * A kernel security identifier (SID) is a fixed-size value
+ * that is mapped by the security server to a
+ * particular security context.  The SID mapping
+ * cannot be assumed to be consistent either across
+ * executions (reboots) of the security server or
+ * across security servers on different nodes.
+ *
+ * Certain SIDs (specified in flask/initial_sids) are
+ * predefined for system initialization. The corresponding
+ * constants are defined in the automatically generated
+ * header file flask.h.
+ */
+typedef uint32_t security_id_t;
+#define	SECSID_NULL			0x00000000 /* unspecified SID */
+#define	SECSID_WILD			0xFFFFFFFF /* wildcard SID */
+
+#define	SEMAGIC 0xf97cff8c
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FMAC_FLASK_TYPES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/fmac.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,58 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_FMAC_FMAC_H
+#define	_SYS_FMAC_FMAC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define	FMAC_MAX_CONTEXT_LEN	4096
+#define	FMAC_POLICY_FILE	"/etc/security/fmac/ss_policy"
+#define	FMAC_CONTEXT_ATTR	"SUNW.fmac.security"
+
+#if defined(_KERNEL)
+#if defined(DEBUG)
+extern int flask_enforcing;
+#else
+#define	flask_enforcing 1
+#endif /* DEBUG */
+#else
+#define	flask_enforcing 1
+#endif /* _KERNEL */
+
+#if defined(_KERNEL)
+extern char *fmac_default_policy_file;
+void fmac_init(void);
+int fmac_load_policy(char *file);
+#endif
+
+#endif /* _SYS_FMAC_FMAC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/generated_defs	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,25 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/mkaccess_vector.awk	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,280 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+function generate_preamble(s, f) {
+
+	while (getline headerdefs < "generated_defs")
+		print headerdefs > f;
+	close("generated_defs");
+
+	printf("\n") > f;
+
+	print("/* THIS FILE WAS GENERATED; DO NOT EDIT */\n") > f;
+	printf("#ifndef %s\n", s) > f;
+	printf("#define %s\n", s) > f;
+
+	printf("\n") > f;
+
+	printf("#ifdef __cplusplus\n") > f;
+	printf("extern \"C\" {\n") > f;
+	printf("#endif\n") > f;
+
+	printf("\n") > f;
+}
+
+function generate_postamble(s, f) {
+
+	printf("#ifdef __cplusplus\n") > f;
+	printf("}\n") > f;
+	printf("#endif\n\n") > f;
+
+	printf("#endif /* %s */\n", s) > f;
+
+}
+
+BEGIN	{
+	outfile = "av_permissions.h"
+	inheritfile = "av_inherit.h"
+	cpermfile = "common_perm_to_string.h"
+	avpermfile = "av_perm_to_string.h"
+	nextstate = "COMMON_OR_AV";
+
+	# Start of av_permissions.h
+	generate_preamble("_SYS_FMAC_AV_PERMISSIONS_H", outfile);
+
+	# Start of av_inherit.h
+	generate_preamble("_SYS_FMAC_AV_INHERIT_H", inheritfile);
+
+	# Start of common_perm_to_string.h
+	generate_preamble("_SYS_FMAC_COMMON_PERM_TO_STRING_H", cpermfile);
+
+	# Start of av_perm_to_string.h
+	generate_preamble("_SYS_FMAC_AV_PERM_TO_STRING_H", avpermfile);
+
+	printf("#include <sys/fmac/flask.h>\n") > inheritfile;
+	printf("#include <sys/fmac/common_perm_to_string.h>\n") > inheritfile;
+
+	printf("typedef struct\n") > inheritfile;
+	printf("{\n") > inheritfile;
+	printf("    security_class_t tclass;\n") > inheritfile;
+	printf("    char **common_pts;\n") > inheritfile; 
+	printf("    access_vector_t common_base;\n") > inheritfile; 
+	printf("} av_inherit_t;\n\n") > inheritfile;
+	printf("static av_inherit_t av_inherit[] = {\n") > inheritfile;
+	
+	printf("typedef struct\n") > avpermfile;
+	printf("{\n") > avpermfile;
+	printf("    security_class_t tclass;\n") > avpermfile;
+	printf("    access_vector_t value;\n") > avpermfile; 
+	printf("    char *name;\n") > avpermfile; 
+	printf("} av_perm_to_string_t;\n\n") > avpermfile;
+	printf("static av_perm_to_string_t av_perm_to_string[] = {\n") > avpermfile;
+}
+/^[ \t]*#/	{ 
+	next;
+}
+$1 == "common"	{ 
+	if (nextstate != "COMMON_OR_AV") {
+		printf("Parse error:  Unexpected COMMON definition on line %d\n", NR);
+		next;	
+	}
+
+	if ($2 in common_defined) {
+		printf("Duplicate COMMON definition for %s on line %d.\n", $2, NR);
+		next;
+	}	
+	common_defined[$2] = 1;
+
+	tclass = $2;
+	common_name = $2; 
+	permission = 1;
+
+	printf("static char *common_%s_perm_to_string[] =\n{\n", $2) > cpermfile;
+
+	nextstate = "COMMON-OPENBRACKET";
+	next;
+}
+$1 == "class"	{
+	if (nextstate != "COMMON_OR_AV" &&
+	    nextstate != "CLASS_OR_CLASS-OPENBRACKET") {
+		printf("Parse error:  Unexpected class definition on line %d\n", NR);
+			next;	
+	}
+
+	tclass = $2;
+
+	if (tclass in av_defined) {
+		printf("Duplicate access vector definition for %s on line %d\n", tclass, NR);
+		next;
+	} 
+	av_defined[tclass] = 1;
+
+	inherits = "";
+	permission = 1;
+
+	nextstate = "INHERITS_OR_CLASS-OPENBRACKET";
+	next;
+}
+$1 == "inherits" {			
+	if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET") {
+		printf("Parse error:  Unexpected INHERITS definition on line %d\n", NR);
+		next;	
+	}
+
+	if (!($2 in common_defined)) {
+		printf("COMMON %s is not defined (line %d).\n", $2, NR);
+		next;
+	}
+
+	inherits = $2;
+	permission = common_base[$2];
+
+	for (combined in common_perms) {
+		split(combined,separate, SUBSEP);
+		if (separate[1] == inherits) {
+			printf("#define %s__%s", toupper(tclass), toupper(separate[2])) > outfile; 
+			spaces = 40 - (length(separate[2]) + length(tclass));
+			if (spaces < 1)
+			      spaces = 1;
+			for (i = 0; i < spaces; i++) 
+				printf(" ") > outfile; 
+			printf("0x%08xUL\n", common_perms[combined]) > outfile; 
+		}
+	}
+	printf("\n") > outfile;
+	
+	printf("   { SECCLASS_%s, common_%s_perm_to_string, 0x%08xUL },\n", toupper(tclass), inherits, permission) > inheritfile; 
+
+	nextstate = "CLASS_OR_CLASS-OPENBRACKET";
+	next;
+}
+$1 == "{"	{ 
+	if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET" &&
+	    nextstate != "CLASS_OR_CLASS-OPENBRACKET" &&
+	    nextstate != "COMMON-OPENBRACKET") {
+		printf("Parse error:  Unexpected { on line %d\n", NR);
+		next;
+	}
+
+	if (nextstate == "INHERITS_OR_CLASS-OPENBRACKET")
+		nextstate = "CLASS-CLOSEBRACKET";
+
+	if (nextstate == "CLASS_OR_CLASS-OPENBRACKET")
+		nextstate = "CLASS-CLOSEBRACKET";
+
+	if (nextstate == "COMMON-OPENBRACKET")
+		nextstate = "COMMON-CLOSEBRACKET";
+}
+/[a-z][a-z_]*/	{
+	if (nextstate != "COMMON-CLOSEBRACKET" &&
+	    nextstate != "CLASS-CLOSEBRACKET") {
+		printf("Parse error:  Unexpected symbol %s on line %d\n", $1, NR);		
+		next;
+	}
+
+	if (nextstate == "COMMON-CLOSEBRACKET") {
+		if ((common_name,$1) in common_perms) {
+			printf("Duplicate permission %s for common %s on line %d.\n", $1, common_name, NR);
+			next;
+		}
+
+		common_perms[common_name,$1] = permission;
+
+		printf("#define COMMON_%s__%s", toupper(common_name), toupper($1)) > outfile; 
+
+		printf("    \"%s\",\n", $1) > cpermfile;
+	} else {
+		if ((tclass,$1) in av_perms) {
+			printf("Duplicate permission %s for %s on line %d.\n", $1, tclass, NR);
+			next;
+		}
+
+		av_perms[tclass,$1] = permission;
+		
+		if (inherits != "") {
+			if ((inherits,$1) in common_perms) {
+				printf("Permission %s in %s on line %d conflicts with common permission.\n", $1, tclass, inherits, NR);
+				next;
+			}
+		}
+
+		printf("#define %s__%s", toupper(tclass), toupper($1)) > outfile; 
+
+		printf("   { SECCLASS_%s, %s__%s, \"%s\" },\n", toupper(tclass), toupper(tclass), toupper($1), $1) > avpermfile; 
+	}
+
+	spaces = 40 - (length($1) + length(tclass));
+
+	if (spaces < 1)
+	      spaces = 1;
+
+	for (i = 0; i < spaces; i++) 
+		printf(" ") > outfile; 
+	printf("0x%08xUL\n", permission) > outfile; 
+	permission = permission * 2;
+}
+$1 == "}"	{
+	if (nextstate != "CLASS-CLOSEBRACKET" && 
+	    nextstate != "COMMON-CLOSEBRACKET") {
+		printf("Parse error:  Unexpected } on line %d\n", NR);
+		next;
+	}
+
+	if (nextstate == "COMMON-CLOSEBRACKET") {
+		common_base[common_name] = permission;
+		printf("};\n\n") > cpermfile; 
+	}
+
+	printf("\n") > outfile;
+
+	nextstate = "COMMON_OR_AV";
+}
+END	{
+	if (nextstate != "COMMON_OR_AV" && nextstate != "CLASS_OR_CLASS-OPENBRACKET")
+		printf("Parse error:  Unexpected end of file\n");
+
+	# End of av_permissions.h
+	generate_postamble("_SYS_FMAC_AV_PERMISSIONS_H", outfile);
+
+	# End of common_perm_to_string.h
+	generate_postamble("_SYS_FMAC_COMMON_PERM_TO_STRING_H", cpermfile);
+
+	printf("};\n\n") > inheritfile;
+	printf("#define AV_INHERIT_SIZE (sizeof (av_inherit)/sizeof (av_inherit_t))\n\n") > inheritfile;
+
+	# End of av_inherit.h
+	generate_postamble("_SYS_FMAC_AV_INHERIT_H", inheritfile);
+
+	printf("};\n\n") > avpermfile;
+	printf("#define AV_PERM_TO_STRING_SIZE (sizeof (av_perm_to_string)/sizeof (av_perm_to_string_t))\n\n") > avpermfile;
+	# End of av_perm_to_string.h
+	generate_postamble("_SYS_FMAC_AV_PERM_TO_STRING_H", avpermfile);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/mkflask.awk	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,153 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Original files contributed to OpenSolaris.org under license by the
+# United States Government (NSA) to Sun Microsystems, Inc.
+#
+
+function generate_preamble(s, f) {
+
+	while (getline headerdefs < "generated_defs")
+		print headerdefs > f;
+	close("generated_defs");
+
+	printf("\n") > f;
+
+	print("/* THIS FILE WAS GENERATED; DO NOT EDIT */\n") > f;
+	printf("#ifndef %s\n", s) > f;
+	printf("#define %s\n", s) > f;
+
+	printf("\n") > f;
+
+	printf("#ifdef __cplusplus\n") > f;
+	printf("extern \"C\" {\n") > f;
+	printf("#endif\n") > f;
+
+	printf("\n") > f;
+}
+
+function generate_postamble(s, f) {
+
+	printf("#ifdef __cplusplus\n") > f;
+	printf("}\n") > f;
+	printf("#endif\n\n") > f;
+
+	printf("#endif /* %s */\n", s) > f;
+
+}
+
+BEGIN	{
+	outfile = "flask.h"
+	debugfile = "class_to_string.h"
+	debugfile2 = "initial_sid_to_string.h"
+	nextstate = "CLASS";
+
+	# Start of flask.h 
+	generate_preamble("_SYS_FMAC_FLASK_H", outfile);
+	printf("\n/*\n * Security object class definitions\n */\n") > outfile;
+
+	# Start of class_to_string.h
+	generate_preamble("_SYS_FMAC_CLASS_TO_STRING_H", debugfile);
+	printf("/*\n * Security object class definitions\n */\n") > debugfile;
+	printf("static char *class_to_string[] =\n{\n") > debugfile;
+	printf("    \"null\",\n") > debugfile;
+
+	# Start of initial_sid_to_string.h
+	generate_preamble("_SYS_FMAC_INITIAL_SID_TO_STRING_H", debugfile2);
+	printf("static char *initial_sid_to_string[] =\n{\n") > debugfile2;
+	printf("    \"null\",\n") > debugfile2;
+}
+/^[ \t]*#/	{ 
+	next;
+}
+$1 == "class"	{ 
+	if (nextstate != "CLASS") {
+		printf("Parse error:  Unexpected class definition on line %d\n", NR);
+		next;	
+	}
+
+	if ($2 in class_found) {
+		printf("Duplicate class definition for %s on line %d.\n", $2, NR);
+		next;
+	}	
+	class_found[$2] = 1;
+
+	class_value++;
+
+	printf("#define SECCLASS_%s", toupper($2)) > outfile;
+
+	for (i = 0; i < 40 - length($2); i++) 
+		printf(" ") > outfile; 
+
+	printf("%d\n", class_value) > outfile; 
+
+	printf("    \"%s\",\n", $2) > debugfile;
+}
+$1 == "sid"	{
+	if (nextstate == "CLASS") {
+		nextstate = "SID";
+		printf("};\n\n") > debugfile;
+		printf("\n/*\n * Security identifier indices for initial entities\n */\n") > outfile;			    
+	}
+
+	if ($2 in sid_found) {
+		printf("Duplicate SID definition for %s on line %d.\n", $2, NR);
+		next;
+	}	
+	sid_found[$2] = 1;
+	sid_value++;
+
+	printf("#define SECINITSID_%s", toupper($2)) > outfile;
+
+	for (i = 0; i < 37 - length($2); i++) 
+		printf(" ") > outfile; 
+
+	printf("%d\n", sid_value) > outfile; 
+		printf("    \"%s\",\n", $2) > debugfile2;
+}
+END	{
+	if (nextstate != "SID")
+		printf("Parse error:  Unexpected end of file\n");
+
+	printf("\n#define SECINITSID_NUM") > outfile;
+
+	for (i = 0; i < 34; i++) 
+		printf(" ") > outfile; 
+
+	printf("%d\n\n", sid_value) > outfile; 
+
+	# End of flask.h
+	generate_postamble("_SYS_FMAC_FLASK_H", outfile);
+
+	# End of class_to_string.h
+	generate_postamble("_SYS_FMAC_CLASS_TO_STRING_H", debugfile);
+
+	printf("};\n\n") > debugfile2;
+
+	# End of initial_sid_to_string.h
+	generate_postamble("_SYS_FMAC_INITIAL_SID_TO_STRING_H", debugfile2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/fmac/security.h	Thu May 01 16:48:12 2008 -0700
@@ -0,0 +1,217 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Original files contributed to OpenSolaris.org under license by the
+ * United States Government (NSA) to Sun Microsystems, Inc.
+ */
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+#ifndef _SYS_FMAC_SECURITY_H
+#define	_SYS_FMAC_SECURITY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Security server interface.
+ */
+
+#include <sys/fmac/flask_types.h>
+#include <sys/fmac/flask.h>
+#include <sys/types.h>
+
+/* Initialize the security server */
+int security_init(void);
+
+/* Load the security policy. */
+int security_load_policy(void *data, size_t len);
+
+/*
+ * Compute access vectors based on a SID pair for
+ * the permissions in a particular class.
+ */
+struct av_decision {
+	access_vector_t allowed;
+	access_vector_t decided;
+	access_vector_t auditallow;
+	access_vector_t auditdeny;
+	uint32_t seqno;
+};
+int security_compute_av(
+	security_id_t ssid,			/* IN */
+	security_id_t tsid,			/* IN */
+	security_class_t tclass,		/* IN */
+	access_vector_t requested,		/* IN */
+	struct av_decision *avd);		/* OUT */
+
+/*
+ * Compute a SID to use for labeling a new object in the
+ * class `tclass' based on a SID pair.
+ */
+int security_transition_sid(
+	security_id_t ssid,			/* IN */
+	security_id_t tsid,			/* IN */
+	security_class_t tclass,		/* IN */
+	security_id_t *out_sid);		/* OUT */
+
+/*
+ * Compute a SID to use when selecting a member of a
+ * polyinstantiated object of class `tclass' based on
+ * a SID pair.
+ */
+int security_member_sid(
+	security_id_t ssid,			/* IN */
+	security_id_t tsid,			/* IN */
+	security_class_t tclass,		/* IN */
+	security_id_t *out_sid);		/* OUT */
+
+/*
+ * Compute a SID to use for relabeling an object in the
+ * class `tclass' based on a SID pair.
+ */
+int security_change_sid(
+	security_id_t ssid,			/* IN */
+	security_id_t tsid,			/* IN */
+	security_class_t tclass,		/* IN */
+	security_id_t *out_sid);		/* OUT */
+
+/*
+ * Write the security context string representation of
+ * the context associated with `sid' into a dynamically
+ * allocated string of the correct size.  Set `*scontext'
+ * to point to this string and set `*scontext_len' to
+ * the length of the string.
+ */
+int security_sid_to_context(
+	security_id_t  sid,			/* IN */
+	security_context_t *scontext,		/* OUT */
+	uint32_t *scontext_len);		/* OUT */
+
+/*
+ * Free a security context.
+ */
+void security_context_free(security_context_t scontext);
+
+/*
+ * Return a SID associated with the security context that
+ * has the string representation specified by `scontext'.
+ */
+int security_context_to_sid(
+	security_context_t scontext,		/* IN */
+	uint32_t scontext_len,			/* IN */
+	security_id_t *out_sid);		/* OUT */
+
+/*
+ * Generate the set of SIDs for legal security contexts
+ * for a given user that can be reached by `fromsid'.
+ * Set `*sids' to point to a dynamically allocated
+ * array containing the set of SIDs.  Set `*nel' to the
+ * number of elements in the array.
+ */
+int security_get_user_sids(
+	security_id_t callsid,
+	char *username,
+	security_id_t **sids,
+	uint32_t *nel);
+
+/*
+ * Return the SIDs to use for an unlabeled file system
+ * that is being mounted from the device with the
+ * the kdevname `name'.  The `fs_sid' SID is returned for
+ * the file system and the `file_sid' SID is returned
+ * for all files within that file system.
+ */
+int security_fs_sid(
+	char *dev,				/* IN */
+	security_id_t *fs_sid,			/* OUT  */
+	security_id_t *file_sid);		/* OUT */
+
+/*
+ * Return the SID of the port specified by
+ * `domain', `type', `protocol', and `port'.
+ */
+int security_port_sid(
+	uint16_t domain,
+	uint16_t type,
+	uint8_t protocol,
+	uint16_t port,
+	security_id_t *out_sid);
+
+/*
+ * Return the SIDs to use for a network interface
+ * with the name `name'.  The `if_sid' SID is returned for
+ * the interface and the `msg_sid' SID is returned as
+ * the default SID for messages received on the
+ * interface.
+ */
+int security_netif_sid(
+	char *name,
+	security_id_t *if_sid,
+	security_id_t *msg_sid);
+
+/*
+ * Return the SID of the node specified by the address
+ * `addr' where `addrlen' is the length of the address
+ * in bytes and `domain' is the communications domain or
+ * address family in which the address should be interpreted.
+ */
+int security_node_sid(
+	uint16_t domain,
+	void *addr,
+	uint32_t addrlen,
+	security_id_t *out_sid);
+
+/*
+ * Return a value indicating how to handle labeling for the
+ * the specified filesystem type, and optionally return a SID
+ * for the filesystem object.
+ */
+#define	SECURITY_FS_USE_XATTR	1 /* use xattr */
+#define	SECURITY_FS_USE_TRANS	2 /* use transition SIDs, e.g. devpts/tmpfs */
+#define	SECURITY_FS_USE_TASK	3 /* use task SIDs, e.g. pipefs/sockfs */
+#define	SECURITY_FS_USE_GENFS	4 /* use the genfs support */
+#define	SECURITY_FS_USE_NONE	5 /* no labeling support */
+int security_fs_use(
+	const char *fstype,			/* IN */
+	unsigned int *behavior,			/* OUT */
+	security_id_t *sid);			/* OUT  */
+
+/*
+ * Return the SID to use for a file in a filesystem
+ * that cannot support a persistent label mapping or use another
+ * fixed labeling behavior like transition SIDs or task SIDs.
+ */
+int security_genfs_sid(
+	const char *fstype,			/* IN */
+	char *name,				/* IN */
+	security_class_t sclass,		/* IN */
+	security_id_t *sid);			/* OUT  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FMAC_SECURITY_H */