<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"> /dev/null                                                |    0 
 25-akpm/security/Kconfig                                 |    2 
 25-akpm/security/Makefile                                |    6 
 25-akpm/security/selinux/Kconfig                         |   34 
 25-akpm/security/selinux/Makefile                        |   10 
 25-akpm/security/selinux/avc.c                           | 1115 ++++
 25-akpm/security/selinux/hooks.c                         | 3405 +++++++++++++++
 25-akpm/security/selinux/include/av_inherit.h            |   35 
 25-akpm/security/selinux/include/av_perm_to_string.h     |  120 
 25-akpm/security/selinux/include/av_permissions.h        |  550 ++
 25-akpm/security/selinux/include/avc.h                   |  159 
 25-akpm/security/selinux/include/avc_ss.h                |   27 
 25-akpm/security/selinux/include/class_to_string.h       |   39 
 25-akpm/security/selinux/include/common_perm_to_string.h |   65 
 25-akpm/security/selinux/include/flask.h                 |   71 
 25-akpm/security/selinux/include/initial_sid_to_string.h |   32 
 25-akpm/security/selinux/include/objsec.h                |   88 
 25-akpm/security/selinux/include/security.h              |   70 
 25-akpm/security/selinux/selinuxfs.c                     |  593 ++
 25-akpm/security/selinux/ss/Makefile                     |   14 
 25-akpm/security/selinux/ss/avtab.c                      |  264 +
 25-akpm/security/selinux/ss/avtab.h                      |   68 
 25-akpm/security/selinux/ss/constraint.h                 |   54 
 25-akpm/security/selinux/ss/context.h                    |  117 
 25-akpm/security/selinux/ss/ebitmap.c                    |  332 +
 25-akpm/security/selinux/ss/ebitmap.h                    |   49 
 25-akpm/security/selinux/ss/global.h                     |   17 
 25-akpm/security/selinux/ss/hashtab.c                    |  277 +
 25-akpm/security/selinux/ss/hashtab.h                    |  125 
 25-akpm/security/selinux/ss/mls.c                        |  741 +++
 25-akpm/security/selinux/ss/mls.h                        |   99 
 25-akpm/security/selinux/ss/mls_types.h                  |   58 
 25-akpm/security/selinux/ss/policydb.c                   | 1429 ++++++
 25-akpm/security/selinux/ss/policydb.h                   |  256 +
 25-akpm/security/selinux/ss/services.c                   | 1413 ++++++
 25-akpm/security/selinux/ss/services.h                   |   21 
 25-akpm/security/selinux/ss/sidtab.c                     |  329 +
 25-akpm/security/selinux/ss/sidtab.h                     |   59 
 25-akpm/security/selinux/ss/symtab.c                     |   40 
 25-akpm/security/selinux/ss/symtab.h                     |   23 
 40 files changed, 12206 insertions(+)

diff -puN security/Kconfig~selinux security/Kconfig
--- 25/security/Kconfig~selinux	Thu Jul 17 09:38:01 2003
+++ 25-akpm/security/Kconfig	Thu Jul 17 09:38:01 2003
@@ -44,5 +44,7 @@ config SECURITY_ROOTPLUG
 	  
 	  If you are unsure how to answer this question, answer N.
 
+source security/selinux/Kconfig
+
 endmenu
 
diff -puN -L security/Kconfig:1.1.1.2 /dev/null /dev/null
diff -puN security/Makefile~selinux security/Makefile
--- 25/security/Makefile~selinux	Thu Jul 17 09:38:01 2003
+++ 25-akpm/security/Makefile	Thu Jul 17 09:38:01 2003
@@ -2,6 +2,8 @@
 # Makefile for the kernel security code
 #
 
+subdir-$(CONFIG_SECURITY_SELINUX)	+= selinux
+
 # if we don't select a security model, use the default capabilities
 ifneq ($(CONFIG_SECURITY),y)
 obj-y		+= capability.o
@@ -9,5 +11,9 @@ endif
 
 # Object file lists
 obj-$(CONFIG_SECURITY)			+= security.o dummy.o
+# Must precede capability.o in order to stack properly.
+ifeq ($(CONFIG_SECURITY_SELINUX),y)
+	obj-$(CONFIG_SECURITY_SELINUX)	+= selinux/built-in.o
+endif
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
diff -puN -L security/Makefile:1.1.1.1 /dev/null /dev/null
diff -puN /dev/null security/selinux/avc.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/avc.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,1115 @@
+/*
+ * Implementation of the kernel access vector cache (AVC).
+ *
+ * Authors:  Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ *           James Morris &lt;jmorris@redhat.com&gt;
+ *
+ * Copyright (C) 2003 Red Hat, Inc., James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2,
+ *      as published by the Free Software Foundation.
+ */
+#include &lt;linux/types.h&gt;
+#include &lt;linux/stddef.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/slab.h&gt;
+#include &lt;linux/fs.h&gt;
+#include &lt;linux/dcache.h&gt;
+#include &lt;linux/skbuff.h&gt;
+#include &lt;net/sock.h&gt;
+#include &lt;linux/un.h&gt;
+#include &lt;net/af_unix.h&gt;
+#include &lt;linux/ip.h&gt;
+#include &lt;linux/udp.h&gt;
+#include &lt;linux/tcp.h&gt;
+#include "avc.h"
+#include "avc_ss.h"
+#include "class_to_string.h"
+#include "common_perm_to_string.h"
+#include "av_inherit.h"
+#include "av_perm_to_string.h"
+#include "objsec.h"
+
+#define AVC_CACHE_SLOTS		512
+#define AVC_CACHE_MAXNODES	410
+
+struct avc_entry {
+	u32			ssid;
+	u32			tsid;
+	u16			tclass;
+	struct av_decision	avd;
+	int			used;	/* used recently */
+};
+
+struct avc_node {
+	struct avc_entry	ae;
+	struct avc_node		*next;
+};
+
+struct avc_cache {
+	struct avc_node	*slots[AVC_CACHE_SLOTS];
+	u32		lru_hint;	/* LRU hint for reclaim scan */
+	u32		active_nodes;
+	u32		latest_notif;	/* latest revocation notification */
+};
+
+struct avc_callback_node {
+	int (*callback) (u32 event, u32 ssid, u32 tsid,
+	                 u16 tclass, u32 perms,
+	                 u32 *out_retained);
+	u32 events;
+	u32 ssid;
+	u32 tsid;
+	u16 tclass;
+	u32 perms;
+	struct avc_callback_node *next;
+};
+
+static spinlock_t avc_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t avc_log_lock = SPIN_LOCK_UNLOCKED;
+static struct avc_node *avc_node_freelist = NULL;
+static struct avc_cache avc_cache;
+static char *avc_audit_buffer = NULL;
+static unsigned avc_cache_stats[AVC_NSTATS];
+static struct avc_callback_node *avc_callbacks = NULL;
+static unsigned int avc_log_level = 4; /* default:  KERN_WARNING */
+static char avc_level_string[4] = "&lt; &gt;";
+
+static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
+{
+	return (ssid ^ (tsid&lt;&lt;2) ^ (tclass&lt;&lt;4)) &amp; (AVC_CACHE_SLOTS - 1);
+}
+
+/**
+ * avc_dump_av - Display an access vector in human-readable form.
+ * @tclass: target security class
+ * @av: access vector
+ */
+void avc_dump_av(u16 tclass, u32 av)
+{
+	char **common_pts = 0;
+	u32 common_base = 0;
+	int i, i2, perm;
+
+	if (av == 0) {
+		printk(" null");
+		return;
+	}
+
+	for (i = 0; i &lt; ARRAY_SIZE(av_inherit); i++) {
+		if (av_inherit[i].tclass == tclass) {
+			common_pts = av_inherit[i].common_pts;
+			common_base = av_inherit[i].common_base;
+			break;
+		}
+	}
+
+	printk(" {");
+	i = 0;
+	perm = 1;
+	while (perm &lt; common_base) {
+		if (perm &amp; av)
+			printk(" %s", common_pts[i]);
+		i++;
+		perm &lt;&lt;= 1;
+	}
+
+	while (i &lt; sizeof(av) * 8) {
+		if (perm &amp; av) {
+			for (i2 = 0; i2 &lt; ARRAY_SIZE(av_perm_to_string); i2++) {
+				if ((av_perm_to_string[i2].tclass == tclass) &amp;&amp;
+				    (av_perm_to_string[i2].value == perm))
+					break;
+			}
+			if (i2 &lt; ARRAY_SIZE(av_perm_to_string))
+				printk(" %s", av_perm_to_string[i2].name);
+		}
+		i++;
+		perm &lt;&lt;= 1;
+	}
+
+	printk(" }");
+}
+
+/**
+ * avc_dump_query - Display a SID pair and a class in human-readable form.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ */
+void avc_dump_query(u32 ssid, u32 tsid, u16 tclass)
+{
+	int rc;
+	char *scontext;
+	u32 scontext_len;
+
+ 	rc = security_sid_to_context(ssid, &amp;scontext, &amp;scontext_len);
+	if (rc)
+		printk("ssid=%d", ssid);
+	else {
+		printk("scontext=%s", scontext);
+		kfree(scontext);
+	}
+
+	rc = security_sid_to_context(tsid, &amp;scontext, &amp;scontext_len);
+	if (rc)
+		printk(" tsid=%d", tsid);
+	else {
+		printk(" tcontext=%s", scontext);
+		kfree(scontext);
+	}
+	printk(" tclass=%s", class_to_string[tclass]);
+}
+
+/**
+ * avc_init - Initialize the AVC.
+ *
+ * Initialize the access vector cache.
+ */
+void avc_init(void)
+{
+	struct avc_node	*new;
+	int i;
+
+	for (i = 0; i &lt; AVC_NSTATS; i++)
+		avc_cache_stats[i] = 0;
+
+	for (i = 0; i &lt; AVC_CACHE_SLOTS; i++)
+		avc_cache.slots[i] = 0;
+	avc_cache.lru_hint = 0;
+	avc_cache.active_nodes = 0;
+	avc_cache.latest_notif = 0;
+
+	for (i = 0; i &lt; AVC_CACHE_MAXNODES; i++) {
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			printk(KERN_WARNING "avc:  only able to allocate "
+			       "%d entries\n", i);
+			break;
+		}
+		memset(new, 0, sizeof(*new));
+		new-&gt;next = avc_node_freelist;
+		avc_node_freelist = new;
+	}
+
+	avc_audit_buffer = (char *)__get_free_page(GFP_ATOMIC);
+	if (!avc_audit_buffer)
+		panic("AVC:  unable to allocate audit buffer\n");
+
+	avc_level_string[1] = '0' + avc_log_level;
+}
+
+#if 0
+static void avc_hash_eval(char *tag)
+{
+	int i, chain_len, max_chain_len, slots_used;
+	struct avc_node *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amp;avc_lock,flags);
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i &lt; AVC_CACHE_SLOTS; i++) {
+		node = avc_cache.slots[i];
+		if (node) {
+			slots_used++;
+			chain_len = 0;
+			while (node) {
+				chain_len++;
+				node = node-&gt;next;
+			}
+			if (chain_len &gt; max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "%s avc:  %d entries and %d/%d buckets used, longest "
+	       "chain length %d\n", tag, avc_cache.active_nodes, slots_used,
+	       AVC_CACHE_SLOTS, max_chain_len);
+}
+#else
+static inline void avc_hash_eval(char *tag)
+{ }
+#endif
+
+static inline struct avc_node *avc_reclaim_node(void)
+{
+	struct avc_node *prev, *cur;
+	int hvalue, try;
+
+	hvalue = avc_cache.lru_hint;
+	for (try = 0; try &lt; 2; try++) {
+		do {
+			prev = NULL;
+			cur = avc_cache.slots[hvalue];
+			while (cur) {
+				if (!cur-&gt;ae.used)
+					goto found;
+
+				cur-&gt;ae.used = 0;
+
+				prev = cur;
+				cur = cur-&gt;next;
+			}
+			hvalue = (hvalue + 1) &amp; (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-&gt;next;
+	else
+		prev-&gt;next = cur-&gt;next;
+
+	return cur;
+}
+
+static inline struct avc_node *avc_claim_node(u32 ssid,
+                                              u32 tsid, u16 tclass)
+{
+	struct avc_node *new;
+	int hvalue;
+
+	hvalue = avc_hash(ssid, tsid, tclass);
+	if (avc_node_freelist) {
+		new = avc_node_freelist;
+		avc_node_freelist = avc_node_freelist-&gt;next;
+		avc_cache.active_nodes++;
+	} else {
+		new = avc_reclaim_node();
+		if (!new)
+			goto out;
+	}
+
+	new-&gt;ae.used = 1;
+	new-&gt;ae.ssid = ssid;
+	new-&gt;ae.tsid = tsid;
+	new-&gt;ae.tclass = tclass;
+	new-&gt;next = avc_cache.slots[hvalue];
+	avc_cache.slots[hvalue] = new;
+
+out:
+	return new;
+}
+
+static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid,
+                                               u16 tclass, int *probes)
+{
+	struct avc_node *cur;
+	int hvalue;
+	int tprobes = 1;
+
+	hvalue = avc_hash(ssid, tsid, tclass);
+	cur = avc_cache.slots[hvalue];
+	while (cur != NULL &amp;&amp;
+	       (ssid != cur-&gt;ae.ssid ||
+		tclass != cur-&gt;ae.tclass ||
+		tsid != cur-&gt;ae.tsid)) {
+		tprobes++;
+		cur = cur-&gt;next;
+	}
+
+	if (cur == NULL) {
+		/* cache miss */
+		goto out;
+	}
+
+	/* cache hit */
+	if (probes)
+		*probes = tprobes;
+
+	cur-&gt;ae.used = 1;
+
+out:
+	return cur;
+}
+
+/**
+ * avc_lookup - Look up an AVC entry.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions, interpreted based on @tclass
+ * @aeref:  AVC entry reference
+ *
+ * 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(u32 ssid, u32 tsid, u16 tclass,
+               u32 requested, struct avc_entry_ref *aeref)
+{
+	struct avc_node *node;
+	int probes, rc = 0;
+
+	avc_cache_stats_incr(AVC_CAV_LOOKUPS);
+	node = avc_search_node(ssid, tsid, tclass,&amp;probes);
+
+	if (node &amp;&amp; ((node-&gt;ae.avd.decided &amp; requested) == requested)) {
+		avc_cache_stats_incr(AVC_CAV_HITS);
+		avc_cache_stats_add(AVC_CAV_PROBES,probes);
+		aeref-&gt;ae = &amp;node-&gt;ae;
+		goto out;
+	}
+
+	avc_cache_stats_incr(AVC_CAV_MISSES);
+	rc = -ENOENT;
+out:
+	return rc;
+}
+
+/**
+ * avc_insert - Insert an AVC entry.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @ae: AVC entry
+ * @aeref:  AVC entry reference
+ *
+ * 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-&gt;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(u32 ssid, u32 tsid, u16 tclass,
+               struct avc_entry *ae, struct avc_entry_ref *aeref)
+{
+	struct avc_node *node;
+	int rc = 0;
+
+	if (ae-&gt;avd.seqno &lt; avc_cache.latest_notif) {
+		printk(KERN_WARNING "avc:  seqno %d &lt; latest_notif %d\n",
+		       ae-&gt;avd.seqno, avc_cache.latest_notif);
+		rc = -EAGAIN;
+		goto out;
+	}
+
+	node = avc_claim_node(ssid, tsid, tclass);
+	if (!node) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	node-&gt;ae.avd.allowed = ae-&gt;avd.allowed;
+	node-&gt;ae.avd.decided = ae-&gt;avd.decided;
+	node-&gt;ae.avd.auditallow = ae-&gt;avd.auditallow;
+	node-&gt;ae.avd.auditdeny = ae-&gt;avd.auditdeny;
+	node-&gt;ae.avd.seqno = ae-&gt;avd.seqno;
+	aeref-&gt;ae = &amp;node-&gt;ae;
+out:
+	return rc;
+}
+
+static inline void avc_print_ipv4_addr(u32 addr, u16 port, char *name1, char *name2)
+{
+	if (addr)
+		printk(" %s=%d.%d.%d.%d", name1, NIPQUAD(addr));
+	if (port)
+		printk(" %s=%d", name2, ntohs(port));
+}
+
+/*
+ * Copied from net/core/utils.c:net_ratelimit and modified for
+ * use by the AVC audit facility.
+ */
+#define AVC_MSG_COST	5*HZ
+#define AVC_MSG_BURST	10*5*HZ
+
+/*
+ * This enforces a rate limit: not more than one kernel message
+ * every 5secs to make a denial-of-service attack impossible.
+ */
+static int avc_ratelimit(void)
+{
+	static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
+	static unsigned long toks = 10*5*HZ;
+	static unsigned long last_msg;
+	static int missed, rc = 0;
+	unsigned long flags;
+	unsigned long now = jiffies;
+
+	spin_lock_irqsave(&amp;ratelimit_lock, flags);
+	toks += now - last_msg;
+	last_msg = now;
+	if (toks &gt; AVC_MSG_BURST)
+		toks = AVC_MSG_BURST;
+	if (toks &gt;= AVC_MSG_COST) {
+		int lost = missed;
+		missed = 0;
+		toks -= AVC_MSG_COST;
+		spin_unlock_irqrestore(&amp;ratelimit_lock, flags);
+		if (lost)
+			printk(KERN_WARNING "AVC: %d messages suppressed.\n",
+			       lost);
+		rc = 1;
+		goto out;
+	}
+	missed++;
+	spin_unlock_irqrestore(&amp;ratelimit_lock, flags);
+out:
+	return rc;
+}
+
+static inline int check_avc_ratelimit(void)
+{
+	if (selinux_enforcing)
+		return avc_ratelimit();
+	else {
+		/* If permissive, then never suppress messages. */
+		return 1;
+	}
+}
+
+/**
+ * avc_audit - Audit the granting or denial of permissions.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions
+ * @avd: access vector decisions
+ * @result: result from avc_has_perm_noaudit
+ * @a:  auxiliary audit data
+ *
+ * Audit the granting or denial of permissions in accordance
+ * with the policy.  This function is typically called by
+ * avc_has_perm() after a permission check, but can also be
+ * called directly by callers who use avc_has_perm_noaudit()
+ * in order to separate the permission check from the auditing.
+ * For example, this separation is useful when the permission check must
+ * be performed under a lock, to allow the lock to be released
+ * before calling the auditing code.
+ */
+void avc_audit(u32 ssid, u32 tsid,
+               u16 tclass, u32 requested,
+               struct av_decision *avd, int result, struct avc_audit_data *a)
+{
+	struct task_struct *tsk = current;
+	struct inode *inode = NULL;
+	char *p;
+	u32 denied, audited;
+
+	denied = requested &amp; ~avd-&gt;allowed;
+	if (denied) {
+		audited = denied;
+		if (!(audited &amp; avd-&gt;auditdeny))
+			return;
+	} else if (result) {
+		audited = denied = requested;
+        } else {
+		audited = requested;
+		if (!(audited &amp; avd-&gt;auditallow))
+			return;
+	}
+
+	if (!check_avc_ratelimit())
+		return;
+
+	/* prevent overlapping printks */
+	spin_lock_irq(&amp;avc_log_lock);
+
+	printk("%s\n", avc_level_string);
+	printk("%savc:  %s ", avc_level_string, denied ? "denied" : "granted");
+	avc_dump_av(tclass,audited);
+	printk(" for ");
+	if (a &amp;&amp; a-&gt;tsk)
+		tsk = a-&gt;tsk;
+	if (tsk &amp;&amp; tsk-&gt;pid) {
+		struct mm_struct *mm;
+		struct vm_area_struct *vma;
+		printk(" pid=%d", tsk-&gt;pid);
+		if (tsk == current)
+			mm = current-&gt;mm;
+		else
+			mm = get_task_mm(tsk);
+		if (mm) {
+			if (down_read_trylock(&amp;mm-&gt;mmap_sem)) {
+				vma = mm-&gt;mmap;
+				while (vma) {
+					if ((vma-&gt;vm_flags &amp; VM_EXECUTABLE) &amp;&amp;
+					    vma-&gt;vm_file) {
+						p = d_path(vma-&gt;vm_file-&gt;f_dentry,
+							   vma-&gt;vm_file-&gt;f_vfsmnt,
+							   avc_audit_buffer,
+							   PAGE_SIZE);
+						printk(" exe=%s", p);
+						break;
+					}
+					vma = vma-&gt;vm_next;
+				}
+				up_read(&amp;mm-&gt;mmap_sem);
+			}
+			if (tsk != current)
+				mmput(mm);
+		} else {
+			printk(" comm=%s", tsk-&gt;comm);
+		}
+	}
+	if (a) {
+		switch (a-&gt;type) {
+		case AVC_AUDIT_DATA_IPC:
+			printk(" key=%d", a-&gt;u.ipc_id);
+			break;
+		case AVC_AUDIT_DATA_CAP:
+			printk(" capability=%d", a-&gt;u.cap);
+			break;
+		case AVC_AUDIT_DATA_FS:
+			if (a-&gt;u.fs.dentry) {
+				if (a-&gt;u.fs.mnt) {
+					p = d_path(a-&gt;u.fs.dentry,
+						   a-&gt;u.fs.mnt,
+						   avc_audit_buffer,
+						   PAGE_SIZE);
+					if (p)
+						printk(" path=%s", p);
+				}
+				inode = a-&gt;u.fs.dentry-&gt;d_inode;
+			} else if (a-&gt;u.fs.inode) {
+				inode = a-&gt;u.fs.inode;
+			}
+			if (inode)
+				printk(" dev=%s ino=%ld",
+				       inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+			break;
+		case AVC_AUDIT_DATA_NET:
+			if (a-&gt;u.net.sk) {
+				struct sock *sk = a-&gt;u.net.sk;
+				struct unix_sock *u;
+				struct inet_opt *inet;
+
+				switch (sk-&gt;sk_family) {
+				case AF_INET:
+					inet = inet_sk(sk);
+					avc_print_ipv4_addr(inet-&gt;rcv_saddr,
+					                    inet-&gt;sport,
+					                    "laddr", "lport");
+					avc_print_ipv4_addr(inet-&gt;daddr,
+					                    inet-&gt;dport,
+					                    "faddr", "fport");
+					break;
+				case AF_UNIX:
+					u = unix_sk(sk);
+					if (u-&gt;dentry) {
+						p = d_path(u-&gt;dentry,
+							   u-&gt;mnt,
+							   avc_audit_buffer,
+							   PAGE_SIZE);
+						printk(" path=%s", p);
+					} else if (u-&gt;addr) {
+						p = avc_audit_buffer;
+						memcpy(p,
+						       u-&gt;addr-&gt;name-&gt;sun_path,
+						       u-&gt;addr-&gt;len-sizeof(short));
+						if (*p == 0) {
+							*p = '@';
+							p += u-&gt;addr-&gt;len-sizeof(short);
+							*p = 0;
+						}
+						printk(" path=%s",
+						       avc_audit_buffer);
+					}
+					break;
+				}
+			}
+			if (a-&gt;u.net.daddr) {
+				printk(" daddr=%d.%d.%d.%d",
+				       NIPQUAD(a-&gt;u.net.daddr));
+				if (a-&gt;u.net.port)
+					printk(" dest=%d", a-&gt;u.net.port);
+			} else if (a-&gt;u.net.port)
+				printk(" port=%d", a-&gt;u.net.port);
+			if (a-&gt;u.net.skb) {
+				struct sk_buff *skb = a-&gt;u.net.skb;
+
+				if ((skb-&gt;protocol == htons(ETH_P_IP)) &amp;&amp;
+				     skb-&gt;nh.iph) {
+					u16 source = 0, dest = 0;
+					u8  protocol = skb-&gt;nh.iph-&gt;protocol;
+
+
+					if (protocol == IPPROTO_TCP &amp;&amp;
+					    skb-&gt;h.th) {
+						source = skb-&gt;h.th-&gt;source;
+						dest = skb-&gt;h.th-&gt;dest;
+					}
+					if (protocol == IPPROTO_UDP &amp;&amp;
+					    skb-&gt;h.uh) {
+						source = skb-&gt;h.uh-&gt;source;
+						dest = skb-&gt;h.uh-&gt;dest;
+					}
+
+					avc_print_ipv4_addr(skb-&gt;nh.iph-&gt;saddr,
+					                    source,
+					                    "saddr", "source");
+					avc_print_ipv4_addr(skb-&gt;nh.iph-&gt;daddr,
+					                    dest,
+					                    "daddr", "dest");
+				}
+			}
+			if (a-&gt;u.net.netif)
+				printk(" netif=%s", a-&gt;u.net.netif);
+			break;
+		}
+	}
+	printk(" ");
+	avc_dump_query(ssid, tsid, tclass);
+	printk("\n");
+
+	spin_unlock_irq(&amp;avc_log_lock);
+}
+
+/**
+ * avc_add_callback - Register a callback for security events.
+ * @callback: callback function
+ * @events: security events
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions
+ *
+ * Register a callback function for events in the set @events
+ * related to the SID pair (@ssid, @tsid) and
+ * and the permissions @perms, interpreting
+ * @perms based on @tclass.  Returns %0 on success or
+ * -%ENOMEM if insufficient memory exists to add the callback.
+ */
+int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
+                                     u16 tclass, u32 perms,
+                                     u32 *out_retained),
+                     u32 events, u32 ssid, u32 tsid,
+                     u16 tclass, u32 perms)
+{
+	struct avc_callback_node *c;
+	int rc = 0;
+
+	c = kmalloc(sizeof(*c), GFP_ATOMIC);
+	if (!c) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	c-&gt;callback = callback;
+	c-&gt;events = events;
+	c-&gt;ssid = ssid;
+	c-&gt;tsid = tsid;
+	c-&gt;perms = perms;
+	c-&gt;next = avc_callbacks;
+	avc_callbacks = c;
+out:
+	return rc;
+}
+
+static inline int avc_sidcmp(u32 x, u32 y)
+{
+	return (x == y || x == SECSID_WILD || y == SECSID_WILD);
+}
+
+static inline void avc_update_node(u32 event, struct avc_node *node, u32 perms)
+{
+	switch (event) {
+	case AVC_CALLBACK_GRANT:
+		node-&gt;ae.avd.allowed |= perms;
+		break;
+	case AVC_CALLBACK_TRY_REVOKE:
+	case AVC_CALLBACK_REVOKE:
+		node-&gt;ae.avd.allowed &amp;= ~perms;
+		break;
+	case AVC_CALLBACK_AUDITALLOW_ENABLE:
+		node-&gt;ae.avd.auditallow |= perms;
+		break;
+	case AVC_CALLBACK_AUDITALLOW_DISABLE:
+		node-&gt;ae.avd.auditallow &amp;= ~perms;
+		break;
+	case AVC_CALLBACK_AUDITDENY_ENABLE:
+		node-&gt;ae.avd.auditdeny |= perms;
+		break;
+	case AVC_CALLBACK_AUDITDENY_DISABLE:
+		node-&gt;ae.avd.auditdeny &amp;= ~perms;
+		break;
+	}
+}
+
+static int avc_update_cache(u32 event, u32 ssid, u32 tsid,
+                            u16 tclass, u32 perms)
+{
+	struct avc_node *node;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amp;avc_lock,flags);
+
+	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
+		/* apply to all matching nodes */
+		for (i = 0; i &lt; AVC_CACHE_SLOTS; i++) {
+			for (node = avc_cache.slots[i]; node;
+			     node = node-&gt;next) {
+				if (avc_sidcmp(ssid, node-&gt;ae.ssid) &amp;&amp;
+				    avc_sidcmp(tsid, node-&gt;ae.tsid) &amp;&amp;
+				    tclass == node-&gt;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);
+		}
+	}
+
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+
+	return 0;
+}
+
+static int avc_control(u32 event, u32 ssid, u32 tsid,
+                       u16 tclass, u32 perms,
+                       u32 seqno, u32 *out_retained)
+{
+	struct avc_callback_node *c;
+	u32 tretained = 0, cretained = 0;
+	int rc = 0;
+	unsigned long flags;
+
+	/*
+	 * 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)
+		avc_update_cache(event,ssid,tsid,tclass,perms);
+
+	for (c = avc_callbacks; c; c = c-&gt;next)
+	{
+		if ((c-&gt;events &amp; event) &amp;&amp;
+		    avc_sidcmp(c-&gt;ssid, ssid) &amp;&amp;
+		    avc_sidcmp(c-&gt;tsid, tsid) &amp;&amp;
+		    c-&gt;tclass == tclass &amp;&amp;
+		    (c-&gt;perms &amp; perms)) {
+			cretained = 0;
+			rc = c-&gt;callback(event, ssid, tsid, tclass,
+					 (c-&gt;perms &amp; perms),
+					 &amp;cretained);
+			if (rc)
+				goto out;
+			tretained |= cretained;
+		}
+	}
+
+	if (event == AVC_CALLBACK_TRY_REVOKE) {
+		/* revoke any unretained permissions */
+		perms &amp;= ~tretained;
+		avc_update_cache(event,ssid,tsid,tclass,perms);
+		*out_retained = tretained;
+	}
+
+	spin_lock_irqsave(&amp;avc_lock,flags);
+	if (seqno &gt; avc_cache.latest_notif)
+		avc_cache.latest_notif = seqno;
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+
+out:
+	return rc;
+}
+
+/**
+ * avc_ss_grant - Grant previously denied permissions.
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions to grant
+ * @seqno: policy sequence number
+ */
+int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass,
+                 u32 perms, u32 seqno)
+{
+	return avc_control(AVC_CALLBACK_GRANT,
+			   ssid, tsid, tclass, perms, seqno, 0);
+}
+
+/**
+ * avc_ss_try_revoke - Try to revoke previously granted permissions.
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions to grant
+ * @seqno: policy sequence number
+ * @out_retained: subset of @perms that are retained
+ *
+ * Try to revoke previously granted permissions, but
+ * only if they are not retained as migrated permissions.
+ * Return the subset of permissions that are retained via @out_retained.
+ */
+int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass,
+                      u32 perms, u32 seqno, u32 *out_retained)
+{
+	return avc_control(AVC_CALLBACK_TRY_REVOKE,
+			   ssid, tsid, tclass, perms, seqno, out_retained);
+}
+
+/**
+ * avc_ss_revoke - Revoke previously granted permissions.
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions to grant
+ * @seqno: policy sequence number
+ *
+ * Revoke previously granted permissions, even if
+ * they are retained as migrated permissions.
+ */
+int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass,
+                  u32 perms, u32 seqno)
+{
+	return avc_control(AVC_CALLBACK_REVOKE,
+			   ssid, tsid, tclass, perms, seqno, 0);
+}
+
+/**
+ * avc_ss_reset - Flush the cache and revalidate migrated permissions.
+ * @seqno: policy sequence number
+ */
+int avc_ss_reset(u32 seqno)
+{
+	struct avc_callback_node *c;
+	int i, rc = 0;
+	struct avc_node *node, *tmp;
+	unsigned long flags;
+
+	avc_hash_eval("reset");
+
+	spin_lock_irqsave(&amp;avc_lock,flags);
+
+	for (i = 0; i &lt; AVC_CACHE_SLOTS; i++) {
+		node = avc_cache.slots[i];
+		while (node) {
+			tmp = node;
+			node = node-&gt;next;
+			tmp-&gt;ae.ssid = tmp-&gt;ae.tsid = SECSID_NULL;
+			tmp-&gt;ae.tclass = SECCLASS_NULL;
+			tmp-&gt;ae.avd.allowed = tmp-&gt;ae.avd.decided = 0;
+			tmp-&gt;ae.avd.auditallow = tmp-&gt;ae.avd.auditdeny = 0;
+			tmp-&gt;ae.used = 0;
+			tmp-&gt;next = avc_node_freelist;
+			avc_node_freelist = tmp;
+			avc_cache.active_nodes--;
+		}
+		avc_cache.slots[i] = 0;
+	}
+	avc_cache.lru_hint = 0;
+
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+
+	for (i = 0; i &lt; AVC_NSTATS; i++)
+		avc_cache_stats[i] = 0;
+
+	for (c = avc_callbacks; c; c = c-&gt;next) {
+		if (c-&gt;events &amp; AVC_CALLBACK_RESET) {
+			rc = c-&gt;callback(AVC_CALLBACK_RESET,
+					 0, 0, 0, 0, 0);
+			if (rc)
+				goto out;
+		}
+	}
+
+	spin_lock_irqsave(&amp;avc_lock,flags);
+	if (seqno &gt; avc_cache.latest_notif)
+		avc_cache.latest_notif = seqno;
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+out:
+	return rc;
+}
+
+/**
+ * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions to grant
+ * @seqno: policy sequence number
+ * @enable: enable flag.
+ */
+int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass,
+                          u32 perms, u32 seqno, u32 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);
+}
+
+/**
+ * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
+ * @ssid: source security identifier or %SECSID_WILD
+ * @tsid: target security identifier or %SECSID_WILD
+ * @tclass: target security class
+ * @perms: permissions to grant
+ * @seqno: policy sequence number
+ * @enable: enable flag.
+ */
+int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass,
+                         u32 perms, u32 seqno, u32 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);
+}
+
+/**
+ * avc_has_perm_noaudit - Check permissions but perform no auditing.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions, interpreted based on @tclass
+ * @aeref:  AVC entry reference
+ * @avd: access vector decisions
+ *
+ * Check the AVC to determine whether the @requested permissions are granted
+ * for the SID pair (@ssid, @tsid), interpreting the permissions
+ * based on @tclass, and call the security server on a cache miss to obtain
+ * a new decision and add it to the cache.  Update @aeref to refer to an AVC
+ * entry with the resulting decisions, and return a copy of the decisions
+ * in @avd.  Return %0 if all @requested permissions are granted,
+ * -%EACCES if any permissions are denied, or another -errno upon
+ * other errors.  This function is typically called by avc_has_perm(),
+ * but may also be called directly to separate permission checking from
+ * auditing, e.g. in cases where a lock must be held for the check but
+ * should be released for the auditing.
+ */
+int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+                         u16 tclass, u32 requested,
+                         struct avc_entry_ref *aeref, struct av_decision *avd)
+{
+	struct avc_entry *ae;
+	int rc = 0;
+	unsigned long flags;
+	struct avc_entry entry;
+	u32 denied;
+	struct avc_entry_ref ref;
+
+	if (!aeref) {
+		avc_entry_ref_init(&amp;ref);
+		aeref = &amp;ref;
+	}
+
+	spin_lock_irqsave(&amp;avc_lock, flags);
+	avc_cache_stats_incr(AVC_ENTRY_LOOKUPS);
+	ae = aeref-&gt;ae;
+	if (ae) {
+		if (ae-&gt;ssid == ssid &amp;&amp;
+		    ae-&gt;tsid == tsid &amp;&amp;
+		    ae-&gt;tclass == tclass &amp;&amp;
+		    ((ae-&gt;avd.decided &amp; requested) == requested)) {
+			avc_cache_stats_incr(AVC_ENTRY_HITS);
+			ae-&gt;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) {
+			spin_unlock_irqrestore(&amp;avc_lock,flags);
+			rc = security_compute_av(ssid,tsid,tclass,requested,&amp;entry.avd);
+			if (rc)
+				goto out;
+			spin_lock_irqsave(&amp;avc_lock, flags);
+			rc = avc_insert(ssid,tsid,tclass,&amp;entry,aeref);
+			if (rc) {
+				spin_unlock_irqrestore(&amp;avc_lock,flags);
+				goto out;
+			}
+		}
+		ae = aeref-&gt;ae;
+	}
+
+	if (avd)
+		memcpy(avd, &amp;ae-&gt;avd, sizeof(*avd));
+
+	denied = requested &amp; ~(ae-&gt;avd.allowed);
+
+	if (!requested || denied) {
+		if (selinux_enforcing) {
+			spin_unlock_irqrestore(&amp;avc_lock,flags);
+			rc = -EACCES;
+			goto out;
+		} else {
+			ae-&gt;avd.allowed |= requested;
+			spin_unlock_irqrestore(&amp;avc_lock,flags);
+			goto out;
+		}
+	}
+
+	spin_unlock_irqrestore(&amp;avc_lock,flags);
+out:
+	return rc;
+}
+
+/**
+ * avc_has_perm - Check permissions and perform any appropriate auditing.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions, interpreted based on @tclass
+ * @aeref:  AVC entry reference
+ * @auditdata: auxiliary audit data
+ *
+ * Check the AVC to determine whether the @requested permissions are granted
+ * for the SID pair (@ssid, @tsid), interpreting the permissions
+ * based on @tclass, and call the security server on a cache miss to obtain
+ * a new decision and add it to the cache.  Update @aeref to refer to an AVC
+ * entry with the resulting decisions.  Audit the granting or denial of
+ * permissions in accordance with the policy.  Return %0 if all @requested
+ * permissions are granted, -%EACCES if any permissions are denied, or
+ * another -errno upon other errors.
+ */
+int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
+                 u32 requested, struct avc_entry_ref *aeref,
+                 struct avc_audit_data *auditdata)
+{
+	struct av_decision avd;
+	int rc;
+
+	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &amp;avd);
+	avc_audit(ssid, tsid, tclass, requested, &amp;avd, rc, auditdata);
+	return rc;
+}
+
+static int __init avc_log_level_setup(char *str)
+{
+	avc_log_level = simple_strtol(str, NULL, 0);
+	if (avc_log_level &gt; 7)
+		avc_log_level = 7;
+	return 1;
+}
+
+__setup("avc_log_level=", avc_log_level_setup);
+
diff -puN /dev/null security/selinux/hooks.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/hooks.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,3405 @@
+/*
+ *  NSA Security-Enhanced Linux (SELinux) security module
+ *
+ *  This file contains the SELinux hook function implementations.
+ *
+ *  Authors:  Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ *            Chris Vance, &lt;cvance@nai.com&gt;
+ *            Wayne Salamon, &lt;wsalamon@nai.com&gt;
+ *            James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
+ *  Copyright (C) 2003 Red Hat, Inc., James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2,
+ *      as published by the Free Software Foundation.
+ */
+
+#define XATTR_SECURITY_PREFIX "security."
+#define XATTR_SELINUX_SUFFIX "selinux"
+#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
+
+#include &lt;linux/config.h&gt;
+#include &lt;linux/module.h&gt;
+#include &lt;linux/init.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/ptrace.h&gt;
+#include &lt;linux/errno.h&gt;
+#include &lt;linux/sched.h&gt;
+#include &lt;linux/security.h&gt;
+#include &lt;linux/xattr.h&gt;
+#include &lt;linux/capability.h&gt;
+#include &lt;linux/unistd.h&gt;
+#include &lt;linux/mm.h&gt;
+#include &lt;linux/mman.h&gt;
+#include &lt;linux/slab.h&gt;
+#include &lt;linux/pagemap.h&gt;
+#include &lt;linux/swap.h&gt;
+#include &lt;linux/smp_lock.h&gt;
+#include &lt;linux/spinlock.h&gt;
+#include &lt;linux/file.h&gt;
+#include &lt;linux/namei.h&gt;
+#include &lt;linux/mount.h&gt;
+#include &lt;linux/ext2_fs.h&gt;
+#include &lt;linux/proc_fs.h&gt;
+#include &lt;linux/kd.h&gt;
+#include &lt;net/icmp.h&gt;
+#include &lt;net/ip.h&gt;		/* for sysctl_local_port_range[] */
+#include &lt;net/tcp.h&gt;		/* struct or_callable used in sock_rcv_skb */
+#include &lt;asm/uaccess.h&gt;
+#include &lt;asm/semaphore.h&gt;
+#include &lt;asm/ioctls.h&gt;
+#include &lt;linux/bitops.h&gt;
+#include &lt;linux/interrupt.h&gt;
+#include &lt;linux/netdevice.h&gt;	/* for network interface checks */
+#include &lt;linux/netlink.h&gt;
+#include &lt;linux/tcp.h&gt;
+#include &lt;linux/quota.h&gt;
+#include &lt;linux/un.h&gt;		/* for Unix socket types */
+#include &lt;net/af_unix.h&gt;	/* for Unix socket types */
+
+#include "avc.h"
+#include "objsec.h"
+
+#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+int selinux_enforcing = 0;
+
+static int __init enforcing_setup(char *str)
+{
+	selinux_enforcing = simple_strtol(str,NULL,0);
+	return 1;
+}
+__setup("enforcing=", enforcing_setup);
+#endif
+
+/* Original (dummy) security module. */
+static struct security_operations *original_ops = NULL;
+
+/* Minimal support for a secondary security module,
+   just to allow the use of the dummy or capability modules.
+   The owlsm module can alternatively be used as a secondary
+   module as long as CONFIG_OWLSM_FD is not enabled. */
+static struct security_operations *secondary_ops = NULL;
+
+/* Lists of inode and superblock security structures initialized
+   before the policy was loaded. */
+static LIST_HEAD(inode_security_head);
+static spinlock_t inode_security_lock = SPIN_LOCK_UNLOCKED;
+
+static LIST_HEAD(superblock_security_head);
+static spinlock_t sb_security_lock = SPIN_LOCK_UNLOCKED;
+
+/* Allocate and free functions for each kind of security blob. */
+
+static int task_alloc_security(struct task_struct *task)
+{
+	struct task_security_struct *tsec;
+
+	tsec = kmalloc(sizeof(struct task_security_struct), GFP_KERNEL);
+	if (!tsec)
+		return -ENOMEM;
+
+	memset(tsec, 0, sizeof(struct task_security_struct));
+	tsec-&gt;magic = SELINUX_MAGIC;
+	tsec-&gt;task = task;
+	tsec-&gt;osid = tsec-&gt;sid = SECINITSID_UNLABELED;
+	task-&gt;security = tsec;
+
+	return 0;
+}
+
+static void task_free_security(struct task_struct *task)
+{
+	struct task_security_struct *tsec = task-&gt;security;
+
+	if (!tsec || tsec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	task-&gt;security = NULL;
+	kfree(tsec);
+}
+
+static int inode_alloc_security(struct inode *inode)
+{
+	struct task_security_struct *tsec = current-&gt;security;
+	struct inode_security_struct *isec;
+
+	isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
+	if (!isec)
+		return -ENOMEM;
+
+	memset(isec, 0, sizeof(struct inode_security_struct));
+	init_MUTEX(&amp;isec-&gt;sem);
+	INIT_LIST_HEAD(&amp;isec-&gt;list);
+	isec-&gt;magic = SELINUX_MAGIC;
+	isec-&gt;inode = inode;
+	isec-&gt;sid = SECINITSID_UNLABELED;
+	isec-&gt;sclass = SECCLASS_FILE;
+	if (tsec &amp;&amp; tsec-&gt;magic == SELINUX_MAGIC)
+		isec-&gt;task_sid = tsec-&gt;sid;
+	else
+		isec-&gt;task_sid = SECINITSID_UNLABELED;
+	inode-&gt;i_security = isec;
+
+	return 0;
+}
+
+static void inode_free_security(struct inode *inode)
+{
+	struct inode_security_struct *isec = inode-&gt;i_security;
+
+	if (!isec || isec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	spin_lock(&amp;inode_security_lock);
+	if (!list_empty(&amp;isec-&gt;list))
+		list_del_init(&amp;isec-&gt;list);
+	spin_unlock(&amp;inode_security_lock);
+
+	inode-&gt;i_security = NULL;
+	kfree(isec);
+}
+
+static int file_alloc_security(struct file *file)
+{
+	struct task_security_struct *tsec = current-&gt;security;
+	struct file_security_struct *fsec;
+
+	fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+	if (!fsec)
+		return -ENOMEM;
+
+	memset(fsec, 0, sizeof(struct file_security_struct));
+	fsec-&gt;magic = SELINUX_MAGIC;
+	fsec-&gt;file = file;
+	if (tsec &amp;&amp; tsec-&gt;magic == SELINUX_MAGIC) {
+		fsec-&gt;sid = tsec-&gt;sid;
+		fsec-&gt;fown_sid = tsec-&gt;sid;
+	} else {
+		fsec-&gt;sid = SECINITSID_UNLABELED;
+		fsec-&gt;fown_sid = SECINITSID_UNLABELED;
+	}
+	file-&gt;f_security = fsec;
+
+	return 0;
+}
+
+static void file_free_security(struct file *file)
+{
+	struct file_security_struct *fsec = file-&gt;f_security;
+
+	if (!fsec || fsec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	file-&gt;f_security = NULL;
+	kfree(fsec);
+}
+
+static int superblock_alloc_security(struct super_block *sb)
+{
+	struct superblock_security_struct *sbsec;
+
+	sbsec = kmalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
+	if (!sbsec)
+		return -ENOMEM;
+
+	memset(sbsec, 0, sizeof(struct superblock_security_struct));
+	init_MUTEX(&amp;sbsec-&gt;sem);
+	INIT_LIST_HEAD(&amp;sbsec-&gt;list);
+	sbsec-&gt;magic = SELINUX_MAGIC;
+	sbsec-&gt;sb = sb;
+	sbsec-&gt;sid = SECINITSID_UNLABELED;
+	sb-&gt;s_security = sbsec;
+
+	return 0;
+}
+
+static void superblock_free_security(struct super_block *sb)
+{
+	struct superblock_security_struct *sbsec = sb-&gt;s_security;
+
+	if (!sbsec || sbsec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	spin_lock(&amp;sb_security_lock);
+	if (!list_empty(&amp;sbsec-&gt;list))
+		list_del_init(&amp;sbsec-&gt;list);
+	spin_unlock(&amp;sb_security_lock);
+
+	sb-&gt;s_security = NULL;
+	kfree(sbsec);
+}
+
+/* The security server must be initialized before
+   any labeling or access decisions can be provided. */
+extern int ss_initialized;
+
+/* The file system's label must be initialized prior to use. */
+
+static char *labeling_behaviors[5] = {
+	"uses xattr",
+	"uses transition SIDs",
+	"uses task SIDs",
+	"uses genfs_contexts",
+	"not configured for labeling"
+};
+
+static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
+
+static inline int inode_doinit(struct inode *inode)
+{
+	return inode_doinit_with_dentry(inode, NULL);
+}
+
+static int superblock_doinit(struct super_block *sb)
+{
+	struct superblock_security_struct *sbsec = sb-&gt;s_security;
+	struct dentry *root = sb-&gt;s_root;
+	struct inode *inode = root-&gt;d_inode;
+	int rc = 0;
+
+	down(&amp;sbsec-&gt;sem);
+	if (sbsec-&gt;initialized)
+		goto out;
+
+	if (!ss_initialized) {
+		/* Defer initialization until selinux_complete_init,
+		   after the initial policy is loaded and the security
+		   server is ready to handle calls. */
+		spin_lock(&amp;sb_security_lock);
+		if (list_empty(&amp;sbsec-&gt;list))
+			list_add(&amp;sbsec-&gt;list, &amp;superblock_security_head);
+		spin_unlock(&amp;sb_security_lock);
+		goto out;
+	}
+
+	/* Determine the labeling behavior to use for this filesystem type. */
+	rc = security_fs_use(sb-&gt;s_type-&gt;name, &amp;sbsec-&gt;behavior, &amp;sbsec-&gt;sid);
+	if (rc) {
+		printk(KERN_WARNING "%s:  security_fs_use(%s) returned %d\n",
+		       __FUNCTION__, sb-&gt;s_type-&gt;name, rc);
+		goto out;
+	}
+
+	if (sbsec-&gt;behavior == SECURITY_FS_USE_XATTR) {
+		/* Make sure that the xattr handler exists and that no
+		   error other than -ENODATA is returned by getxattr on
+		   the root directory.  -ENODATA is ok, as this may be
+		   the first boot of the SELinux kernel before we have
+		   assigned xattr values to the filesystem. */
+		if (!inode-&gt;i_op-&gt;getxattr) {
+			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
+			       "xattr support\n", sb-&gt;s_id, sb-&gt;s_type-&gt;name);
+			rc = -EOPNOTSUPP;
+			goto out;
+		}
+		rc = inode-&gt;i_op-&gt;getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+		if (rc &lt; 0 &amp;&amp; rc != -ENODATA) {
+			if (rc == -EOPNOTSUPP)
+				printk(KERN_WARNING "SELinux: (dev %s, type "
+				       "%s) has no security xattr handler\n",
+				       sb-&gt;s_id, sb-&gt;s_type-&gt;name);
+			else
+				printk(KERN_WARNING "SELinux: (dev %s, type "
+				       "%s) getxattr errno %d\n", sb-&gt;s_id,
+				       sb-&gt;s_type-&gt;name, -rc);
+			goto out;
+		}
+	}
+
+	if (strcmp(sb-&gt;s_type-&gt;name, "proc") == 0)
+		sbsec-&gt;proc = 1;
+
+	sbsec-&gt;initialized = 1;
+
+	printk(KERN_INFO "SELinux: initialized (dev %s, type %s), %s\n",
+	       sb-&gt;s_id, sb-&gt;s_type-&gt;name,
+	       labeling_behaviors[sbsec-&gt;behavior-1]);
+
+	/* Initialize the root inode. */
+	rc = inode_doinit_with_dentry(sb-&gt;s_root-&gt;d_inode, sb-&gt;s_root);
+out:
+	up(&amp;sbsec-&gt;sem);
+	return rc;
+}
+
+static inline u16 inode_mode_to_security_class(umode_t mode)
+{
+	switch (mode &amp; S_IFMT) {
+	case S_IFSOCK:
+		return SECCLASS_SOCK_FILE;
+	case S_IFLNK:
+		return SECCLASS_LNK_FILE;
+	case S_IFREG:
+		return SECCLASS_FILE;
+	case S_IFBLK:
+		return SECCLASS_BLK_FILE;
+	case S_IFDIR:
+		return SECCLASS_DIR;
+	case S_IFCHR:
+		return SECCLASS_CHR_FILE;
+	case S_IFIFO:
+		return SECCLASS_FIFO_FILE;
+
+	}
+
+	return SECCLASS_FILE;
+}
+
+static inline u16 socket_type_to_security_class(int family, int type)
+{
+	switch (family) {
+	case PF_UNIX:
+		switch (type) {
+		case SOCK_STREAM:
+			return SECCLASS_UNIX_STREAM_SOCKET;
+		case SOCK_DGRAM:
+			return SECCLASS_UNIX_DGRAM_SOCKET;
+		}
+	case PF_INET:
+	case PF_INET6:
+		switch (type) {
+		case SOCK_STREAM:
+			return SECCLASS_TCP_SOCKET;
+		case SOCK_DGRAM:
+			return SECCLASS_UDP_SOCKET;
+		case SOCK_RAW:
+			return SECCLASS_RAWIP_SOCKET;
+		}
+	case PF_NETLINK:
+		return SECCLASS_NETLINK_SOCKET;
+	case PF_PACKET:
+		return SECCLASS_PACKET_SOCKET;
+	case PF_KEY:
+		return SECCLASS_KEY_SOCKET;
+	}
+
+	return SECCLASS_SOCKET;
+}
+
+#ifdef CONFIG_PROC_FS
+static int selinux_proc_get_sid(struct proc_dir_entry *de,
+				u16 tclass,
+				u32 *sid)
+{
+	int buflen, rc;
+	char *buffer, *path, *end;
+
+	buffer = (char*)__get_free_page(GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buflen = PAGE_SIZE;
+	end = buffer+buflen;
+	*--end = '\0';
+	buflen--;
+	path = end-1;
+	*path = '/';
+	while (de &amp;&amp; de != de-&gt;parent) {
+		buflen -= de-&gt;namelen + 1;
+		if (buflen &lt; 0)
+			break;
+		end -= de-&gt;namelen;
+		memcpy(end, de-&gt;name, de-&gt;namelen);
+		*--end = '/';
+		path = end;
+		de = de-&gt;parent;
+	}
+	rc = security_genfs_sid("proc", path, tclass, sid);
+	free_page((unsigned long)buffer);
+	return rc;
+}
+#else
+static int selinux_proc_get_sid(struct proc_dir_entry *de,
+				u16 tclass,
+				u32 *sid)
+{
+	return -EINVAL;
+}
+#endif
+
+/* The inode's security attributes must be initialized before first use. */
+static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
+{
+	struct superblock_security_struct *sbsec = NULL;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+	u32 sid;
+	struct dentry *dentry;
+#define INITCONTEXTLEN 255
+	char *context = NULL;
+	unsigned len = 0;
+	int rc = 0;
+	int hold_sem = 0;
+
+	if (isec-&gt;initialized)
+		goto out;
+
+	down(&amp;isec-&gt;sem);
+	hold_sem = 1;
+	if (isec-&gt;initialized)
+		goto out;
+
+	sbsec = inode-&gt;i_sb-&gt;s_security;
+	if (!sbsec || !sbsec-&gt;initialized) {
+		/* Defer initialization until selinux_complete_init,
+		   after the initial policy is loaded and the security
+		   server is ready to handle calls. */
+		spin_lock(&amp;inode_security_lock);
+		if (list_empty(&amp;isec-&gt;list))
+			list_add(&amp;isec-&gt;list, &amp;inode_security_head);
+		spin_unlock(&amp;inode_security_lock);
+		goto out;
+	}
+
+	switch (sbsec-&gt;behavior) {
+	case SECURITY_FS_USE_XATTR:
+		if (!inode-&gt;i_op-&gt;getxattr) {
+			isec-&gt;sid = SECINITSID_FILE;
+			break;
+		}
+
+		/* Need a dentry, since the xattr API requires one.
+		   Life would be simpler if we could just pass the inode. */
+		if (opt_dentry) {
+			/* Called from d_instantiate or d_splice_alias. */
+			dentry = dget(opt_dentry);
+		} else {
+			/* Called from selinux_complete_init, try to find a dentry. */
+			dentry = d_find_alias(inode);
+		}
+		if (!dentry) {
+			printk(KERN_WARNING "%s:  no dentry for dev=%s "
+			       "ino=%ld\n", __FUNCTION__, inode-&gt;i_sb-&gt;s_id,
+			       inode-&gt;i_ino);
+			goto out;
+		}
+
+		len = INITCONTEXTLEN;
+		context = kmalloc(len, GFP_KERNEL);
+		if (!context) {
+			rc = -ENOMEM;
+			dput(dentry);
+			goto out;
+		}
+		rc = inode-&gt;i_op-&gt;getxattr(dentry, XATTR_NAME_SELINUX,
+					   context, len);
+		if (rc == -ERANGE) {
+			/* Need a larger buffer.  Query for the right size. */
+			rc = inode-&gt;i_op-&gt;getxattr(dentry, XATTR_NAME_SELINUX,
+						   NULL, 0);
+			if (rc &lt; 0) {
+				dput(dentry);
+				goto out;
+			}
+			kfree(context);
+			len = rc;
+			context = kmalloc(len, GFP_KERNEL);
+			if (!context) {
+				rc = -ENOMEM;
+				dput(dentry);
+				goto out;
+			}
+			rc = inode-&gt;i_op-&gt;getxattr(dentry,
+						   XATTR_NAME_SELINUX,
+						   context, len);
+		}
+		dput(dentry);
+		if (rc &lt; 0) {
+			if (rc != -ENODATA) {
+				printk(KERN_WARNING "%s:  getxattr returned "
+				       "%d for dev=%s ino=%ld\n", __FUNCTION__,
+				       -rc, inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+				kfree(context);
+				goto out;
+			}
+			/* Map ENODATA to the default file SID */
+			sid = SECINITSID_FILE;
+			rc = 0;
+		} else {
+			rc = security_context_to_sid(context, rc, &amp;sid);
+			if (rc) {
+				printk(KERN_WARNING "%s:  context_to_sid(%s) "
+				       "returned %d for dev=%s ino=%ld\n",
+				       __FUNCTION__, context, -rc,
+				       inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+				kfree(context);
+				goto out;
+			}
+		}
+		kfree(context);
+		isec-&gt;sid = sid;
+		break;
+	case SECURITY_FS_USE_TASK:
+		isec-&gt;sid = isec-&gt;task_sid;
+		break;
+	case SECURITY_FS_USE_TRANS:
+		/* Default to the fs SID. */
+		isec-&gt;sid = sbsec-&gt;sid;
+
+		/* Try to obtain a transition SID. */
+		isec-&gt;sclass = inode_mode_to_security_class(inode-&gt;i_mode);
+		rc = security_transition_sid(isec-&gt;task_sid,
+					     sbsec-&gt;sid,
+					     isec-&gt;sclass,
+					     &amp;sid);
+		if (rc)
+			goto out;
+		isec-&gt;sid = sid;
+		break;
+	default:
+		/* Default to the fs SID. */
+		isec-&gt;sid = sbsec-&gt;sid;
+
+		if (sbsec-&gt;proc) {
+			struct proc_inode *proci = PROC_I(inode);
+			if (proci-&gt;pde) {
+				isec-&gt;sclass = inode_mode_to_security_class(inode-&gt;i_mode);
+				rc = selinux_proc_get_sid(proci-&gt;pde,
+							  isec-&gt;sclass,
+							  &amp;sid);
+				if (rc)
+					goto out;
+				isec-&gt;sid = sid;
+			}
+		}
+		break;
+	}
+
+	isec-&gt;initialized = 1;
+
+out:
+	if (inode-&gt;i_sock) {
+		struct socket *sock = SOCKET_I(inode);
+		if (sock-&gt;sk) {
+			isec-&gt;sclass = socket_type_to_security_class(sock-&gt;sk-&gt;sk_family,
+			                                             sock-&gt;sk-&gt;sk_type);
+		} else {
+			isec-&gt;sclass = SECCLASS_SOCKET;
+		}
+	} else {
+		isec-&gt;sclass = inode_mode_to_security_class(inode-&gt;i_mode);
+	}
+
+	if (hold_sem)
+		up(&amp;isec-&gt;sem);
+	return rc;
+}
+
+/* Convert a Linux signal to an access vector. */
+static inline u32 signal_to_av(int sig)
+{
+	u32 perm = 0;
+
+	switch (sig) {
+	case SIGCHLD:
+		/* Commonly granted from child to parent. */
+		perm = PROCESS__SIGCHLD;
+		break;
+	case SIGKILL:
+		/* Cannot be caught or ignored */
+		perm = PROCESS__SIGKILL;
+		break;
+	case SIGSTOP:
+		/* Cannot be caught or ignored */
+		perm = PROCESS__SIGSTOP;
+		break;
+	default:
+		/* All other signals. */
+		perm = PROCESS__SIGNAL;
+		break;
+	}
+
+	return perm;
+}
+
+/* Check permission betweeen a pair of tasks, e.g. signal checks,
+   fork check, ptrace check, etc. */
+int task_has_perm(struct task_struct *tsk1,
+		  struct task_struct *tsk2,
+		  u32 perms)
+{
+	struct task_security_struct *tsec1, *tsec2;
+
+	tsec1 = tsk1-&gt;security;
+	tsec2 = tsk2-&gt;security;
+	return avc_has_perm(tsec1-&gt;sid, tsec2-&gt;sid,
+			    SECCLASS_PROCESS, perms, &amp;tsec2-&gt;avcr, NULL);
+}
+
+/* Check whether a task is allowed to use a capability. */
+int task_has_capability(struct task_struct *tsk,
+			int cap)
+{
+	struct task_security_struct *tsec;
+	struct avc_audit_data ad;
+
+	tsec = tsk-&gt;security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,CAP);
+	ad.tsk = tsk;
+	ad.u.cap = cap;
+
+	return avc_has_perm(tsec-&gt;sid, tsec-&gt;sid,
+			    SECCLASS_CAPABILITY, CAP_TO_MASK(cap), NULL, &amp;ad);
+}
+
+/* Check whether a task is allowed to use a system operation. */
+int task_has_system(struct task_struct *tsk,
+		    u32 perms)
+{
+	struct task_security_struct *tsec;
+
+	tsec = tsk-&gt;security;
+
+	return avc_has_perm(tsec-&gt;sid, SECINITSID_KERNEL,
+			    SECCLASS_SYSTEM, perms, NULL, NULL);
+}
+
+/* Check whether a task has a particular permission to an inode.
+   The 'aeref' parameter is optional and allows other AVC
+   entry references to be passed (e.g. the one in the struct file).
+   The 'adp' parameter is optional and allows other audit
+   data to be passed (e.g. the dentry). */
+int inode_has_perm(struct task_struct *tsk,
+		   struct inode *inode,
+		   u32 perms,
+		   struct avc_entry_ref *aeref,
+		   struct avc_audit_data *adp)
+{
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = tsk-&gt;security;
+	isec = inode-&gt;i_security;
+
+	if (!adp) {
+		adp = &amp;ad;
+		AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+		ad.u.fs.inode = inode;
+	}
+
+	return avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			    perms, aeref ? aeref : &amp;isec-&gt;avcr, adp);
+}
+
+/* Same as inode_has_perm, but pass explicit audit data containing
+   the dentry to help the auditing code to more easily generate the
+   pathname if needed. */
+static inline int dentry_has_perm(struct task_struct *tsk,
+				  struct vfsmount *mnt,
+				  struct dentry *dentry,
+				  u32 av)
+{
+	struct inode *inode = dentry-&gt;d_inode;
+	struct avc_audit_data ad;
+	AVC_AUDIT_DATA_INIT(&amp;ad,FS);
+	ad.u.fs.mnt = mnt;
+	ad.u.fs.dentry = dentry;
+	return inode_has_perm(tsk, inode, av, NULL, &amp;ad);
+}
+
+/* Check whether a task can use an open file descriptor to
+   access an inode in a given way.  Check access to the
+   descriptor itself, and then use dentry_has_perm to
+   check a particular permission to the file.
+   Access to the descriptor is implicitly granted if it
+   has the same SID as the process.  If av is zero, then
+   access to the file is not checked, e.g. for cases
+   where only the descriptor is affected like seek. */
+static inline int file_has_perm(struct task_struct *tsk,
+				struct file *file,
+				u32 av)
+{
+	struct task_security_struct *tsec = tsk-&gt;security;
+	struct file_security_struct *fsec = file-&gt;f_security;
+	struct vfsmount *mnt = file-&gt;f_vfsmnt;
+	struct dentry *dentry = file-&gt;f_dentry;
+	struct inode *inode = dentry-&gt;d_inode;
+	struct avc_audit_data ad;
+	int rc;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+	ad.u.fs.mnt = mnt;
+	ad.u.fs.dentry = dentry;
+
+	if (tsec-&gt;sid != fsec-&gt;sid) {
+		rc = avc_has_perm(tsec-&gt;sid, fsec-&gt;sid,
+				  SECCLASS_FD,
+				  FD__USE,
+				  &amp;fsec-&gt;avcr, &amp;ad);
+		if (rc)
+			return rc;
+	}
+
+	/* av is zero if only checking access to the descriptor. */
+	if (av)
+		return inode_has_perm(tsk, inode, av, &amp;fsec-&gt;inode_avcr, &amp;ad);
+
+	return 0;
+}
+
+/* Check whether a task can create a file. */
+static int may_create(struct inode *dir,
+		      struct dentry *dentry,
+		      u16 tclass)
+{
+	struct task_security_struct *tsec;
+	struct inode_security_struct *dsec;
+	struct superblock_security_struct *sbsec;
+	u32 newsid;
+	struct avc_audit_data ad;
+	int rc;
+
+	tsec = current-&gt;security;
+	dsec = dir-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+	ad.u.fs.dentry = dentry;
+
+	rc = avc_has_perm(tsec-&gt;sid, dsec-&gt;sid, SECCLASS_DIR,
+			  DIR__ADD_NAME | DIR__SEARCH,
+			  &amp;dsec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+
+	if (tsec-&gt;create_sid) {
+		newsid = tsec-&gt;create_sid;
+	} else {
+		rc = security_transition_sid(tsec-&gt;sid, dsec-&gt;sid, tclass,
+					     &amp;newsid);
+		if (rc)
+			return rc;
+	}
+
+	rc = avc_has_perm(tsec-&gt;sid, newsid, tclass, FILE__CREATE, NULL, &amp;ad);
+	if (rc)
+		return rc;
+
+	sbsec = dir-&gt;i_sb-&gt;s_security;
+
+	return avc_has_perm(newsid, sbsec-&gt;sid,
+			    SECCLASS_FILESYSTEM,
+			    FILESYSTEM__ASSOCIATE, NULL, &amp;ad);
+}
+
+#define MAY_LINK   0
+#define MAY_UNLINK 1
+#define MAY_RMDIR  2
+
+/* Check whether a task can link, unlink, or rmdir a file/directory. */
+static int may_link(struct inode *dir,
+		    struct dentry *dentry,
+		    int kind)
+
+{
+	struct task_security_struct *tsec;
+	struct inode_security_struct *dsec, *isec;
+	struct avc_audit_data ad;
+	u32 av;
+	int rc;
+
+	tsec = current-&gt;security;
+	dsec = dir-&gt;i_security;
+	isec = dentry-&gt;d_inode-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+	ad.u.fs.dentry = dentry;
+
+	av = DIR__SEARCH;
+	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
+	rc = avc_has_perm(tsec-&gt;sid, dsec-&gt;sid, SECCLASS_DIR,
+			  av, &amp;dsec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+
+	switch (kind) {
+	case MAY_LINK:
+		av = FILE__LINK;
+		break;
+	case MAY_UNLINK:
+		av = FILE__UNLINK;
+		break;
+	case MAY_RMDIR:
+		av = DIR__RMDIR;
+		break;
+	default:
+		printk(KERN_WARNING "may_link:  unrecognized kind %d\n", kind);
+		return 0;
+	}
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			  av, &amp;isec-&gt;avcr, &amp;ad);
+	return rc;
+}
+
+static inline int may_rename(struct inode *old_dir,
+			     struct dentry *old_dentry,
+			     struct inode *new_dir,
+			     struct dentry *new_dentry)
+{
+	struct task_security_struct *tsec;
+	struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
+	struct avc_audit_data ad;
+	u32 av;
+	int old_is_dir, new_is_dir;
+	int rc;
+
+	tsec = current-&gt;security;
+	old_dsec = old_dir-&gt;i_security;
+	old_isec = old_dentry-&gt;d_inode-&gt;i_security;
+	old_is_dir = S_ISDIR(old_dentry-&gt;d_inode-&gt;i_mode);
+	new_dsec = new_dir-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+
+	ad.u.fs.dentry = old_dentry;
+	rc = avc_has_perm(tsec-&gt;sid, old_dsec-&gt;sid, SECCLASS_DIR,
+			  DIR__REMOVE_NAME | DIR__SEARCH,
+			  &amp;old_dsec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+	rc = avc_has_perm(tsec-&gt;sid, old_isec-&gt;sid,
+			  old_isec-&gt;sclass,
+			  FILE__RENAME,
+			  &amp;old_isec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+	if (old_is_dir &amp;&amp; new_dir != old_dir) {
+		rc = avc_has_perm(tsec-&gt;sid, old_isec-&gt;sid,
+				  old_isec-&gt;sclass,
+				  DIR__REPARENT,
+				  &amp;old_isec-&gt;avcr, &amp;ad);
+		if (rc)
+			return rc;
+	}
+
+	ad.u.fs.dentry = new_dentry;
+	av = DIR__ADD_NAME | DIR__SEARCH;
+	if (new_dentry-&gt;d_inode)
+		av |= DIR__REMOVE_NAME;
+	rc = avc_has_perm(tsec-&gt;sid, new_dsec-&gt;sid, SECCLASS_DIR,
+			  av,&amp;new_dsec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+	if (new_dentry-&gt;d_inode) {
+		new_isec = new_dentry-&gt;d_inode-&gt;i_security;
+		new_is_dir = S_ISDIR(new_dentry-&gt;d_inode-&gt;i_mode);
+		rc = avc_has_perm(tsec-&gt;sid, new_isec-&gt;sid,
+				  new_isec-&gt;sclass,
+				  (new_is_dir ? DIR__RMDIR : FILE__UNLINK),
+				  &amp;new_isec-&gt;avcr, &amp;ad);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+/* Check whether a task can perform a filesystem operation. */
+int superblock_has_perm(struct task_struct *tsk,
+			struct super_block *sb,
+			u32 perms,
+			struct avc_audit_data *ad)
+{
+	struct task_security_struct *tsec;
+	struct superblock_security_struct *sbsec;
+
+	tsec = tsk-&gt;security;
+	sbsec = sb-&gt;s_security;
+	return avc_has_perm(tsec-&gt;sid, sbsec-&gt;sid, SECCLASS_FILESYSTEM,
+			    perms, NULL, ad);
+}
+
+/* Convert a Linux mode and permission mask to an access vector. */
+static inline u32 file_mask_to_av(int mode, int mask)
+{
+	u32 av = 0;
+
+	if ((mode &amp; S_IFMT) != S_IFDIR) {
+		if (mask &amp; MAY_EXEC)
+			av |= FILE__EXECUTE;
+		if (mask &amp; MAY_READ)
+			av |= FILE__READ;
+
+		if (mask &amp; MAY_APPEND)
+			av |= FILE__APPEND;
+		else if (mask &amp; MAY_WRITE)
+			av |= FILE__WRITE;
+
+	} else {
+		if (mask &amp; MAY_EXEC)
+			av |= DIR__SEARCH;
+		if (mask &amp; MAY_WRITE)
+			av |= DIR__WRITE;
+		if (mask &amp; MAY_READ)
+			av |= DIR__READ;
+	}
+
+	return av;
+}
+
+/* Convert a Linux file to an access vector. */
+static inline u32 file_to_av(struct file *file)
+{
+	u32 av = 0;
+
+	if (file-&gt;f_mode &amp; FMODE_READ)
+		av |= FILE__READ;
+	if (file-&gt;f_mode &amp; FMODE_WRITE) {
+		if (file-&gt;f_flags &amp; O_APPEND)
+			av |= FILE__APPEND;
+		else
+			av |= FILE__WRITE;
+	}
+
+	return av;
+}
+
+/* Set an inode's SID to a specified value. */
+int inode_security_set_sid(struct inode *inode, u32 sid)
+{
+	struct inode_security_struct *isec = inode-&gt;i_security;
+
+	down(&amp;isec-&gt;sem);
+	isec-&gt;sclass = inode_mode_to_security_class(inode-&gt;i_mode);
+	isec-&gt;sid = sid;
+	isec-&gt;initialized = 1;
+	up(&amp;isec-&gt;sem);
+	return 0;
+}
+
+/* Set the security attributes on a newly created file. */
+static int post_create(struct inode *dir,
+		       struct dentry *dentry)
+{
+
+	struct task_security_struct *tsec;
+	struct inode *inode;
+	struct inode_security_struct *dsec;
+	struct superblock_security_struct *sbsec;
+	u32 newsid;
+	char *context;
+	unsigned int len;
+	int rc;
+
+	tsec = current-&gt;security;
+	dsec = dir-&gt;i_security;
+
+	inode = dentry-&gt;d_inode;
+	if (!inode) {
+		/* Some file system types (e.g. NFS) may not instantiate
+		   a dentry for all create operations (e.g. symlink),
+		   so we have to check to see if the inode is non-NULL. */
+		printk(KERN_WARNING "post_create:  no inode, dir (dev=%s, "
+		       "ino=%ld)\n", dir-&gt;i_sb-&gt;s_id, dir-&gt;i_ino);
+		return 0;
+	}
+
+	if (tsec-&gt;create_sid) {
+		newsid = tsec-&gt;create_sid;
+	} else {
+		rc = security_transition_sid(tsec-&gt;sid, dsec-&gt;sid,
+					     inode_mode_to_security_class(inode-&gt;i_mode),
+					     &amp;newsid);
+		if (rc) {
+			printk(KERN_WARNING "post_create:  "
+			       "security_transition_sid failed, rc=%d (dev=%s "
+			       "ino=%ld)\n",
+			       -rc, inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+			return rc;
+		}
+	}
+
+	rc = inode_security_set_sid(inode, newsid);
+	if (rc) {
+		printk(KERN_WARNING "post_create:  inode_security_set_sid "
+		       "failed, rc=%d (dev=%s ino=%ld)\n",
+		       -rc, inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+		return rc;
+	}
+
+	sbsec = dir-&gt;i_sb-&gt;s_security;
+	if (!sbsec)
+		return 0;
+
+	if (sbsec-&gt;behavior == SECURITY_FS_USE_XATTR &amp;&amp;
+	    inode-&gt;i_op-&gt;setxattr) {
+		/* Use extended attributes. */
+		rc = security_sid_to_context(newsid, &amp;context, &amp;len);
+		if (rc) {
+			printk(KERN_WARNING "post_create:  sid_to_context "
+			       "failed, rc=%d (dev=%s ino=%ld)\n",
+			       -rc, inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+			return rc;
+		}
+		down(&amp;inode-&gt;i_sem);
+		rc = inode-&gt;i_op-&gt;setxattr(dentry,
+					   XATTR_NAME_SELINUX,
+					   context, len, 0);
+		up(&amp;inode-&gt;i_sem);
+		kfree(context);
+		if (rc &lt; 0) {
+			printk(KERN_WARNING "post_create:  setxattr failed, "
+			       "rc=%d (dev=%s ino=%ld)\n",
+			       -rc, inode-&gt;i_sb-&gt;s_id, inode-&gt;i_ino);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+
+/* Hook functions begin here. */
+
+static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+{
+	int rc;
+
+	rc = secondary_ops-&gt;ptrace(parent,child);
+	if (rc)
+		return rc;
+
+	return task_has_perm(parent, child, PROCESS__PTRACE);
+}
+
+static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
+                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
+{
+	int error;
+
+	error = task_has_perm(current, target, PROCESS__GETCAP);
+	if (error)
+		return error;
+
+	return secondary_ops-&gt;capget(target, effective, inheritable, permitted);
+}
+
+static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
+                                kernel_cap_t *inheritable, kernel_cap_t *permitted)
+{
+	int error;
+
+	error = task_has_perm(current, target, PROCESS__SETCAP);
+	if (error)
+		return error;
+
+	return secondary_ops-&gt;capset_check(target, effective, inheritable, permitted);
+}
+
+static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
+                               kernel_cap_t *inheritable, kernel_cap_t *permitted)
+{
+	int error;
+
+	error = task_has_perm(current, target, PROCESS__SETCAP);
+	if (error)
+		return;
+
+	return secondary_ops-&gt;capset_set(target, effective, inheritable, permitted);
+}
+
+static int selinux_capable(struct task_struct *tsk, int cap)
+{
+	int rc;
+
+	rc = secondary_ops-&gt;capable(tsk, cap);
+	if (rc)
+		return rc;
+
+	return task_has_capability(tsk,cap);
+}
+
+static int selinux_sysctl(ctl_table *table, int op)
+{
+	int error = 0;
+	u32 av;
+	struct task_security_struct *tsec;
+	u32 tsid;
+	int rc;
+
+	tsec = current-&gt;security;
+
+	rc = selinux_proc_get_sid(table-&gt;de, (op == 001) ?
+	                          SECCLASS_DIR : SECCLASS_FILE, &amp;tsid);
+	if (rc) {
+		/* Default to the well-defined sysctl SID. */
+		tsid = SECINITSID_SYSCTL;
+	}
+
+	/* The op values are "defined" in sysctl.c, thereby creating
+	 * a bad coupling between this module and sysctl.c */
+	if(op == 001) {
+		error = avc_has_perm(tsec-&gt;sid, tsid,
+				     SECCLASS_DIR, DIR__SEARCH, NULL, NULL);
+	} else {
+		av = 0;
+		if (op &amp; 004)
+			av |= FILE__READ;
+		if (op &amp; 002)
+			av |= FILE__WRITE;
+		if (av)
+			error = avc_has_perm(tsec-&gt;sid, tsid,
+					     SECCLASS_FILE, av, NULL, NULL);
+        }
+
+	return error;
+}
+
+static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
+{
+	int rc = 0;
+
+	if (!sb)
+		return 0;
+
+	switch (cmds) {
+		case Q_SYNC:
+		case Q_QUOTAON:
+		case Q_QUOTAOFF:
+	        case Q_SETINFO:
+		case Q_SETQUOTA:
+			rc = superblock_has_perm(current,
+						 sb,
+						 FILESYSTEM__QUOTAMOD, NULL);
+			break;
+	        case Q_GETFMT:
+	        case Q_GETINFO:
+		case Q_GETQUOTA:
+			rc = superblock_has_perm(current,
+						 sb,
+						 FILESYSTEM__QUOTAGET, NULL);
+			break;
+		default:
+			rc = 0;  /* let the kernel handle invalid cmds */
+			break;
+	}
+	return rc;
+}
+
+static int selinux_quota_on(struct file *f)
+{
+	return file_has_perm(current, f, FILE__QUOTAON);;
+}
+
+static int selinux_syslog(int type)
+{
+	int rc;
+
+	rc = secondary_ops-&gt;syslog(type);
+	if (rc)
+		return rc;
+
+	switch (type) {
+		case 3:         /* Read last kernel messages */
+			rc = task_has_system(current, SYSTEM__SYSLOG_READ);
+			break;
+		case 6:         /* Disable logging to console */
+		case 7:         /* Enable logging to console */
+		case 8:		/* Set level of messages printed to console */
+			rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
+			break;
+		case 0:         /* Close log */
+		case 1:         /* Open log */
+		case 2:         /* Read from log */
+		case 4:         /* Read/clear last kernel messages */
+		case 5:         /* Clear ring buffer */
+		default:
+			rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
+			break;
+	}
+	return rc;
+}
+
+/*
+ * Check that a process has enough memory to allocate a new virtual
+ * mapping. 0 means there is enough memory for the allocation to
+ * succeed and -ENOMEM implies there is not.
+ *
+ * We currently support three overcommit policies, which are set via the
+ * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-acounting
+ *
+ * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
+ * Additional code 2002 Jul 20 by Robert Love.
+ */
+static int selinux_vm_enough_memory(long pages)
+{
+	unsigned long free, allowed;
+	int rc;
+	struct task_security_struct *tsec = current-&gt;security;
+
+	vm_acct_memory(pages);
+
+        /*
+	 * Sometimes we want to use more memory than we have
+	 */
+	if (sysctl_overcommit_memory == 1)
+		return 0;
+
+	if (sysctl_overcommit_memory == 0) {
+		free = get_page_cache_size();
+		free += nr_free_pages();
+		free += nr_swap_pages;
+
+		/*
+		 * Any slabs which are created with the
+		 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+		 * which are reclaimable, under pressure.  The dentry
+		 * cache and most inode caches should fall into this
+		 */
+		free += atomic_read(&amp;slab_reclaim_pages);
+
+		/*
+		 * Leave the last 3% for privileged processes.
+		 * Don't audit the check, as it is applied to all processes
+		 * that allocate mappings.
+		 */
+		rc = secondary_ops-&gt;capable(current, CAP_SYS_ADMIN);
+		if (!rc) {
+			rc = avc_has_perm_noaudit(tsec-&gt;sid, tsec-&gt;sid,
+						  SECCLASS_CAPABILITY,
+						  CAP_TO_MASK(CAP_SYS_ADMIN),
+						  NULL, NULL);
+		}
+		if (rc)
+			free -= free / 32;
+
+		if (free &gt; pages)
+			return 0;
+		vm_unacct_memory(pages);
+		return -ENOMEM;
+	}
+
+	allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+	allowed += total_swap_pages;
+
+	if (atomic_read(&amp;vm_committed_space) &lt; allowed)
+		return 0;
+
+	vm_unacct_memory(pages);
+
+	return -ENOMEM;
+}
+
+static int selinux_netlink_send(struct sk_buff *skb)
+{
+	if (capable(CAP_NET_ADMIN))
+		cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
+	else
+		NETLINK_CB(skb).eff_cap = 0;
+	return 0;
+}
+
+static int selinux_netlink_recv(struct sk_buff *skb)
+{
+	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
+/* binprm security operations */
+
+static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+{
+	int rc;
+
+	/* Make sure that the secondary module doesn't use the
+	   bprm-&gt;security field, since we do not yet support chaining
+	   of multiple security structures on the field.  Neither
+	   the dummy nor the capability module use the field.  The owlsm
+	   module uses the field if CONFIG_OWLSM_FD is enabled. */
+	rc = secondary_ops-&gt;bprm_alloc_security(bprm);
+	if (rc)
+		return rc;
+	if (bprm-&gt;security) {
+		printk(KERN_WARNING "%s: no support yet for chaining on the "
+		       "security field by secondary modules.\n", __FUNCTION__);
+		/* Release the secondary module's security object. */
+		secondary_ops-&gt;bprm_free_security(bprm);
+		/* Unregister the secondary module to prevent problems
+		   with subsequent binprm hooks. This will revert to the
+		   original (dummy) module for the secondary operations. */
+		rc = security_ops-&gt;unregister_security("unknown", secondary_ops);
+		if (rc)
+			return rc;
+		printk(KERN_WARNING "%s: Unregistered the secondary security "
+		       "module.\n", __FUNCTION__);
+	}
+	bprm-&gt;security = NULL;
+	return 0;
+}
+
+static int selinux_bprm_set_security(struct linux_binprm *bprm)
+{
+	struct task_security_struct *tsec;
+	struct inode *inode = bprm-&gt;file-&gt;f_dentry-&gt;d_inode;
+	struct inode_security_struct *isec;
+	u32 newsid;
+	struct avc_audit_data ad;
+	int rc;
+
+	rc = secondary_ops-&gt;bprm_set_security(bprm);
+	if (rc)
+		return rc;
+
+	if (bprm-&gt;sh_bang || bprm-&gt;security)
+		/* The security field should already be set properly. */
+		return 0;
+
+	tsec = current-&gt;security;
+	isec = inode-&gt;i_security;
+
+	/* Default to the current task SID. */
+	bprm-&gt;security = (void *)tsec-&gt;sid;
+
+	/* Reset create SID on execve. */
+	tsec-&gt;create_sid = 0;
+
+	if (tsec-&gt;exec_sid) {
+		newsid = tsec-&gt;exec_sid;
+		/* Reset exec SID on execve. */
+		tsec-&gt;exec_sid = 0;
+	} else {
+		/* Check for a default transition on this program. */
+		rc = security_transition_sid(tsec-&gt;sid, isec-&gt;sid,
+		                             SECCLASS_PROCESS, &amp;newsid);
+		if (rc)
+			return rc;
+	}
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, FS);
+	ad.u.fs.mnt = bprm-&gt;file-&gt;f_vfsmnt;
+	ad.u.fs.dentry = bprm-&gt;file-&gt;f_dentry;
+
+	if (bprm-&gt;file-&gt;f_vfsmnt-&gt;mnt_flags &amp; MNT_NOSUID)
+		newsid = tsec-&gt;sid;
+
+        if (tsec-&gt;sid == newsid) {
+		rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid,
+				  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS,
+				  &amp;isec-&gt;avcr, &amp;ad);
+		if (rc)
+			return rc;
+	} else {
+		/* Check permissions for the transition. */
+		rc = avc_has_perm(tsec-&gt;sid, newsid,
+				  SECCLASS_PROCESS, PROCESS__TRANSITION,
+				  NULL,
+				  &amp;ad);
+		if (rc)
+			return rc;
+
+		rc = avc_has_perm(newsid, isec-&gt;sid,
+				  SECCLASS_FILE, FILE__ENTRYPOINT,
+				  &amp;isec-&gt;avcr, &amp;ad);
+		if (rc)
+			return rc;
+
+		/* Set the security field to the new SID. */
+		bprm-&gt;security = (void*) newsid;
+	}
+
+	return 0;
+}
+
+static int selinux_bprm_check_security (struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+
+static int selinux_bprm_secureexec (struct linux_binprm *bprm)
+{
+	struct task_security_struct *tsec = current-&gt;security;
+	int atsecure = 0;
+
+	if (tsec-&gt;osid != tsec-&gt;sid) {
+		/* Enable secure mode for SIDs transitions unless
+		   the noatsecure permission is granted between
+		   the two SIDs, i.e. ahp returns 0. */
+		atsecure = avc_has_perm(tsec-&gt;osid, tsec-&gt;sid,
+					 SECCLASS_PROCESS,
+					 PROCESS__NOATSECURE, NULL, NULL);
+	}
+
+	/* Note that we must include the legacy uid/gid test below
+	   to retain it, as the new userland will simply use the
+	   value passed by AT_SECURE to decide whether to enable
+	   secure mode. */
+	return ( atsecure || current-&gt;euid != current-&gt;uid ||
+		current-&gt;egid != current-&gt;gid);
+}
+
+static void selinux_bprm_free_security(struct linux_binprm *bprm)
+{
+	/* Nothing to do - not dynamically allocated. */
+	return;
+}
+
+/* Derived from fs/exec.c:flush_old_files. */
+static inline void flush_unauthorized_files(struct files_struct * files)
+{
+	struct avc_audit_data ad;
+	struct file *file;
+	long j = -1;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,FS);
+
+	spin_lock(&amp;files-&gt;file_lock);
+	for (;;) {
+		unsigned long set, i;
+
+		j++;
+		i = j * __NFDBITS;
+		if (i &gt;= files-&gt;max_fds || i &gt;= files-&gt;max_fdset)
+			break;
+		set = files-&gt;open_fds-&gt;fds_bits[j];
+		if (!set)
+			continue;
+		spin_unlock(&amp;files-&gt;file_lock);
+		for ( ; set ; i++,set &gt;&gt;= 1) {
+			if (set &amp; 1) {
+				file = fget(i);
+				if (!file)
+					continue;
+				if (file_has_perm(current,
+						  file,
+						  file_to_av(file)))
+					sys_close(i);
+				fput(file);
+			}
+		}
+		spin_lock(&amp;files-&gt;file_lock);
+
+	}
+	spin_unlock(&amp;files-&gt;file_lock);
+}
+
+static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
+{
+	struct task_security_struct *tsec, *psec;
+	u32 sid;
+	struct av_decision avd;
+	int rc;
+
+	secondary_ops-&gt;bprm_compute_creds(bprm);
+
+	tsec = current-&gt;security;
+
+	sid = (u32)bprm-&gt;security;
+	if (!sid)
+		sid = tsec-&gt;sid;
+
+	tsec-&gt;osid = tsec-&gt;sid;
+	if (tsec-&gt;sid != sid) {
+		/* Check for shared state.  If not ok, leave SID
+		   unchanged and kill. */
+		if ((atomic_read(&amp;current-&gt;fs-&gt;count) &gt; 1 ||
+		     atomic_read(&amp;current-&gt;files-&gt;count) &gt; 1 ||
+		     atomic_read(&amp;current-&gt;sighand-&gt;count) &gt; 1)) {
+			rc = avc_has_perm(tsec-&gt;sid, sid,
+					  SECCLASS_PROCESS, PROCESS__SHARE,
+					  NULL, NULL);
+			if (rc) {
+				force_sig_specific(SIGKILL, current);
+				return;
+			}
+		}
+
+		/* Check for ptracing, and update the task SID if ok.
+		   Otherwise, leave SID unchanged and kill. */
+		task_lock(current);
+		if (current-&gt;ptrace &amp; PT_PTRACED) {
+			psec = current-&gt;parent-&gt;security;
+			rc = avc_has_perm_noaudit(psec-&gt;sid, sid,
+					  SECCLASS_PROCESS, PROCESS__PTRACE,
+					  NULL, &amp;avd);
+			if (!rc)
+				tsec-&gt;sid = sid;
+			task_unlock(current);
+			avc_audit(psec-&gt;sid, sid, SECCLASS_PROCESS,
+				  PROCESS__PTRACE, &amp;avd, rc, NULL);
+			if (rc) {
+				force_sig_specific(SIGKILL, current);
+				return;
+			}
+		} else {
+			tsec-&gt;sid = sid;
+			task_unlock(current);
+		}
+
+		/* Close files for which the new task SID is not authorized. */
+		flush_unauthorized_files(current-&gt;files);
+
+		/* Wake up the parent if it is waiting so that it can
+		   recheck wait permission to the new task SID. */
+		wake_up_interruptible(&amp;current-&gt;parent-&gt;wait_chldexit);
+	}
+}
+
+/* superblock security operations */
+
+static int selinux_sb_alloc_security(struct super_block *sb)
+{
+	return superblock_alloc_security(sb);
+}
+
+static void selinux_sb_free_security(struct super_block *sb)
+{
+	superblock_free_security(sb);
+}
+
+static int selinux_sb_kern_mount(struct super_block *sb)
+{
+	struct avc_audit_data ad;
+	int rc;
+
+	rc = superblock_doinit(sb);
+	if (rc)
+		return rc;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,FS);
+	ad.u.fs.dentry = sb-&gt;s_root;
+	return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &amp;ad);
+}
+
+static int selinux_sb_statfs(struct super_block *sb)
+{
+	struct avc_audit_data ad;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,FS);
+	ad.u.fs.dentry = sb-&gt;s_root;
+	return superblock_has_perm(current, sb, FILESYSTEM__GETATTR, &amp;ad);
+}
+
+static int selinux_mount(char * dev_name,
+                         struct nameidata *nd,
+                         char * type,
+                         unsigned long flags,
+                         void * data)
+{
+	if (flags &amp; MS_REMOUNT)
+		return superblock_has_perm(current, nd-&gt;mnt-&gt;mnt_sb,
+		                           FILESYSTEM__REMOUNT, NULL);
+	else
+		return dentry_has_perm(current, nd-&gt;mnt, nd-&gt;dentry,
+		                       FILE__MOUNTON);
+}
+
+static int selinux_umount(struct vfsmount *mnt, int flags)
+{
+	return superblock_has_perm(current,mnt-&gt;mnt_sb,
+	                           FILESYSTEM__UNMOUNT,NULL);
+}
+
+/* inode security operations */
+
+static int selinux_inode_alloc_security(struct inode *inode)
+{
+	return inode_alloc_security(inode);
+}
+
+static void selinux_inode_free_security(struct inode *inode)
+{
+	inode_free_security(inode);
+}
+
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
+{
+	return may_create(dir, dentry, SECCLASS_FILE);
+}
+
+static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask)
+{
+	post_create(dir, dentry);
+}
+
+static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+{
+	int rc;
+
+	rc = secondary_ops-&gt;inode_link(old_dentry,dir,new_dentry);
+	if (rc)
+		return rc;
+	return may_link(dir, old_dentry, MAY_LINK);
+}
+
+static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry)
+{
+	return;
+}
+
+static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+	return may_link(dir, dentry, MAY_UNLINK);
+}
+
+static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
+{
+	return may_create(dir, dentry, SECCLASS_LNK_FILE);
+}
+
+static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name)
+{
+	post_create(dir, dentry);
+}
+
+static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
+{
+	return may_create(dir, dentry, SECCLASS_DIR);
+}
+
+static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask)
+{
+	post_create(dir, dentry);
+}
+
+static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	return may_link(dir, dentry, MAY_RMDIR);
+}
+
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	return may_create(dir, dentry, inode_mode_to_security_class(mode));
+}
+
+static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	post_create(dir, dentry);
+}
+
+static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
+                                struct inode *new_inode, struct dentry *new_dentry)
+{
+	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
+}
+
+static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry,
+                                      struct inode *new_inode, struct dentry *new_dentry)
+{
+	return;
+}
+
+static int selinux_inode_readlink(struct dentry *dentry)
+{
+	return dentry_has_perm(current, NULL, dentry, FILE__READ);
+}
+
+static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
+{
+	int rc;
+
+	rc = secondary_ops-&gt;inode_follow_link(dentry,nameidata);
+	if (rc)
+		return rc;
+	return dentry_has_perm(current, NULL, dentry, FILE__READ);
+}
+
+static int selinux_inode_permission(struct inode *inode, int mask)
+{
+	if (!mask) {
+		/* No permission to check.  Existence test. */
+		return 0;
+	}
+
+	return inode_has_perm(current, inode,
+			       file_mask_to_av(inode-&gt;i_mode, mask), NULL, NULL);
+}
+
+static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	if (iattr-&gt;ia_valid &amp; (ATTR_MODE | ATTR_UID | ATTR_GID |
+			       ATTR_ATIME_SET | ATTR_MTIME_SET))
+		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+
+	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
+}
+
+static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+{
+	return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
+}
+
+static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+{
+	struct task_security_struct *tsec = current-&gt;security;
+	struct inode *inode = dentry-&gt;d_inode;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+	struct superblock_security_struct *sbsec;
+	struct avc_audit_data ad;
+	u32 newsid;
+	int rc = 0;
+
+	if (strcmp(name, XATTR_NAME_SELINUX)) {
+		if (!strncmp(name, XATTR_SECURITY_PREFIX,
+			     sizeof XATTR_SECURITY_PREFIX - 1) &amp;&amp;
+		    !capable(CAP_SYS_ADMIN)) {
+			/* A different attribute in the security namespace.
+			   Restrict to administrator. */
+			return -EPERM;
+		}
+
+		/* Not an attribute we recognize, so just check the
+		   ordinary setattr permission. */
+		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+	}
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,FS);
+	ad.u.fs.dentry = dentry;
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			  FILE__RELABELFROM,
+			  &amp;isec-&gt;avcr, &amp;ad);
+	if (rc)
+		return rc;
+
+	rc = security_context_to_sid(value, size, &amp;newsid);
+	if (rc)
+		return rc;
+
+	rc = avc_has_perm(tsec-&gt;sid, newsid, isec-&gt;sclass,
+			  FILE__RELABELTO, NULL, &amp;ad);
+	if (rc)
+		return rc;
+
+	sbsec = inode-&gt;i_sb-&gt;s_security;
+	if (!sbsec)
+		return 0;
+
+	return avc_has_perm(newsid,
+			    sbsec-&gt;sid,
+			    SECCLASS_FILESYSTEM,
+			    FILESYSTEM__ASSOCIATE,
+			    NULL,
+			    &amp;ad);
+}
+
+static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+                                        void *value, size_t size, int flags)
+{
+	struct inode *inode = dentry-&gt;d_inode;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+	u32 newsid;
+	int rc;
+
+	if (strcmp(name, XATTR_NAME_SELINUX)) {
+		/* Not an attribute we recognize, so nothing to do. */
+		return;
+	}
+
+	rc = security_context_to_sid(value, size, &amp;newsid);
+	if (rc) {
+		printk(KERN_WARNING "%s:  unable to obtain SID for context "
+		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
+		return;
+	}
+
+	isec-&gt;sid = newsid;
+	return;
+}
+
+static int selinux_inode_getxattr (struct dentry *dentry, char *name)
+{
+	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+}
+
+static int selinux_inode_listxattr (struct dentry *dentry)
+{
+	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+}
+
+static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+{
+	if (strcmp(name, XATTR_NAME_SELINUX)) {
+		if (!strncmp(name, XATTR_SECURITY_PREFIX,
+			     sizeof XATTR_SECURITY_PREFIX - 1) &amp;&amp;
+		    !capable(CAP_SYS_ADMIN)) {
+			/* A different attribute in the security namespace.
+			   Restrict to administrator. */
+			return -EPERM;
+		}
+
+		/* Not an attribute we recognize, so just check the
+		   ordinary setattr permission. Might want a separate
+		   permission for removexattr. */
+		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+	}
+
+	/* No one is allowed to remove a SELinux security label.
+	   You can change the label, but all data must be labeled. */
+	return -EACCES;
+}
+
+static int selinux_inode_getsecurity(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	struct inode *inode = dentry-&gt;d_inode;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+	char *context;
+	unsigned len;
+	int rc;
+
+	/* Permission check handled by selinux_inode_getxattr hook.*/
+
+	if (strcmp(name, XATTR_SELINUX_SUFFIX))
+		return -EOPNOTSUPP;
+
+	rc = security_sid_to_context(isec-&gt;sid, &amp;context, &amp;len);
+	if (rc)
+		return rc;
+
+	if (!buffer || !size) {
+		kfree(context);
+		return len;
+	}
+	if (size &lt; len) {
+		kfree(context);
+		return -ERANGE;
+	}
+	memcpy(buffer, context, len);
+	kfree(context);
+	return len;
+}
+
+static int selinux_inode_setsecurity(struct dentry *dentry, const char *name,
+                                     const void *value, size_t size, int flags)
+{
+	struct inode *inode = dentry-&gt;d_inode;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+	u32 newsid;
+	int rc;
+
+	if (strcmp(name, XATTR_SELINUX_SUFFIX))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EACCES;
+
+	rc = security_context_to_sid((void*)value, size, &amp;newsid);
+	if (rc)
+		return rc;
+
+	isec-&gt;sid = newsid;
+	return 0;
+}
+
+static int selinux_inode_listsecurity(struct dentry *dentry, char *buffer)
+{
+	const int len = sizeof(XATTR_NAME_SELINUX);
+	if (buffer)
+		memcpy(buffer, XATTR_NAME_SELINUX, len);
+	return len;
+}
+
+/* file security operations */
+
+static int selinux_file_permission(struct file *file, int mask)
+{
+	struct inode *inode = file-&gt;f_dentry-&gt;d_inode;
+
+	if (!mask) {
+		/* No permission to check.  Existence test. */
+		return 0;
+	}
+
+	/* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
+	if ((file-&gt;f_flags &amp; O_APPEND) &amp;&amp; (mask &amp; MAY_WRITE))
+		mask |= MAY_APPEND;
+
+	return file_has_perm(current, file,
+			     file_mask_to_av(inode-&gt;i_mode, mask));
+}
+
+static int selinux_file_alloc_security(struct file *file)
+{
+	return file_alloc_security(file);
+}
+
+static void selinux_file_free_security(struct file *file)
+{
+	file_free_security(file);
+}
+
+static int selinux_file_ioctl(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	int error = 0;
+
+	switch (cmd) {
+		case FIONREAD:
+		/* fall through */
+		case FIBMAP:
+		/* fall through */
+		case FIGETBSZ:
+		/* fall through */
+		case EXT2_IOC_GETFLAGS:
+		/* fall through */
+		case EXT2_IOC_GETVERSION:
+			error = file_has_perm(current, file, FILE__GETATTR);
+			break;
+
+		case EXT2_IOC_SETFLAGS:
+		/* fall through */
+		case EXT2_IOC_SETVERSION:
+			error = file_has_perm(current, file, FILE__SETATTR);
+			break;
+
+		/* sys_ioctl() checks */
+		case FIONBIO:
+		/* fall through */
+		case FIOASYNC:
+			error = file_has_perm(current, file, 0);
+			break;
+
+	        case KDSKBENT:
+	        case KDSKBSENT:
+		  	if (!capable(CAP_SYS_TTY_CONFIG))
+				error = -EPERM;
+			break;
+
+		/* default case assumes that the command will go
+		 * to the file's ioctl() function.
+		 */
+		default:
+			error = file_has_perm(current, file, FILE__IOCTL);
+
+	}
+	return error;
+}
+
+static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+{
+	u32 av;
+
+	if (file) {
+		/* read access is always possible with a mapping */
+		av = FILE__READ;
+
+		/* write access only matters if the mapping is shared */
+		if ((flags &amp; MAP_TYPE) == MAP_SHARED &amp;&amp; (prot &amp; PROT_WRITE))
+			av |= FILE__WRITE;
+
+		if (prot &amp; PROT_EXEC)
+			av |= FILE__EXECUTE;
+
+		return file_has_perm(current, file, av);
+	}
+	return 0;
+}
+
+static int selinux_file_mprotect(struct vm_area_struct *vma,
+				 unsigned long prot)
+{
+	return selinux_file_mmap(vma-&gt;vm_file, prot, vma-&gt;vm_flags);
+}
+
+static int selinux_file_lock(struct file *file, unsigned int cmd)
+{
+	return file_has_perm(current, file, FILE__LOCK);
+}
+
+static int selinux_file_fcntl(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	int err = 0;
+
+	switch (cmd) {
+	        case F_SETFL:
+			if (!file-&gt;f_dentry || !file-&gt;f_dentry-&gt;d_inode) {
+				err = -EINVAL;
+				break;
+			}
+
+			if ((file-&gt;f_flags &amp; O_APPEND) &amp;&amp; !(arg &amp; O_APPEND)) {
+				err = file_has_perm(current, file,FILE__WRITE);
+				break;
+			}
+			/* fall through */
+	        case F_SETOWN:
+	        case F_SETSIG:
+	        case F_GETFL:
+	        case F_GETOWN:
+	        case F_GETSIG:
+			/* Just check FD__USE permission */
+			err = file_has_perm(current, file, 0);
+			break;
+		case F_GETLK:
+		case F_SETLK:
+	        case F_SETLKW:
+	        case F_GETLK64:
+		case F_SETLK64:
+	        case F_SETLKW64:
+			if (!file-&gt;f_dentry || !file-&gt;f_dentry-&gt;d_inode) {
+				err = -EINVAL;
+				break;
+			}
+			err = file_has_perm(current, file, FILE__LOCK);
+			break;
+	}
+
+	return err;
+}
+
+static int selinux_file_set_fowner(struct file *file)
+{
+	struct task_security_struct *tsec;
+	struct file_security_struct *fsec;
+
+	tsec = current-&gt;security;
+	fsec = file-&gt;f_security;
+	fsec-&gt;fown_sid = tsec-&gt;sid;
+
+	return 0;
+}
+
+static int selinux_file_send_sigiotask(struct task_struct *tsk,
+				       struct fown_struct *fown,
+				       int fd, int reason)
+{
+        struct file *file;
+	u32 perm;
+	struct task_security_struct *tsec;
+	struct file_security_struct *fsec;
+
+	/* struct fown_struct is never outside the context of a struct file */
+        file = (struct file *)((long)fown - offsetof(struct file,f_owner));
+
+	tsec = tsk-&gt;security;
+	fsec = file-&gt;f_security;
+
+	if (!fown-&gt;signum)
+		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
+	else
+		perm = signal_to_av(fown-&gt;signum);
+
+	return avc_has_perm(fsec-&gt;fown_sid, tsec-&gt;sid,
+			    SECCLASS_PROCESS, perm, NULL, NULL);
+}
+
+static int selinux_file_receive(struct file *file)
+{
+	return file_has_perm(current, file, file_to_av(file));
+}
+
+/* task security operations */
+
+static int selinux_task_create(unsigned long clone_flags)
+{
+	return task_has_perm(current, current, PROCESS__FORK);
+}
+
+static int selinux_task_alloc_security(struct task_struct *tsk)
+{
+	struct task_security_struct *tsec1, *tsec2;
+	int rc;
+
+	tsec1 = current-&gt;security;
+
+	rc = task_alloc_security(tsk);
+	if (rc)
+		return rc;
+	tsec2 = tsk-&gt;security;
+
+	tsec2-&gt;osid = tsec1-&gt;osid;
+	tsec2-&gt;sid = tsec1-&gt;sid;
+
+	/* Retain the exec and create SIDs across fork */
+	tsec2-&gt;exec_sid = tsec1-&gt;exec_sid;
+	tsec2-&gt;create_sid = tsec1-&gt;create_sid;
+
+	return 0;
+}
+
+static void selinux_task_free_security(struct task_struct *tsk)
+{
+	task_free_security(tsk);
+}
+
+static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+	/* Since setuid only affects the current process, and
+	   since the SELinux controls are not based on the Linux
+	   identity attributes, SELinux does not need to control
+	   this operation.  However, SELinux does control the use
+	   of the CAP_SETUID and CAP_SETGID capabilities using the
+	   capable hook. */
+	return 0;
+}
+
+static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+	return secondary_ops-&gt;task_post_setuid(id0,id1,id2,flags);
+}
+
+static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
+{
+	/* See the comment for setuid above. */
+	return 0;
+}
+
+static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
+{
+	return task_has_perm(current, p, PROCESS__SETPGID);
+}
+
+static int selinux_task_getpgid(struct task_struct *p)
+{
+	return task_has_perm(current, p, PROCESS__GETPGID);
+}
+
+static int selinux_task_getsid(struct task_struct *p)
+{
+	return task_has_perm(current, p, PROCESS__GETSESSION);
+}
+
+static int selinux_task_setgroups(int gidsetsize, gid_t *grouplist)
+{
+	/* See the comment for setuid above. */
+	return 0;
+}
+
+static int selinux_task_setnice(struct task_struct *p, int nice)
+{
+	return task_has_perm(current,p, PROCESS__SETSCHED);
+}
+
+static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
+{
+	/* SELinux does not currently provide a process
+	   resource limit policy based on security contexts.
+	   It does control the use of the CAP_SYS_RESOURCE capability
+	   using the capable hook. */
+	return 0;
+}
+
+static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
+{
+	struct task_security_struct *tsec1, *tsec2;
+
+	tsec1 = current-&gt;security;
+	tsec2 = p-&gt;security;
+
+	/* No auditing from the setscheduler hook, since the runqueue lock
+	   is held and the system will deadlock if we try to log an audit
+	   message. */
+	return avc_has_perm_noaudit(tsec1-&gt;sid, tsec2-&gt;sid,
+				    SECCLASS_PROCESS, PROCESS__SETSCHED,
+				    &amp;tsec2-&gt;avcr, NULL);
+}
+
+static int selinux_task_getscheduler(struct task_struct *p)
+{
+	return task_has_perm(current, p, PROCESS__GETSCHED);
+}
+
+static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig)
+{
+	u32 perm;
+
+	if (info &amp;&amp; ((unsigned long)info == 1 ||
+	             (unsigned long)info == 2 || SI_FROMKERNEL(info)))
+		return 0;
+
+	if (!sig)
+		perm = PROCESS__SIGNULL; /* null signal; existence test */
+	else
+		perm = signal_to_av(sig);
+
+	return task_has_perm(current, p, perm);
+}
+
+static int selinux_task_prctl(int option,
+			      unsigned long arg2,
+			      unsigned long arg3,
+			      unsigned long arg4,
+			      unsigned long arg5)
+{
+	/* The current prctl operations do not appear to require
+	   any SELinux controls since they merely observe or modify
+	   the state of the current process. */
+	return 0;
+}
+
+static int selinux_task_wait(struct task_struct *p)
+{
+	u32 perm;
+
+	perm = signal_to_av(p-&gt;exit_signal);
+
+	return task_has_perm(p, current, perm);
+}
+
+static void selinux_task_reparent_to_init(struct task_struct *p)
+{
+  	struct task_security_struct *tsec;
+
+	secondary_ops-&gt;task_reparent_to_init(p);
+
+	tsec = p-&gt;security;
+	tsec-&gt;osid = tsec-&gt;sid;
+	tsec-&gt;sid = SECINITSID_KERNEL;
+	return;
+}
+
+static void selinux_task_to_inode(struct task_struct *p,
+				  struct inode *inode)
+{
+	struct task_security_struct *tsec = p-&gt;security;
+	struct inode_security_struct *isec = inode-&gt;i_security;
+
+	isec-&gt;sid = tsec-&gt;sid;
+	isec-&gt;initialized = 1;
+	return;
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+
+/* socket security operations */
+static int socket_has_perm(struct task_struct *task, struct socket *sock,
+			   u32 perms)
+{
+	struct inode_security_struct *isec;
+	struct task_security_struct *tsec;
+	struct avc_audit_data ad;
+	int err;
+
+	tsec = task-&gt;security;
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = sock-&gt;sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   perms, &amp;isec-&gt;avcr, &amp;ad);
+
+	return err;
+}
+
+static int selinux_socket_create(int family, int type, int protocol)
+{
+	int err;
+	struct task_security_struct *tsec;
+
+	tsec = current-&gt;security;
+
+	err = avc_has_perm(tsec-&gt;sid, tsec-&gt;sid,
+			   socket_type_to_security_class(family, type),
+			   SOCKET__CREATE, NULL, NULL);
+
+	return err;
+}
+
+static void selinux_socket_post_create(struct socket *sock, int family, int type, int protocol)
+{
+	int err;
+	struct inode_security_struct *isec;
+	struct task_security_struct *tsec;
+
+	err = inode_doinit(SOCK_INODE(sock));
+	if (err &lt; 0)
+		return;
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	tsec = current-&gt;security;
+	isec-&gt;sclass = socket_type_to_security_class(family, type);
+	isec-&gt;sid = tsec-&gt;sid;
+
+	return;
+}
+
+/* Range of port numbers used to automatically bind.
+   Need to determine whether we should perform a name_bind
+   permission check between the socket and the port number. */
+#define ip_local_port_range_0 sysctl_local_port_range[0]
+#define ip_local_port_range_1 sysctl_local_port_range[1]
+
+static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+	int err;
+
+	err = socket_has_perm(current, sock, SOCKET__BIND);
+	if (err)
+		return err;
+
+	/*
+	 * If PF_INET, check name_bind permission for the port.
+	 */
+	if (sock-&gt;sk-&gt;sk_family == PF_INET) {
+		struct inode_security_struct *isec;
+		struct task_security_struct *tsec;
+		struct avc_audit_data ad;
+		struct sockaddr_in *addr = (struct sockaddr_in *)address;
+		unsigned short snum = ntohs(addr-&gt;sin_port);
+		struct sock *sk = sock-&gt;sk;
+		u32 sid;
+
+		tsec = current-&gt;security;
+		isec = SOCK_INODE(sock)-&gt;i_security;
+
+		if (snum&amp;&amp;(snum &lt; max(PROT_SOCK,ip_local_port_range_0) ||
+			   snum &gt; ip_local_port_range_1)) {
+			err = security_port_sid(sk-&gt;sk_family, sk-&gt;sk_type,
+						sk-&gt;sk_protocol, snum, &amp;sid);
+			if (err)
+				return err;
+			AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+			ad.u.net.port = snum;
+			err = avc_has_perm(isec-&gt;sid, sid,
+					   isec-&gt;sclass,
+					   SOCKET__NAME_BIND, NULL, &amp;ad);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+	int err;
+	struct sock *sk = sock-&gt;sk;
+	struct avc_audit_data ad;
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	tsec = current-&gt;security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, NET);
+	ad.u.net.sk = sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__CONNECT, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_listen(struct socket *sock, int backlog)
+{
+	int err;
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, NET);
+	ad.u.net.sk = sock-&gt;sk;
+
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__LISTEN, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
+{
+	int err;
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+	struct inode_security_struct *newisec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, NET);
+	ad.u.net.sk = sock-&gt;sk;
+
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__ACCEPT, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	err = inode_doinit(SOCK_INODE(newsock));
+	if (err &lt; 0)
+		return err;
+	newisec = SOCK_INODE(newsock)-&gt;i_security;
+
+	newisec-&gt;sclass = isec-&gt;sclass;
+	newisec-&gt;sid = isec-&gt;sid;
+
+	return 0;
+}
+
+static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
+ 				  int size)
+{
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+	struct avc_audit_data ad;
+	struct sock *sk;
+	int err;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	tsec = current-&gt;security;
+
+	sk = sock-&gt;sk;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, NET);
+	ad.u.net.sk = sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__WRITE, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
+				  int size, int flags)
+{
+	struct inode_security_struct *isec;
+	struct task_security_struct *tsec;
+	struct avc_audit_data ad;
+	int err;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+	tsec = current-&gt;security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = sock-&gt;sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__READ, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_getsockname(struct socket *sock)
+{
+	struct inode_security_struct *isec;
+	struct task_security_struct *tsec;
+	struct avc_audit_data ad;
+	int err;
+
+	tsec = current-&gt;security;
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = sock-&gt;sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__GETATTR, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_getpeername(struct socket *sock)
+{
+	struct inode_security_struct *isec;
+	struct task_security_struct *tsec;
+	struct avc_audit_data ad;
+	int err;
+
+	tsec = current-&gt;security;
+	isec = SOCK_INODE(sock)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = sock-&gt;sk;
+	err = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, isec-&gt;sclass,
+			   SOCKET__GETATTR, &amp;isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
+{
+	return socket_has_perm(current, sock, SOCKET__SETOPT);
+}
+
+static int selinux_socket_getsockopt(struct socket *sock, int level,
+				     int optname)
+{
+	return socket_has_perm(current, sock, SOCKET__GETOPT);
+}
+
+static int selinux_socket_shutdown(struct socket *sock, int how)
+{
+	return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
+}
+
+static int selinux_socket_unix_stream_connect(struct socket *sock,
+					      struct socket *other,
+					      struct sock *newsk)
+{
+	struct inode_security_struct *isec;
+	struct inode_security_struct *other_isec;
+	struct avc_audit_data ad;
+	int err;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+	other_isec = SOCK_INODE(other)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = other-&gt;sk;
+
+	err = avc_has_perm(isec-&gt;sid, other_isec-&gt;sid,
+			   isec-&gt;sclass,
+			   UNIX_STREAM_SOCKET__CONNECTTO,
+			   &amp;other_isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int selinux_socket_unix_may_send(struct socket *sock,
+					struct socket *other)
+{
+	struct inode_security_struct *isec;
+	struct inode_security_struct *other_isec;
+	struct avc_audit_data ad;
+	int err;
+
+	isec = SOCK_INODE(sock)-&gt;i_security;
+	other_isec = SOCK_INODE(other)-&gt;i_security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad,NET);
+	ad.u.net.sk = other-&gt;sk;
+
+	err = avc_has_perm(isec-&gt;sid, other_isec-&gt;sid,
+			   isec-&gt;sclass,
+			   SOCKET__SENDTO,
+			   &amp;other_isec-&gt;avcr, &amp;ad);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+#endif
+
+static int ipc_alloc_security(struct task_struct *task,
+			      struct kern_ipc_perm *perm,
+			      u16 sclass)
+{
+	struct task_security_struct *tsec = task-&gt;security;
+	struct ipc_security_struct *isec;
+
+	isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
+	if (!isec)
+		return -ENOMEM;
+
+	memset(isec, 0, sizeof(struct ipc_security_struct));
+	isec-&gt;magic = SELINUX_MAGIC;
+	isec-&gt;sclass = sclass;
+	isec-&gt;ipc_perm = perm;
+	if (tsec) {
+		isec-&gt;sid = tsec-&gt;sid;
+	} else {
+		isec-&gt;sid = SECINITSID_UNLABELED;
+	}
+	perm-&gt;security = isec;
+
+	return 0;
+}
+
+static void ipc_free_security(struct kern_ipc_perm *perm)
+{
+	struct ipc_security_struct *isec = perm-&gt;security;
+	if (!isec || isec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	perm-&gt;security = NULL;
+	kfree(isec);
+}
+
+static int msg_msg_alloc_security(struct msg_msg *msg)
+{
+	struct msg_security_struct *msec;
+
+	msec = kmalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
+	if (!msec)
+		return -ENOMEM;
+
+	memset(msec, 0, sizeof(struct msg_security_struct));
+	msec-&gt;magic = SELINUX_MAGIC;
+	msec-&gt;msg = msg;
+	msec-&gt;sid = SECINITSID_UNLABELED;
+	msg-&gt;security = msec;
+
+	return 0;
+}
+
+static void msg_msg_free_security(struct msg_msg *msg)
+{
+	struct msg_security_struct *msec = msg-&gt;security;
+	if (!msec || msec-&gt;magic != SELINUX_MAGIC)
+		return;
+
+	msg-&gt;security = NULL;
+	kfree(msec);
+}
+
+static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
+			u16 sclass, u32 perms)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+	isec = ipc_perms-&gt;security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+	ad.u.ipc_id = ipc_perms-&gt;key;
+
+	return avc_has_perm(tsec-&gt;sid, isec-&gt;sid, sclass,
+			    perms, &amp;isec-&gt;avcr, &amp;ad);
+}
+
+static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
+{
+	return msg_msg_alloc_security(msg);
+}
+
+static void selinux_msg_msg_free_security(struct msg_msg *msg)
+{
+	return msg_msg_free_security(msg);
+}
+
+/* message queue security operations */
+static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+	int rc;
+
+	rc = ipc_alloc_security(current, &amp;msq-&gt;q_perm, SECCLASS_MSGQ);
+	if (rc)
+		return rc;
+
+	tsec = current-&gt;security;
+	isec = msq-&gt;q_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+ 	ad.u.ipc_id = msq-&gt;q_perm.key;
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_MSGQ,
+			  MSGQ__CREATE, &amp;isec-&gt;avcr, &amp;ad);
+	if (rc) {
+		ipc_free_security(&amp;msq-&gt;q_perm);
+		return rc;
+	}
+	return 0;
+}
+
+static void selinux_msg_queue_free_security(struct msg_queue *msq)
+{
+	ipc_free_security(&amp;msq-&gt;q_perm);
+}
+
+static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+	isec = msq-&gt;q_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+	ad.u.ipc_id = msq-&gt;q_perm.key;
+
+	return avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_MSGQ,
+			    MSGQ__ASSOCIATE, &amp;isec-&gt;avcr, &amp;ad);
+}
+
+static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+{
+	int err;
+	int perms;
+
+	switch(cmd) {
+	case IPC_INFO:
+	case MSG_INFO:
+		/* No specific object, just general system-wide information. */
+		return task_has_system(current, SYSTEM__IPC_INFO);
+	case IPC_STAT:
+	case MSG_STAT:
+		perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
+		break;
+	case IPC_SET:
+		perms = MSGQ__SETATTR;
+		break;
+	case IPC_RMID:
+		perms = MSGQ__DESTROY;
+		break;
+	default:
+		return 0;
+	}
+
+	err = ipc_has_perm(&amp;msq-&gt;q_perm, SECCLASS_MSGQ, perms);
+	return err;
+}
+
+static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct msg_security_struct *msec;
+	struct avc_audit_data ad;
+	int rc;
+
+	tsec = current-&gt;security;
+	isec = msq-&gt;q_perm.security;
+	msec = msg-&gt;security;
+
+	/*
+	 * First time through, need to assign label to the message
+	 */
+	if (msec-&gt;sid == SECINITSID_UNLABELED) {
+		/*
+		 * Compute new sid based on current process and
+		 * message queue this message will be stored in
+		 */
+		rc = security_transition_sid(tsec-&gt;sid,
+					     isec-&gt;sid,
+					     SECCLASS_MSG,
+					     &amp;msec-&gt;sid);
+		if (rc)
+			return rc;
+	}
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+	ad.u.ipc_id = msq-&gt;q_perm.key;
+
+	/* Can this process write to the queue? */
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_MSGQ,
+			  MSGQ__WRITE, &amp;isec-&gt;avcr, &amp;ad);
+	if (!rc)
+		/* Can this process send the message */
+		rc = avc_has_perm(tsec-&gt;sid, msec-&gt;sid,
+				  SECCLASS_MSG, MSG__SEND,
+				  &amp;msec-&gt;avcr, &amp;ad);
+	if (!rc)
+		/* Can the message be put in the queue? */
+		rc = avc_has_perm(msec-&gt;sid, isec-&gt;sid,
+				  SECCLASS_MSGQ, MSGQ__ENQUEUE,
+				  &amp;isec-&gt;avcr, &amp;ad);
+
+	return rc;
+}
+
+static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+				    struct task_struct *target,
+				    long type, int mode)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct msg_security_struct *msec;
+	struct avc_audit_data ad;
+	int rc;
+
+	tsec = target-&gt;security;
+	isec = msq-&gt;q_perm.security;
+	msec = msg-&gt;security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+ 	ad.u.ipc_id = msq-&gt;q_perm.key;
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid,
+			  SECCLASS_MSGQ, MSGQ__READ,
+			  &amp;isec-&gt;avcr, &amp;ad);
+	if (!rc)
+		rc = avc_has_perm(tsec-&gt;sid, msec-&gt;sid,
+				  SECCLASS_MSG, MSG__RECEIVE,
+				  &amp;msec-&gt;avcr, &amp;ad);
+	return rc;
+}
+
+/* Shared Memory security operations */
+static int selinux_shm_alloc_security(struct shmid_kernel *shp)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+	int rc;
+
+	rc = ipc_alloc_security(current, &amp;shp-&gt;shm_perm, SECCLASS_SHM);
+	if (rc)
+		return rc;
+
+	tsec = current-&gt;security;
+	isec = shp-&gt;shm_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+ 	ad.u.ipc_id = shp-&gt;shm_perm.key;
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_SHM,
+			  SHM__CREATE, &amp;isec-&gt;avcr, &amp;ad);
+	if (rc) {
+		ipc_free_security(&amp;shp-&gt;shm_perm);
+		return rc;
+	}
+	return 0;
+}
+
+static void selinux_shm_free_security(struct shmid_kernel *shp)
+{
+	ipc_free_security(&amp;shp-&gt;shm_perm);
+}
+
+static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+	isec = shp-&gt;shm_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+	ad.u.ipc_id = shp-&gt;shm_perm.key;
+
+	return avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_SHM,
+			    SHM__ASSOCIATE, &amp;isec-&gt;avcr, &amp;ad);
+}
+
+/* Note, at this point, shp is locked down */
+static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
+{
+	int perms;
+	int err;
+
+	switch(cmd) {
+	case IPC_INFO:
+	case SHM_INFO:
+		/* No specific object, just general system-wide information. */
+		return task_has_system(current, SYSTEM__IPC_INFO);
+	case IPC_STAT:
+	case SHM_STAT:
+		perms = SHM__GETATTR | SHM__ASSOCIATE;
+		break;
+	case IPC_SET:
+		perms = SHM__SETATTR;
+		break;
+	case SHM_LOCK:
+	case SHM_UNLOCK:
+		perms = SHM__LOCK;
+		break;
+	case IPC_RMID:
+		perms = SHM__DESTROY;
+		break;
+	default:
+		return 0;
+	}
+
+	err = ipc_has_perm(&amp;shp-&gt;shm_perm, SECCLASS_SHM, perms);
+	return err;
+}
+
+static int selinux_shm_shmat(struct shmid_kernel *shp,
+			     char *shmaddr, int shmflg)
+{
+	u32 perms;
+
+	if (shmflg &amp; SHM_RDONLY)
+		perms = SHM__READ;
+	else
+		perms = SHM__READ | SHM__WRITE;
+
+	return ipc_has_perm(&amp;shp-&gt;shm_perm, SECCLASS_SHM, perms);
+}
+
+/* Semaphore security operations */
+static int selinux_sem_alloc_security(struct sem_array *sma)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+	int rc;
+
+	rc = ipc_alloc_security(current, &amp;sma-&gt;sem_perm, SECCLASS_SEM);
+	if (rc)
+		return rc;
+
+	tsec = current-&gt;security;
+	isec = sma-&gt;sem_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+ 	ad.u.ipc_id = sma-&gt;sem_perm.key;
+
+	rc = avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_SEM,
+			  SEM__CREATE, &amp;isec-&gt;avcr, &amp;ad);
+	if (rc) {
+		ipc_free_security(&amp;sma-&gt;sem_perm);
+		return rc;
+	}
+	return 0;
+}
+
+static void selinux_sem_free_security(struct sem_array *sma)
+{
+	ipc_free_security(&amp;sma-&gt;sem_perm);
+}
+
+static int selinux_sem_associate(struct sem_array *sma, int semflg)
+{
+	struct task_security_struct *tsec;
+	struct ipc_security_struct *isec;
+	struct avc_audit_data ad;
+
+	tsec = current-&gt;security;
+	isec = sma-&gt;sem_perm.security;
+
+	AVC_AUDIT_DATA_INIT(&amp;ad, IPC);
+	ad.u.ipc_id = sma-&gt;sem_perm.key;
+
+	return avc_has_perm(tsec-&gt;sid, isec-&gt;sid, SECCLASS_SEM,
+			    SEM__ASSOCIATE, &amp;isec-&gt;avcr, &amp;ad);
+}
+
+/* Note, at this point, sma is locked down */
+static int selinux_sem_semctl(struct sem_array *sma, int cmd)
+{
+	int err;
+	u32 perms;
+
+	switch(cmd) {
+	case IPC_INFO:
+	case SEM_INFO:
+		/* No specific object, just general system-wide information. */
+		return task_has_system(current, SYSTEM__IPC_INFO);
+	case GETPID:
+	case GETNCNT:
+	case GETZCNT:
+		perms = SEM__GETATTR;
+		break;
+	case GETVAL:
+	case GETALL:
+		perms = SEM__READ;
+		break;
+	case SETVAL:
+	case SETALL:
+		perms = SEM__WRITE;
+		break;
+	case IPC_RMID:
+		perms = SEM__DESTROY;
+		break;
+	case IPC_SET:
+		perms = SEM__SETATTR;
+		break;
+	case IPC_STAT:
+	case SEM_STAT:
+		perms = SEM__GETATTR | SEM__ASSOCIATE;
+		break;
+	default:
+		return 0;
+	}
+
+	err = ipc_has_perm(&amp;sma-&gt;sem_perm, SECCLASS_SEM, perms);
+	return err;
+}
+
+static int selinux_sem_semop(struct sem_array *sma,
+			     struct sembuf *sops, unsigned nsops, int alter)
+{
+	u32 perms;
+
+	if (alter)
+		perms = SEM__READ | SEM__WRITE;
+	else
+		perms = SEM__READ;
+
+	return ipc_has_perm(&amp;sma-&gt;sem_perm, SECCLASS_SEM, perms);
+}
+
+static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+{
+	struct ipc_security_struct *isec = ipcp-&gt;security;
+	u16 sclass = SECCLASS_IPC;
+	u32 av = 0;
+
+	if (isec &amp;&amp; isec-&gt;magic == SELINUX_MAGIC)
+		sclass = isec-&gt;sclass;
+
+	av = 0;
+	if (flag &amp; S_IRUGO)
+		av |= IPC__UNIX_READ;
+	if (flag &amp; S_IWUGO)
+		av |= IPC__UNIX_WRITE;
+
+	if (av == 0)
+		return 0;
+
+	return ipc_has_perm(ipcp, sclass, av);
+}
+
+/* module stacking operations */
+int selinux_register_security (const char *name, struct security_operations *ops)
+{
+	if (secondary_ops != original_ops) {
+		printk(KERN_INFO "%s:  There is already a secondary security "
+		       "module registered.\n", __FUNCTION__);
+		return -EINVAL;
+ 	}
+
+	secondary_ops = ops;
+
+	printk(KERN_INFO "%s:  Registering secondary module %s\n",
+	       __FUNCTION__,
+	       name);
+
+	return 0;
+}
+
+int selinux_unregister_security (const char *name, struct security_operations *ops)
+{
+	if (ops != secondary_ops) {
+		printk (KERN_INFO "%s:  trying to unregister a security module "
+		        "that is not registered.\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	secondary_ops = original_ops;
+
+	return 0;
+}
+
+static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
+{
+	if (inode)
+		inode_doinit_with_dentry(inode, dentry);
+}
+
+static int selinux_getprocattr(struct task_struct *p,
+			       char *name, void *value, size_t size)
+{
+	struct task_security_struct *tsec;
+	u32 sid;
+	char *context;
+	size_t len;
+	int error;
+
+	if (current != p) {
+		error = task_has_perm(current, p, PROCESS__GETATTR);
+		if (error)
+			return error;
+	}
+
+	if (!size)
+		return -ERANGE;
+
+	tsec = p-&gt;security;
+
+	if (!strcmp(name, "current"))
+		sid = tsec-&gt;sid;
+	else if (!strcmp(name, "prev"))
+		sid = tsec-&gt;osid;
+	else if (!strcmp(name, "exec"))
+		sid = tsec-&gt;exec_sid;
+	else if (!strcmp(name, "fscreate"))
+		sid = tsec-&gt;create_sid;
+	else
+		return -EINVAL;
+
+	if (!sid)
+		return 0;
+
+	error = security_sid_to_context(sid, &amp;context, &amp;len);
+	if (error)
+		return error;
+	if (len &gt; size) {
+		kfree(context);
+		return -ERANGE;
+	}
+	memcpy(value, context, len);
+	kfree(context);
+	return len;
+}
+
+static int selinux_setprocattr(struct task_struct *p,
+			       char *name, void *value, size_t size)
+{
+	struct task_security_struct *tsec;
+	u32 sid = 0;
+	int error;
+
+	if (current != p || !strcmp(name, "current")) {
+		/* SELinux only allows a process to change its own
+		   security attributes, and it only allows the process
+		   current SID to change via exec. */
+		return -EACCES;
+	}
+
+	/*
+	 * Basic control over ability to set these attributes at all.
+	 * current == p, but we'll pass them separately in case the
+	 * above restriction is ever removed.
+	 */
+	if (!strcmp(name, "exec"))
+		error = task_has_perm(current, p, PROCESS__SETEXEC);
+	else if (!strcmp(name, "fscreate"))
+		error = task_has_perm(current, p, PROCESS__SETFSCREATE);
+	else
+		error = -EINVAL;
+	if (error)
+		return error;
+
+	/* Obtain a SID for the context, if one was specified. */
+	if (size) {
+		int error;
+		error = security_context_to_sid(value, size, &amp;sid);
+		if (error)
+			return error;
+	}
+
+	/* Permission checking based on the specified context is
+	   performed during the actual operation (execve,
+	   open/mkdir/...), when we know the full context of the
+	   operation.  See selinux_bprm_set_security for the execve
+	   checks and may_create for the file creation checks. The
+	   operation will then fail if the context is not permitted. */
+	tsec = p-&gt;security;
+	if (!strcmp(name, "exec"))
+		tsec-&gt;exec_sid = sid;
+	else if (!strcmp(name, "fscreate"))
+		tsec-&gt;create_sid = sid;
+	else
+		return -EINVAL;
+
+	return size;
+}
+
+struct security_operations selinux_ops = {
+	.ptrace =			selinux_ptrace,
+	.capget =			selinux_capget,
+	.capset_check =			selinux_capset_check,
+	.capset_set =			selinux_capset_set,
+	.sysctl =			selinux_sysctl,
+	.capable =			selinux_capable,
+	.quotactl =			selinux_quotactl,
+	.quota_on =			selinux_quota_on,
+	.syslog =			selinux_syslog,
+	.vm_enough_memory =		selinux_vm_enough_memory,
+
+	.netlink_send =			selinux_netlink_send,
+        .netlink_recv =			selinux_netlink_recv,
+
+	.bprm_alloc_security =		selinux_bprm_alloc_security,
+	.bprm_free_security =		selinux_bprm_free_security,
+	.bprm_compute_creds =		selinux_bprm_compute_creds,
+	.bprm_set_security =		selinux_bprm_set_security,
+	.bprm_check_security =		selinux_bprm_check_security,
+	.bprm_secureexec =		selinux_bprm_secureexec,
+
+	.sb_alloc_security =		selinux_sb_alloc_security,
+	.sb_free_security =		selinux_sb_free_security,
+	.sb_kern_mount =	        selinux_sb_kern_mount,
+	.sb_statfs =			selinux_sb_statfs,
+	.sb_mount =			selinux_mount,
+	.sb_umount =			selinux_umount,
+
+	.inode_alloc_security =		selinux_inode_alloc_security,
+	.inode_free_security =		selinux_inode_free_security,
+	.inode_create =			selinux_inode_create,
+	.inode_post_create =		selinux_inode_post_create,
+	.inode_link =			selinux_inode_link,
+	.inode_post_link =		selinux_inode_post_link,
+	.inode_unlink =			selinux_inode_unlink,
+	.inode_symlink =		selinux_inode_symlink,
+	.inode_post_symlink =		selinux_inode_post_symlink,
+	.inode_mkdir =			selinux_inode_mkdir,
+	.inode_post_mkdir =		selinux_inode_post_mkdir,
+	.inode_rmdir =			selinux_inode_rmdir,
+	.inode_mknod =			selinux_inode_mknod,
+	.inode_post_mknod =		selinux_inode_post_mknod,
+	.inode_rename =			selinux_inode_rename,
+	.inode_post_rename =		selinux_inode_post_rename,
+	.inode_readlink =		selinux_inode_readlink,
+	.inode_follow_link =		selinux_inode_follow_link,
+	.inode_permission =		selinux_inode_permission,
+	.inode_setattr =		selinux_inode_setattr,
+	.inode_getattr =		selinux_inode_getattr,
+	.inode_setxattr =		selinux_inode_setxattr,
+	.inode_post_setxattr =		selinux_inode_post_setxattr,
+	.inode_getxattr =		selinux_inode_getxattr,
+	.inode_listxattr =		selinux_inode_listxattr,
+	.inode_removexattr =		selinux_inode_removexattr,
+	.inode_getsecurity =            selinux_inode_getsecurity,
+	.inode_setsecurity =            selinux_inode_setsecurity,
+	.inode_listsecurity =           selinux_inode_listsecurity,
+
+	.file_permission =		selinux_file_permission,
+	.file_alloc_security =		selinux_file_alloc_security,
+	.file_free_security =		selinux_file_free_security,
+	.file_ioctl =			selinux_file_ioctl,
+	.file_mmap =			selinux_file_mmap,
+	.file_mprotect =		selinux_file_mprotect,
+	.file_lock =			selinux_file_lock,
+	.file_fcntl =			selinux_file_fcntl,
+	.file_set_fowner =		selinux_file_set_fowner,
+	.file_send_sigiotask =		selinux_file_send_sigiotask,
+	.file_receive =			selinux_file_receive,
+
+	.task_create =			selinux_task_create,
+	.task_alloc_security =		selinux_task_alloc_security,
+	.task_free_security =		selinux_task_free_security,
+	.task_setuid =			selinux_task_setuid,
+	.task_post_setuid =		selinux_task_post_setuid,
+	.task_setgid =			selinux_task_setgid,
+	.task_setpgid =			selinux_task_setpgid,
+	.task_getpgid =			selinux_task_getpgid,
+	.task_getsid =		        selinux_task_getsid,
+	.task_setgroups =		selinux_task_setgroups,
+	.task_setnice =			selinux_task_setnice,
+	.task_setrlimit =		selinux_task_setrlimit,
+	.task_setscheduler =		selinux_task_setscheduler,
+	.task_getscheduler =		selinux_task_getscheduler,
+	.task_kill =			selinux_task_kill,
+	.task_wait =			selinux_task_wait,
+	.task_prctl =			selinux_task_prctl,
+	.task_reparent_to_init =	selinux_task_reparent_to_init,
+	.task_to_inode =                selinux_task_to_inode,
+
+	.ipc_permission =		selinux_ipc_permission,
+
+	.msg_msg_alloc_security =	selinux_msg_msg_alloc_security,
+	.msg_msg_free_security =	selinux_msg_msg_free_security,
+
+	.msg_queue_alloc_security =	selinux_msg_queue_alloc_security,
+	.msg_queue_free_security =	selinux_msg_queue_free_security,
+	.msg_queue_associate =		selinux_msg_queue_associate,
+	.msg_queue_msgctl =		selinux_msg_queue_msgctl,
+	.msg_queue_msgsnd =		selinux_msg_queue_msgsnd,
+	.msg_queue_msgrcv =		selinux_msg_queue_msgrcv,
+
+	.shm_alloc_security =		selinux_shm_alloc_security,
+	.shm_free_security =		selinux_shm_free_security,
+	.shm_associate =		selinux_shm_associate,
+	.shm_shmctl =			selinux_shm_shmctl,
+	.shm_shmat =			selinux_shm_shmat,
+
+	.sem_alloc_security = 		selinux_sem_alloc_security,
+	.sem_free_security =  		selinux_sem_free_security,
+	.sem_associate =		selinux_sem_associate,
+	.sem_semctl =			selinux_sem_semctl,
+	.sem_semop =			selinux_sem_semop,
+
+	.register_security =		selinux_register_security,
+	.unregister_security =		selinux_unregister_security,
+
+	.d_instantiate =                selinux_d_instantiate,
+
+	.getprocattr =                  selinux_getprocattr,
+	.setprocattr =                  selinux_setprocattr,
+
+#ifdef CONFIG_SECURITY_NETWORK
+        .unix_stream_connect =		selinux_socket_unix_stream_connect,
+	.unix_may_send =		selinux_socket_unix_may_send,
+
+	.socket_create =		selinux_socket_create,
+	.socket_post_create =		selinux_socket_post_create,
+	.socket_bind =			selinux_socket_bind,
+	.socket_connect =		selinux_socket_connect,
+	.socket_listen =		selinux_socket_listen,
+	.socket_accept =		selinux_socket_accept,
+	.socket_sendmsg =		selinux_socket_sendmsg,
+	.socket_recvmsg =		selinux_socket_recvmsg,
+	.socket_getsockname =		selinux_socket_getsockname,
+	.socket_getpeername =		selinux_socket_getpeername,
+	.socket_getsockopt =		selinux_socket_getsockopt,
+	.socket_setsockopt =		selinux_socket_setsockopt,
+	.socket_shutdown =		selinux_socket_shutdown,
+#endif
+};
+
+__init int selinux_init(void)
+{
+	struct task_security_struct *tsec;
+
+	printk(KERN_INFO "SELinux:  Initializing.\n");
+
+	/* Set the security state for the initial task. */
+	if (task_alloc_security(current))
+		panic("SELinux:  Failed to initialize initial task.\n");
+	tsec = current-&gt;security;
+	tsec-&gt;osid = tsec-&gt;sid = SECINITSID_KERNEL;
+
+	avc_init();
+
+	original_ops = secondary_ops = security_ops;
+	if (!secondary_ops)
+		panic ("SELinux: No initial security operations\n");
+	if (register_security (&amp;selinux_ops))
+		panic("SELinux: Unable to register with kernel.\n");
+
+	if (selinux_enforcing) {
+		printk(KERN_INFO "SELinux:  Starting in enforcing mode\n");
+	} else {
+		printk(KERN_INFO "SELinux:  Starting in permissive mode\n");
+	}
+	return 0;
+}
+
+void selinux_complete_init(void)
+{
+	printk(KERN_INFO "SELinux:  Completing initialization.\n");
+
+	/* Set up any superblocks initialized prior to the policy load. */
+	printk(KERN_INFO "SELinux:  Setting up existing superblocks.\n");
+	spin_lock(&amp;sb_security_lock);
+next_sb:
+	if (!list_empty(&amp;superblock_security_head)) {
+		struct superblock_security_struct *sbsec =
+				list_entry(superblock_security_head.next,
+				           struct superblock_security_struct,
+				           list);
+		struct super_block *sb = sbsec-&gt;sb;
+		spin_lock(&amp;sb_lock);
+		sb-&gt;s_count++;
+		spin_unlock(&amp;sb_lock);
+		spin_unlock(&amp;sb_security_lock);
+		down_read(&amp;sb-&gt;s_umount);
+		if (sb-&gt;s_root)
+			superblock_doinit(sb);
+		drop_super(sb);
+		spin_lock(&amp;sb_security_lock);
+		list_del_init(&amp;sbsec-&gt;list);
+		goto next_sb;
+	}
+	spin_unlock(&amp;sb_security_lock);
+
+	/* Set up any inodes initialized prior to the policy load. */
+	printk(KERN_INFO "SELinux:  Setting up existing inodes.\n");
+	spin_lock(&amp;inode_security_lock);
+next_inode:
+	if (!list_empty(&amp;inode_security_head)) {
+		struct inode_security_struct *isec =
+				list_entry(inode_security_head.next,
+				           struct inode_security_struct, list);
+		struct inode *inode = isec-&gt;inode;
+		spin_unlock(&amp;inode_security_lock);
+		inode = igrab(inode);
+		if (inode) {
+			inode_doinit(inode);
+			iput(inode);
+		}
+		spin_lock(&amp;inode_security_lock);
+		list_del_init(&amp;isec-&gt;list);
+		goto next_inode;
+	}
+	spin_unlock(&amp;inode_security_lock);
+}
+
+/* SELinux requires early initialization in order to label
+   all processes and objects when they are created. */
+security_initcall(selinux_init);
+
diff -puN /dev/null security/selinux/include/avc.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/avc.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,159 @@
+/*
+ * Access vector cache interface for object managers.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SELINUX_AVC_H_
+#define _SELINUX_AVC_H_
+
+#include &lt;linux/stddef.h&gt;
+#include &lt;linux/errno.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/kdev_t.h&gt;
+#include &lt;linux/spinlock.h&gt;
+#include &lt;asm/system.h&gt;
+#include "flask.h"
+#include "av_permissions.h"
+#include "security.h"
+
+#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+extern int selinux_enforcing;
+#else
+#define selinux_enforcing 1
+#endif
+
+/*
+ * An entry in the AVC.
+ */
+struct avc_entry;
+
+/*
+ * A reference to an AVC entry.
+ */
+struct avc_entry_ref {
+	struct avc_entry *ae;
+};
+
+/* Initialize an AVC entry reference before first use. */
+static inline void avc_entry_ref_init(struct avc_entry_ref *h)
+{
+	h-&gt;ae = NULL;
+}
+
+struct task_struct;
+struct vfsmount;
+struct dentry;
+struct inode;
+struct sock;
+struct sk_buff;
+
+/* Auxiliary data to use in generating the audit record. */
+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
+	struct task_struct *tsk;
+	union 	{
+		struct {
+			struct vfsmount *mnt;
+			struct dentry *dentry;
+			struct inode *inode;
+		} fs;
+		struct {
+			char *netif;
+			struct sk_buff *skb;
+			struct sock *sk;
+			u16 port;
+			u32 daddr;
+		} net;
+		int cap;
+		int ipc_id;
+	} u;
+};
+
+/* Initialize an AVC audit data structure. */
+#define AVC_AUDIT_DATA_INIT(_d,_t) \
+        { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)-&gt;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];
+
+#ifdef AVC_CACHE_STATS
+static inline void avc_cache_stats_incr(int type)
+{
+	avc_cache_stats[type]++;
+}
+
+static inline void avc_cache_stats_add(int type, unsigned val)
+{
+	avc_cache_stats[type] += val;
+}
+#else
+static inline void avc_cache_stats_incr(int type)
+{ }
+
+static inline void avc_cache_stats_add(int type, unsigned val)
+{ }
+#endif
+
+/*
+ * AVC display support
+ */
+void avc_dump_av(u16 tclass, u32 av);
+void avc_dump_query(u32 ssid, u32 tsid, u16 tclass);
+void avc_dump_cache(char *tag);
+
+/*
+ * AVC operations
+ */
+
+void avc_init(void);
+
+int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
+               u32 requested, struct avc_entry_ref *aeref);
+
+int avc_insert(u32 ssid, u32 tsid, u16 tclass,
+               struct avc_entry *ae, struct avc_entry_ref *out_aeref);
+
+void avc_audit(u32 ssid, u32 tsid,
+               u16 tclass, u32 requested,
+               struct av_decision *avd, int result, struct avc_audit_data *auditdata);
+
+int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+                         u16 tclass, u32 requested,
+                         struct avc_entry_ref *aeref, struct av_decision *avd);
+
+int avc_has_perm(u32 ssid, u32 tsid,
+                 u16 tclass, u32 requested,
+                 struct avc_entry_ref *aeref, struct avc_audit_data *auditdata);
+
+#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
+
+int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
+                                     u16 tclass, u32 perms,
+				     u32 *out_retained),
+		     u32 events, u32 ssid, u32 tsid,
+		     u16 tclass, u32 perms);
+
+#endif /* _SELINUX_AVC_H_ */
+
diff -puN /dev/null security/selinux/include/avc_ss.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/avc_ss.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,27 @@
+/*
+ * Access vector cache interface for the security server.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SELINUX_AVC_SS_H_
+#define _SELINUX_AVC_SS_H_
+
+#include "flask.h"
+
+int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
+
+int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno,
+		      u32 *out_retained);
+
+int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
+
+int avc_ss_reset(u32 seqno);
+
+int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass, u32 perms,
+			  u32 seqno, u32 enable);
+
+int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, u32 perms,
+			 u32 seqno, u32 enable);
+
+#endif /* _SELINUX_AVC_SS_H_ */
+
diff -puN /dev/null security/selinux/include/av_inherit.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/av_inherit.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,35 @@
+/* This file is automatically generated.  Do not edit. */
+/* FLASK */
+
+struct av_inherit
+{
+    u16 tclass;
+    char **common_pts;
+    u32 common_base;
+};
+
+static struct av_inherit av_inherit[] = {
+   { SECCLASS_DIR, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_LNK_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_CHR_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_BLK_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_SOCK_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_FIFO_FILE, common_file_perm_to_string, 0x00020000UL },
+   { SECCLASS_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_TCP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_UDP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_RAWIP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_PACKET_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_KEY_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_UNIX_STREAM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_UNIX_DGRAM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_IPC, common_ipc_perm_to_string, 0x00000200UL },
+   { SECCLASS_SEM, common_ipc_perm_to_string, 0x00000200UL },
+   { SECCLASS_MSGQ, common_ipc_perm_to_string, 0x00000200UL },
+   { SECCLASS_SHM, common_ipc_perm_to_string, 0x00000200UL },
+};
+
+
+/* FLASK */
diff -puN /dev/null security/selinux/include/av_permissions.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/av_permissions.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,550 @@
+/* This file is automatically generated.  Do not edit. */
+/* FLASK */
+
+#define COMMON_FILE__IOCTL                               0x00000001UL
+#define COMMON_FILE__READ                                0x00000002UL
+#define COMMON_FILE__WRITE                               0x00000004UL
+#define COMMON_FILE__CREATE                              0x00000008UL
+#define COMMON_FILE__GETATTR                             0x00000010UL
+#define COMMON_FILE__SETATTR                             0x00000020UL
+#define COMMON_FILE__LOCK                                0x00000040UL
+#define COMMON_FILE__RELABELFROM                         0x00000080UL
+#define COMMON_FILE__RELABELTO                           0x00000100UL
+#define COMMON_FILE__APPEND                              0x00000200UL
+#define COMMON_FILE__UNLINK                              0x00000400UL
+#define COMMON_FILE__LINK                                0x00000800UL
+#define COMMON_FILE__RENAME                              0x00001000UL
+#define COMMON_FILE__EXECUTE                             0x00002000UL
+#define COMMON_FILE__SWAPON                              0x00004000UL
+#define COMMON_FILE__QUOTAON                             0x00008000UL
+#define COMMON_FILE__MOUNTON                             0x00010000UL
+
+#define COMMON_SOCKET__IOCTL                             0x00000001UL
+#define COMMON_SOCKET__READ                              0x00000002UL
+#define COMMON_SOCKET__WRITE                             0x00000004UL
+#define COMMON_SOCKET__CREATE                            0x00000008UL
+#define COMMON_SOCKET__GETATTR                           0x00000010UL
+#define COMMON_SOCKET__SETATTR                           0x00000020UL
+#define COMMON_SOCKET__LOCK                              0x00000040UL
+#define COMMON_SOCKET__RELABELFROM                       0x00000080UL
+#define COMMON_SOCKET__RELABELTO                         0x00000100UL
+#define COMMON_SOCKET__APPEND                            0x00000200UL
+#define COMMON_SOCKET__BIND                              0x00000400UL
+#define COMMON_SOCKET__CONNECT                           0x00000800UL
+#define COMMON_SOCKET__LISTEN                            0x00001000UL
+#define COMMON_SOCKET__ACCEPT                            0x00002000UL
+#define COMMON_SOCKET__GETOPT                            0x00004000UL
+#define COMMON_SOCKET__SETOPT                            0x00008000UL
+#define COMMON_SOCKET__SHUTDOWN                          0x00010000UL
+#define COMMON_SOCKET__RECVFROM                          0x00020000UL
+#define COMMON_SOCKET__SENDTO                            0x00040000UL
+#define COMMON_SOCKET__RECV_MSG                          0x00080000UL
+#define COMMON_SOCKET__SEND_MSG                          0x00100000UL
+#define COMMON_SOCKET__NAME_BIND                         0x00200000UL
+
+#define COMMON_IPC__CREATE                               0x00000001UL
+#define COMMON_IPC__DESTROY                              0x00000002UL
+#define COMMON_IPC__GETATTR                              0x00000004UL
+#define COMMON_IPC__SETATTR                              0x00000008UL
+#define COMMON_IPC__READ                                 0x00000010UL
+#define COMMON_IPC__WRITE                                0x00000020UL
+#define COMMON_IPC__ASSOCIATE                            0x00000040UL
+#define COMMON_IPC__UNIX_READ                            0x00000080UL
+#define COMMON_IPC__UNIX_WRITE                           0x00000100UL
+
+#define FILESYSTEM__MOUNT                         0x00000001UL
+#define FILESYSTEM__REMOUNT                       0x00000002UL
+#define FILESYSTEM__UNMOUNT                       0x00000004UL
+#define FILESYSTEM__GETATTR                       0x00000008UL
+#define FILESYSTEM__RELABELFROM                   0x00000010UL
+#define FILESYSTEM__RELABELTO                     0x00000020UL
+#define FILESYSTEM__TRANSITION                    0x00000040UL
+#define FILESYSTEM__ASSOCIATE                     0x00000080UL
+#define FILESYSTEM__QUOTAMOD                      0x00000100UL
+#define FILESYSTEM__QUOTAGET                      0x00000200UL
+
+#define DIR__EXECUTE                              0x00002000UL
+#define DIR__UNLINK                               0x00000400UL
+#define DIR__SETATTR                              0x00000020UL
+#define DIR__QUOTAON                              0x00008000UL
+#define DIR__RELABELFROM                          0x00000080UL
+#define DIR__LINK                                 0x00000800UL
+#define DIR__WRITE                                0x00000004UL
+#define DIR__IOCTL                                0x00000001UL
+#define DIR__RELABELTO                            0x00000100UL
+#define DIR__READ                                 0x00000002UL
+#define DIR__RENAME                               0x00001000UL
+#define DIR__APPEND                               0x00000200UL
+#define DIR__LOCK                                 0x00000040UL
+#define DIR__SWAPON                               0x00004000UL
+#define DIR__GETATTR                              0x00000010UL
+#define DIR__MOUNTON                              0x00010000UL
+#define DIR__CREATE                               0x00000008UL
+
+#define DIR__ADD_NAME                             0x00020000UL
+#define DIR__REMOVE_NAME                          0x00040000UL
+#define DIR__REPARENT                             0x00080000UL
+#define DIR__SEARCH                               0x00100000UL
+#define DIR__RMDIR                                0x00200000UL
+
+#define FILE__EXECUTE                             0x00002000UL
+#define FILE__UNLINK                              0x00000400UL
+#define FILE__SETATTR                             0x00000020UL
+#define FILE__QUOTAON                             0x00008000UL
+#define FILE__RELABELFROM                         0x00000080UL
+#define FILE__LINK                                0x00000800UL
+#define FILE__WRITE                               0x00000004UL
+#define FILE__IOCTL                               0x00000001UL
+#define FILE__RELABELTO                           0x00000100UL
+#define FILE__READ                                0x00000002UL
+#define FILE__RENAME                              0x00001000UL
+#define FILE__APPEND                              0x00000200UL
+#define FILE__LOCK                                0x00000040UL
+#define FILE__SWAPON                              0x00004000UL
+#define FILE__GETATTR                             0x00000010UL
+#define FILE__MOUNTON                             0x00010000UL
+#define FILE__CREATE                              0x00000008UL
+
+#define FILE__EXECUTE_NO_TRANS                    0x00020000UL
+#define FILE__ENTRYPOINT                          0x00040000UL
+
+#define LNK_FILE__EXECUTE                         0x00002000UL
+#define LNK_FILE__UNLINK                          0x00000400UL
+#define LNK_FILE__SETATTR                         0x00000020UL
+#define LNK_FILE__QUOTAON                         0x00008000UL
+#define LNK_FILE__RELABELFROM                     0x00000080UL
+#define LNK_FILE__LINK                            0x00000800UL
+#define LNK_FILE__WRITE                           0x00000004UL
+#define LNK_FILE__IOCTL                           0x00000001UL
+#define LNK_FILE__RELABELTO                       0x00000100UL
+#define LNK_FILE__READ                            0x00000002UL
+#define LNK_FILE__RENAME                          0x00001000UL
+#define LNK_FILE__APPEND                          0x00000200UL
+#define LNK_FILE__LOCK                            0x00000040UL
+#define LNK_FILE__SWAPON                          0x00004000UL
+#define LNK_FILE__GETATTR                         0x00000010UL
+#define LNK_FILE__MOUNTON                         0x00010000UL
+#define LNK_FILE__CREATE                          0x00000008UL
+
+#define CHR_FILE__EXECUTE                         0x00002000UL
+#define CHR_FILE__UNLINK                          0x00000400UL
+#define CHR_FILE__SETATTR                         0x00000020UL
+#define CHR_FILE__QUOTAON                         0x00008000UL
+#define CHR_FILE__RELABELFROM                     0x00000080UL
+#define CHR_FILE__LINK                            0x00000800UL
+#define CHR_FILE__WRITE                           0x00000004UL
+#define CHR_FILE__IOCTL                           0x00000001UL
+#define CHR_FILE__RELABELTO                       0x00000100UL
+#define CHR_FILE__READ                            0x00000002UL
+#define CHR_FILE__RENAME                          0x00001000UL
+#define CHR_FILE__APPEND                          0x00000200UL
+#define CHR_FILE__LOCK                            0x00000040UL
+#define CHR_FILE__SWAPON                          0x00004000UL
+#define CHR_FILE__GETATTR                         0x00000010UL
+#define CHR_FILE__MOUNTON                         0x00010000UL
+#define CHR_FILE__CREATE                          0x00000008UL
+
+#define BLK_FILE__EXECUTE                         0x00002000UL
+#define BLK_FILE__UNLINK                          0x00000400UL
+#define BLK_FILE__SETATTR                         0x00000020UL
+#define BLK_FILE__QUOTAON                         0x00008000UL
+#define BLK_FILE__RELABELFROM                     0x00000080UL
+#define BLK_FILE__LINK                            0x00000800UL
+#define BLK_FILE__WRITE                           0x00000004UL
+#define BLK_FILE__IOCTL                           0x00000001UL
+#define BLK_FILE__RELABELTO                       0x00000100UL
+#define BLK_FILE__READ                            0x00000002UL
+#define BLK_FILE__RENAME                          0x00001000UL
+#define BLK_FILE__APPEND                          0x00000200UL
+#define BLK_FILE__LOCK                            0x00000040UL
+#define BLK_FILE__SWAPON                          0x00004000UL
+#define BLK_FILE__GETATTR                         0x00000010UL
+#define BLK_FILE__MOUNTON                         0x00010000UL
+#define BLK_FILE__CREATE                          0x00000008UL
+
+#define SOCK_FILE__EXECUTE                        0x00002000UL
+#define SOCK_FILE__UNLINK                         0x00000400UL
+#define SOCK_FILE__SETATTR                        0x00000020UL
+#define SOCK_FILE__QUOTAON                        0x00008000UL
+#define SOCK_FILE__RELABELFROM                    0x00000080UL
+#define SOCK_FILE__LINK                           0x00000800UL
+#define SOCK_FILE__WRITE                          0x00000004UL
+#define SOCK_FILE__IOCTL                          0x00000001UL
+#define SOCK_FILE__RELABELTO                      0x00000100UL
+#define SOCK_FILE__READ                           0x00000002UL
+#define SOCK_FILE__RENAME                         0x00001000UL
+#define SOCK_FILE__APPEND                         0x00000200UL
+#define SOCK_FILE__LOCK                           0x00000040UL
+#define SOCK_FILE__SWAPON                         0x00004000UL
+#define SOCK_FILE__GETATTR                        0x00000010UL
+#define SOCK_FILE__MOUNTON                        0x00010000UL
+#define SOCK_FILE__CREATE                         0x00000008UL
+
+#define FIFO_FILE__EXECUTE                        0x00002000UL
+#define FIFO_FILE__UNLINK                         0x00000400UL
+#define FIFO_FILE__SETATTR                        0x00000020UL
+#define FIFO_FILE__QUOTAON                        0x00008000UL
+#define FIFO_FILE__RELABELFROM                    0x00000080UL
+#define FIFO_FILE__LINK                           0x00000800UL
+#define FIFO_FILE__WRITE                          0x00000004UL
+#define FIFO_FILE__IOCTL                          0x00000001UL
+#define FIFO_FILE__RELABELTO                      0x00000100UL
+#define FIFO_FILE__READ                           0x00000002UL
+#define FIFO_FILE__RENAME                         0x00001000UL
+#define FIFO_FILE__APPEND                         0x00000200UL
+#define FIFO_FILE__LOCK                           0x00000040UL
+#define FIFO_FILE__SWAPON                         0x00004000UL
+#define FIFO_FILE__GETATTR                        0x00000010UL
+#define FIFO_FILE__MOUNTON                        0x00010000UL
+#define FIFO_FILE__CREATE                         0x00000008UL
+
+#define FD__USE                                   0x00000001UL
+
+#define SOCKET__RELABELTO                         0x00000100UL
+#define SOCKET__RECV_MSG                          0x00080000UL
+#define SOCKET__RELABELFROM                       0x00000080UL
+#define SOCKET__SETOPT                            0x00008000UL
+#define SOCKET__APPEND                            0x00000200UL
+#define SOCKET__SETATTR                           0x00000020UL
+#define SOCKET__SENDTO                            0x00040000UL
+#define SOCKET__GETOPT                            0x00004000UL
+#define SOCKET__READ                              0x00000002UL
+#define SOCKET__SHUTDOWN                          0x00010000UL
+#define SOCKET__LISTEN                            0x00001000UL
+#define SOCKET__BIND                              0x00000400UL
+#define SOCKET__WRITE                             0x00000004UL
+#define SOCKET__ACCEPT                            0x00002000UL
+#define SOCKET__CONNECT                           0x00000800UL
+#define SOCKET__LOCK                              0x00000040UL
+#define SOCKET__IOCTL                             0x00000001UL
+#define SOCKET__CREATE                            0x00000008UL
+#define SOCKET__NAME_BIND                         0x00200000UL
+#define SOCKET__SEND_MSG                          0x00100000UL
+#define SOCKET__RECVFROM                          0x00020000UL
+#define SOCKET__GETATTR                           0x00000010UL
+
+#define TCP_SOCKET__RELABELTO                     0x00000100UL
+#define TCP_SOCKET__RECV_MSG                      0x00080000UL
+#define TCP_SOCKET__RELABELFROM                   0x00000080UL
+#define TCP_SOCKET__SETOPT                        0x00008000UL
+#define TCP_SOCKET__APPEND                        0x00000200UL
+#define TCP_SOCKET__SETATTR                       0x00000020UL
+#define TCP_SOCKET__SENDTO                        0x00040000UL
+#define TCP_SOCKET__GETOPT                        0x00004000UL
+#define TCP_SOCKET__READ                          0x00000002UL
+#define TCP_SOCKET__SHUTDOWN                      0x00010000UL
+#define TCP_SOCKET__LISTEN                        0x00001000UL
+#define TCP_SOCKET__BIND                          0x00000400UL
+#define TCP_SOCKET__WRITE                         0x00000004UL
+#define TCP_SOCKET__ACCEPT                        0x00002000UL
+#define TCP_SOCKET__CONNECT                       0x00000800UL
+#define TCP_SOCKET__LOCK                          0x00000040UL
+#define TCP_SOCKET__IOCTL                         0x00000001UL
+#define TCP_SOCKET__CREATE                        0x00000008UL
+#define TCP_SOCKET__NAME_BIND                     0x00200000UL
+#define TCP_SOCKET__SEND_MSG                      0x00100000UL
+#define TCP_SOCKET__RECVFROM                      0x00020000UL
+#define TCP_SOCKET__GETATTR                       0x00000010UL
+
+#define TCP_SOCKET__CONNECTTO                     0x00400000UL
+#define TCP_SOCKET__NEWCONN                       0x00800000UL
+#define TCP_SOCKET__ACCEPTFROM                    0x01000000UL
+
+#define UDP_SOCKET__RELABELTO                     0x00000100UL
+#define UDP_SOCKET__RECV_MSG                      0x00080000UL
+#define UDP_SOCKET__RELABELFROM                   0x00000080UL
+#define UDP_SOCKET__SETOPT                        0x00008000UL
+#define UDP_SOCKET__APPEND                        0x00000200UL
+#define UDP_SOCKET__SETATTR                       0x00000020UL
+#define UDP_SOCKET__SENDTO                        0x00040000UL
+#define UDP_SOCKET__GETOPT                        0x00004000UL
+#define UDP_SOCKET__READ                          0x00000002UL
+#define UDP_SOCKET__SHUTDOWN                      0x00010000UL
+#define UDP_SOCKET__LISTEN                        0x00001000UL
+#define UDP_SOCKET__BIND                          0x00000400UL
+#define UDP_SOCKET__WRITE                         0x00000004UL
+#define UDP_SOCKET__ACCEPT                        0x00002000UL
+#define UDP_SOCKET__CONNECT                       0x00000800UL
+#define UDP_SOCKET__LOCK                          0x00000040UL
+#define UDP_SOCKET__IOCTL                         0x00000001UL
+#define UDP_SOCKET__CREATE                        0x00000008UL
+#define UDP_SOCKET__NAME_BIND                     0x00200000UL
+#define UDP_SOCKET__SEND_MSG                      0x00100000UL
+#define UDP_SOCKET__RECVFROM                      0x00020000UL
+#define UDP_SOCKET__GETATTR                       0x00000010UL
+
+#define RAWIP_SOCKET__RELABELTO                   0x00000100UL
+#define RAWIP_SOCKET__RECV_MSG                    0x00080000UL
+#define RAWIP_SOCKET__RELABELFROM                 0x00000080UL
+#define RAWIP_SOCKET__SETOPT                      0x00008000UL
+#define RAWIP_SOCKET__APPEND                      0x00000200UL
+#define RAWIP_SOCKET__SETATTR                     0x00000020UL
+#define RAWIP_SOCKET__SENDTO                      0x00040000UL
+#define RAWIP_SOCKET__GETOPT                      0x00004000UL
+#define RAWIP_SOCKET__READ                        0x00000002UL
+#define RAWIP_SOCKET__SHUTDOWN                    0x00010000UL
+#define RAWIP_SOCKET__LISTEN                      0x00001000UL
+#define RAWIP_SOCKET__BIND                        0x00000400UL
+#define RAWIP_SOCKET__WRITE                       0x00000004UL
+#define RAWIP_SOCKET__ACCEPT                      0x00002000UL
+#define RAWIP_SOCKET__CONNECT                     0x00000800UL
+#define RAWIP_SOCKET__LOCK                        0x00000040UL
+#define RAWIP_SOCKET__IOCTL                       0x00000001UL
+#define RAWIP_SOCKET__CREATE                      0x00000008UL
+#define RAWIP_SOCKET__NAME_BIND                   0x00200000UL
+#define RAWIP_SOCKET__SEND_MSG                    0x00100000UL
+#define RAWIP_SOCKET__RECVFROM                    0x00020000UL
+#define RAWIP_SOCKET__GETATTR                     0x00000010UL
+
+#define NODE__TCP_RECV                            0x00000001UL
+#define NODE__TCP_SEND                            0x00000002UL
+#define NODE__UDP_RECV                            0x00000004UL
+#define NODE__UDP_SEND                            0x00000008UL
+#define NODE__RAWIP_RECV                          0x00000010UL
+#define NODE__RAWIP_SEND                          0x00000020UL
+#define NODE__ENFORCE_DEST                        0x00000040UL
+
+#define NETIF__TCP_RECV                           0x00000001UL
+#define NETIF__TCP_SEND                           0x00000002UL
+#define NETIF__UDP_RECV                           0x00000004UL
+#define NETIF__UDP_SEND                           0x00000008UL
+#define NETIF__RAWIP_RECV                         0x00000010UL
+#define NETIF__RAWIP_SEND                         0x00000020UL
+
+#define NETLINK_SOCKET__RELABELTO                 0x00000100UL
+#define NETLINK_SOCKET__RECV_MSG                  0x00080000UL
+#define NETLINK_SOCKET__RELABELFROM               0x00000080UL
+#define NETLINK_SOCKET__SETOPT                    0x00008000UL
+#define NETLINK_SOCKET__APPEND                    0x00000200UL
+#define NETLINK_SOCKET__SETATTR                   0x00000020UL
+#define NETLINK_SOCKET__SENDTO                    0x00040000UL
+#define NETLINK_SOCKET__GETOPT                    0x00004000UL
+#define NETLINK_SOCKET__READ                      0x00000002UL
+#define NETLINK_SOCKET__SHUTDOWN                  0x00010000UL
+#define NETLINK_SOCKET__LISTEN                    0x00001000UL
+#define NETLINK_SOCKET__BIND                      0x00000400UL
+#define NETLINK_SOCKET__WRITE                     0x00000004UL
+#define NETLINK_SOCKET__ACCEPT                    0x00002000UL
+#define NETLINK_SOCKET__CONNECT                   0x00000800UL
+#define NETLINK_SOCKET__LOCK                      0x00000040UL
+#define NETLINK_SOCKET__IOCTL                     0x00000001UL
+#define NETLINK_SOCKET__CREATE                    0x00000008UL
+#define NETLINK_SOCKET__NAME_BIND                 0x00200000UL
+#define NETLINK_SOCKET__SEND_MSG                  0x00100000UL
+#define NETLINK_SOCKET__RECVFROM                  0x00020000UL
+#define NETLINK_SOCKET__GETATTR                   0x00000010UL
+
+#define PACKET_SOCKET__RELABELTO                  0x00000100UL
+#define PACKET_SOCKET__RECV_MSG                   0x00080000UL
+#define PACKET_SOCKET__RELABELFROM                0x00000080UL
+#define PACKET_SOCKET__SETOPT                     0x00008000UL
+#define PACKET_SOCKET__APPEND                     0x00000200UL
+#define PACKET_SOCKET__SETATTR                    0x00000020UL
+#define PACKET_SOCKET__SENDTO                     0x00040000UL
+#define PACKET_SOCKET__GETOPT                     0x00004000UL
+#define PACKET_SOCKET__READ                       0x00000002UL
+#define PACKET_SOCKET__SHUTDOWN                   0x00010000UL
+#define PACKET_SOCKET__LISTEN                     0x00001000UL
+#define PACKET_SOCKET__BIND                       0x00000400UL
+#define PACKET_SOCKET__WRITE                      0x00000004UL
+#define PACKET_SOCKET__ACCEPT                     0x00002000UL
+#define PACKET_SOCKET__CONNECT                    0x00000800UL
+#define PACKET_SOCKET__LOCK                       0x00000040UL
+#define PACKET_SOCKET__IOCTL                      0x00000001UL
+#define PACKET_SOCKET__CREATE                     0x00000008UL
+#define PACKET_SOCKET__NAME_BIND                  0x00200000UL
+#define PACKET_SOCKET__SEND_MSG                   0x00100000UL
+#define PACKET_SOCKET__RECVFROM                   0x00020000UL
+#define PACKET_SOCKET__GETATTR                    0x00000010UL
+
+#define KEY_SOCKET__RELABELTO                     0x00000100UL
+#define KEY_SOCKET__RECV_MSG                      0x00080000UL
+#define KEY_SOCKET__RELABELFROM                   0x00000080UL
+#define KEY_SOCKET__SETOPT                        0x00008000UL
+#define KEY_SOCKET__APPEND                        0x00000200UL
+#define KEY_SOCKET__SETATTR                       0x00000020UL
+#define KEY_SOCKET__SENDTO                        0x00040000UL
+#define KEY_SOCKET__GETOPT                        0x00004000UL
+#define KEY_SOCKET__READ                          0x00000002UL
+#define KEY_SOCKET__SHUTDOWN                      0x00010000UL
+#define KEY_SOCKET__LISTEN                        0x00001000UL
+#define KEY_SOCKET__BIND                          0x00000400UL
+#define KEY_SOCKET__WRITE                         0x00000004UL
+#define KEY_SOCKET__ACCEPT                        0x00002000UL
+#define KEY_SOCKET__CONNECT                       0x00000800UL
+#define KEY_SOCKET__LOCK                          0x00000040UL
+#define KEY_SOCKET__IOCTL                         0x00000001UL
+#define KEY_SOCKET__CREATE                        0x00000008UL
+#define KEY_SOCKET__NAME_BIND                     0x00200000UL
+#define KEY_SOCKET__SEND_MSG                      0x00100000UL
+#define KEY_SOCKET__RECVFROM                      0x00020000UL
+#define KEY_SOCKET__GETATTR                       0x00000010UL
+
+#define UNIX_STREAM_SOCKET__RELABELTO             0x00000100UL
+#define UNIX_STREAM_SOCKET__RECV_MSG              0x00080000UL
+#define UNIX_STREAM_SOCKET__RELABELFROM           0x00000080UL
+#define UNIX_STREAM_SOCKET__SETOPT                0x00008000UL
+#define UNIX_STREAM_SOCKET__APPEND                0x00000200UL
+#define UNIX_STREAM_SOCKET__SETATTR               0x00000020UL
+#define UNIX_STREAM_SOCKET__SENDTO                0x00040000UL
+#define UNIX_STREAM_SOCKET__GETOPT                0x00004000UL
+#define UNIX_STREAM_SOCKET__READ                  0x00000002UL
+#define UNIX_STREAM_SOCKET__SHUTDOWN              0x00010000UL
+#define UNIX_STREAM_SOCKET__LISTEN                0x00001000UL
+#define UNIX_STREAM_SOCKET__BIND                  0x00000400UL
+#define UNIX_STREAM_SOCKET__WRITE                 0x00000004UL
+#define UNIX_STREAM_SOCKET__ACCEPT                0x00002000UL
+#define UNIX_STREAM_SOCKET__CONNECT               0x00000800UL
+#define UNIX_STREAM_SOCKET__LOCK                  0x00000040UL
+#define UNIX_STREAM_SOCKET__IOCTL                 0x00000001UL
+#define UNIX_STREAM_SOCKET__CREATE                0x00000008UL
+#define UNIX_STREAM_SOCKET__NAME_BIND             0x00200000UL
+#define UNIX_STREAM_SOCKET__SEND_MSG              0x00100000UL
+#define UNIX_STREAM_SOCKET__RECVFROM              0x00020000UL
+#define UNIX_STREAM_SOCKET__GETATTR               0x00000010UL
+
+#define UNIX_STREAM_SOCKET__CONNECTTO             0x00400000UL
+#define UNIX_STREAM_SOCKET__NEWCONN               0x00800000UL
+#define UNIX_STREAM_SOCKET__ACCEPTFROM            0x01000000UL
+
+#define UNIX_DGRAM_SOCKET__RELABELTO              0x00000100UL
+#define UNIX_DGRAM_SOCKET__RECV_MSG               0x00080000UL
+#define UNIX_DGRAM_SOCKET__RELABELFROM            0x00000080UL
+#define UNIX_DGRAM_SOCKET__SETOPT                 0x00008000UL
+#define UNIX_DGRAM_SOCKET__APPEND                 0x00000200UL
+#define UNIX_DGRAM_SOCKET__SETATTR                0x00000020UL
+#define UNIX_DGRAM_SOCKET__SENDTO                 0x00040000UL
+#define UNIX_DGRAM_SOCKET__GETOPT                 0x00004000UL
+#define UNIX_DGRAM_SOCKET__READ                   0x00000002UL
+#define UNIX_DGRAM_SOCKET__SHUTDOWN               0x00010000UL
+#define UNIX_DGRAM_SOCKET__LISTEN                 0x00001000UL
+#define UNIX_DGRAM_SOCKET__BIND                   0x00000400UL
+#define UNIX_DGRAM_SOCKET__WRITE                  0x00000004UL
+#define UNIX_DGRAM_SOCKET__ACCEPT                 0x00002000UL
+#define UNIX_DGRAM_SOCKET__CONNECT                0x00000800UL
+#define UNIX_DGRAM_SOCKET__LOCK                   0x00000040UL
+#define UNIX_DGRAM_SOCKET__IOCTL                  0x00000001UL
+#define UNIX_DGRAM_SOCKET__CREATE                 0x00000008UL
+#define UNIX_DGRAM_SOCKET__NAME_BIND              0x00200000UL
+#define UNIX_DGRAM_SOCKET__SEND_MSG               0x00100000UL
+#define UNIX_DGRAM_SOCKET__RECVFROM               0x00020000UL
+#define UNIX_DGRAM_SOCKET__GETATTR                0x00000010UL
+
+#define PROCESS__FORK                             0x00000001UL
+#define PROCESS__TRANSITION                       0x00000002UL
+#define PROCESS__SIGCHLD                          0x00000004UL
+#define PROCESS__SIGKILL                          0x00000008UL
+#define PROCESS__SIGSTOP                          0x00000010UL
+#define PROCESS__SIGNULL                          0x00000020UL
+#define PROCESS__SIGNAL                           0x00000040UL
+#define PROCESS__PTRACE                           0x00000080UL
+#define PROCESS__GETSCHED                         0x00000100UL
+#define PROCESS__SETSCHED                         0x00000200UL
+#define PROCESS__GETSESSION                       0x00000400UL
+#define PROCESS__GETPGID                          0x00000800UL
+#define PROCESS__SETPGID                          0x00001000UL
+#define PROCESS__GETCAP                           0x00002000UL
+#define PROCESS__SETCAP                           0x00004000UL
+#define PROCESS__SHARE                            0x00008000UL
+#define PROCESS__GETATTR                          0x00010000UL
+#define PROCESS__SETEXEC                          0x00020000UL
+#define PROCESS__SETFSCREATE                      0x00040000UL
+#define PROCESS__NOATSECURE                       0x00080000UL
+
+#define IPC__SETATTR                              0x00000008UL
+#define IPC__READ                                 0x00000010UL
+#define IPC__ASSOCIATE                            0x00000040UL
+#define IPC__DESTROY                              0x00000002UL
+#define IPC__UNIX_WRITE                           0x00000100UL
+#define IPC__CREATE                               0x00000001UL
+#define IPC__UNIX_READ                            0x00000080UL
+#define IPC__GETATTR                              0x00000004UL
+#define IPC__WRITE                                0x00000020UL
+
+#define SEM__SETATTR                              0x00000008UL
+#define SEM__READ                                 0x00000010UL
+#define SEM__ASSOCIATE                            0x00000040UL
+#define SEM__DESTROY                              0x00000002UL
+#define SEM__UNIX_WRITE                           0x00000100UL
+#define SEM__CREATE                               0x00000001UL
+#define SEM__UNIX_READ                            0x00000080UL
+#define SEM__GETATTR                              0x00000004UL
+#define SEM__WRITE                                0x00000020UL
+
+#define MSGQ__SETATTR                             0x00000008UL
+#define MSGQ__READ                                0x00000010UL
+#define MSGQ__ASSOCIATE                           0x00000040UL
+#define MSGQ__DESTROY                             0x00000002UL
+#define MSGQ__UNIX_WRITE                          0x00000100UL
+#define MSGQ__CREATE                              0x00000001UL
+#define MSGQ__UNIX_READ                           0x00000080UL
+#define MSGQ__GETATTR                             0x00000004UL
+#define MSGQ__WRITE                               0x00000020UL
+
+#define MSGQ__ENQUEUE                             0x00000200UL
+
+#define MSG__SEND                                 0x00000001UL
+#define MSG__RECEIVE                              0x00000002UL
+
+#define SHM__SETATTR                              0x00000008UL
+#define SHM__READ                                 0x00000010UL
+#define SHM__ASSOCIATE                            0x00000040UL
+#define SHM__DESTROY                              0x00000002UL
+#define SHM__UNIX_WRITE                           0x00000100UL
+#define SHM__CREATE                               0x00000001UL
+#define SHM__UNIX_READ                            0x00000080UL
+#define SHM__GETATTR                              0x00000004UL
+#define SHM__WRITE                                0x00000020UL
+
+#define SHM__LOCK                                 0x00000200UL
+
+#define SECURITY__COMPUTE_AV                      0x00000001UL
+#define SECURITY__COMPUTE_CREATE                  0x00000002UL
+#define SECURITY__COMPUTE_MEMBER                  0x00000004UL
+#define SECURITY__CHECK_CONTEXT                   0x00000008UL
+#define SECURITY__LOAD_POLICY                     0x00000010UL
+#define SECURITY__COMPUTE_RELABEL                 0x00000020UL
+#define SECURITY__COMPUTE_USER                    0x00000040UL
+#define SECURITY__SETENFORCE                      0x00000080UL
+
+#define SYSTEM__IPC_INFO                          0x00000001UL
+#define SYSTEM__SYSLOG_READ                       0x00000002UL
+#define SYSTEM__SYSLOG_MOD                        0x00000004UL
+#define SYSTEM__SYSLOG_CONSOLE                    0x00000008UL
+
+#define CAPABILITY__CHOWN                         0x00000001UL
+#define CAPABILITY__DAC_OVERRIDE                  0x00000002UL
+#define CAPABILITY__DAC_READ_SEARCH               0x00000004UL
+#define CAPABILITY__FOWNER                        0x00000008UL
+#define CAPABILITY__FSETID                        0x00000010UL
+#define CAPABILITY__KILL                          0x00000020UL
+#define CAPABILITY__SETGID                        0x00000040UL
+#define CAPABILITY__SETUID                        0x00000080UL
+#define CAPABILITY__SETPCAP                       0x00000100UL
+#define CAPABILITY__LINUX_IMMUTABLE               0x00000200UL
+#define CAPABILITY__NET_BIND_SERVICE              0x00000400UL
+#define CAPABILITY__NET_BROADCAST                 0x00000800UL
+#define CAPABILITY__NET_ADMIN                     0x00001000UL
+#define CAPABILITY__NET_RAW                       0x00002000UL
+#define CAPABILITY__IPC_LOCK                      0x00004000UL
+#define CAPABILITY__IPC_OWNER                     0x00008000UL
+#define CAPABILITY__SYS_MODULE                    0x00010000UL
+#define CAPABILITY__SYS_RAWIO                     0x00020000UL
+#define CAPABILITY__SYS_CHROOT                    0x00040000UL
+#define CAPABILITY__SYS_PTRACE                    0x00080000UL
+#define CAPABILITY__SYS_PACCT                     0x00100000UL
+#define CAPABILITY__SYS_ADMIN                     0x00200000UL
+#define CAPABILITY__SYS_BOOT                      0x00400000UL
+#define CAPABILITY__SYS_NICE                      0x00800000UL
+#define CAPABILITY__SYS_RESOURCE                  0x01000000UL
+#define CAPABILITY__SYS_TIME                      0x02000000UL
+#define CAPABILITY__SYS_TTY_CONFIG                0x04000000UL
+#define CAPABILITY__MKNOD                         0x08000000UL
+#define CAPABILITY__LEASE                         0x10000000UL
+
+#define PASSWD__PASSWD                            0x00000001UL
+#define PASSWD__CHFN                              0x00000002UL
+#define PASSWD__CHSH                              0x00000004UL
+
+
+/* FLASK */
diff -puN /dev/null security/selinux/include/av_perm_to_string.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/av_perm_to_string.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,120 @@
+/* This file is automatically generated.  Do not edit. */
+/* FLASK */
+
+struct av_perm_to_string
+{
+    u16 tclass;
+    u32 value;
+    char *name;
+};
+
+static struct av_perm_to_string av_perm_to_string[] = {
+   { SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod" },
+   { SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget" },
+   { SECCLASS_DIR, DIR__ADD_NAME, "add_name" },
+   { SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name" },
+   { SECCLASS_DIR, DIR__REPARENT, "reparent" },
+   { SECCLASS_DIR, DIR__SEARCH, "search" },
+   { SECCLASS_DIR, DIR__RMDIR, "rmdir" },
+   { SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans" },
+   { SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint" },
+   { SECCLASS_FD, FD__USE, "use" },
+   { SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto" },
+   { SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn" },
+   { SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom" },
+   { SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv" },
+   { SECCLASS_NODE, NODE__TCP_SEND, "tcp_send" },
+   { SECCLASS_NODE, NODE__UDP_RECV, "udp_recv" },
+   { SECCLASS_NODE, NODE__UDP_SEND, "udp_send" },
+   { SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv" },
+   { SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send" },
+   { SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest" },
+   { SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv" },
+   { SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send" },
+   { SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv" },
+   { SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send" },
+   { SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv" },
+   { SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send" },
+   { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto" },
+   { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn" },
+   { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom" },
+   { SECCLASS_PROCESS, PROCESS__FORK, "fork" },
+   { SECCLASS_PROCESS, PROCESS__TRANSITION, "transition" },
+   { SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld" },
+   { SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill" },
+   { SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop" },
+   { SECCLASS_PROCESS, PROCESS__SIGNULL, "signull" },
+   { SECCLASS_PROCESS, PROCESS__SIGNAL, "signal" },
+   { SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace" },
+   { SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched" },
+   { SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched" },
+   { SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession" },
+   { SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid" },
+   { SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid" },
+   { SECCLASS_PROCESS, PROCESS__GETCAP, "getcap" },
+   { SECCLASS_PROCESS, PROCESS__SETCAP, "setcap" },
+   { SECCLASS_PROCESS, PROCESS__SHARE, "share" },
+   { SECCLASS_PROCESS, PROCESS__GETATTR, "getattr" },
+   { SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec" },
+   { SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate" },
+   { SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure" },
+   { SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue" },
+   { SECCLASS_MSG, MSG__SEND, "send" },
+   { SECCLASS_MSG, MSG__RECEIVE, "receive" },
+   { SECCLASS_SHM, SHM__LOCK, "lock" },
+   { SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av" },
+   { SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create" },
+   { SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member" },
+   { SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context" },
+   { SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy" },
+   { SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel" },
+   { SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user" },
+   { SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce" },
+   { SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info" },
+   { SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read" },
+   { SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod" },
+   { SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console" },
+   { SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown" },
+   { SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override" },
+   { SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search" },
+   { SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner" },
+   { SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid" },
+   { SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap" },
+   { SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable" },
+   { SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service" },
+   { SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast" },
+   { SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin" },
+   { SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw" },
+   { SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock" },
+   { SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time" },
+   { SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config" },
+   { SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod" },
+   { SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease" },
+   { SECCLASS_PASSWD, PASSWD__PASSWD, "passwd" },
+   { SECCLASS_PASSWD, PASSWD__CHFN, "chfn" },
+   { SECCLASS_PASSWD, PASSWD__CHSH, "chsh" },
+};
+
+
+/* FLASK */
diff -puN /dev/null security/selinux/include/class_to_string.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/class_to_string.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,39 @@
+/* This file is automatically generated.  Do not edit. */
+/*
+ * Security object class definitions
+ */
+static char *class_to_string[] =
+{
+    "null",
+    "security",
+    "process",
+    "system",
+    "capability",
+    "filesystem",
+    "file",
+    "dir",
+    "fd",
+    "lnk_file",
+    "chr_file",
+    "blk_file",
+    "sock_file",
+    "fifo_file",
+    "socket",
+    "tcp_socket",
+    "udp_socket",
+    "rawip_socket",
+    "node",
+    "netif",
+    "netlink_socket",
+    "packet_socket",
+    "key_socket",
+    "unix_stream_socket",
+    "unix_dgram_socket",
+    "sem",
+    "msg",
+    "msgq",
+    "shm",
+    "ipc",
+    "passwd",
+};
+
diff -puN /dev/null security/selinux/include/common_perm_to_string.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/common_perm_to_string.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,65 @@
+/* This file is automatically generated.  Do not edit. */
+/* FLASK */
+
+static char *common_file_perm_to_string[] =
+{
+    "ioctl",
+    "read",
+    "write",
+    "create",
+    "getattr",
+    "setattr",
+    "lock",
+    "relabelfrom",
+    "relabelto",
+    "append",
+    "unlink",
+    "link",
+    "rename",
+    "execute",
+    "swapon",
+    "quotaon",
+    "mounton",
+};
+
+static char *common_socket_perm_to_string[] =
+{
+    "ioctl",
+    "read",
+    "write",
+    "create",
+    "getattr",
+    "setattr",
+    "lock",
+    "relabelfrom",
+    "relabelto",
+    "append",
+    "bind",
+    "connect",
+    "listen",
+    "accept",
+    "getopt",
+    "setopt",
+    "shutdown",
+    "recvfrom",
+    "sendto",
+    "recv_msg",
+    "send_msg",
+    "name_bind",
+};
+
+static char *common_ipc_perm_to_string[] =
+{
+    "create",
+    "destroy",
+    "getattr",
+    "setattr",
+    "read",
+    "write",
+    "associate",
+    "unix_read",
+    "unix_write",
+};
+
+
+/* FLASK */
diff -puN /dev/null security/selinux/include/flask.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/flask.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,71 @@
+/* This file is automatically generated.  Do not edit. */
+#ifndef _SELINUX_FLASK_H_
+#define _SELINUX_FLASK_H_
+
+/*
+ * Security object class definitions
+ */
+#define SECCLASS_SECURITY                                1
+#define SECCLASS_PROCESS                                 2
+#define SECCLASS_SYSTEM                                  3
+#define SECCLASS_CAPABILITY                              4
+#define SECCLASS_FILESYSTEM                              5
+#define SECCLASS_FILE                                    6
+#define SECCLASS_DIR                                     7
+#define SECCLASS_FD                                      8
+#define SECCLASS_LNK_FILE                                9
+#define SECCLASS_CHR_FILE                                10
+#define SECCLASS_BLK_FILE                                11
+#define SECCLASS_SOCK_FILE                               12
+#define SECCLASS_FIFO_FILE                               13
+#define SECCLASS_SOCKET                                  14
+#define SECCLASS_TCP_SOCKET                              15
+#define SECCLASS_UDP_SOCKET                              16
+#define SECCLASS_RAWIP_SOCKET                            17
+#define SECCLASS_NODE                                    18
+#define SECCLASS_NETIF                                   19
+#define SECCLASS_NETLINK_SOCKET                          20
+#define SECCLASS_PACKET_SOCKET                           21
+#define SECCLASS_KEY_SOCKET                              22
+#define SECCLASS_UNIX_STREAM_SOCKET                      23
+#define SECCLASS_UNIX_DGRAM_SOCKET                       24
+#define SECCLASS_SEM                                     25
+#define SECCLASS_MSG                                     26
+#define SECCLASS_MSGQ                                    27
+#define SECCLASS_SHM                                     28
+#define SECCLASS_IPC                                     29
+#define SECCLASS_PASSWD                                  30
+
+/*
+ * Security identifier indices for initial entities
+ */
+#define SECINITSID_KERNEL                               1
+#define SECINITSID_SECURITY                             2
+#define SECINITSID_UNLABELED                            3
+#define SECINITSID_FS                                   4
+#define SECINITSID_FILE                                 5
+#define SECINITSID_FILE_LABELS                          6
+#define SECINITSID_INIT                                 7
+#define SECINITSID_ANY_SOCKET                           8
+#define SECINITSID_PORT                                 9
+#define SECINITSID_NETIF                                10
+#define SECINITSID_NETMSG                               11
+#define SECINITSID_NODE                                 12
+#define SECINITSID_IGMP_PACKET                          13
+#define SECINITSID_ICMP_SOCKET                          14
+#define SECINITSID_TCP_SOCKET                           15
+#define SECINITSID_SYSCTL_MODPROBE                      16
+#define SECINITSID_SYSCTL                               17
+#define SECINITSID_SYSCTL_FS                            18
+#define SECINITSID_SYSCTL_KERNEL                        19
+#define SECINITSID_SYSCTL_NET                           20
+#define SECINITSID_SYSCTL_NET_UNIX                      21
+#define SECINITSID_SYSCTL_VM                            22
+#define SECINITSID_SYSCTL_DEV                           23
+#define SECINITSID_KMOD                                 24
+#define SECINITSID_POLICY                               25
+#define SECINITSID_SCMP_PACKET                          26
+
+#define SECINITSID_NUM                                  26
+
+#endif
diff -puN /dev/null security/selinux/include/initial_sid_to_string.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/initial_sid_to_string.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,32 @@
+/* This file is automatically generated.  Do not edit. */
+static char *initial_sid_to_string[] =
+{
+    "null",
+    "kernel",
+    "security",
+    "unlabeled",
+    "fs",
+    "file",
+    "file_labels",
+    "init",
+    "any_socket",
+    "port",
+    "netif",
+    "netmsg",
+    "node",
+    "igmp_packet",
+    "icmp_socket",
+    "tcp_socket",
+    "sysctl_modprobe",
+    "sysctl",
+    "sysctl_fs",
+    "sysctl_kernel",
+    "sysctl_net",
+    "sysctl_net_unix",
+    "sysctl_vm",
+    "sysctl_dev",
+    "kmod",
+    "policy",
+    "scmp_packet",
+};
+
diff -puN /dev/null security/selinux/include/objsec.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/objsec.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,88 @@
+/*
+ *  NSA Security-Enhanced Linux (SELinux) security module
+ *
+ *  This file contains the SELinux security data structures for kernel objects.
+ *
+ *  Author(s):  Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ *              Chris Vance, &lt;cvance@nai.com&gt;
+ *              Wayne Salamon, &lt;wsalamon@nai.com&gt;
+ *              James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
+ *  Copyright (C) 2003 Red Hat, Inc., James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2,
+ *      as published by the Free Software Foundation.
+ */
+#ifndef _SELINUX_OBJSEC_H_
+#define _SELINUX_OBJSEC_H_
+
+#include &lt;linux/list.h&gt;
+#include &lt;linux/sched.h&gt;
+#include &lt;linux/fs.h&gt;
+#include &lt;linux/in.h&gt;
+#include "flask.h"
+#include "avc.h"
+
+struct task_security_struct {
+        unsigned long magic;           /* magic number for this module */
+	struct task_struct *task;      /* back pointer to task object */
+	u32 osid;            /* SID prior to last execve */
+	u32 sid;             /* current SID */
+	u32 exec_sid;        /* exec SID */
+	u32 create_sid;      /* fscreate SID */
+        struct avc_entry_ref avcr;     /* reference to process permissions */
+};
+
+struct inode_security_struct {
+	unsigned long magic;           /* magic number for this module */
+        struct inode *inode;           /* back pointer to inode object */
+	struct list_head list;         /* list of inode_security_struct */
+	u32 task_sid;        /* SID of creating task */
+	u32 sid;             /* SID of this object */
+	u16 sclass;       /* security class of this object */
+	struct avc_entry_ref avcr;     /* reference to object permissions */
+	unsigned char initialized;     /* initialization flag */
+	struct semaphore sem;
+	unsigned char inherit;         /* inherit SID from parent entry */
+};
+
+struct file_security_struct {
+	unsigned long magic;            /* magic number for this module */
+	struct file *file;              /* back pointer to file object */
+	u32 sid;              /* SID of open file description */
+	u32 fown_sid;         /* SID of file owner (for SIGIO) */
+	struct avc_entry_ref avcr;	/* reference to fd permissions */
+	struct avc_entry_ref inode_avcr;     /* reference to object permissions */
+};
+
+struct superblock_security_struct {
+	unsigned long magic;            /* magic number for this module */
+	struct super_block *sb;         /* back pointer to sb object */
+	struct list_head list;          /* list of superblock_security_struct */
+	u32 sid;              /* SID of file system */
+	unsigned int behavior;          /* labeling behavior */
+	unsigned char initialized;      /* initialization flag */
+	unsigned char proc;             /* proc fs */
+	struct semaphore sem;
+};
+
+struct msg_security_struct {
+        unsigned long magic;		/* magic number for this module */
+	struct msg_msg *msg;		/* back pointer */
+	u32 sid;              /* SID of message */
+        struct avc_entry_ref avcr;	/* reference to permissions */
+};
+
+struct ipc_security_struct {
+        unsigned long magic;		/* magic number for this module */
+	struct kern_ipc_perm *ipc_perm; /* back pointer */
+	u16 sclass;	/* security class of this object */
+	u32 sid;              /* SID of IPC resource */
+        struct avc_entry_ref avcr;	/* reference to permissions */
+};
+
+extern int inode_security_set_sid(struct inode *inode, u32 sid);
+
+#endif /* _SELINUX_OBJSEC_H_ */
diff -puN /dev/null security/selinux/include/security.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/include/security.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,70 @@
+/*
+ * Security server interface.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SELINUX_SECURITY_H_
+#define _SELINUX_SECURITY_H_
+
+#include "flask.h"
+
+#define SECSID_NULL			0x00000000 /* unspecified SID */
+#define SECSID_WILD			0xffffffff /* wildcard SID */
+#define SECCLASS_NULL			0x0000 /* no class */
+
+#define SELINUX_MAGIC 0xf97cff8c
+
+int security_load_policy(void * data, size_t len);
+
+struct av_decision {
+	u32 allowed;
+	u32 decided;
+	u32 auditallow;
+	u32 auditdeny;
+	u32 seqno;
+};
+
+int security_compute_av(u32 ssid, u32 tsid,
+	u16 tclass, u32 requested,
+	struct av_decision *avd);
+
+int security_transition_sid(u32 ssid, u32 tsid,
+	u16 tclass, u32 *out_sid);
+
+int security_member_sid(u32 ssid, u32 tsid,
+	u16 tclass, u32 *out_sid);
+
+int security_change_sid(u32 ssid, u32 tsid,
+	u16 tclass, u32 *out_sid);
+
+int security_sid_to_context(u32 sid, char **scontext,
+	u32 *scontext_len);
+
+int security_context_to_sid(char *scontext, u32 scontext_len,
+	u32 *out_sid);
+
+int security_get_user_sids(u32 callsid, char *username,
+			   u32 **sids, u32 *nel);
+
+int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
+	u32 *out_sid);
+
+int security_netif_sid(char *name, u32 *if_sid,
+	u32 *msg_sid);
+
+int security_node_sid(u16 domain, void *addr, u32 addrlen,
+	u32 *out_sid);
+
+#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, unsigned int *behavior,
+	u32 *sid);
+
+int security_genfs_sid(const char *fstype, char *name, u16 sclass,
+	u32 *sid);
+
+#endif /* _SELINUX_SECURITY_H_ */
+
diff -puN /dev/null security/selinux/Kconfig
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/Kconfig	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,34 @@
+config SECURITY_SELINUX
+	bool "NSA SELinux Support"
+	depends on SECURITY
+	default n
+	help
+	  This enables NSA Security-Enhanced Linux (SELinux).
+	  You will also need a policy configuration and a labeled filesystem.
+	  You can obtain the policy compiler (checkpolicy), the utility for
+	  labeling filesystems (setfiles), and an example policy configuration
+	  from http://www.nsa.gov/selinux.
+	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_SELINUX_DEVELOP
+	bool "NSA SELinux Development Support"
+	depends on SECURITY_SELINUX
+	default y
+	help
+	  This enables the development support option of NSA SELinux,
+	  which is useful for experimenting with SELinux and developing
+	  policies.  If unsure, say Y.  With this option enabled, the
+	  kernel will start in permissive mode (log everything, deny nothing)
+	  unless you specify enforcing=1 on the kernel command line.  You
+	  can interactively toggle the kernel between enforcing mode and
+	  permissive mode (if permitted by the policy) via /selinux/enforce.
+
+config SECURITY_SELINUX_MLS
+	bool "NSA SELinux MLS policy (EXPERIMENTAL)"
+	depends on SECURITY_SELINUX &amp;&amp; EXPERIMENTAL
+	default n
+	help
+	  This enables the NSA SELinux Multi-Level Security (MLS) policy in
+	  addition to the default RBAC/TE policy.  This policy is
+	  experimental and has not been configured for use.  Unless you
+	  specifically want to experiment with MLS, say N.
diff -puN /dev/null security/selinux/Makefile
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/Makefile	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,10 @@
+#
+# Makefile for building the SELinux module as part of the kernel tree.
+#
+
+obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
+
+selinux-objs := avc.o hooks.o selinuxfs.o
+
+EXTRA_CFLAGS += -Isecurity/selinux/include
+
diff -puN /dev/null security/selinux/selinuxfs.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/selinuxfs.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,593 @@
+#include &lt;linux/config.h&gt;
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/slab.h&gt;
+#include &lt;linux/vmalloc.h&gt;
+#include &lt;linux/fs.h&gt;
+#include &lt;linux/init.h&gt;
+#include &lt;linux/string.h&gt;
+#include &lt;linux/security.h&gt;
+#include &lt;asm/uaccess.h&gt;
+
+/* selinuxfs pseudo filesystem for exporting the security policy API.
+   Based on the proc code and the fs/nfsd/nfsctl.c code. */
+
+#include "flask.h"
+#include "avc.h"
+#include "avc_ss.h"
+#include "security.h"
+#include "objsec.h"
+
+/* Check whether a task is allowed to use a security operation. */
+int task_has_security(struct task_struct *tsk,
+		      u32 perms)
+{
+	struct task_security_struct *tsec;
+
+	tsec = tsk-&gt;security;
+
+	return avc_has_perm(tsec-&gt;sid, SECINITSID_SECURITY,
+			    SECCLASS_SECURITY, perms, NULL, NULL);
+}
+
+enum sel_inos {
+	SEL_ROOT_INO = 2,
+	SEL_LOAD,	/* load policy */
+	SEL_ENFORCE,	/* get or set enforcing status */
+	SEL_CONTEXT,	/* validate context */
+	SEL_ACCESS,	/* compute access decision */
+	SEL_CREATE,	/* compute create labeling decision */
+	SEL_RELABEL,	/* compute relabeling decision */
+	SEL_USER	/* compute reachable user contexts */
+};
+
+static ssize_t sel_read_enforce(struct file *filp, char *buf,
+				size_t count, loff_t *ppos)
+{
+	char *page;
+	ssize_t length;
+	ssize_t end;
+
+	if (count &lt; 0 || count &gt; PAGE_SIZE)
+		return -EINVAL;
+	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	memset(page, 0, PAGE_SIZE);
+
+	length = snprintf(page, PAGE_SIZE, "%d", selinux_enforcing);
+	if (length &lt; 0) {
+		free_page((unsigned long)page);
+		return length;
+	}
+
+	if (*ppos &gt;= length) {
+		free_page((unsigned long)page);
+		return 0;
+	}
+	if (count + *ppos &gt; length)
+		count = length - *ppos;
+	end = count + *ppos;
+	if (copy_to_user(buf, (char *) page + *ppos, count)) {
+		count = -EFAULT;
+		goto out;
+	}
+	*ppos = end;
+out:
+	free_page((unsigned long)page);
+	return count;
+}
+
+#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+static ssize_t sel_write_enforce(struct file * file, const char * buf,
+				 size_t count, loff_t *ppos)
+
+{
+	char *page;
+	ssize_t length;
+	int new_value;
+
+	if (count &lt; 0 || count &gt;= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	memset(page, 0, PAGE_SIZE);
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%d", &amp;new_value) != 1)
+		goto out;
+
+	if (new_value != selinux_enforcing) {
+		length = task_has_security(current, SECURITY__SETENFORCE);
+		if (length)
+			goto out;
+		selinux_enforcing = new_value;
+		if (selinux_enforcing)
+			avc_ss_reset(0);
+	}
+	length = count;
+out:
+	free_page((unsigned long) page);
+	return length;
+}
+#else
+#define sel_write_enforce NULL
+#endif
+
+static struct file_operations sel_enforce_ops = {
+	.read		= sel_read_enforce,
+	.write		= sel_write_enforce,
+};
+
+static ssize_t sel_write_load(struct file * file, const char * buf,
+			      size_t count, loff_t *ppos)
+
+{
+	ssize_t length;
+	void *data;
+
+	length = task_has_security(current, SECURITY__LOAD_POLICY);
+	if (length)
+		return length;
+
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+
+	if ((count &lt; 0) || (count &gt; 64 * 1024 * 1024) || (data = vmalloc(count)) == NULL)
+		return -ENOMEM;
+
+	length = -EFAULT;
+	if (copy_from_user(data, buf, count) != 0)
+		goto out;
+
+	length = security_load_policy(data, count);
+	if (length)
+		goto out;
+
+	length = count;
+out:
+	vfree(data);
+	return length;
+}
+
+static struct file_operations sel_load_ops = {
+	.write		= sel_write_load,
+};
+
+
+static ssize_t sel_write_context(struct file * file, const char * buf,
+				 size_t count, loff_t *ppos)
+
+{
+	char *page;
+	u32 sid;
+	ssize_t length;
+
+	length = task_has_security(current, SECURITY__CHECK_CONTEXT);
+	if (length)
+		return length;
+
+	if (count &lt; 0 || count &gt;= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	memset(page, 0, PAGE_SIZE);
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = security_context_to_sid(page, count, &amp;sid);
+	if (length &lt; 0)
+		goto out;
+
+	length = count;
+out:
+	free_page((unsigned long) page);
+	return length;
+}
+
+static struct file_operations sel_context_ops = {
+	.write		= sel_write_context,
+};
+
+
+/*
+ * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
+ */
+static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
+static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
+static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
+static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
+
+static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+	[SEL_ACCESS] = sel_write_access,
+	[SEL_CREATE] = sel_write_create,
+	[SEL_RELABEL] = sel_write_relabel,
+	[SEL_USER] = sel_write_user,
+};
+
+/* an argresp is stored in an allocated page and holds the
+ * size of the argument or response, along with its content
+ */
+struct argresp {
+	ssize_t size;
+	char data[0];
+};
+
+#define PAYLOAD_SIZE (PAGE_SIZE - sizeof(struct argresp))
+
+/*
+ * transaction based IO methods.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+static ssize_t TA_write(struct file *file, const char *buf, size_t size, loff_t *pos)
+{
+	ino_t ino =  file-&gt;f_dentry-&gt;d_inode-&gt;i_ino;
+	struct argresp *ar;
+	ssize_t rv = 0;
+
+	if (ino &gt;= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
+		return -EINVAL;
+	if (file-&gt;private_data)
+		return -EINVAL; /* only one write allowed per open */
+	if (size &gt; PAYLOAD_SIZE - 1) /* allow one byte for null terminator */
+		return -EFBIG;
+
+	ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!ar)
+		return -ENOMEM;
+	memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */
+	ar-&gt;size = 0;
+	down(&amp;file-&gt;f_dentry-&gt;d_inode-&gt;i_sem);
+	if (file-&gt;private_data)
+		rv = -EINVAL;
+	else
+		file-&gt;private_data = ar;
+	up(&amp;file-&gt;f_dentry-&gt;d_inode-&gt;i_sem);
+	if (rv) {
+		kfree(ar);
+		return rv;
+	}
+	if (copy_from_user(ar-&gt;data, buf, size))
+		return -EFAULT;
+
+	rv =  write_op[ino](file, ar-&gt;data, size);
+	if (rv&gt;0) {
+		ar-&gt;size = rv;
+		rv = size;
+	}
+	return rv;
+}
+
+static ssize_t TA_read(struct file *file, char *buf, size_t size, loff_t *pos)
+{
+	struct argresp *ar;
+	ssize_t rv = 0;
+
+	if (file-&gt;private_data == NULL)
+		rv = TA_write(file, buf, 0, pos);
+	if (rv &lt; 0)
+		return rv;
+
+	ar = file-&gt;private_data;
+	if (!ar)
+		return 0;
+	if (*pos &gt;= ar-&gt;size)
+		return 0;
+	if (*pos + size &gt; ar-&gt;size)
+		size = ar-&gt;size - *pos;
+	if (copy_to_user(buf, ar-&gt;data + *pos, size))
+		return -EFAULT;
+	*pos += size;
+	return size;
+}
+
+static int TA_open(struct inode *inode, struct file *file)
+{
+	file-&gt;private_data = NULL;
+	return 0;
+}
+
+static int TA_release(struct inode *inode, struct file *file)
+{
+	void *p = file-&gt;private_data;
+	file-&gt;private_data = NULL;
+	kfree(p);
+	return 0;
+}
+
+static struct file_operations transaction_ops = {
+	.write		= TA_write,
+	.read		= TA_read,
+	.open		= TA_open,
+	.release	= TA_release,
+};
+
+/*
+ * payload - write methods
+ * If the method has a response, the response should be put in buf,
+ * and the length returned.  Otherwise return 0 or and -error.
+ */
+
+static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
+{
+	char *scon, *tcon;
+	u32 ssid, tsid;
+	u16 tclass;
+	u32 req;
+	struct av_decision avd;
+	ssize_t length;
+
+	length = task_has_security(current, SECURITY__COMPUTE_AV);
+	if (length)
+		return length;
+
+	length = -ENOMEM;
+	scon = kmalloc(size+1, GFP_KERNEL);
+	if (!scon)
+		return length;
+	memset(scon, 0, size+1);
+
+	tcon = kmalloc(size+1, GFP_KERNEL);
+	if (!tcon)
+		goto out;
+	memset(tcon, 0, size+1);
+
+	length = -EINVAL;
+	if (sscanf(buf, "%s %s %hu %x", scon, tcon, &amp;tclass, &amp;req) != 4)
+		goto out2;
+
+	length = security_context_to_sid(scon, strlen(scon)+1, &amp;ssid);
+	if (length &lt; 0)
+		goto out2;
+	length = security_context_to_sid(tcon, strlen(tcon)+1, &amp;tsid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_compute_av(ssid, tsid, tclass, req, &amp;avd);
+	if (length &lt; 0)
+		goto out2;
+
+	length = snprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u",
+			  avd.allowed, avd.decided,
+			  avd.auditallow, avd.auditdeny,
+			  avd.seqno);
+out2:
+	kfree(tcon);
+out:
+	kfree(scon);
+	return length;
+}
+
+static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
+{
+	char *scon, *tcon;
+	u32 ssid, tsid, newsid;
+	u16 tclass;
+	ssize_t length;
+	char *newcon;
+	u32 len;
+
+	length = task_has_security(current, SECURITY__COMPUTE_CREATE);
+	if (length)
+		return length;
+
+	length = -ENOMEM;
+	scon = kmalloc(size+1, GFP_KERNEL);
+	if (!scon)
+		return length;
+	memset(scon, 0, size+1);
+
+	tcon = kmalloc(size+1, GFP_KERNEL);
+	if (!tcon)
+		goto out;
+	memset(tcon, 0, size+1);
+
+	length = -EINVAL;
+	if (sscanf(buf, "%s %s %hu", scon, tcon, &amp;tclass) != 3)
+		goto out2;
+
+	length = security_context_to_sid(scon, strlen(scon)+1, &amp;ssid);
+	if (length &lt; 0)
+		goto out2;
+	length = security_context_to_sid(tcon, strlen(tcon)+1, &amp;tsid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_transition_sid(ssid, tsid, tclass, &amp;newsid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_sid_to_context(newsid, &amp;newcon, &amp;len);
+	if (length &lt; 0)
+		goto out2;
+
+	if (len &gt; PAYLOAD_SIZE) {
+		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
+		       "max\n", __FUNCTION__, len);
+		length = -ERANGE;
+		goto out3;
+	}
+
+	memcpy(buf, newcon, len);
+	length = len;
+out3:
+	kfree(newcon);
+out2:
+	kfree(tcon);
+out:
+	kfree(scon);
+	return length;
+}
+
+static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
+{
+	char *scon, *tcon;
+	u32 ssid, tsid, newsid;
+	u16 tclass;
+	ssize_t length;
+	char *newcon;
+	u32 len;
+
+	length = task_has_security(current, SECURITY__COMPUTE_RELABEL);
+	if (length)
+		return length;
+
+	length = -ENOMEM;
+	scon = kmalloc(size+1, GFP_KERNEL);
+	if (!scon)
+		return length;
+	memset(scon, 0, size+1);
+
+	tcon = kmalloc(size+1, GFP_KERNEL);
+	if (!tcon)
+		goto out;
+	memset(tcon, 0, size+1);
+
+	length = -EINVAL;
+	if (sscanf(buf, "%s %s %hu", scon, tcon, &amp;tclass) != 3)
+		goto out2;
+
+	length = security_context_to_sid(scon, strlen(scon)+1, &amp;ssid);
+	if (length &lt; 0)
+		goto out2;
+	length = security_context_to_sid(tcon, strlen(tcon)+1, &amp;tsid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_change_sid(ssid, tsid, tclass, &amp;newsid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_sid_to_context(newsid, &amp;newcon, &amp;len);
+	if (length &lt; 0)
+		goto out2;
+
+	if (len &gt; PAYLOAD_SIZE) {
+		length = -ERANGE;
+		goto out3;
+	}
+
+	memcpy(buf, newcon, len);
+	length = len;
+out3:
+	kfree(newcon);
+out2:
+	kfree(tcon);
+out:
+	kfree(scon);
+	return length;
+}
+
+static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
+{
+	char *con, *user, *ptr;
+	u32 sid, *sids;
+	ssize_t length;
+	char *newcon;
+	int i, rc;
+	u32 len, nsids;
+
+	length = task_has_security(current, SECURITY__COMPUTE_USER);
+	if (length)
+		return length;
+
+	length = -ENOMEM;
+	con = kmalloc(size+1, GFP_KERNEL);
+	if (!con)
+		return length;
+	memset(con, 0, size+1);
+
+	user = kmalloc(size+1, GFP_KERNEL);
+	if (!user)
+		goto out;
+	memset(user, 0, size+1);
+
+	length = -EINVAL;
+	if (sscanf(buf, "%s %s", con, user) != 2)
+		goto out2;
+
+	length = security_context_to_sid(con, strlen(con)+1, &amp;sid);
+	if (length &lt; 0)
+		goto out2;
+
+	length = security_get_user_sids(sid, user, &amp;sids, &amp;nsids);
+	if (length &lt; 0)
+		goto out2;
+
+	length = sprintf(buf, "%u", nsids) + 1;
+	ptr = buf + length;
+	for (i = 0; i &lt; nsids; i++) {
+		rc = security_sid_to_context(sids[i], &amp;newcon, &amp;len);
+		if (rc) {
+			length = rc;
+			goto out3;
+		}
+		if ((length + len) &gt;= PAYLOAD_SIZE) {
+			kfree(newcon);
+			length = -ERANGE;
+			goto out3;
+		}
+		memcpy(ptr, newcon, len);
+		kfree(newcon);
+		ptr += len;
+		length += len;
+	}
+out3:
+	kfree(sids);
+out2:
+	kfree(user);
+out:
+	kfree(con);
+	return length;
+}
+
+
+static int sel_fill_super(struct super_block * sb, void * data, int silent)
+{
+	static struct tree_descr selinux_files[] = {
+		[SEL_LOAD] = {"load", &amp;sel_load_ops, S_IRUSR|S_IWUSR},
+		[SEL_ENFORCE] = {"enforce", &amp;sel_enforce_ops, S_IRUSR|S_IWUSR},
+		[SEL_CONTEXT] = {"context", &amp;sel_context_ops, S_IRUGO|S_IWUGO},
+		[SEL_ACCESS] = {"access", &amp;transaction_ops, S_IRUGO|S_IWUGO},
+		[SEL_CREATE] = {"create", &amp;transaction_ops, S_IRUGO|S_IWUGO},
+		[SEL_RELABEL] = {"relabel", &amp;transaction_ops, S_IRUGO|S_IWUGO},
+		[SEL_USER] = {"user", &amp;transaction_ops, S_IRUGO|S_IWUGO},
+		/* last one */ {""}
+	};
+	return simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
+}
+
+static struct super_block *sel_get_sb(struct file_system_type *fs_type,
+				      int flags, const char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, sel_fill_super);
+}
+
+static struct file_system_type sel_fs_type = {
+	.name		= "selinuxfs",
+	.get_sb		= sel_get_sb,
+	.kill_sb	= kill_litter_super,
+};
+
+static int __init init_sel_fs(void)
+{
+	return register_filesystem(&amp;sel_fs_type);
+}
+
+__initcall(init_sel_fs);
diff -puN /dev/null security/selinux/ss/avtab.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/avtab.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,264 @@
+/*
+ * Implementation of the access vector table type.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "avtab.h"
+#include "policydb.h"
+
+#define AVTAB_HASH(keyp) \
+((keyp-&gt;target_class + \
+ (keyp-&gt;target_type &lt;&lt; 2) + \
+ (keyp-&gt;source_type &lt;&lt; 9)) &amp; \
+ AVTAB_HASH_MASK)
+
+int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+{
+	int hvalue;
+	struct avtab_node *prev, *cur, *newnode;
+
+	if (!h)
+		return -EINVAL;
+
+	hvalue = AVTAB_HASH(key);
+	for (prev = NULL, cur = h-&gt;htable[hvalue];
+	     cur;
+	     prev = cur, cur = cur-&gt;next) {
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type == cur-&gt;key.target_type &amp;&amp;
+		    key-&gt;target_class == cur-&gt;key.target_class &amp;&amp;
+		    (datum-&gt;specified &amp; cur-&gt;datum.specified))
+			return -EEXIST;
+		if (key-&gt;source_type &lt; cur-&gt;key.source_type)
+			break;
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type &lt; cur-&gt;key.target_type)
+			break;
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type == cur-&gt;key.target_type &amp;&amp;
+		    key-&gt;target_class &lt; cur-&gt;key.target_class)
+			break;
+	}
+
+	newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
+	if (newnode == NULL)
+		return -ENOMEM;
+	memset(newnode, 0, sizeof(*newnode));
+	newnode-&gt;key = *key;
+	newnode-&gt;datum = *datum;
+	if (prev) {
+		newnode-&gt;next = prev-&gt;next;
+		prev-&gt;next = newnode;
+	} else {
+		newnode-&gt;next = h-&gt;htable[hvalue];
+		h-&gt;htable[hvalue] = newnode;
+	}
+
+	h-&gt;nel++;
+	return 0;
+}
+
+
+struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
+{
+	int hvalue;
+	struct avtab_node *cur;
+
+	if (!h)
+		return NULL;
+
+	hvalue = AVTAB_HASH(key);
+	for (cur = h-&gt;htable[hvalue]; cur; cur = cur-&gt;next) {
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type == cur-&gt;key.target_type &amp;&amp;
+		    key-&gt;target_class == cur-&gt;key.target_class &amp;&amp;
+		    (specified &amp; cur-&gt;datum.specified))
+			return &amp;cur-&gt;datum;
+
+		if (key-&gt;source_type &lt; cur-&gt;key.source_type)
+			break;
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type &lt; cur-&gt;key.target_type)
+			break;
+		if (key-&gt;source_type == cur-&gt;key.source_type &amp;&amp;
+		    key-&gt;target_type == cur-&gt;key.target_type &amp;&amp;
+		    key-&gt;target_class &lt; cur-&gt;key.target_class)
+			break;
+	}
+
+	return NULL;
+}
+
+void avtab_destroy(struct avtab *h)
+{
+	int i;
+	struct avtab_node *cur, *temp;
+
+	if (!h)
+		return;
+
+	for (i = 0; i &lt; AVTAB_SIZE; i++) {
+		cur = h-&gt;htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur-&gt;next;
+			kfree(temp);
+		}
+		h-&gt;htable[i] = NULL;
+	}
+	kfree(h-&gt;htable);
+}
+
+
+int avtab_map(struct avtab *h,
+	      int (*apply) (struct avtab_key *k,
+			    struct avtab_datum *d,
+			    void *args),
+	      void *args)
+{
+	int i, ret;
+	struct avtab_node *cur;
+
+	if (!h)
+		return 0;
+
+	for (i = 0; i &lt; AVTAB_SIZE; i++) {
+		cur = h-&gt;htable[i];
+		while (cur != NULL) {
+			ret = apply(&amp;cur-&gt;key, &amp;cur-&gt;datum, args);
+			if (ret)
+				return ret;
+			cur = cur-&gt;next;
+		}
+	}
+	return 0;
+}
+
+int avtab_init(struct avtab *h)
+{
+	int i;
+
+	h-&gt;htable = kmalloc(sizeof(*(h-&gt;htable)) * AVTAB_SIZE, GFP_KERNEL);
+	if (!h-&gt;htable)
+		return -ENOMEM;
+	for (i = 0; i &lt; AVTAB_SIZE; i++)
+		h-&gt;htable[i] = NULL;
+	h-&gt;nel = 0;
+	return 0;
+}
+
+void avtab_hash_eval(struct avtab *h, char *tag)
+{
+	int i, chain_len, slots_used, max_chain_len;
+	struct avtab_node *cur;
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i &lt; AVTAB_SIZE; i++) {
+		cur = h-&gt;htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur-&gt;next;
+			}
+
+			if (chain_len &gt; max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
+	       "chain length %d\n", tag, h-&gt;nel, slots_used, AVTAB_SIZE,
+	       max_chain_len);
+}
+
+int avtab_read(struct avtab *a, void *fp, u32 config)
+{
+	int i, rc = -EINVAL;
+	struct avtab_key avkey;
+	struct avtab_datum avdatum;
+	u32 *buf;
+	u32 nel, items, items2;
+
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		printk(KERN_ERR "security: avtab: truncated table\n");
+		goto bad;
+	}
+	nel = le32_to_cpu(buf[0]);
+	if (!nel) {
+		printk(KERN_ERR "security: avtab: table is empty\n");
+		goto bad;
+	}
+	for (i = 0; i &lt; nel; i++) {
+		memset(&amp;avkey, 0, sizeof(avkey));
+		memset(&amp;avdatum, 0, sizeof(avdatum));
+
+		buf = next_entry(fp, sizeof(u32));
+		if (!buf) {
+			printk(KERN_ERR "security: avtab: truncated entry\n");
+			goto bad;
+		}
+		items2 = le32_to_cpu(buf[0]);
+		buf = next_entry(fp, sizeof(u32)*items2);
+		if (!buf) {
+			printk(KERN_ERR "security: avtab: truncated entry\n");
+			goto bad;
+		}
+		items = 0;
+		avkey.source_type = le32_to_cpu(buf[items++]);
+		avkey.target_type = le32_to_cpu(buf[items++]);
+		avkey.target_class = le32_to_cpu(buf[items++]);
+		avdatum.specified = le32_to_cpu(buf[items++]);
+		if (!(avdatum.specified &amp; (AVTAB_AV | AVTAB_TYPE))) {
+			printk(KERN_ERR "security: avtab: null entry\n");
+			goto bad;
+		}
+		if ((avdatum.specified &amp; AVTAB_AV) &amp;&amp;
+		    (avdatum.specified &amp; AVTAB_TYPE)) {
+			printk(KERN_ERR "security: avtab: entry has both "
+			       "access vectors and types\n");
+			goto bad;
+		}
+		if (avdatum.specified &amp; AVTAB_AV) {
+			if (avdatum.specified &amp; AVTAB_ALLOWED)
+				avtab_allowed(&amp;avdatum) = le32_to_cpu(buf[items++]);
+			if (avdatum.specified &amp; AVTAB_AUDITDENY)
+				avtab_auditdeny(&amp;avdatum) = le32_to_cpu(buf[items++]);
+			if (avdatum.specified &amp; AVTAB_AUDITALLOW)
+				avtab_auditallow(&amp;avdatum) = le32_to_cpu(buf[items++]);
+		} else {
+			if (avdatum.specified &amp; AVTAB_TRANSITION)
+				avtab_transition(&amp;avdatum) = le32_to_cpu(buf[items++]);
+			if (avdatum.specified &amp; AVTAB_CHANGE)
+				avtab_change(&amp;avdatum) = le32_to_cpu(buf[items++]);
+			if (avdatum.specified &amp; AVTAB_MEMBER)
+				avtab_member(&amp;avdatum) = le32_to_cpu(buf[items++]);
+		}
+		if (items != items2) {
+			printk(KERN_ERR "security: avtab: entry only had %d "
+			       "items, expected %d\n", items2, items);
+			goto bad;
+		}
+		rc = avtab_insert(a, &amp;avkey, &amp;avdatum);
+		if (rc) {
+			if (rc == -ENOMEM)
+				printk(KERN_ERR "security: avtab: out of memory\n");
+			if (rc == -EEXIST)
+				printk(KERN_ERR "security: avtab: duplicate entry\n");
+			goto bad;
+		}
+	}
+
+	rc = 0;
+out:
+	return rc;
+
+bad:
+	avtab_destroy(a);
+	goto out;
+}
+
diff -puN /dev/null security/selinux/ss/avtab.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/avtab.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ *  Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_AVTAB_H_
+#define _SS_AVTAB_H_
+
+struct avtab_key {
+	u32 source_type;	/* source type */
+	u32 target_type;	/* target type */
+	u32 target_class;	/* target object class */
+};
+
+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)
+	u32 specified;	/* what fields are specified */
+	u32 data[3];	/* access vectors or types */
+#define avtab_allowed(x) (x)-&gt;data[0]
+#define avtab_auditdeny(x) (x)-&gt;data[1]
+#define avtab_auditallow(x) (x)-&gt;data[2]
+#define avtab_transition(x) (x)-&gt;data[0]
+#define avtab_change(x) (x)-&gt;data[1]
+#define avtab_member(x) (x)-&gt;data[2]
+};
+
+struct avtab_node {
+	struct avtab_key key;
+	struct avtab_datum datum;
+	struct avtab_node *next;
+};
+
+struct avtab {
+	struct avtab_node **htable;
+	u32 nel;	/* number of elements */
+};
+
+int avtab_init(struct avtab *);
+int avtab_insert(struct avtab *h, struct avtab_key *k, struct avtab_datum *d);
+struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified);
+void avtab_destroy(struct avtab *h);
+int avtab_map(struct avtab *h,
+	      int (*apply) (struct avtab_key *k,
+			    struct avtab_datum *d,
+			    void *args),
+	      void *args);
+void avtab_hash_eval(struct avtab *h, char *tag);
+int avtab_read(struct avtab *a, void *fp, u32 config);
+
+#define AVTAB_HASH_BITS 15
+#define AVTAB_HASH_BUCKETS (1 &lt;&lt; AVTAB_HASH_BITS)
+#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
+
+#define AVTAB_SIZE AVTAB_HASH_BUCKETS
+
+#endif	/* _SS_AVTAB_H_ */
+
diff -puN /dev/null security/selinux/ss/constraint.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/constraint.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_CONSTRAINT_H_
+#define _SS_CONSTRAINT_H_
+
+#include "ebitmap.h"
+
+#define CEXPR_MAXDEPTH 5
+
+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 */
+	u32 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 */
+	u32 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 */
+	u32 op;			/* operator */
+
+	struct ebitmap names;	/* names */
+
+	struct constraint_expr *next;   /* next expression */
+};
+
+struct constraint_node {
+	u32 permissions;	/* constrained permissions */
+	struct constraint_expr *expr;	/* constraint on permissions */
+	struct constraint_node *next;	/* next constraint */
+};
+
+#endif	/* _SS_CONSTRAINT_H_ */
diff -puN /dev/null security/selinux/ss/context.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/context.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_CONTEXT_H_
+#define _SS_CONTEXT_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.
+ */
+struct context {
+	u32 user;
+	u32 role;
+	u32 type;
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+	struct mls_range range;
+#endif
+};
+
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+
+static inline void mls_context_init(struct context *c)
+{
+	memset(&amp;c-&gt;range, 0, sizeof(c-&gt;range));
+}
+
+static inline int mls_context_cpy(struct context *dst, struct context *src)
+{
+	int rc;
+
+	dst-&gt;range.level[0].sens = src-&gt;range.level[0].sens;
+	rc = ebitmap_cpy(&amp;dst-&gt;range.level[0].cat, &amp;src-&gt;range.level[0].cat);
+	if (rc)
+		goto out;
+
+	dst-&gt;range.level[1].sens = src-&gt;range.level[1].sens;
+	rc = ebitmap_cpy(&amp;dst-&gt;range.level[1].cat, &amp;src-&gt;range.level[1].cat);
+	if (rc)
+		ebitmap_destroy(&amp;dst-&gt;range.level[0].cat);
+out:
+	return rc;
+}
+
+static inline int mls_context_cmp(struct context *c1, struct context *c2)
+{
+	return ((c1-&gt;range.level[0].sens == c2-&gt;range.level[0].sens) &amp;&amp;
+		ebitmap_cmp(&amp;c1-&gt;range.level[0].cat,&amp;c2-&gt;range.level[0].cat) &amp;&amp;
+		(c1-&gt;range.level[1].sens == c2-&gt;range.level[1].sens) &amp;&amp;
+		ebitmap_cmp(&amp;c1-&gt;range.level[1].cat,&amp;c2-&gt;range.level[1].cat));
+}
+
+static inline void mls_context_destroy(struct context *c)
+{
+	ebitmap_destroy(&amp;c-&gt;range.level[0].cat);
+	ebitmap_destroy(&amp;c-&gt;range.level[1].cat);
+	mls_context_init(c);
+}
+
+#else
+
+static inline void mls_context_init(struct context *c)
+{ }
+
+static inline int mls_context_cpy(struct context *dst, struct context *src)
+{ return 0; }
+
+static inline int mls_context_cmp(struct context *c1, struct context *c2)
+{ return 1; }
+
+static inline void mls_context_destroy(struct context *c)
+{ }
+
+#endif
+
+static inline void context_init(struct context *c)
+{
+	memset(c, 0, sizeof(*c));
+}
+
+static inline int context_cpy(struct context *dst, struct context *src)
+{
+	dst-&gt;user = src-&gt;user;
+	dst-&gt;role = src-&gt;role;
+	dst-&gt;type = src-&gt;type;
+	return mls_context_cpy(dst, src);
+}
+
+static inline void context_destroy(struct context *c)
+{
+	c-&gt;user = c-&gt;role = c-&gt;type = 0;
+	mls_context_destroy(c);
+}
+
+static inline int context_cmp(struct context *c1, struct context *c2)
+{
+	return ((c1-&gt;user == c2-&gt;user) &amp;&amp;
+		(c1-&gt;role == c2-&gt;role) &amp;&amp;
+		(c1-&gt;type == c2-&gt;type) &amp;&amp;
+		mls_context_cmp(c1, c2));
+}
+
+#endif	/* _SS_CONTEXT_H_ */
+
diff -puN /dev/null security/selinux/ss/ebitmap.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/ebitmap.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,332 @@
+/*
+ * Implementation of the extensible bitmap type.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "ebitmap.h"
+#include "policydb.h"
+
+int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2)
+{
+	struct ebitmap_node *n1, *n2, *new, *prev;
+
+	ebitmap_init(dst);
+
+	n1 = e1-&gt;node;
+	n2 = e2-&gt;node;
+	prev = 0;
+	while (n1 || n2) {
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			ebitmap_destroy(dst);
+			return -ENOMEM;
+		}
+		memset(new, 0, sizeof(*new));
+		if (n1 &amp;&amp; n2 &amp;&amp; n1-&gt;startbit == n2-&gt;startbit) {
+			new-&gt;startbit = n1-&gt;startbit;
+			new-&gt;map = n1-&gt;map | n2-&gt;map;
+			n1 = n1-&gt;next;
+			n2 = n2-&gt;next;
+		} else if (!n2 || (n1 &amp;&amp; n1-&gt;startbit &lt; n2-&gt;startbit)) {
+			new-&gt;startbit = n1-&gt;startbit;
+			new-&gt;map = n1-&gt;map;
+			n1 = n1-&gt;next;
+		} else {
+			new-&gt;startbit = n2-&gt;startbit;
+			new-&gt;map = n2-&gt;map;
+			n2 = n2-&gt;next;
+		}
+
+		new-&gt;next = 0;
+		if (prev)
+			prev-&gt;next = new;
+		else
+			dst-&gt;node = new;
+		prev = new;
+	}
+
+	dst-&gt;highbit = (e1-&gt;highbit &gt; e2-&gt;highbit) ? e1-&gt;highbit : e2-&gt;highbit;
+	return 0;
+}
+
+int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
+{
+	struct ebitmap_node *n1, *n2;
+
+	if (e1-&gt;highbit != e2-&gt;highbit)
+		return 0;
+
+	n1 = e1-&gt;node;
+	n2 = e2-&gt;node;
+	while (n1 &amp;&amp; n2 &amp;&amp;
+	       (n1-&gt;startbit == n2-&gt;startbit) &amp;&amp;
+	       (n1-&gt;map == n2-&gt;map)) {
+		n1 = n1-&gt;next;
+		n2 = n2-&gt;next;
+	}
+
+	if (n1 || n2)
+		return 0;
+
+	return 1;
+}
+
+int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
+{
+	struct ebitmap_node *n, *new, *prev;
+
+	ebitmap_init(dst);
+	n = src-&gt;node;
+	prev = 0;
+	while (n) {
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			ebitmap_destroy(dst);
+			return -ENOMEM;
+		}
+		memset(new, 0, sizeof(*new));
+		new-&gt;startbit = n-&gt;startbit;
+		new-&gt;map = n-&gt;map;
+		new-&gt;next = 0;
+		if (prev)
+			prev-&gt;next = new;
+		else
+			dst-&gt;node = new;
+		prev = new;
+		n = n-&gt;next;
+	}
+
+	dst-&gt;highbit = src-&gt;highbit;
+	return 0;
+}
+
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
+{
+	struct ebitmap_node *n1, *n2;
+
+	if (e1-&gt;highbit &lt; e2-&gt;highbit)
+		return 0;
+
+	n1 = e1-&gt;node;
+	n2 = e2-&gt;node;
+	while (n1 &amp;&amp; n2 &amp;&amp; (n1-&gt;startbit &lt;= n2-&gt;startbit)) {
+		if (n1-&gt;startbit &lt; n2-&gt;startbit) {
+			n1 = n1-&gt;next;
+			continue;
+		}
+		if ((n1-&gt;map &amp; n2-&gt;map) != n2-&gt;map)
+			return 0;
+
+		n1 = n1-&gt;next;
+		n2 = n2-&gt;next;
+	}
+
+	if (n2)
+		return 0;
+
+	return 1;
+}
+
+int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
+{
+	struct ebitmap_node *n;
+
+	if (e-&gt;highbit &lt; bit)
+		return 0;
+
+	n = e-&gt;node;
+	while (n &amp;&amp; (n-&gt;startbit &lt;= bit)) {
+		if ((n-&gt;startbit + MAPSIZE) &gt; bit) {
+			if (n-&gt;map &amp; (MAPBIT &lt;&lt; (bit - n-&gt;startbit)))
+				return 1;
+			else
+				return 0;
+		}
+		n = n-&gt;next;
+	}
+
+	return 0;
+}
+
+int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
+{
+	struct ebitmap_node *n, *prev, *new;
+
+	prev = 0;
+	n = e-&gt;node;
+	while (n &amp;&amp; n-&gt;startbit &lt;= bit) {
+		if ((n-&gt;startbit + MAPSIZE) &gt; bit) {
+			if (value) {
+				n-&gt;map |= (MAPBIT &lt;&lt; (bit - n-&gt;startbit));
+			} else {
+				n-&gt;map &amp;= ~(MAPBIT &lt;&lt; (bit - n-&gt;startbit));
+				if (!n-&gt;map) {
+					/* drop this node from the bitmap */
+
+					if (!n-&gt;next) {
+						/*
+						 * this was the highest map
+						 * within the bitmap
+						 */
+						if (prev)
+							e-&gt;highbit = prev-&gt;startbit + MAPSIZE;
+						else
+							e-&gt;highbit = 0;
+					}
+					if (prev)
+						prev-&gt;next = n-&gt;next;
+					else
+						e-&gt;node = n-&gt;next;
+
+					kfree(n);
+				}
+			}
+			return 0;
+		}
+		prev = n;
+		n = n-&gt;next;
+	}
+
+	if (!value)
+		return 0;
+
+	new = kmalloc(sizeof(*new), GFP_ATOMIC);
+	if (!new)
+		return -ENOMEM;
+	memset(new, 0, sizeof(*new));
+
+	new-&gt;startbit = bit &amp; ~(MAPSIZE - 1);
+	new-&gt;map = (MAPBIT &lt;&lt; (bit - new-&gt;startbit));
+
+	if (!n)
+		/* this node will be the highest map within the bitmap */
+		e-&gt;highbit = new-&gt;startbit + MAPSIZE;
+
+	if (prev) {
+		new-&gt;next = prev-&gt;next;
+		prev-&gt;next = new;
+	} else {
+		new-&gt;next = e-&gt;node;
+		e-&gt;node = new;
+	}
+
+	return 0;
+}
+
+void ebitmap_destroy(struct ebitmap *e)
+{
+	struct ebitmap_node *n, *temp;
+
+	if (!e)
+		return;
+
+	n = e-&gt;node;
+	while (n) {
+		temp = n;
+		n = n-&gt;next;
+		kfree(temp);
+	}
+
+	e-&gt;highbit = 0;
+	e-&gt;node = 0;
+	return;
+}
+
+int ebitmap_read(struct ebitmap *e, void *fp)
+{
+	int rc = -EINVAL;
+	struct ebitmap_node *n, *l;
+	u32 *buf, mapsize, count, i;
+	u64 map;
+
+	ebitmap_init(e);
+
+	buf = next_entry(fp, sizeof(u32)*3);
+	if (!buf)
+		goto out;
+
+	mapsize = le32_to_cpu(buf[0]);
+	e-&gt;highbit = le32_to_cpu(buf[1]);
+	count = le32_to_cpu(buf[2]);
+
+	if (mapsize != MAPSIZE) {
+		printk(KERN_ERR "security: ebitmap: map size %d does not "
+		       "match my size %d (high bit was %d)\n", mapsize,
+		       MAPSIZE, e-&gt;highbit);
+		goto out;
+	}
+	if (!e-&gt;highbit) {
+		e-&gt;node = NULL;
+		goto ok;
+	}
+	if (e-&gt;highbit &amp; (MAPSIZE - 1)) {
+		printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
+		       "multiple of the map size (%d)\n", e-&gt;highbit, MAPSIZE);
+		goto bad;
+	}
+	l = NULL;
+	for (i = 0; i &lt; count; i++) {
+		buf = next_entry(fp, sizeof(u32));
+		if (!buf) {
+			printk(KERN_ERR "security: ebitmap: truncated map\n");
+			goto bad;
+		}
+		n = kmalloc(sizeof(*n), GFP_KERNEL);
+		if (!n) {
+			printk(KERN_ERR "security: ebitmap: out of memory\n");
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memset(n, 0, sizeof(*n));
+
+		n-&gt;startbit = le32_to_cpu(buf[0]);
+
+		if (n-&gt;startbit &amp; (MAPSIZE - 1)) {
+			printk(KERN_ERR "security: ebitmap start bit (%d) is "
+			       "not a multiple of the map size (%d)\n",
+			       n-&gt;startbit, MAPSIZE);
+			goto bad_free;
+		}
+		if (n-&gt;startbit &gt; (e-&gt;highbit - MAPSIZE)) {
+			printk(KERN_ERR "security: ebitmap start bit (%d) is "
+			       "beyond the end of the bitmap (%d)\n",
+			       n-&gt;startbit, (e-&gt;highbit - MAPSIZE));
+			goto bad_free;
+		}
+		buf = next_entry(fp, sizeof(u64));
+		if (!buf) {
+			printk(KERN_ERR "security: ebitmap: truncated map\n");
+			goto bad_free;
+		}
+		memcpy(&amp;map, buf, sizeof(u64));
+		n-&gt;map = le64_to_cpu(map);
+
+		if (!n-&gt;map) {
+			printk(KERN_ERR "security: ebitmap: null map in "
+			       "ebitmap (startbit %d)\n", n-&gt;startbit);
+			goto bad_free;
+		}
+		if (l) {
+			if (n-&gt;startbit &lt;= l-&gt;startbit) {
+				printk(KERN_ERR "security: ebitmap: start "
+				       "bit %d comes after start bit %d\n",
+				       n-&gt;startbit, l-&gt;startbit);
+				goto bad_free;
+			}
+			l-&gt;next = n;
+		} else
+			e-&gt;node = n;
+
+		l = n;
+	}
+
+ok:
+	rc = 0;
+out:
+	return rc;
+bad_free:
+	kfree(n);
+bad:
+	ebitmap_destroy(e);
+	goto out;
+}
diff -puN /dev/null security/selinux/ss/ebitmap.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/ebitmap.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_EBITMAP_H_
+#define _SS_EBITMAP_H_
+
+#define MAPTYPE u64			/* 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 */
+
+struct ebitmap_node {
+	u32 startbit;		/* starting position in the total bitmap */
+	MAPTYPE map;		/* this node's portion of the bitmap */
+	struct ebitmap_node *next;
+};
+
+struct ebitmap {
+	struct ebitmap_node *node;	/* first node in the bitmap */
+	u32 highbit;	/* highest position in the total bitmap */
+};
+
+#define ebitmap_length(e) ((e)-&gt;highbit)
+#define ebitmap_startbit(e) ((e)-&gt;node ? (e)-&gt;node-&gt;startbit : 0)
+
+static inline void ebitmap_init(struct ebitmap *e)
+{
+	memset(e, 0, sizeof(*e));
+}
+
+int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
+int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2);
+int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
+int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
+int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
+void ebitmap_destroy(struct ebitmap *e);
+int ebitmap_read(struct ebitmap *e, void *fp);
+
+#endif	/* _SS_EBITMAP_H_ */
diff -puN /dev/null security/selinux/ss/global.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/global.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,17 @@
+#ifndef _SS_GLOBAL_H_
+#define _SS_GLOBAL_H_
+
+#include &lt;linux/kernel.h&gt;
+#include &lt;linux/slab.h&gt;
+#include &lt;linux/string.h&gt;
+#include &lt;linux/ctype.h&gt;
+#include &lt;linux/in.h&gt;
+#include &lt;linux/spinlock.h&gt;
+#include &lt;asm/semaphore.h&gt;
+
+#include "flask.h"
+#include "avc.h"
+#include "avc_ss.h"
+#include "security.h"
+
+#endif /* _SS_GLOBAL_H_ */
diff -puN /dev/null security/selinux/ss/hashtab.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/hashtab.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,277 @@
+/*
+ * Implementation of the hash table type.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "hashtab.h"
+
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
+                               int (*keycmp)(struct hashtab *h, void *key1, void *key2),
+                               u32 size)
+{
+	struct hashtab *p;
+	u32 i;
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL)
+		return p;
+
+	memset(p, 0, sizeof(*p));
+	p-&gt;size = size;
+	p-&gt;nel = 0;
+	p-&gt;hash_value = hash_value;
+	p-&gt;keycmp = keycmp;
+	p-&gt;htable = kmalloc(sizeof(*(p-&gt;htable)) * size, GFP_KERNEL);
+	if (p-&gt;htable == NULL) {
+		kfree(p);
+		return NULL;
+	}
+
+	for (i = 0; i &lt; size; i++)
+		p-&gt;htable[i] = NULL;
+
+	return p;
+}
+
+int hashtab_insert(struct hashtab *h, void *key, void *datum)
+{
+	u32 hvalue;
+	struct hashtab_node *prev, *cur, *newnode;
+
+	if (!h || h-&gt;nel == HASHTAB_MAX_NODES)
+		return -EINVAL;
+
+	hvalue = h-&gt;hash_value(h, key);
+	prev = NULL;
+	cur = h-&gt;htable[hvalue];
+	while (cur &amp;&amp; h-&gt;keycmp(h, key, cur-&gt;key) &gt; 0) {
+		prev = cur;
+		cur = cur-&gt;next;
+	}
+
+	if (cur &amp;&amp; (h-&gt;keycmp(h, key, cur-&gt;key) == 0))
+		return -EEXIST;
+
+	newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
+	if (newnode == NULL)
+		return -ENOMEM;
+	memset(newnode, 0, sizeof(*newnode));
+	newnode-&gt;key = key;
+	newnode-&gt;datum = datum;
+	if (prev) {
+		newnode-&gt;next = prev-&gt;next;
+		prev-&gt;next = newnode;
+	} else {
+		newnode-&gt;next = h-&gt;htable[hvalue];
+		h-&gt;htable[hvalue] = newnode;
+	}
+
+	h-&gt;nel++;
+	return 0;
+}
+
+int hashtab_remove(struct hashtab *h, void *key,
+		   void (*destroy)(void *k, void *d, void *args),
+		   void *args)
+{
+	u32 hvalue;
+	struct hashtab_node *cur, *last;
+
+	if (!h)
+		return -EINVAL;
+
+	hvalue = h-&gt;hash_value(h, key);
+	last = NULL;
+	cur = h-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; h-&gt;keycmp(h, key, cur-&gt;key) &gt; 0) {
+		last = cur;
+		cur = cur-&gt;next;
+	}
+
+	if (cur == NULL || (h-&gt;keycmp(h, key, cur-&gt;key) != 0))
+		return -ENOENT;
+
+	if (last == NULL)
+		h-&gt;htable[hvalue] = cur-&gt;next;
+	else
+		last-&gt;next = cur-&gt;next;
+
+	if (destroy)
+		destroy(cur-&gt;key, cur-&gt;datum, args);
+	kfree(cur);
+	h-&gt;nel--;
+	return 0;
+}
+
+int hashtab_replace(struct hashtab *h, void *key, void *datum,
+		    void (*destroy)(void *k, void *d, void *args),
+		    void *args)
+{
+	u32 hvalue;
+	struct hashtab_node *prev, *cur, *newnode;
+
+	if (!h)
+		return -EINVAL;
+
+	hvalue = h-&gt;hash_value(h, key);
+	prev = NULL;
+	cur = h-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; h-&gt;keycmp(h, key, cur-&gt;key) &gt; 0) {
+		prev = cur;
+		cur = cur-&gt;next;
+	}
+
+	if (cur &amp;&amp; (h-&gt;keycmp(h, key, cur-&gt;key) == 0)) {
+		if (destroy)
+			destroy(cur-&gt;key, cur-&gt;datum, args);
+		cur-&gt;key = key;
+		cur-&gt;datum = datum;
+	} else {
+		newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
+		if (newnode == NULL)
+			return -ENOMEM;
+		memset(newnode, 0, sizeof(*newnode));
+		newnode-&gt;key = key;
+		newnode-&gt;datum = datum;
+		if (prev) {
+			newnode-&gt;next = prev-&gt;next;
+			prev-&gt;next = newnode;
+		} else {
+			newnode-&gt;next = h-&gt;htable[hvalue];
+			h-&gt;htable[hvalue] = newnode;
+		}
+	}
+
+	return 0;
+}
+
+void *hashtab_search(struct hashtab *h, void *key)
+{
+	u32 hvalue;
+	struct hashtab_node *cur;
+
+	if (!h)
+		return NULL;
+
+	hvalue = h-&gt;hash_value(h, key);
+	cur = h-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; h-&gt;keycmp(h, key, cur-&gt;key) &gt; 0)
+		cur = cur-&gt;next;
+
+	if (cur == NULL || (h-&gt;keycmp(h, key, cur-&gt;key) != 0))
+		return NULL;
+
+	return cur-&gt;datum;
+}
+
+void hashtab_destroy(struct hashtab *h)
+{
+	u32 i;
+	struct hashtab_node *cur, *temp;
+
+	if (!h)
+		return;
+
+	for (i = 0; i &lt; h-&gt;size; i++) {
+		cur = h-&gt;htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur-&gt;next;
+			kfree(temp);
+		}
+		h-&gt;htable[i] = NULL;
+	}
+
+	kfree(h-&gt;htable);
+	h-&gt;htable = NULL;
+
+	kfree(h);
+}
+
+int hashtab_map(struct hashtab *h,
+		int (*apply)(void *k, void *d, void *args),
+		void *args)
+{
+	u32 i;
+	int ret;
+	struct hashtab_node *cur;
+
+	if (!h)
+		return 0;
+
+	for (i = 0; i &lt; h-&gt;size; i++) {
+		cur = h-&gt;htable[i];
+		while (cur != NULL) {
+			ret = apply(cur-&gt;key, cur-&gt;datum, args);
+			if (ret)
+				return ret;
+			cur = cur-&gt;next;
+		}
+	}
+	return 0;
+}
+
+
+void hashtab_map_remove_on_error(struct hashtab *h,
+                                 int (*apply)(void *k, void *d, void *args),
+                                 void (*destroy)(void *k, void *d, void *args),
+                                 void *args)
+{
+	u32 i;
+	int ret;
+	struct hashtab_node *last, *cur, *temp;
+
+	if (!h)
+		return;
+
+	for (i = 0; i &lt; h-&gt;size; i++) {
+		last = NULL;
+		cur = h-&gt;htable[i];
+		while (cur != NULL) {
+			ret = apply(cur-&gt;key, cur-&gt;datum, args);
+			if (ret) {
+				if (last)
+					last-&gt;next = cur-&gt;next;
+				else
+					h-&gt;htable[i] = cur-&gt;next;
+
+				temp = cur;
+				cur = cur-&gt;next;
+				if (destroy)
+					destroy(temp-&gt;key, temp-&gt;datum, args);
+				kfree(temp);
+				h-&gt;nel--;
+			} else {
+				last = cur;
+				cur = cur-&gt;next;
+			}
+		}
+	}
+	return;
+}
+
+void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
+{
+	u32 i, chain_len, slots_used, max_chain_len;
+	struct hashtab_node *cur;
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (slots_used = max_chain_len = i = 0; i &lt; h-&gt;size; i++) {
+		cur = h-&gt;htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur-&gt;next;
+			}
+
+			if (chain_len &gt; max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	info-&gt;slots_used = slots_used;
+	info-&gt;max_chain_len = max_chain_len;
+}
diff -puN /dev/null security/selinux/ss/hashtab.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/hashtab.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_HASHTAB_H_
+#define _SS_HASHTAB_H_
+
+#define HASHTAB_MAX_NODES	0xffffffff
+
+struct hashtab_node {
+	void *key;
+	void *datum;
+	struct hashtab_node *next;
+};
+
+struct hashtab {
+	struct hashtab_node **htable;	/* hash table */
+	u32 size;			/* number of slots in hash table */
+	u32 nel;			/* number of elements in hash table */
+	u32 (*hash_value)(struct hashtab *h, void *key);
+					/* hash function */
+	int (*keycmp)(struct hashtab *h, void *key1, void *key2);
+					/* key comparison function */
+};
+
+struct hashtab_info {
+	u32 slots_used;
+	u32 max_chain_len;
+};
+
+/*
+ * Creates a new hash table with the specified characteristics.
+ *
+ * Returns NULL if insufficent space is available or
+ * the new hash table otherwise.
+ */
+struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
+                               int (*keycmp)(struct hashtab *h, void *key1, void *key2),
+                               u32 size);
+
+/*
+ * Inserts the specified (key, datum) pair into the specified hash table.
+ *
+ * Returns -ENOMEM on memory allocation error,
+ * -EEXIST if there is already an entry with the same key,
+ * -EINVAL for general errors or
+ * 0 otherwise.
+ */
+int hashtab_insert(struct hashtab *h, void *k, void *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 -ENOENT if no entry has the specified key,
+ * -EINVAL for general errors or
+ *0 otherwise.
+ */
+int hashtab_remove(struct hashtab *h, void *k,
+		   void (*destroy)(void *k, void *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 -ENOMEM if insufficient space is available,
+ * -EINVAL for general errors or
+ * 0 otherwise.
+ */
+int hashtab_replace(struct hashtab *h, void *k, void *d,
+		    void (*destroy)(void *k, void *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.
+ */
+void *hashtab_search(struct hashtab *h, void *k);
+
+/*
+ * Destroys the specified hash table.
+ */
+void hashtab_destroy(struct hashtab *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(struct hashtab *h,
+		int (*apply)(void *k, void *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(struct hashtab *h,
+                                 int (*apply)(void *k, void *d, void *args),
+                                 void (*destroy)(void *k, void *d, void *args),
+                                 void *args);
+
+
+/* Fill info with some hash table statistics */
+void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
+
+#endif	/* _SS_HASHTAB_H */
diff -puN /dev/null security/selinux/ss/Makefile
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/Makefile	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,14 @@
+#
+# Makefile for building the SELinux security server as part of the kernel tree.
+#
+
+EXTRA_CFLAGS += -Isecurity/selinux/include -include security/selinux/ss/global.h
+
+obj-y := ss.o
+
+ss-objs := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o
+
+ifeq ($(CONFIG_SECURITY_SELINUX_MLS),y)
+ss-objs += mls.o
+endif
+
diff -puN /dev/null security/selinux/ss/mls.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/mls.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,741 @@
+/*
+ * Implementation of the multi-level security (MLS) policy.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#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(struct context *scontext,
+		    struct context *tcontext,
+		    struct class_datum *tclass,
+		    u32 *allowed)
+{
+	unsigned int rel[2];
+	int l;
+
+	for (l = 0; l &lt; 2; l++)
+		rel[l] = mls_level_relation(scontext-&gt;range.level[l],
+					    tcontext-&gt;range.level[l]);
+
+	if (rel[1] != MLS_RELATION_EQ) {
+		if (rel[1] != MLS_RELATION_DOM &amp;&amp;
+		    !ebitmap_get_bit(&amp;policydb.trustedreaders, scontext-&gt;type - 1) &amp;&amp;
+		    !ebitmap_get_bit(&amp;policydb.trustedobjects, tcontext-&gt;type - 1)) {
+			/* read(s,t) = (s.high &gt;= t.high) = False */
+			*allowed = (*allowed) &amp; ~(tclass-&gt;mlsperms.read);
+		}
+		if (rel[1] != MLS_RELATION_DOMBY &amp;&amp;
+		    !ebitmap_get_bit(&amp;policydb.trustedreaders, tcontext-&gt;type - 1) &amp;&amp;
+		    !ebitmap_get_bit(&amp;policydb.trustedobjects, scontext-&gt;type - 1)) {
+			/* readby(s,t) = read(t,s) = False */
+			*allowed = (*allowed) &amp; ~(tclass-&gt;mlsperms.readby);
+		}
+	}
+	if (((rel[0] != MLS_RELATION_DOMBY &amp;&amp; rel[0] != MLS_RELATION_EQ) ||
+	    ((!mls_level_eq(tcontext-&gt;range.level[0],
+			    tcontext-&gt;range.level[1])) &amp;&amp;
+	     (rel[1] != MLS_RELATION_DOM &amp;&amp; rel[1] != MLS_RELATION_EQ))) &amp;&amp;
+	    !ebitmap_get_bit(&amp;policydb.trustedwriters, scontext-&gt;type - 1) &amp;&amp;
+	    !ebitmap_get_bit(&amp;policydb.trustedobjects, tcontext-&gt;type - 1)) {
+		/*
+		 * write(s,t) = ((s.low &lt;= t.low = t.high) or (s.low
+		 * &lt;= t.low &lt;= t.high &lt;= s.high)) = False
+		 */
+		*allowed = (*allowed) &amp; ~(tclass-&gt;mlsperms.write);
+	}
+
+	if (((rel[0] != MLS_RELATION_DOM &amp;&amp; rel[0] != MLS_RELATION_EQ) ||
+	    ((!mls_level_eq(scontext-&gt;range.level[0],
+			    scontext-&gt;range.level[1])) &amp;&amp;
+	     (rel[1] != MLS_RELATION_DOMBY &amp;&amp; rel[1] != MLS_RELATION_EQ))) &amp;&amp;
+	    !ebitmap_get_bit(&amp;policydb.trustedwriters, tcontext-&gt;type - 1) &amp;&amp;
+	    !ebitmap_get_bit(&amp;policydb.trustedobjects, scontext-&gt;type - 1)) {
+		/* writeby(s,t) = write(t,s) = False */
+		*allowed = (*allowed) &amp; ~(tclass-&gt;mlsperms.writeby);
+	}
+}
+
+/*
+ * Return the length in bytes for the MLS fields of the
+ * security context string representation of `context'.
+ */
+int mls_compute_context_len(struct context * context)
+{
+	int i, l, len;
+
+
+	len = 0;
+	for (l = 0; l &lt; 2; l++) {
+		len += strlen(policydb.p_sens_val_to_name[context-&gt;range.level[l].sens - 1]) + 1;
+
+		for (i = 1; i &lt;= ebitmap_length(&amp;context-&gt;range.level[l].cat); i++)
+			if (ebitmap_get_bit(&amp;context-&gt;range.level[l].cat, i - 1))
+				len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+
+		if (mls_level_relation(context-&gt;range.level[0], context-&gt;range.level[1])
+				== MLS_RELATION_EQ)
+			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.
+ */
+int mls_sid_to_context(struct context *context,
+		       char **scontext)
+{
+	char *scontextp;
+	int i, l;
+
+	scontextp = *scontext;
+
+	for (l = 0; l &lt; 2; l++) {
+		strcpy(scontextp,
+		       policydb.p_sens_val_to_name[context-&gt;range.level[l].sens - 1]);
+		scontextp += strlen(policydb.p_sens_val_to_name[context-&gt;range.level[l].sens - 1]);
+		*scontextp = ':';
+		scontextp++;
+		for (i = 1; i &lt;= ebitmap_length(&amp;context-&gt;range.level[l].cat); i++)
+			if (ebitmap_get_bit(&amp;context-&gt;range.level[l].cat, i - 1)) {
+				strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
+				scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+				*scontextp = ',';
+				scontextp++;
+			}
+		if (mls_level_relation(context-&gt;range.level[0], context-&gt;range.level[1])
+				!= MLS_RELATION_EQ) {
+			scontextp--;
+			sprintf(scontextp, "-");
+			scontextp++;
+
+		} else {
+			break;
+		}
+	}
+
+	*scontext = scontextp;
+	return 0;
+}
+
+/*
+ * Return 1 if the MLS fields in the security context
+ * structure `c' are valid.  Return 0 otherwise.
+ */
+int mls_context_isvalid(struct policydb *p, struct context *c)
+{
+	unsigned int relation;
+	struct level_datum *levdatum;
+	struct user_datum *usrdatum;
+	struct mls_range_list *rnode;
+	int i, l;
+
+	/*
+	 * MLS range validity checks: high must dominate low, low level must
+	 * be valid (category set &lt;-&gt; sensitivity check), and high level must
+	 * be valid (category set &lt;-&gt; sensitivity check)
+	 */
+	relation = mls_level_relation(c-&gt;range.level[1],
+				      c-&gt;range.level[0]);
+	if (!(relation &amp; (MLS_RELATION_DOM | MLS_RELATION_EQ)))
+		/* High does not dominate low. */
+		return 0;
+
+	for (l = 0; l &lt; 2; l++) {
+		if (!c-&gt;range.level[l].sens || c-&gt;range.level[l].sens &gt; p-&gt;p_levels.nprim)
+			return 0;
+		levdatum = hashtab_search(p-&gt;p_levels.table,
+			p-&gt;p_sens_val_to_name[c-&gt;range.level[l].sens - 1]);
+		if (!levdatum)
+			return 0;
+
+		for (i = 1; i &lt;= ebitmap_length(&amp;c-&gt;range.level[l].cat); i++) {
+			if (ebitmap_get_bit(&amp;c-&gt;range.level[l].cat, i - 1)) {
+				if (i &gt; p-&gt;p_cats.nprim)
+					return 0;
+				if (!ebitmap_get_bit(&amp;levdatum-&gt;level-&gt;cat, i - 1))
+					/*
+					 * Category may not be associated with
+					 * sensitivity in low level.
+					 */
+					return 0;
+			}
+		}
+	}
+
+	if (c-&gt;role == OBJECT_R_VAL)
+		return 1;
+
+	/*
+	 * User must be authorized for the MLS range.
+	 */
+	if (!c-&gt;user || c-&gt;user &gt; p-&gt;p_users.nprim)
+		return 0;
+	usrdatum = p-&gt;user_val_to_struct[c-&gt;user - 1];
+	for (rnode = usrdatum-&gt;ranges; rnode; rnode = rnode-&gt;next) {
+		if (mls_range_contains(rnode-&gt;range, c-&gt;range))
+			break;
+	}
+	if (!rnode)
+		/* user may not be associated with range */
+		return 0;
+
+	return 1;
+}
+
+
+/*
+ * 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,
+		       struct context *context)
+{
+
+	char delim;
+	char *scontextp, *p;
+	struct level_datum *levdatum;
+	struct cat_datum *catdatum;
+	int l, rc = -EINVAL;
+
+	if (!oldc) {
+		/* No MLS component to the security context.  Try
+		   to use a default 'unclassified' value. */
+		levdatum = hashtab_search(policydb.p_levels.table,
+		                          "unclassified");
+		if (!levdatum)
+			goto out;
+		context-&gt;range.level[0].sens = levdatum-&gt;level-&gt;sens;
+		context-&gt;range.level[1].sens = context-&gt;range.level[0].sens;
+		rc = 0;
+		goto out;
+	}
+
+	/* Extract low sensitivity. */
+	scontextp = p = *scontext;
+	while (*p &amp;&amp; *p != ':' &amp;&amp; *p != '-')
+		p++;
+
+	delim = *p;
+	if (delim != 0)
+		*p++ = 0;
+
+	for (l = 0; l &lt; 2; l++) {
+		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
+		if (!levdatum)
+			goto out;
+
+		context-&gt;range.level[l].sens = levdatum-&gt;level-&gt;sens;
+
+		if (delim == ':') {
+			/* Extract low category set. */
+			while (1) {
+				scontextp = p;
+				while (*p &amp;&amp; *p != ',' &amp;&amp; *p != '-')
+					p++;
+				delim = *p;
+				if (delim != 0)
+					*p++ = 0;
+
+				catdatum = hashtab_search(policydb.p_cats.table,
+				                          scontextp);
+				if (!catdatum)
+					goto out;
+
+				rc = ebitmap_set_bit(&amp;context-&gt;range.level[l].cat,
+				                     catdatum-&gt;value - 1, 1);
+				if (rc)
+					goto out;
+				if (delim != ',')
+					break;
+			}
+		}
+		if (delim == '-') {
+			/* Extract high sensitivity. */
+			scontextp = p;
+			while (*p &amp;&amp; *p != ':')
+				p++;
+
+			delim = *p;
+			if (delim != 0)
+				*p++ = 0;
+		} else
+			break;
+	}
+
+	if (l == 0) {
+		context-&gt;range.level[1].sens = context-&gt;range.level[0].sens;
+		rc = ebitmap_cpy(&amp;context-&gt;range.level[1].cat,
+				 &amp;context-&gt;range.level[0].cat);
+		if (rc)
+			goto out;
+	}
+	*scontext = p;
+	rc = 0;
+out:
+	return rc;
+}
+
+/*
+ * Copies the MLS range from `src' into `dst'.
+ */
+static inline int mls_copy_context(struct context *dst,
+				   struct context *src)
+{
+	int l, rc = 0;
+
+	/* Copy the MLS range from the source context */
+	for (l = 0; l &lt; 2; l++) {
+
+		dst-&gt;range.level[l].sens = src-&gt;range.level[l].sens;
+		rc = ebitmap_cpy(&amp;dst-&gt;range.level[l].cat,
+				 &amp;src-&gt;range.level[l].cat);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+/*
+ * 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(struct policydb *oldp,
+			struct policydb *newp,
+			struct context *c)
+{
+	struct level_datum *levdatum;
+	struct cat_datum *catdatum;
+	struct ebitmap bitmap;
+	int l, i;
+
+	for (l = 0; l &lt; 2; l++) {
+		levdatum = hashtab_search(newp-&gt;p_levels.table,
+			oldp-&gt;p_sens_val_to_name[c-&gt;range.level[l].sens - 1]);
+
+		if (!levdatum)
+			return -EINVAL;
+		c-&gt;range.level[l].sens = levdatum-&gt;level-&gt;sens;
+
+		ebitmap_init(&amp;bitmap);
+		for (i = 1; i &lt;= ebitmap_length(&amp;c-&gt;range.level[l].cat); i++) {
+			if (ebitmap_get_bit(&amp;c-&gt;range.level[l].cat, i - 1)) {
+				int rc;
+
+				catdatum = hashtab_search(newp-&gt;p_cats.table,
+				         	oldp-&gt;p_cat_val_to_name[i - 1]);
+				if (!catdatum)
+					return -EINVAL;
+				rc = ebitmap_set_bit(&amp;bitmap, catdatum-&gt;value - 1, 1);
+				if (rc)
+					return rc;
+			}
+		}
+		ebitmap_destroy(&amp;c-&gt;range.level[l].cat);
+		c-&gt;range.level[l].cat = bitmap;
+	}
+
+	return 0;
+}
+
+int mls_compute_sid(struct context *scontext,
+		    struct context *tcontext,
+		    u16 tclass,
+		    u32 specified,
+		    struct context *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-&gt;type != tcontext-&gt;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:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+void mls_user_destroy(struct user_datum *usrdatum)
+{
+	struct mls_range_list *rnode, *rtmp;
+	rnode = usrdatum-&gt;ranges;
+	while (rnode) {
+		rtmp = rnode;
+		rnode = rnode-&gt;next;
+		ebitmap_destroy(&amp;rtmp-&gt;range.level[0].cat);
+		ebitmap_destroy(&amp;rtmp-&gt;range.level[1].cat);
+		kfree(rtmp);
+	}
+}
+
+int mls_read_perm(struct perm_datum *perdatum, void *fp)
+{
+	u32 *buf;
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf)
+		return -EINVAL;
+	perdatum-&gt;base_perms = le32_to_cpu(buf[0]);
+	return 0;
+}
+
+/*
+ * Read a MLS level structure from a policydb binary
+ * representation file.
+ */
+struct mls_level *mls_read_level(void *fp)
+{
+	struct mls_level *l;
+	u32 *buf;
+
+	l = kmalloc(sizeof(*l), GFP_ATOMIC);
+	if (!l) {
+		printk(KERN_ERR "security: mls: out of memory\n");
+		return NULL;
+	}
+	memset(l, 0, sizeof(*l));
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		printk(KERN_ERR "security: mls: truncated level\n");
+		goto bad;
+	}
+	l-&gt;sens = cpu_to_le32(buf[0]);
+
+	if (ebitmap_read(&amp;l-&gt;cat, fp)) {
+		printk(KERN_ERR "security: mls:  error reading level "
+		       "categories\n");
+		goto bad;
+	}
+	return l;
+
+bad:
+	kfree(l);
+	return NULL;
+}
+
+
+/*
+ * Read a MLS range structure from a policydb binary
+ * representation file.
+ */
+static int mls_read_range_helper(struct mls_range *r, void *fp)
+{
+	u32 *buf;
+	int items, rc = -EINVAL;
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf)
+		goto out;
+
+	items = le32_to_cpu(buf[0]);
+	buf = next_entry(fp, sizeof(u32) * items);
+	if (!buf) {
+		printk(KERN_ERR "security: mls:  truncated range\n");
+		goto out;
+	}
+	r-&gt;level[0].sens = le32_to_cpu(buf[0]);
+	if (items &gt; 1) {
+		r-&gt;level[1].sens = le32_to_cpu(buf[1]);
+	} else {
+		r-&gt;level[1].sens = r-&gt;level[0].sens;
+	}
+
+	rc = ebitmap_read(&amp;r-&gt;level[0].cat, fp);
+	if (rc) {
+		printk(KERN_ERR "security: mls:  error reading low "
+		       "categories\n");
+		goto out;
+	}
+	if (items &gt; 1) {
+		rc = ebitmap_read(&amp;r-&gt;level[1].cat, fp);
+		if (rc) {
+			printk(KERN_ERR "security: mls:  error reading high "
+			       "categories\n");
+			goto bad_high;
+		}
+	} else {
+		rc = ebitmap_cpy(&amp;r-&gt;level[1].cat, &amp;r-&gt;level[0].cat);
+		if (rc) {
+			printk(KERN_ERR "security: mls:  out of memory\n");
+			goto bad_high;
+		}
+	}
+
+	rc = 0;
+out:
+	return rc;
+bad_high:
+	ebitmap_destroy(&amp;r-&gt;level[0].cat);
+	goto out;
+}
+
+int mls_read_range(struct context *c, void *fp)
+{
+	return mls_read_range_helper(&amp;c-&gt;range, fp);
+}
+
+
+/*
+ * Read a MLS perms structure from a policydb binary
+ * representation file.
+ */
+int mls_read_class(struct class_datum *cladatum, void *fp)
+{
+	struct mls_perms *p = &amp;cladatum-&gt;mlsperms;
+	u32 *buf;
+
+	buf = next_entry(fp, sizeof(u32)*4);
+	if (!buf) {
+		printk(KERN_ERR "security: mls:  truncated mls permissions\n");
+		return -EINVAL;
+	}
+	p-&gt;read = le32_to_cpu(buf[0]);
+	p-&gt;readby = le32_to_cpu(buf[1]);
+	p-&gt;write = le32_to_cpu(buf[2]);
+	p-&gt;writeby = le32_to_cpu(buf[3]);
+	return 0;
+}
+
+int mls_read_user(struct user_datum *usrdatum, void *fp)
+{
+	struct mls_range_list *r, *l;
+	int rc = 0;
+	u32 nel, i;
+	u32 *buf;
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		rc = -EINVAL;
+		goto out;
+	}
+	nel = le32_to_cpu(buf[0]);
+	l = NULL;
+	for (i = 0; i &lt; nel; i++) {
+		r = kmalloc(sizeof(*r), GFP_ATOMIC);
+		if (!r) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		memset(r, 0, sizeof(*r));
+
+		rc = mls_read_range_helper(&amp;r-&gt;range, fp);
+		if (rc)
+			goto out;
+
+		if (l)
+			l-&gt;next = r;
+		else
+			usrdatum-&gt;ranges = r;
+		l = r;
+	}
+out:
+	return rc;
+}
+
+int mls_read_nlevels(struct policydb *p, void *fp)
+{
+	u32 *buf;
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf)
+		return -EINVAL;
+	p-&gt;nlevels = le32_to_cpu(buf[0]);
+	return 0;
+}
+
+int mls_read_trusted(struct policydb *p, void *fp)
+{
+	int rc = 0;
+
+	rc = ebitmap_read(&amp;p-&gt;trustedreaders, fp);
+	if (rc)
+		goto out;
+	rc = ebitmap_read(&amp;p-&gt;trustedwriters, fp);
+	if (rc)
+		goto out;
+	rc = ebitmap_read(&amp;p-&gt;trustedobjects, fp);
+out:
+	return rc;
+}
+
+int sens_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct level_datum *levdatum;
+
+
+	levdatum = datum;
+	p = datap;
+
+	if (!levdatum-&gt;isalias)
+		p-&gt;p_sens_val_to_name[levdatum-&gt;level-&gt;sens - 1] = key;
+
+	return 0;
+}
+
+int cat_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct cat_datum *catdatum;
+
+
+	catdatum = datum;
+	p = datap;
+
+
+	if (!catdatum-&gt;isalias)
+		p-&gt;p_cat_val_to_name[catdatum-&gt;value - 1] = key;
+
+	return 0;
+}
+
+int sens_destroy(void *key, void *datum, void *p)
+{
+	struct level_datum *levdatum;
+
+	kfree(key);
+	levdatum = datum;
+	if (!levdatum-&gt;isalias) {
+		ebitmap_destroy(&amp;levdatum-&gt;level-&gt;cat);
+		kfree(levdatum-&gt;level);
+	}
+	kfree(datum);
+	return 0;
+}
+
+int cat_destroy(void *key, void *datum, void *p)
+{
+	kfree(key);
+	kfree(datum);
+	return 0;
+}
+
+int sens_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct level_datum *levdatum;
+	int rc;
+	u32 *buf, len;
+
+	levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+	if (!levdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(levdatum, 0, sizeof(*levdatum));
+
+	buf = next_entry(fp, sizeof(u32)*2);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	levdatum-&gt;isalias = le32_to_cpu(buf[1]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_ATOMIC);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	levdatum-&gt;level = mls_read_level(fp);
+	if (!levdatum-&gt;level) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	rc = hashtab_insert(h, key, levdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	sens_destroy(key, levdatum, NULL);
+	goto out;
+}
+
+
+int cat_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct cat_datum *catdatum;
+	int rc;
+	u32 *buf, len;
+
+	catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+	if (!catdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(catdatum, 0, sizeof(*catdatum));
+
+	buf = next_entry(fp, sizeof(u32)*3);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	catdatum-&gt;value = le32_to_cpu(buf[1]);
+	catdatum-&gt;isalias = le32_to_cpu(buf[2]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_ATOMIC);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	rc = hashtab_insert(h, key, catdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+
+bad:
+	cat_destroy(key, catdatum, NULL);
+	goto out;
+}
diff -puN /dev/null security/selinux/ss/mls.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/mls.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,99 @@
+/*
+ * Multi-level security (MLS) policy operations.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_MLS_H_
+#define _SS_MLS_H_
+
+#include "context.h"
+#include "policydb.h"
+
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+
+void mls_compute_av(struct context *scontext,
+		    struct context *tcontext,
+		    struct class_datum *tclass,
+		    u32 *allowed);
+
+int mls_compute_context_len(struct context *context);
+int mls_sid_to_context(struct context *context, char **scontext);
+int mls_context_isvalid(struct policydb *p, struct context *c);
+
+int mls_context_to_sid(char oldc,
+	               char **scontext,
+		       struct context *context);
+
+int mls_convert_context(struct policydb *oldp,
+			struct policydb *newp,
+			struct context *context);
+
+int mls_compute_sid(struct context *scontext,
+		    struct context *tcontext,
+		    u16 tclass,
+		    u32 specified,
+		    struct context *newcontext);
+
+int sens_index(void *key, void *datum, void *datap);
+int cat_index(void *key, void *datum, void *datap);
+int sens_destroy(void *key, void *datum, void *p);
+int cat_destroy(void *key, void *datum, void *p);
+int sens_read(struct policydb *p, struct hashtab *h, void *fp);
+int cat_read(struct policydb *p, struct hashtab *h, void *fp);
+
+#define mls_for_user_ranges(user, usercon) { \
+struct mls_range_list *__ranges; \
+for (__ranges = user-&gt;ranges; __ranges; __ranges = __ranges-&gt;next) { \
+usercon.range = __ranges-&gt;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) printk(", %d levels", p-&gt;nlevels);
+
+#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
+
+void mls_user_destroy(struct user_datum *usrdatum);
+int mls_read_range(struct context *c, void *fp);
+int mls_read_perm(struct perm_datum *perdatum, void *fp);
+int mls_read_class(struct class_datum *cladatum,  void *fp);
+int mls_read_user(struct user_datum *usrdatum, void *fp);
+int mls_read_nlevels(struct policydb *p, void *fp);
+int mls_read_trusted(struct policydb *p, void *fp);
+
+#else
+
+#define	mls_compute_av(scontext, tcontext, tclass_datum, allowed)
+#define mls_compute_context_len(context) 0
+#define	mls_sid_to_context(context, scontextpp)
+#define mls_context_isvalid(p, c) 1
+#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
+
+#endif	/* _SS_MLS_H */
+
diff -puN /dev/null security/selinux/ss/mls_types.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/mls_types.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,58 @@
+/*
+ * Type definitions for the multi-level security (MLS) policy.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_MLS_TYPES_H_
+#define _SS_MLS_TYPES_H_
+
+struct mls_level {
+	u32 sens;		/* sensitivity */
+	struct ebitmap cat;	/* category set */
+};
+
+struct mls_range {
+	struct mls_level level[2]; /* low == level[0], high == level[1] */
+};
+
+struct mls_range_list {
+	struct mls_range range;
+	struct mls_range_list *next;
+};
+
+#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) &amp;&amp; ebitmap_cmp(&amp;(l1).cat,&amp;(l2).cat))
+
+#define mls_level_relation(l1,l2) ( \
+(((l1).sens == (l2).sens) &amp;&amp; ebitmap_cmp(&amp;(l1).cat,&amp;(l2).cat)) ? \
+				    MLS_RELATION_EQ : \
+(((l1).sens &gt;= (l2).sens) &amp;&amp; ebitmap_contains(&amp;(l1).cat, &amp;(l2).cat)) ? \
+				    MLS_RELATION_DOM : \
+(((l2).sens &gt;= (l1).sens) &amp;&amp; ebitmap_contains(&amp;(l2).cat, &amp;(l1).cat)) ? \
+				    MLS_RELATION_DOMBY : \
+				    MLS_RELATION_INCOMP )
+
+#define mls_range_contains(r1,r2) \
+((mls_level_relation((r1).level[0], (r2).level[0]) &amp; \
+	  (MLS_RELATION_EQ | MLS_RELATION_DOMBY)) &amp;&amp; \
+	 (mls_level_relation((r1).level[1], (r2).level[1]) &amp; \
+	  (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.
+ */
+struct mls_perms {
+	u32 read;     /* permissions that map to `read' */
+	u32 readby;   /* permissions that map to `readby' */
+	u32 write;    /* permissions that map to `write' */
+	u32 writeby;  /* permissions that map to `writeby' */
+};
+
+#endif	/* _SS_MLS_TYPES_H_ */
diff -puN /dev/null security/selinux/ss/policydb.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/policydb.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,1429 @@
+/*
+ * Implementation of the policy database.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "policydb.h"
+#include "mls.h"
+
+#define _DEBUG_HASHES
+
+#ifdef DEBUG_HASHES
+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(struct policydb *p)
+{
+	char *key = 0;
+	int rc;
+	struct role_datum *role;
+
+	role = kmalloc(sizeof(*role), GFP_KERNEL);
+	if (!role) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(role, 0, sizeof(*role));
+	role-&gt;value = ++p-&gt;p_roles.nprim;
+	if (role-&gt;value != OBJECT_R_VAL) {
+		rc = -EINVAL;
+		goto out_free_role;
+	}
+	key = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto out_free_role;
+	}
+	strcpy(key, OBJECT_R);
+	rc = hashtab_insert(p-&gt;p_roles.table, key, role);
+	if (rc)
+		goto out_free_key;
+out:
+	return rc;
+
+out_free_key:
+	kfree(key);
+out_free_role:
+	kfree(role);
+	goto out;
+}
+
+/*
+ * Initialize a policy database structure.
+ */
+int policydb_init(struct policydb *p)
+{
+	int i, rc;
+
+	memset(p, 0, sizeof(*p));
+
+	for (i = 0; i &lt; SYM_NUM; i++) {
+		rc = symtab_init(&amp;p-&gt;symtab[i], symtab_sizes[i]);
+		if (rc)
+			goto out_free_symtab;
+	}
+
+	rc = avtab_init(&amp;p-&gt;te_avtab);
+	if (rc)
+		goto out_free_symtab;
+
+	rc = roles_init(p);
+	if (rc)
+		goto out_free_avtab;
+
+out:
+	return rc;
+
+out_free_avtab:
+	avtab_destroy(&amp;p-&gt;te_avtab);
+
+out_free_symtab:
+	for (i = 0; i &lt; SYM_NUM; i++)
+		hashtab_destroy(p-&gt;symtab[i].table);
+	goto out;
+}
+
+/*
+ * 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(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct common_datum *comdatum;
+
+	comdatum = datum;
+	p = datap;
+	p-&gt;p_common_val_to_name[comdatum-&gt;value - 1] = key;
+	return 0;
+}
+
+static int class_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct class_datum *cladatum;
+
+	cladatum = datum;
+	p = datap;
+	p-&gt;p_class_val_to_name[cladatum-&gt;value - 1] = key;
+	p-&gt;class_val_to_struct[cladatum-&gt;value - 1] = cladatum;
+	return 0;
+}
+
+static int role_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct role_datum *role;
+
+	role = datum;
+	p = datap;
+	p-&gt;p_role_val_to_name[role-&gt;value - 1] = key;
+	p-&gt;role_val_to_struct[role-&gt;value - 1] = role;
+	return 0;
+}
+
+static int type_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct type_datum *typdatum;
+
+	typdatum = datum;
+	p = datap;
+
+	if (typdatum-&gt;primary)
+		p-&gt;p_type_val_to_name[typdatum-&gt;value - 1] = key;
+
+	return 0;
+}
+
+static int user_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct user_datum *usrdatum;
+
+	usrdatum = datum;
+	p = datap;
+	p-&gt;p_user_val_to_name[usrdatum-&gt;value - 1] = key;
+	p-&gt;user_val_to_struct[usrdatum-&gt;value - 1] = usrdatum;
+	return 0;
+}
+
+static int (*index_f[SYM_NUM]) (void *key, void *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.
+ *
+ * Caller must clean up upon failure.
+ */
+int policydb_index_classes(struct policydb *p)
+{
+	int rc;
+
+	p-&gt;p_common_val_to_name =
+		kmalloc(p-&gt;p_commons.nprim * sizeof(char *), GFP_KERNEL);
+	if (!p-&gt;p_common_val_to_name) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = hashtab_map(p-&gt;p_commons.table, common_index, p);
+	if (rc)
+		goto out;
+
+	p-&gt;class_val_to_struct =
+		kmalloc(p-&gt;p_classes.nprim * sizeof(*(p-&gt;class_val_to_struct)), GFP_KERNEL);
+	if (!p-&gt;class_val_to_struct) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	p-&gt;p_class_val_to_name =
+		kmalloc(p-&gt;p_classes.nprim * sizeof(char *), GFP_KERNEL);
+	if (!p-&gt;p_class_val_to_name) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = hashtab_map(p-&gt;p_classes.table, class_index, p);
+out:
+	return rc;
+}
+
+#ifdef DEBUG_HASHES
+static void symtab_hash_eval(struct symtab *s)
+{
+	int i;
+
+	for (i = 0; i &lt; SYM_NUM; i++) {
+		struct hashtab *h = s[i].table;
+		struct hashtab_info info;
+
+		hashtab_stat(h, &amp;info);
+		printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, "
+		       "longest chain length %d\n", symtab_name[i], h-&gt;nel,
+		       info.slots_used, h-&gt;size, info.max_chain_len);
+	}
+}
+#endif
+
+/*
+ * Define the other val_to_name and val_to_struct arrays
+ * in a policy database structure.
+ *
+ * Caller must clean up on failure.
+ */
+int policydb_index_others(struct policydb *p)
+{
+	int i, rc = 0;
+
+	printk(KERN_INFO "security:  %d users, %d roles, %d types",
+	       p-&gt;p_users.nprim, p-&gt;p_roles.nprim, p-&gt;p_types.nprim);
+	mls_policydb_index_others(p);
+	printk("\n");
+
+	printk(KERN_INFO "security:  %d classes, %d rules\n",
+	       p-&gt;p_classes.nprim, p-&gt;te_avtab.nel);
+
+#ifdef DEBUG_HASHES
+	avtab_hash_eval(&amp;p-&gt;te_avtab, "rules");
+	symtab_hash_eval(p-&gt;symtab);
+#endif
+
+	p-&gt;role_val_to_struct =
+		kmalloc(p-&gt;p_roles.nprim * sizeof(*(p-&gt;role_val_to_struct)),
+		        GFP_KERNEL);
+	if (!p-&gt;role_val_to_struct) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	p-&gt;user_val_to_struct =
+		kmalloc(p-&gt;p_users.nprim * sizeof(*(p-&gt;user_val_to_struct)),
+		        GFP_KERNEL);
+	if (!p-&gt;user_val_to_struct) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	for (i = SYM_ROLES; i &lt; SYM_NUM; i++) {
+		p-&gt;sym_val_to_name[i] =
+			kmalloc(p-&gt;symtab[i].nprim * sizeof(char *), GFP_KERNEL);
+		if (!p-&gt;sym_val_to_name[i]) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		rc = hashtab_map(p-&gt;symtab[i].table, index_f[i], p);
+		if (rc)
+			goto out;
+	}
+
+out:
+	return rc;
+}
+
+/*
+ * The following *_destroy functions are used to
+ * free any memory allocated for each kind of
+ * symbol data in the policy database.
+ */
+
+static int perm_destroy(void *key, void *datum, void *p)
+{
+	kfree(key);
+	kfree(datum);
+	return 0;
+}
+
+static int common_destroy(void *key, void *datum, void *p)
+{
+	struct common_datum *comdatum;
+
+	kfree(key);
+	comdatum = datum;
+	hashtab_map(comdatum-&gt;permissions.table, perm_destroy, 0);
+	hashtab_destroy(comdatum-&gt;permissions.table);
+	kfree(datum);
+	return 0;
+}
+
+static int class_destroy(void *key, void *datum, void *p)
+{
+	struct class_datum *cladatum;
+	struct constraint_node *constraint, *ctemp;
+	struct constraint_expr *e, *etmp;
+
+	kfree(key);
+	cladatum = datum;
+	hashtab_map(cladatum-&gt;permissions.table, perm_destroy, 0);
+	hashtab_destroy(cladatum-&gt;permissions.table);
+	constraint = cladatum-&gt;constraints;
+	while (constraint) {
+		e = constraint-&gt;expr;
+		while (e) {
+			ebitmap_destroy(&amp;e-&gt;names);
+			etmp = e;
+			e = e-&gt;next;
+			kfree(etmp);
+		}
+		ctemp = constraint;
+		constraint = constraint-&gt;next;
+		kfree(ctemp);
+	}
+	kfree(cladatum-&gt;comkey);
+	kfree(datum);
+	return 0;
+}
+
+static int role_destroy(void *key, void *datum, void *p)
+{
+	struct role_datum *role;
+
+	kfree(key);
+	role = datum;
+	ebitmap_destroy(&amp;role-&gt;dominates);
+	ebitmap_destroy(&amp;role-&gt;types);
+	kfree(datum);
+	return 0;
+}
+
+static int type_destroy(void *key, void *datum, void *p)
+{
+	kfree(key);
+	kfree(datum);
+	return 0;
+}
+
+static int user_destroy(void *key, void *datum, void *p)
+{
+	struct user_datum *usrdatum;
+
+	kfree(key);
+	usrdatum = datum;
+	ebitmap_destroy(&amp;usrdatum-&gt;roles);
+	mls_user_destroy(usrdatum);
+	kfree(datum);
+	return 0;
+}
+
+static int (*destroy_f[SYM_NUM]) (void *key, void *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(struct policydb *p)
+{
+	struct ocontext *c, *ctmp;
+	struct genfs *g, *gtmp;
+	int i;
+
+	for (i = 0; i &lt; SYM_NUM; i++) {
+		hashtab_map(p-&gt;symtab[i].table, destroy_f[i], 0);
+		hashtab_destroy(p-&gt;symtab[i].table);
+	}
+
+	for (i = 0; i &lt; SYM_NUM; i++) {
+		if (p-&gt;sym_val_to_name[i])
+			kfree(p-&gt;sym_val_to_name[i]);
+	}
+
+	if (p-&gt;class_val_to_struct)
+		kfree(p-&gt;class_val_to_struct);
+	if (p-&gt;role_val_to_struct)
+		kfree(p-&gt;role_val_to_struct);
+	if (p-&gt;user_val_to_struct)
+		kfree(p-&gt;user_val_to_struct);
+
+	avtab_destroy(&amp;p-&gt;te_avtab);
+
+	for (i = 0; i &lt; OCON_NUM; i++) {
+		c = p-&gt;ocontexts[i];
+		while (c) {
+			ctmp = c;
+			c = c-&gt;next;
+			context_destroy(&amp;ctmp-&gt;context[0]);
+			context_destroy(&amp;ctmp-&gt;context[1]);
+			if (i == OCON_ISID || i == OCON_FS ||
+			    i == OCON_NETIF || i == OCON_FSUSE)
+				kfree(ctmp-&gt;u.name);
+			kfree(ctmp);
+		}
+	}
+
+	g = p-&gt;genfs;
+	while (g) {
+		kfree(g-&gt;fstype);
+		c = g-&gt;head;
+		while (c) {
+			ctmp = c;
+			c = c-&gt;next;
+			context_destroy(&amp;ctmp-&gt;context[0]);
+			kfree(ctmp-&gt;u.name);
+			kfree(ctmp);
+		}
+		gtmp = g;
+		g = g-&gt;next;
+		kfree(gtmp);
+	}
+
+	return;
+}
+
+/*
+ * Load the initial SIDs specified in a policy database
+ * structure into a SID table.
+ */
+int policydb_load_isids(struct policydb *p, struct sidtab *s)
+{
+	struct ocontext *head, *c;
+	int rc;
+
+	rc = sidtab_init(s);
+	if (rc) {
+		printk(KERN_ERR "security:  out of memory on SID table init\n");
+		goto out;
+	}
+
+	head = p-&gt;ocontexts[OCON_ISID];
+	for (c = head; c; c = c-&gt;next) {
+		if (!c-&gt;context[0].user) {
+			printk(KERN_ERR "security:  SID %s was never "
+			       "defined.\n", c-&gt;u.name);
+			rc = -EINVAL;
+			goto out;
+		}
+		if (sidtab_insert(s, c-&gt;sid[0], &amp;c-&gt;context[0])) {
+			printk(KERN_ERR "security:  unable to load initial "
+			       "SID %s.\n", c-&gt;u.name);
+			rc = -EINVAL;
+			goto out;
+		}
+	}
+out:
+	return rc;
+}
+
+/*
+ * Return 1 if the fields in the security context
+ * structure `c' are valid.  Return 0 otherwise.
+ */
+int policydb_context_isvalid(struct policydb *p, struct context *c)
+{
+	struct role_datum *role;
+	struct user_datum *usrdatum;
+
+	/*
+	 * Role must be authorized for the type.
+	 */
+	if (!c-&gt;role || c-&gt;role &gt; p-&gt;p_roles.nprim)
+		return 0;
+
+	if (c-&gt;role != OBJECT_R_VAL) {
+		role = p-&gt;role_val_to_struct[c-&gt;role - 1];
+		if (!ebitmap_get_bit(&amp;role-&gt;types,
+				     c-&gt;type - 1))
+			/* role may not be associated with type */
+			return 0;
+
+		/*
+		 * User must be authorized for the role.
+		 */
+		if (!c-&gt;user || c-&gt;user &gt; p-&gt;p_users.nprim)
+			return 0;
+		usrdatum = p-&gt;user_val_to_struct[c-&gt;user - 1];
+		if (!usrdatum)
+			return 0;
+
+		if (!ebitmap_get_bit(&amp;usrdatum-&gt;roles,
+				     c-&gt;role - 1))
+			/* user may not be associated with role */
+			return 0;
+	}
+
+	if (!mls_context_isvalid(p, c))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Read and validate a security context structure
+ * from a policydb binary representation file.
+ */
+static int context_read_and_validate(struct context *c,
+				     struct policydb *p,
+				     void *fp)
+{
+	u32 *buf;
+	int rc = 0;
+
+	buf = next_entry(fp, sizeof(u32)*3);
+	if (!buf) {
+		printk(KERN_ERR "security: context truncated\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	c-&gt;user = le32_to_cpu(buf[0]);
+	c-&gt;role = le32_to_cpu(buf[1]);
+	c-&gt;type = le32_to_cpu(buf[2]);
+	if (mls_read_range(c, fp)) {
+		printk(KERN_ERR "security: error reading MLS range of "
+		       "context\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (!policydb_context_isvalid(p, c)) {
+		printk(KERN_ERR "security:  invalid security context\n");
+		context_destroy(c);
+		rc = -EINVAL;
+	}
+out:
+	return rc;
+}
+
+/*
+ * The following *_read functions are used to
+ * read the symbol data from a policy database
+ * binary representation file.
+ */
+
+static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct perm_datum *perdatum;
+	int rc;
+	u32 *buf, len;
+
+	perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
+	if (!perdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(perdatum, 0, sizeof(*perdatum));
+
+	buf = next_entry(fp, sizeof(u32)*2);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	perdatum-&gt;value = le32_to_cpu(buf[1]);
+	rc = mls_read_perm(perdatum, fp);
+	if (rc)
+		goto bad;
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	rc = hashtab_insert(h, key, perdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	perm_destroy(key, perdatum, NULL);
+	goto out;
+}
+
+static int common_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct common_datum *comdatum;
+	u32 *buf, len, nel;
+	int i, rc;
+
+	comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
+	if (!comdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(comdatum, 0, sizeof(*comdatum));
+
+	buf = next_entry(fp, sizeof(u32)*4);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	comdatum-&gt;value = le32_to_cpu(buf[1]);
+
+	rc = symtab_init(&amp;comdatum-&gt;permissions, PERM_SYMTAB_SIZE);
+	if (rc)
+		goto bad;
+	comdatum-&gt;permissions.nprim = le32_to_cpu(buf[2]);
+	nel = le32_to_cpu(buf[3]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	for (i = 0; i &lt; nel; i++) {
+		rc = perm_read(p, comdatum-&gt;permissions.table, fp);
+		if (rc)
+			goto bad;
+	}
+
+	rc = hashtab_insert(h, key, comdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	common_destroy(key, comdatum, NULL);
+	goto out;
+}
+
+static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct class_datum *cladatum;
+	struct constraint_node *c, *lc;
+	struct constraint_expr *e, *le;
+	u32 *buf, len, len2, ncons, nexpr, nel;
+	int i, j, depth, rc;
+
+	cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
+	if (!cladatum) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memset(cladatum, 0, sizeof(*cladatum));
+
+	buf = next_entry(fp, sizeof(u32)*6);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	len2 = le32_to_cpu(buf[1]);
+	cladatum-&gt;value = le32_to_cpu(buf[2]);
+
+	rc = symtab_init(&amp;cladatum-&gt;permissions, PERM_SYMTAB_SIZE);
+	if (rc)
+		goto bad;
+	cladatum-&gt;permissions.nprim = le32_to_cpu(buf[3]);
+	nel = le32_to_cpu(buf[4]);
+
+	ncons = le32_to_cpu(buf[5]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	if (len2) {
+		cladatum-&gt;comkey = kmalloc(len2 + 1,GFP_KERNEL);
+		if (!cladatum-&gt;comkey) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		buf = next_entry(fp, len2);
+		if (!buf) {
+			rc = -EINVAL;
+			goto bad;
+		}
+		memcpy(cladatum-&gt;comkey, buf, len2);
+		cladatum-&gt;comkey[len2] = 0;
+
+		cladatum-&gt;comdatum = hashtab_search(p-&gt;p_commons.table,
+						    cladatum-&gt;comkey);
+		if (!cladatum-&gt;comdatum) {
+			printk(KERN_ERR "security:  unknown common %s\n",
+			       cladatum-&gt;comkey);
+			rc = -EINVAL;
+			goto bad;
+		}
+	}
+	for (i = 0; i &lt; nel; i++) {
+		rc = perm_read(p, cladatum-&gt;permissions.table, fp);
+		if (rc)
+			goto bad;
+	}
+
+	lc = NULL;
+	rc = -EINVAL;
+	for (i = 0; i &lt; ncons; i++) {
+		c = kmalloc(sizeof(*c), GFP_KERNEL);
+		if (!c) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memset(c, 0, sizeof(*c));
+		buf = next_entry(fp, sizeof(u32)*2);
+		if (!buf)
+			goto bad;
+		c-&gt;permissions = le32_to_cpu(buf[0]);
+		nexpr = le32_to_cpu(buf[1]);
+		le = NULL;
+		depth = -1;
+		for (j = 0; j &lt; nexpr; j++) {
+			e = kmalloc(sizeof(*e), GFP_KERNEL);
+			if (!e) {
+				rc = -ENOMEM;
+				goto bad;
+			}
+			memset(e, 0, sizeof(*e));
+			buf = next_entry(fp, sizeof(u32)*3);
+			if (!buf) {
+				kfree(e);
+				goto bad;
+			}
+			e-&gt;expr_type = le32_to_cpu(buf[0]);
+			e-&gt;attr = le32_to_cpu(buf[1]);
+			e-&gt;op = le32_to_cpu(buf[2]);
+
+			switch (e-&gt;expr_type) {
+			case CEXPR_NOT:
+				if (depth &lt; 0) {
+					kfree(e);
+					goto bad;
+				}
+				break;
+			case CEXPR_AND:
+			case CEXPR_OR:
+				if (depth &lt; 1) {
+					kfree(e);
+					goto bad;
+				}
+				depth--;
+				break;
+			case CEXPR_ATTR:
+				if (depth == (CEXPR_MAXDEPTH-1)) {
+					kfree(e);
+					goto bad;
+				}
+				depth++;
+				break;
+			case CEXPR_NAMES:
+				if (depth == (CEXPR_MAXDEPTH-1)) {
+					kfree(e);
+					goto bad;
+				}
+				depth++;
+				if (ebitmap_read(&amp;e-&gt;names, fp)) {
+					kfree(e);
+					goto bad;
+				}
+				break;
+			default:
+				kfree(e);
+				goto bad;
+				break;
+			}
+			if (le) {
+				le-&gt;next = e;
+			} else {
+				c-&gt;expr = e;
+			}
+			le = e;
+		}
+		if (depth != 0)
+			goto bad;
+		if (lc) {
+			lc-&gt;next = c;
+		} else {
+			cladatum-&gt;constraints = c;
+		}
+		lc = c;
+	}
+
+	rc = mls_read_class(cladatum, fp);
+	if (rc)
+		goto bad;
+
+	rc = hashtab_insert(h, key, cladatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	class_destroy(key, cladatum, NULL);
+	goto out;
+}
+
+static int role_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct role_datum *role;
+	int rc;
+	u32 *buf, len;
+
+	role = kmalloc(sizeof(*role), GFP_KERNEL);
+	if (!role) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(role, 0, sizeof(*role));
+
+	buf = next_entry(fp, sizeof(u32)*2);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	role-&gt;value = le32_to_cpu(buf[1]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	rc = ebitmap_read(&amp;role-&gt;dominates, fp);
+	if (rc)
+		goto bad;
+
+	rc = ebitmap_read(&amp;role-&gt;types, fp);
+	if (rc)
+		goto bad;
+
+	if (strcmp(key, OBJECT_R) == 0) {
+		if (role-&gt;value != OBJECT_R_VAL) {
+			printk(KERN_ERR "Role %s has wrong value %d\n",
+			       OBJECT_R, role-&gt;value);
+			rc = -EINVAL;
+			goto bad;
+		}
+		rc = 0;
+		goto bad;
+	}
+
+	rc = hashtab_insert(h, key, role);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	role_destroy(key, role, NULL);
+	goto out;
+}
+
+static int type_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct type_datum *typdatum;
+	int rc;
+	u32 *buf, len;
+
+	typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
+	if (!typdatum) {
+		rc = -ENOMEM;
+		return rc;
+	}
+	memset(typdatum, 0, sizeof(*typdatum));
+
+	buf = next_entry(fp, sizeof(u32)*3);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	typdatum-&gt;value = le32_to_cpu(buf[1]);
+	typdatum-&gt;primary = le32_to_cpu(buf[2]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	rc = hashtab_insert(h, key, typdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	type_destroy(key, typdatum, NULL);
+	goto out;
+}
+
+static int user_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct user_datum *usrdatum;
+	int rc;
+	u32 *buf, len;
+
+
+	usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
+	if (!usrdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(usrdatum, 0, sizeof(*usrdatum));
+
+	buf = next_entry(fp, sizeof(u32)*2);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	len = le32_to_cpu(buf[0]);
+	usrdatum-&gt;value = le32_to_cpu(buf[1]);
+
+	buf = next_entry(fp, len);
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	key = kmalloc(len + 1,GFP_KERNEL);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(key, buf, len);
+	key[len] = 0;
+
+	rc = ebitmap_read(&amp;usrdatum-&gt;roles, fp);
+	if (rc)
+		goto bad;
+
+	rc = mls_read_user(usrdatum, fp);
+	if (rc)
+		goto bad;
+
+	rc = hashtab_insert(h, key, usrdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	user_destroy(key, usrdatum, NULL);
+	goto out;
+}
+
+static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
+{
+	common_read,
+	class_read,
+	role_read,
+	type_read,
+	user_read
+	mls_read_f
+};
+
+#define mls_config(x) \
+       ((x) &amp; 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(struct policydb *p, void *fp)
+{
+	struct role_allow *ra, *lra;
+	struct role_trans *tr, *ltr;
+	struct ocontext *l, *c, *newc;
+	struct genfs *genfs_p, *genfs, *newgenfs;
+	int i, j, rc;
+	u32 *buf, len, len2, config, nprim, nel, nel2;
+	char *policydb_str;
+
+	config = 0;
+	mls_set_config(config);
+
+	rc = policydb_init(p);
+	if (rc)
+		goto out;
+
+	rc = -EINVAL;
+	/* Read the magic number and string length. */
+	buf = next_entry(fp, sizeof(u32)* 2);
+	if (!buf)
+		goto bad;
+
+	for (i = 0; i &lt; 2; i++)
+		buf[i] = le32_to_cpu(buf[i]);
+
+	if (buf[0] != POLICYDB_MAGIC) {
+		printk(KERN_ERR "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)) {
+		printk(KERN_ERR "security:  policydb string length %d does not "
+		       "match expected length %d\n",
+		       len, strlen(POLICYDB_STRING));
+		goto bad;
+	}
+	buf = next_entry(fp, len);
+	if (!buf) {
+		printk(KERN_ERR "security:  truncated policydb string identifier\n");
+		goto bad;
+	}
+	policydb_str = kmalloc(len + 1,GFP_KERNEL);
+	if (!policydb_str) {
+		printk(KERN_ERR "security:  unable to allocate memory for policydb "
+		       "string of length %d\n", len);
+		rc = -ENOMEM;
+		goto bad;
+	}
+	memcpy(policydb_str, buf, len);
+	policydb_str[len] = 0;
+	if (strcmp(policydb_str, POLICYDB_STRING)) {
+		printk(KERN_ERR "security:  policydb string %s does not match "
+		       "my string %s\n", policydb_str, POLICYDB_STRING);
+		kfree(policydb_str);
+		goto bad;
+	}
+	/* Done with policydb_str. */
+	kfree(policydb_str);
+	policydb_str = NULL;
+
+	/* Read the version, config, and table sizes. */
+	buf = next_entry(fp, sizeof(u32)*4);
+	if (!buf)
+		goto bad;
+	for (i = 0; i &lt; 4; i++)
+		buf[i] = le32_to_cpu(buf[i]);
+
+	if (buf[0] != POLICYDB_VERSION) {
+		printk(KERN_ERR "security:  policydb version %d does not match "
+		       "my version %d\n", buf[0], POLICYDB_VERSION);
+		goto bad;
+	}
+	if (buf[1] != config) {
+		printk(KERN_ERR "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) {
+		printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
+		       "not match mine (%d,%d)\n",
+		       buf[2], buf[3], SYM_NUM, OCON_NUM);
+		goto bad;
+	}
+
+	rc = mls_read_nlevels(p, fp);
+	if (rc)
+		goto bad;
+
+	for (i = 0; i &lt; SYM_NUM; i++) {
+		buf = next_entry(fp, sizeof(u32)*2);
+		if (!buf) {
+			rc = -EINVAL;
+			goto bad;
+		}
+		nprim = le32_to_cpu(buf[0]);
+		nel = le32_to_cpu(buf[1]);
+		for (j = 0; j &lt; nel; j++) {
+			rc = read_f[i](p, p-&gt;symtab[i].table, fp);
+			if (rc)
+				goto bad;
+		}
+
+		p-&gt;symtab[i].nprim = nprim;
+	}
+
+	rc = avtab_read(&amp;p-&gt;te_avtab, fp, config);
+	if (rc)
+		goto bad;
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	nel = le32_to_cpu(buf[0]);
+	ltr = NULL;
+	for (i = 0; i &lt; nel; i++) {
+		tr = kmalloc(sizeof(*tr), GFP_KERNEL);
+		if (!tr) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memset(tr, 0, sizeof(*tr));
+		if (ltr) {
+			ltr-&gt;next = tr;
+		} else {
+			p-&gt;role_tr = tr;
+		}
+		buf = next_entry(fp, sizeof(u32)*3);
+		if (!buf) {
+			rc = -EINVAL;
+			goto bad;
+		}
+		tr-&gt;role = le32_to_cpu(buf[0]);
+		tr-&gt;type = le32_to_cpu(buf[1]);
+		tr-&gt;new_role = le32_to_cpu(buf[2]);
+		ltr = tr;
+	}
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	nel = le32_to_cpu(buf[0]);
+	lra = NULL;
+	for (i = 0; i &lt; nel; i++) {
+		ra = kmalloc(sizeof(*ra), GFP_KERNEL);
+		if (!ra) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memset(ra, 0, sizeof(*ra));
+		if (lra) {
+			lra-&gt;next = ra;
+		} else {
+			p-&gt;role_allow = ra;
+		}
+		buf = next_entry(fp, sizeof(u32)*2);
+		if (!buf) {
+			rc = -EINVAL;
+			goto bad;
+		}
+		ra-&gt;role = le32_to_cpu(buf[0]);
+		ra-&gt;new_role = le32_to_cpu(buf[1]);
+		lra = ra;
+	}
+
+	rc = policydb_index_classes(p);
+	if (rc)
+		goto bad;
+
+	rc = policydb_index_others(p);
+	if (rc)
+		goto bad;
+
+	for (i = 0; i &lt; OCON_NUM; i++) {
+		buf = next_entry(fp, sizeof(u32));
+		if (!buf) {
+			rc = -EINVAL;
+			goto bad;
+		}
+		nel = le32_to_cpu(buf[0]);
+		l = NULL;
+		for (j = 0; j &lt; nel; j++) {
+			c = kmalloc(sizeof(*c), GFP_KERNEL);
+			if (!c) {
+				rc = -ENOMEM;
+				goto bad;
+			}
+			memset(c, 0, sizeof(*c));
+			if (l) {
+				l-&gt;next = c;
+			} else {
+				p-&gt;ocontexts[i] = c;
+			}
+			l = c;
+			rc = -EINVAL;
+			switch (i) {
+			case OCON_ISID:
+				buf = next_entry(fp, sizeof(u32));
+				if (!buf)
+					goto bad;
+				c-&gt;sid[0] = le32_to_cpu(buf[0]);
+				rc = context_read_and_validate(&amp;c-&gt;context[0], p, fp);
+				if (rc)
+					goto bad;
+				break;
+			case OCON_FS:
+			case OCON_NETIF:
+				buf = next_entry(fp, sizeof(u32));
+				if (!buf)
+					goto bad;
+				len = le32_to_cpu(buf[0]);
+				buf = next_entry(fp, len);
+				if (!buf)
+					goto bad;
+				c-&gt;u.name = kmalloc(len + 1,GFP_KERNEL);
+				if (!c-&gt;u.name) {
+					rc = -ENOMEM;
+					goto bad;
+				}
+				memcpy(c-&gt;u.name, buf, len);
+				c-&gt;u.name[len] = 0;
+				rc = context_read_and_validate(&amp;c-&gt;context[0], p, fp);
+				if (rc)
+					goto bad;
+				rc = context_read_and_validate(&amp;c-&gt;context[1], p, fp);
+				if (rc)
+					goto bad;
+				break;
+			case OCON_PORT:
+				buf = next_entry(fp, sizeof(u32)*3);
+				if (!buf)
+					goto bad;
+				c-&gt;u.port.protocol = le32_to_cpu(buf[0]);
+				c-&gt;u.port.low_port = le32_to_cpu(buf[1]);
+				c-&gt;u.port.high_port = le32_to_cpu(buf[2]);
+				rc = context_read_and_validate(&amp;c-&gt;context[0], p, fp);
+				if (rc)
+					goto bad;
+				break;
+			case OCON_NODE:
+				buf = next_entry(fp, sizeof(u32)* 2);
+				if (!buf)
+					goto bad;
+				c-&gt;u.node.addr = le32_to_cpu(buf[0]);
+				c-&gt;u.node.mask = le32_to_cpu(buf[1]);
+				rc = context_read_and_validate(&amp;c-&gt;context[0], p, fp);
+				if (rc)
+					goto bad;
+				break;
+			case OCON_FSUSE:
+				buf = next_entry(fp, sizeof(u32)*2);
+				if (!buf)
+					goto bad;
+				c-&gt;v.behavior = le32_to_cpu(buf[0]);
+				len = le32_to_cpu(buf[1]);
+				buf = next_entry(fp, len);
+				if (!buf)
+					goto bad;
+				c-&gt;u.name = kmalloc(len + 1,GFP_KERNEL);
+				if (!c-&gt;u.name) {
+					rc = -ENOMEM;
+					goto bad;
+				}
+				memcpy(c-&gt;u.name, buf, len);
+				c-&gt;u.name[len] = 0;
+				rc = context_read_and_validate(&amp;c-&gt;context[0], p, fp);
+				if (rc)
+					goto bad;
+				break;
+			}
+		}
+	}
+
+	buf = next_entry(fp, sizeof(u32));
+	if (!buf) {
+		rc = -EINVAL;
+		goto bad;
+	}
+	nel = le32_to_cpu(buf[0]);
+	genfs_p = NULL;
+	rc = -EINVAL;
+	for (i = 0; i &lt; nel; i++) {
+		newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
+		if (!newgenfs) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memset(newgenfs, 0, sizeof(*newgenfs));
+		buf = next_entry(fp, sizeof(u32));
+		if (!buf)
+			goto bad;
+		len = le32_to_cpu(buf[0]);
+		buf = next_entry(fp, len);
+		if (!buf)
+			goto bad;
+		newgenfs-&gt;fstype = kmalloc(len + 1,GFP_KERNEL);
+		if (!newgenfs-&gt;fstype) {
+			rc = -ENOMEM;
+			goto bad;
+		}
+		memcpy(newgenfs-&gt;fstype, buf, len);
+		newgenfs-&gt;fstype[len] = 0;
+		for (genfs_p = NULL, genfs = p-&gt;genfs; genfs;
+		     genfs_p = genfs, genfs = genfs-&gt;next) {
+			if (strcmp(newgenfs-&gt;fstype, genfs-&gt;fstype) == 0) {
+				printk(KERN_ERR "security:  dup genfs "
+				       "fstype %s\n", newgenfs-&gt;fstype);
+				goto bad;
+			}
+			if (strcmp(newgenfs-&gt;fstype, genfs-&gt;fstype) &lt; 0)
+				break;
+		}
+		newgenfs-&gt;next = genfs;
+		if (genfs_p)
+			genfs_p-&gt;next = newgenfs;
+		else
+			p-&gt;genfs = newgenfs;
+		buf = next_entry(fp, sizeof(u32));
+		if (!buf)
+			goto bad;
+		nel2 = le32_to_cpu(buf[0]);
+		for (j = 0; j &lt; nel2; j++) {
+			newc = kmalloc(sizeof(*newc), GFP_KERNEL);
+			if (!newc) {
+				rc = -ENOMEM;
+				goto bad;
+			}
+			memset(newc, 0, sizeof(*newc));
+			buf = next_entry(fp, sizeof(u32));
+			if (!buf)
+				goto bad;
+			len = le32_to_cpu(buf[0]);
+			buf = next_entry(fp, len);
+			if (!buf)
+				goto bad;
+			newc-&gt;u.name = kmalloc(len + 1,GFP_KERNEL);
+			if (!newc-&gt;u.name) {
+				rc = -ENOMEM;
+				goto bad;
+			}
+			memcpy(newc-&gt;u.name, buf, len);
+			newc-&gt;u.name[len] = 0;
+			buf = next_entry(fp, sizeof(u32));
+			if (!buf)
+				goto bad;
+			newc-&gt;v.sclass = le32_to_cpu(buf[0]);
+			if (context_read_and_validate(&amp;newc-&gt;context[0], p, fp))
+				goto bad;
+			for (l = NULL, c = newgenfs-&gt;head; c;
+			     l = c, c = c-&gt;next) {
+				if (!strcmp(newc-&gt;u.name, c-&gt;u.name) &amp;&amp;
+				    (!c-&gt;v.sclass || !newc-&gt;v.sclass ||
+				     newc-&gt;v.sclass == c-&gt;v.sclass)) {
+					printk(KERN_ERR "security:  dup genfs "
+					       "entry (%s,%s)\n",
+					       newgenfs-&gt;fstype, c-&gt;u.name);
+					goto bad;
+				}
+				len = strlen(newc-&gt;u.name);
+				len2 = strlen(c-&gt;u.name);
+				if (len &gt; len2)
+					break;
+			}
+			newc-&gt;next = c;
+			if (l)
+				l-&gt;next = newc;
+			else
+				newgenfs-&gt;head = newc;
+		}
+	}
+
+	rc = mls_read_trusted(p, fp);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	policydb_destroy(p);
+	goto out;
+}
diff -puN /dev/null security/selinux/ss/policydb.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/policydb.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,256 @@
+/*
+ * A policy database (policydb) specifies the
+ * configuration data for the security policy.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_POLICYDB_H_
+#define _SS_POLICYDB_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 */
+struct perm_datum {
+	u32 value;		/* permission bit + 1 */
+#ifdef CONFIG_SECURITY_SELINUX_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' */
+	u32 base_perms;		/* MLS base permission mask */
+#endif
+};
+
+/* Attributes of a common prefix for access vectors */
+struct common_datum {
+	u32 value;			/* internal common value */
+	struct symtab permissions;	/* common permissions */
+};
+
+/* Class attributes */
+struct class_datum {
+	u32 value;			/* class value */
+	char *comkey;			/* common name */
+	struct common_datum *comdatum;	/* common datum */
+	struct symtab permissions;	/* class-specific permission symbol table */
+	struct constraint_node *constraints;	/* constraints on class permissions */
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+	struct mls_perms mlsperms;	/* MLS base permission masks */
+#endif
+};
+
+/* Role attributes */
+struct role_datum {
+	u32 value;			/* internal role value */
+	struct ebitmap dominates;	/* set of roles dominated by this role */
+	struct ebitmap types;		/* set of authorized types for role */
+};
+
+struct role_trans {
+	u32 role;		/* current role */
+	u32 type;		/* program executable type */
+	u32 new_role;		/* new role */
+	struct role_trans *next;
+};
+
+struct role_allow {
+	u32 role;		/* current role */
+	u32 new_role;		/* new role */
+	struct role_allow *next;
+};
+
+/* Type attributes */
+struct type_datum {
+	u32 value;		/* internal type value */
+	unsigned char primary;	/* primary name? */
+};
+
+/* User attributes */
+struct user_datum {
+	u32 value;			/* internal user value */
+	struct ebitmap roles;		/* set of authorized roles for user */
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+	struct mls_range_list *ranges;	/* list of authorized MLS ranges for user */
+#endif
+};
+
+
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+/* Sensitivity attributes */
+struct level_datum {
+	struct mls_level *level;	/* sensitivity and associated categories */
+	unsigned char isalias;	/* is this sensitivity an alias for another? */
+};
+
+/* Category attributes */
+struct cat_datum {
+	u32 value;		/* internal category bit + 1 */
+	unsigned char isalias;  /* is this category an alias for another? */
+};
+#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.
+ */
+struct ocontext {
+	union {
+		char *name;	/* name of initial SID, fs, netif, fstype, path */
+		struct {
+			u8 protocol;
+			u16 low_port;
+			u16 high_port;
+		} port;		/* TCP or UDP port information */
+		struct {
+			u32 addr;
+			u32 mask;
+		} node;		/* node information */
+	} u;
+	union {
+		u32 sclass;  /* security class for genfs */
+		u32 behavior;  /* labeling behavior for fs_use */
+	} v;
+	struct context context[2];	/* security context(s) */
+	u32 sid[2];	/* SID(s) */
+	struct ocontext *next;
+};
+
+struct genfs {
+	char *fstype;
+	struct ocontext *head;
+	struct genfs *next;
+};
+
+/* 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_SECURITY_SELINUX_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 */
+struct policydb {
+	/* symbol tables */
+	struct symtab 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) */
+	struct class_datum **class_val_to_struct;
+	struct role_datum **role_val_to_struct;
+	struct user_datum **user_val_to_struct;
+
+	/* type enforcement access vectors and transitions */
+	struct avtab te_avtab;
+
+	/* role transitions */
+	struct role_trans *role_tr;
+
+	/* role allows */
+	struct role_allow *role_allow;
+
+	/* security contexts of initial SIDs, unlabeled file systems,
+	   TCP or UDP port numbers, network interfaces and nodes */
+	struct ocontext *ocontexts[OCON_NUM];
+
+        /* security contexts for files in filesystems that cannot support
+	   a persistent label mapping or use another
+	   fixed labeling behavior. */
+  	struct genfs *genfs;
+
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+	/* number of legitimate MLS levels */
+	u32 nlevels;
+
+	struct ebitmap trustedreaders;
+	struct ebitmap trustedwriters;
+	struct ebitmap trustedobjects;
+#endif
+};
+
+extern int policydb_init(struct policydb *p);
+extern int policydb_index_classes(struct policydb *p);
+extern int policydb_index_others(struct policydb *p);
+extern int constraint_expr_destroy(struct constraint_expr *expr);
+extern void policydb_destroy(struct policydb *p);
+extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
+extern int policydb_context_isvalid(struct policydb *p, struct context *c);
+extern int policydb_read(struct policydb *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 SELINUX_MAGIC
+#define POLICYDB_STRING "SE Linux"
+
+struct policy_file {
+	char *data;
+	size_t len;
+};
+
+static inline void *next_entry(struct policy_file *fp, size_t bytes)
+{
+	void *buf;
+
+	if (bytes &gt; fp-&gt;len)
+		return NULL;
+
+	buf = fp-&gt;data;
+	fp-&gt;data += bytes;
+	fp-&gt;len -= bytes;
+	return buf;
+}
+
+#endif	/* _SS_POLICYDB_H_ */
+
diff -puN /dev/null security/selinux/ss/services.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/services.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,1413 @@
+/*
+ * Implementation of the security services.
+ *
+ * Authors : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ *           James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *  Copyright (C) 2003 Red Hat, Inc., James Morris &lt;jmorris@redhat.com&gt;
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2,
+ *      as published by the Free Software Foundation.
+ */
+#include "context.h"
+#include "policydb.h"
+#include "sidtab.h"
+#include "services.h"
+#include "mls.h"
+
+static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED;
+#define POLICY_RDLOCK read_lock(&amp;policy_rwlock)
+#define POLICY_WRLOCK write_lock_irq(&amp;policy_rwlock)
+#define POLICY_RDUNLOCK read_unlock(&amp;policy_rwlock)
+#define POLICY_WRUNLOCK write_unlock_irq(&amp;policy_rwlock)
+
+static DECLARE_MUTEX(load_sem);
+#define LOAD_LOCK down(&amp;load_sem)
+#define LOAD_UNLOCK up(&amp;load_sem)
+
+struct sidtab sidtab;
+struct policydb 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 u32 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(struct context *scontext,
+				struct context *tcontext,
+				struct constraint_expr *cexpr)
+{
+	u32 val1, val2;
+	struct context *c;
+	struct role_datum *r1, *r2;
+	struct constraint_expr *e;
+	int s[CEXPR_MAXDEPTH];
+	int sp = -1;
+
+	for (e = cexpr; e; e = e-&gt;next) {
+		switch (e-&gt;expr_type) {
+		case CEXPR_NOT:
+			BUG_ON(sp &lt; 0);
+			s[sp] = !s[sp];
+			break;
+		case CEXPR_AND:
+			BUG_ON(sp &lt; 1);
+			sp--;
+			s[sp] &amp;= s[sp+1];
+			break;
+		case CEXPR_OR:
+			BUG_ON(sp &lt; 1);
+			sp--;
+			s[sp] |= s[sp+1];
+			break;
+		case CEXPR_ATTR:
+			if (sp == (CEXPR_MAXDEPTH-1))
+				return 0;
+			switch (e-&gt;attr) {
+			case CEXPR_USER:
+				val1 = scontext-&gt;user;
+				val2 = tcontext-&gt;user;
+				break;
+			case CEXPR_TYPE:
+				val1 = scontext-&gt;type;
+				val2 = tcontext-&gt;type;
+				break;
+			case CEXPR_ROLE:
+				val1 = scontext-&gt;role;
+				val2 = tcontext-&gt;role;
+				r1 = policydb.role_val_to_struct[val1 - 1];
+				r2 = policydb.role_val_to_struct[val2 - 1];
+				switch (e-&gt;op) {
+				case CEXPR_DOM:
+					s[++sp] = ebitmap_get_bit(&amp;r1-&gt;dominates,
+								  val2 - 1);
+					continue;
+				case CEXPR_DOMBY:
+					s[++sp] = ebitmap_get_bit(&amp;r2-&gt;dominates,
+								  val1 - 1);
+					continue;
+				case CEXPR_INCOMP:
+					s[++sp] = ( !ebitmap_get_bit(&amp;r1-&gt;dominates,
+								     val2 - 1) &amp;&amp;
+						    !ebitmap_get_bit(&amp;r2-&gt;dominates,
+								     val1 - 1) );
+					continue;
+				default:
+					break;
+				}
+				break;
+			default:
+				BUG();
+				return 0;
+			}
+
+			switch (e-&gt;op) {
+			case CEXPR_EQ:
+				s[++sp] = (val1 == val2);
+				break;
+			case CEXPR_NEQ:
+				s[++sp] = (val1 != val2);
+				break;
+			default:
+				BUG();
+				return 0;
+			}
+			break;
+		case CEXPR_NAMES:
+			if (sp == (CEXPR_MAXDEPTH-1))
+				return 0;
+			c = scontext;
+			if (e-&gt;attr &amp; CEXPR_TARGET)
+				c = tcontext;
+			if (e-&gt;attr &amp; CEXPR_USER)
+				val1 = c-&gt;user;
+			else if (e-&gt;attr &amp; CEXPR_ROLE)
+				val1 = c-&gt;role;
+			else if (e-&gt;attr &amp; CEXPR_TYPE)
+				val1 = c-&gt;type;
+			else {
+				BUG();
+				return 0;
+			}
+
+			switch (e-&gt;op) {
+			case CEXPR_EQ:
+				s[++sp] = ebitmap_get_bit(&amp;e-&gt;names, val1 - 1);
+				break;
+			case CEXPR_NEQ:
+				s[++sp] = !ebitmap_get_bit(&amp;e-&gt;names, val1 - 1);
+				break;
+			default:
+				BUG();
+				return 0;
+			}
+			break;
+		default:
+			BUG();
+			return 0;
+		}
+	}
+
+	BUG_ON(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(struct context *scontext,
+				     struct context *tcontext,
+				     u16 tclass,
+				     u32 requested,
+				     struct av_decision *avd)
+{
+	struct constraint_node *constraint;
+	struct role_allow *ra;
+	struct avtab_key avkey;
+	struct avtab_datum *avdatum;
+	struct class_datum *tclass_datum;
+
+	if (!tclass || tclass &gt; policydb.p_classes.nprim) {
+		printk(KERN_ERR "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-&gt;allowed = 0;
+	avd-&gt;decided = 0xffffffff;
+	avd-&gt;auditallow = 0;
+	avd-&gt;auditdeny = 0xffffffff;
+	avd-&gt;seqno = latest_granting;
+
+	/*
+	 * If a specific type enforcement rule was defined for
+	 * this permission check, then use it.
+	 */
+	avkey.source_type = scontext-&gt;type;
+	avkey.target_type = tcontext-&gt;type;
+	avkey.target_class = tclass;
+	avdatum = avtab_search(&amp;policydb.te_avtab, &amp;avkey, AVTAB_AV);
+	if (avdatum) {
+		if (avdatum-&gt;specified &amp; AVTAB_ALLOWED)
+			avd-&gt;allowed = avtab_allowed(avdatum);
+		if (avdatum-&gt;specified &amp; AVTAB_AUDITDENY)
+			avd-&gt;auditdeny = avtab_auditdeny(avdatum);
+		if (avdatum-&gt;specified &amp; AVTAB_AUDITALLOW)
+			avd-&gt;auditallow = avtab_auditallow(avdatum);
+	}
+
+	/*
+	 * Remove any permissions prohibited by the MLS policy.
+	 */
+	mls_compute_av(scontext, tcontext, tclass_datum, &amp;avd-&gt;allowed);
+
+	/*
+	 * Remove any permissions prohibited by a constraint.
+	 */
+	constraint = tclass_datum-&gt;constraints;
+	while (constraint) {
+		if ((constraint-&gt;permissions &amp; (avd-&gt;allowed)) &amp;&amp;
+		    !constraint_expr_eval(scontext, tcontext,
+					  constraint-&gt;expr)) {
+			avd-&gt;allowed = (avd-&gt;allowed) &amp; ~(constraint-&gt;permissions);
+		}
+		constraint = constraint-&gt;next;
+	}
+
+	/*
+	 * If checking process transition permission and the
+	 * role is changing, then check the (current_role, new_role)
+	 * pair.
+	 */
+	if (tclass == SECCLASS_PROCESS &amp;&amp;
+	    avd-&gt;allowed &amp;&amp; PROCESS__TRANSITION &amp;&amp;
+	    scontext-&gt;role != tcontext-&gt;role) {
+		for (ra = policydb.role_allow; ra; ra = ra-&gt;next) {
+			if (scontext-&gt;role == ra-&gt;role &amp;&amp;
+			    tcontext-&gt;role == ra-&gt;new_role)
+				break;
+		}
+		if (!ra)
+			avd-&gt;allowed = (avd-&gt;allowed) &amp; ~(PROCESS__TRANSITION);
+	}
+
+	return 0;
+}
+
+/**
+ * security_compute_av - Compute access vector decisions.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions
+ * @avd: access vector decisions
+ *
+ * Compute a set of access vector decisions based on the
+ * SID pair (@ssid, @tsid) for the permissions in @tclass.
+ * Return -%EINVAL if any of the parameters are invalid or %0
+ * if the access vector decisions were computed successfully.
+ */
+int security_compute_av(u32 ssid,
+			u32 tsid,
+			u16 tclass,
+			u32 requested,
+			struct av_decision *avd)
+{
+	struct context *scontext = 0, *tcontext = 0;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		avd-&gt;allowed = requested;
+		avd-&gt;decided = requested;
+		avd-&gt;auditallow = 0;
+		avd-&gt;auditdeny = 0xffffffff;
+		avd-&gt;seqno = latest_granting;
+		return 0;
+	}
+
+	POLICY_RDLOCK;
+
+	scontext = sidtab_search(&amp;sidtab, ssid);
+	if (!scontext) {
+		printk(KERN_ERR "security_compute_av:  unrecognized SID %d\n",
+		       ssid);
+		rc = -EINVAL;
+		goto out;
+	}
+	tcontext = sidtab_search(&amp;sidtab, tsid);
+	if (!tcontext) {
+		printk(KERN_ERR "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.
+ */
+int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
+{
+	char *scontextp;
+
+	*scontext = 0;
+	*scontext_len = 0;
+
+	/* Compute the size of the context. */
+	*scontext_len += strlen(policydb.p_user_val_to_name[context-&gt;user - 1]) + 1;
+	*scontext_len += strlen(policydb.p_role_val_to_name[context-&gt;role - 1]) + 1;
+	*scontext_len += strlen(policydb.p_type_val_to_name[context-&gt;type - 1]) + 1;
+	*scontext_len += mls_compute_context_len(context);
+
+	/* Allocate space for the context; caller must free this space. */
+	scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC);
+	if (!scontextp) {
+		return -ENOMEM;
+	}
+	*scontext = scontextp;
+
+	/*
+	 * Copy the user name, role name and type name into the context.
+	 */
+	sprintf(scontextp, "%s:%s:%s:",
+		policydb.p_user_val_to_name[context-&gt;user - 1],
+		policydb.p_role_val_to_name[context-&gt;role - 1],
+		policydb.p_type_val_to_name[context-&gt;type - 1]);
+	scontextp += strlen(policydb.p_user_val_to_name[context-&gt;user - 1]) +
+	             1 + strlen(policydb.p_role_val_to_name[context-&gt;role - 1]) +
+	             1 + strlen(policydb.p_type_val_to_name[context-&gt;type - 1]) + 1;
+
+	mls_sid_to_context(context, &amp;scontextp);
+
+	scontextp--;
+	*scontextp = 0;
+
+	return 0;
+}
+
+#include "initial_sid_to_string.h"
+
+/**
+ * security_sid_to_context - Obtain a context for a given SID.
+ * @sid: security identifier, SID
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ *
+ * Write the 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(u32 sid, char **scontext, u32 *scontext_len)
+{
+	struct context *context;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		if (sid &lt;= SECINITSID_NUM) {
+			char *scontextp;
+
+			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+			scontextp = kmalloc(*scontext_len,GFP_KERNEL);
+			strcpy(scontextp, initial_sid_to_string[sid]);
+			*scontext = scontextp;
+			goto out;
+		}
+		printk(KERN_ERR "security_sid_to_context:  called before initial "
+		       "load_policy on unknown SID %d\n", sid);
+		rc = -EINVAL;
+		goto out;
+	}
+	POLICY_RDLOCK;
+	context = sidtab_search(&amp;sidtab, sid);
+	if (!context) {
+		printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
+		       "%d\n", sid);
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+	rc = context_struct_to_string(context, scontext, scontext_len);
+out_unlock:
+	POLICY_RDUNLOCK;
+out:
+	return rc;
+
+}
+
+/**
+ * security_context_to_sid - Obtain a SID for a given security context.
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ * @sid: security identifier, SID
+ *
+ * Obtains a SID associated with the security context that
+ * has the string representation specified by @scontext.
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+{
+	char *scontext2;
+	struct context context;
+	struct role_datum *role;
+	struct type_datum *typdatum;
+	struct user_datum *usrdatum;
+	char *scontextp, *p, oldc;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		int i;
+
+		for (i = 1; i &lt; SECINITSID_NUM; i++) {
+			if (!strcmp(initial_sid_to_string[i], scontext)) {
+				*sid = i;
+				goto out;
+			}
+		}
+		printk(KERN_ERR "security_context_to_sid: called before "
+		       "initial load_policy on unknown context %s\n", scontext);
+		rc = -EINVAL;
+		goto out;
+	}
+	*sid = SECSID_NULL;
+
+	/* Copy the string so that we can modify the copy as we parse it.
+	   The string should already by null terminated, but we append a
+	   null suffix to the copy to avoid problems with the existing
+	   attr package, which doesn't view the null terminator as part
+	   of the attribute value. */
+	scontext2 = kmalloc(scontext_len+1,GFP_KERNEL);
+	if (!scontext2) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memcpy(scontext2, scontext, scontext_len);
+	scontext2[scontext_len] = 0;
+
+	context_init(&amp;context);
+	*sid = SECSID_NULL;
+
+	POLICY_RDLOCK;
+
+	/* Parse the security context. */
+
+	rc = -EINVAL;
+	scontextp = (char *) scontext2;
+
+	/* Extract the user. */
+	p = scontextp;
+	while (*p &amp;&amp; *p != ':')
+		p++;
+
+	if (*p == 0)
+		goto out_unlock;
+
+	*p++ = 0;
+
+	usrdatum = hashtab_search(policydb.p_users.table, scontextp);
+	if (!usrdatum)
+		goto out_unlock;
+
+	context.user = usrdatum-&gt;value;
+
+	/* Extract role. */
+	scontextp = p;
+	while (*p &amp;&amp; *p != ':')
+		p++;
+
+	if (*p == 0)
+		goto out_unlock;
+
+	*p++ = 0;
+
+	role = hashtab_search(policydb.p_roles.table, scontextp);
+	if (!role)
+		goto out_unlock;
+	context.role = role-&gt;value;
+
+	/* Extract type. */
+	scontextp = p;
+	while (*p &amp;&amp; *p != ':')
+		p++;
+	oldc = *p;
+	*p++ = 0;
+
+	typdatum = hashtab_search(policydb.p_types.table, scontextp);
+	if (!typdatum)
+		goto out_unlock;
+
+	context.type = typdatum-&gt;value;
+
+	rc = mls_context_to_sid(oldc, &amp;p, &amp;context);
+	if (rc)
+		goto out_unlock;
+
+	/* Check the validity of the new context. */
+	if (!policydb_context_isvalid(&amp;policydb, &amp;context)) {
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+	/* Obtain the new sid. */
+	rc = sidtab_context_to_sid(&amp;sidtab, &amp;context, sid);
+out_unlock:
+	POLICY_RDUNLOCK;
+	context_destroy(&amp;context);
+	kfree(scontext2);
+out:
+	return rc;
+}
+
+static inline int compute_sid_handle_invalid_context(
+	struct context *scontext,
+	struct context *tcontext,
+	u16 tclass,
+	struct context *newcontext)
+{
+	int rc = 0;
+
+	if (selinux_enforcing) {
+		rc = -EACCES;
+	} else {
+		char *s, *t, *n;
+		u32 slen, tlen, nlen;
+
+		context_struct_to_string(scontext, &amp;s, &amp;slen);
+		context_struct_to_string(tcontext, &amp;t, &amp;tlen);
+		context_struct_to_string(newcontext, &amp;n, &amp;nlen);
+		printk(KERN_ERR "security_compute_sid:  invalid context %s", n);
+		printk(" for scontext=%s", s);
+		printk(" tcontext=%s", t);
+		printk(" tclass=%s\n", policydb.p_class_val_to_name[tclass-1]);
+		kfree(s);
+		kfree(t);
+		kfree(n);
+	}
+	return rc;
+}
+
+static int security_compute_sid(u32 ssid,
+				u32 tsid,
+				u16 tclass,
+				u32 specified,
+				u32 *out_sid)
+{
+	struct context *scontext = 0, *tcontext = 0, newcontext;
+	struct role_trans *roletr = 0;
+	struct avtab_key avkey;
+	struct avtab_datum *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;
+		}
+		goto out;
+	}
+
+	POLICY_RDLOCK;
+
+	scontext = sidtab_search(&amp;sidtab, ssid);
+	if (!scontext) {
+		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
+		       ssid);
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+	tcontext = sidtab_search(&amp;sidtab, tsid);
+	if (!tcontext) {
+		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
+		       tsid);
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+
+	context_init(&amp;newcontext);
+
+	/* Set the user identity. */
+	switch (specified) {
+	case AVTAB_TRANSITION:
+	case AVTAB_CHANGE:
+		/* Use the process user identity. */
+		newcontext.user = scontext-&gt;user;
+		break;
+	case AVTAB_MEMBER:
+		/* Use the related object owner. */
+		newcontext.user = tcontext-&gt;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-&gt;role;
+		newcontext.type = scontext-&gt;type;
+		break;
+	default:
+		/* Use the well-defined object role. */
+		newcontext.role = OBJECT_R_VAL;
+		/* Use the type of the related object. */
+		newcontext.type = tcontext-&gt;type;
+	}
+
+	/* Look for a type transition/member/change rule. */
+	avkey.source_type = scontext-&gt;type;
+	avkey.target_type = tcontext-&gt;type;
+	avkey.target_class = tclass;
+	avdatum = avtab_search(&amp;policydb.te_avtab, &amp;avkey, AVTAB_TYPE);
+	type_change = (avdatum &amp;&amp; (avdatum-&gt;specified &amp; 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 &amp; AVTAB_TRANSITION) {
+			/* Look for a role transition rule. */
+			for (roletr = policydb.role_tr; roletr;
+			     roletr = roletr-&gt;next) {
+				if (roletr-&gt;role == scontext-&gt;role &amp;&amp;
+				    roletr-&gt;type == tcontext-&gt;type) {
+					/* Use the role transition rule. */
+					newcontext.role = roletr-&gt;new_role;
+					break;
+				}
+			}
+		}
+
+		if (!type_change &amp;&amp; !roletr) {
+			/* No change in process role or type. */
+			*out_sid = ssid;
+			goto out_unlock;
+
+		}
+		break;
+	default:
+		if (!type_change &amp;&amp;
+		    (newcontext.user == tcontext-&gt;user) &amp;&amp;
+		    mls_context_cmp(scontext, tcontext)) {
+                        /* No change in object type, owner,
+			   or MLS attributes. */
+			*out_sid = tsid;
+			goto out_unlock;
+		}
+		break;
+	}
+
+	/* Set the MLS attributes.
+	   This is done last because it may allocate memory. */
+	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &amp;newcontext);
+	if (rc)
+		goto out_unlock;
+
+	/* Check the validity of the context. */
+	if (!policydb_context_isvalid(&amp;policydb, &amp;newcontext)) {
+		rc = compute_sid_handle_invalid_context(scontext,
+							tcontext,
+							tclass,
+							&amp;newcontext);
+		if (rc)
+			goto out_unlock;
+	}
+	/* Obtain the sid for the context. */
+	rc = sidtab_context_to_sid(&amp;sidtab, &amp;newcontext, out_sid);
+out_unlock:
+	POLICY_RDUNLOCK;
+	context_destroy(&amp;newcontext);
+out:
+	return rc;
+}
+
+/**
+ * security_transition_sid - Compute the SID for a new subject/object.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @out_sid: security identifier for new subject/object
+ *
+ * Compute a SID to use for labeling a new subject or object in the
+ * class @tclass based on a SID pair (@ssid, @tsid).
+ * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
+ * if insufficient memory is available, or %0 if the new SID was
+ * computed successfully.
+ */
+int security_transition_sid(u32 ssid,
+			    u32 tsid,
+			    u16 tclass,
+			    u32 *out_sid)
+{
+	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
+}
+
+/**
+ * security_member_sid - Compute the SID for member selection.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @out_sid: security identifier for selected member
+ *
+ * Compute a SID to use when selecting a member of a polyinstantiated
+ * object of class @tclass based on a SID pair (@ssid, @tsid).
+ * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
+ * if insufficient memory is available, or %0 if the SID was
+ * computed successfully.
+ */
+int security_member_sid(u32 ssid,
+			u32 tsid,
+			u16 tclass,
+			u32 *out_sid)
+{
+	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
+}
+
+/**
+ * security_change_sid - Compute the SID for object relabeling.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @out_sid: security identifier for selected member
+ *
+ * Compute a SID to use for relabeling an object of class @tclass
+ * based on a SID pair (@ssid, @tsid).
+ * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
+ * if insufficient memory is available, or %0 if the SID was
+ * computed successfully.
+ */
+int security_change_sid(u32 ssid,
+			u32 tsid,
+			u16 tclass,
+			u32 *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(void *key, void *datum, void *p)
+{
+	struct hashtab *h;
+	struct perm_datum *perdatum, *perdatum2;
+	int rc = 0;
+
+
+	h = p;
+	perdatum = datum;
+
+	perdatum2 = hashtab_search(h, key);
+	if (!perdatum2) {
+		printk(KERN_ERR "security:  permission %s disappeared",
+		       (char *)key);
+		rc = -ENOENT;
+		goto out;
+	}
+	if (perdatum-&gt;value != perdatum2-&gt;value) {
+		printk(KERN_ERR "security:  the value of permission %s changed",
+		       (char *)key);
+		rc = -EINVAL;
+	}
+out:
+	return rc;
+}
+
+/*
+ * 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(void *key, void *datum, void *p)
+{
+	struct policydb *newp;
+	struct class_datum *cladatum, *cladatum2;
+	int rc;
+
+	newp = p;
+	cladatum = datum;
+
+	cladatum2 = hashtab_search(newp-&gt;p_classes.table, key);
+	if (!cladatum2) {
+		printk(KERN_ERR "security:  class %s disappeared\n",
+		       (char *)key);
+		rc = -ENOENT;
+		goto out;
+	}
+	if (cladatum-&gt;value != cladatum2-&gt;value) {
+		printk(KERN_ERR "security:  the value of class %s changed\n",
+		       (char *)key);
+		rc = -EINVAL;
+		goto out;
+	}
+	if ((cladatum-&gt;comdatum &amp;&amp; !cladatum2-&gt;comdatum) ||
+	    (!cladatum-&gt;comdatum &amp;&amp; cladatum2-&gt;comdatum)) {
+		printk(KERN_ERR "security:  the inherits clause for the access "
+		       "vector definition for class %s changed\n", (char *)key);
+		rc = -EINVAL;
+		goto out;
+	}
+	if (cladatum-&gt;comdatum) {
+		rc = hashtab_map(cladatum-&gt;comdatum-&gt;permissions.table, validate_perm,
+		                 cladatum2-&gt;comdatum-&gt;permissions.table);
+		if (rc) {
+			printk(" in the access vector definition for class "
+			       "%s\n", (char *)key);
+			goto out;
+		}
+	}
+	rc = hashtab_map(cladatum-&gt;permissions.table, validate_perm,
+	                 cladatum2-&gt;permissions.table);
+	if (rc)
+		printk(" in access vector definition for class %s\n",
+		       (char *)key);
+out:
+	return rc;
+}
+
+/* Clone the SID into the new SID table. */
+static int clone_sid(u32 sid,
+		     struct context *context,
+		     void *arg)
+{
+	struct sidtab *s = arg;
+
+	return sidtab_insert(s, sid, context);
+}
+
+static inline int convert_context_handle_invalid_context(struct context *context)
+{
+	int rc = 0;
+
+	if (selinux_enforcing) {
+		rc = -EINVAL;
+	} else {
+		char *s;
+		u32 len;
+
+		context_struct_to_string(context, &amp;s, &amp;len);
+		printk(KERN_ERR "security:  context %s is invalid\n", s);
+		kfree(s);
+	}
+	return rc;
+}
+
+struct convert_context_args {
+	struct policydb *oldp;
+	struct policydb *newp;
+};
+
+/*
+ * Convert the values in the security context
+ * structure `c' from the values specified
+ * in the policy `p-&gt;oldp' to the values specified
+ * in the policy `p-&gt;newp'.  Verify that the
+ * context is valid under the new policy.
+ */
+static int convert_context(u32 key,
+			   struct context *c,
+			   void *p)
+{
+	struct convert_context_args *args;
+	struct context oldc;
+	struct role_datum *role;
+	struct type_datum *typdatum;
+	struct user_datum *usrdatum;
+	char *s;
+	u32 len;
+	int rc = -EINVAL;
+
+	args = p;
+
+	rc = context_cpy(&amp;oldc, c);
+	if (rc)
+		goto out;
+
+	/* Convert the user. */
+	usrdatum = hashtab_search(args-&gt;newp-&gt;p_users.table,
+	                          args-&gt;oldp-&gt;p_user_val_to_name[c-&gt;user - 1]);
+	if (!usrdatum) {
+		goto bad;
+	}
+	c-&gt;user = usrdatum-&gt;value;
+
+	/* Convert the role. */
+	role = hashtab_search(args-&gt;newp-&gt;p_roles.table,
+	                      args-&gt;oldp-&gt;p_role_val_to_name[c-&gt;role - 1]);
+	if (!role) {
+		goto bad;
+	}
+	c-&gt;role = role-&gt;value;
+
+	/* Convert the type. */
+	typdatum = hashtab_search(args-&gt;newp-&gt;p_types.table,
+	                          args-&gt;oldp-&gt;p_type_val_to_name[c-&gt;type - 1]);
+	if (!typdatum) {
+		goto bad;
+	}
+	c-&gt;type = typdatum-&gt;value;
+
+	rc = mls_convert_context(args-&gt;oldp, args-&gt;newp, c);
+	if (rc)
+		goto bad;
+
+	/* Check the validity of the new context. */
+	if (!policydb_context_isvalid(args-&gt;newp, c)) {
+		rc = convert_context_handle_invalid_context(&amp;oldc);
+		if (rc)
+			goto bad;
+	}
+
+	context_destroy(&amp;oldc);
+out:
+	return rc;
+bad:
+	context_struct_to_string(&amp;oldc, &amp;s, &amp;len);
+	context_destroy(&amp;oldc);
+	printk(KERN_ERR "security:  invalidating context %s\n", s);
+	kfree(s);
+	goto out;
+}
+
+extern void selinux_complete_init(void);
+
+/**
+ * security_load_policy - Load a security policy configuration.
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ * Load a new set of security policy configuration data,
+ * validate it and convert the SID table as necessary.
+ * This function will flush the access vector cache after
+ * loading the new policy.
+ */
+int security_load_policy(void *data, size_t len)
+{
+	struct policydb oldpolicydb, newpolicydb;
+	struct sidtab oldsidtab, newsidtab;
+	struct convert_context_args args;
+	u32 seqno;
+	int rc = 0;
+	struct policy_file file = { data, len }, *fp = &amp;file;
+
+	LOAD_LOCK;
+
+	if (!ss_initialized) {
+		if (policydb_read(&amp;policydb, fp)) {
+			LOAD_UNLOCK;
+			return -EINVAL;
+		}
+		if (policydb_load_isids(&amp;policydb, &amp;sidtab)) {
+			LOAD_UNLOCK;
+			policydb_destroy(&amp;policydb);
+			return -EINVAL;
+		}
+		ss_initialized = 1;
+		LOAD_UNLOCK;
+		selinux_complete_init();
+		return 0;
+	}
+
+#if 0
+	sidtab_hash_eval(&amp;sidtab, "sids");
+#endif
+
+	if (policydb_read(&amp;newpolicydb, fp)) {
+		LOAD_UNLOCK;
+		return -EINVAL;
+	}
+
+	sidtab_init(&amp;newsidtab);
+
+	/* Verify that the existing classes did not change. */
+	if (hashtab_map(policydb.p_classes.table, validate_class, &amp;newpolicydb)) {
+		printk(KERN_ERR "security:  the definition of an existing "
+		       "class changed\n");
+		rc = -EINVAL;
+		goto err;
+	}
+
+	/* Clone the SID table. */
+	sidtab_shutdown(&amp;sidtab);
+	if (sidtab_map(&amp;sidtab, clone_sid, &amp;newsidtab)) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	/* Convert the internal representations of contexts
+	   in the new SID table and remove invalid SIDs. */
+	args.oldp = &amp;policydb;
+	args.newp = &amp;newpolicydb;
+	sidtab_map_remove_on_error(&amp;newsidtab, convert_context, &amp;args);
+
+	/* Save the old policydb and SID table to free later. */
+	memcpy(&amp;oldpolicydb, &amp;policydb, sizeof policydb);
+	sidtab_set(&amp;oldsidtab, &amp;sidtab);
+
+	/* Install the new policydb and SID table. */
+	POLICY_WRLOCK;
+	memcpy(&amp;policydb, &amp;newpolicydb, sizeof policydb);
+	sidtab_set(&amp;sidtab, &amp;newsidtab);
+	seqno = ++latest_granting;
+	POLICY_WRUNLOCK;
+	LOAD_UNLOCK;
+
+	/* Free the old policydb and SID table. */
+	policydb_destroy(&amp;oldpolicydb);
+	sidtab_destroy(&amp;oldsidtab);
+
+	avc_ss_reset(seqno);
+
+	return 0;
+
+err:
+	LOAD_UNLOCK;
+	sidtab_destroy(&amp;newsidtab);
+	policydb_destroy(&amp;newpolicydb);
+	return rc;
+
+}
+
+/**
+ * security_port_sid - Obtain the SID for a port.
+ * @domain: communication domain aka address family
+ * @type: socket type
+ * @protocol: protocol number
+ * @port: port number
+ * @out_sid: security identifier
+ */
+int security_port_sid(u16 domain,
+		      u16 type,
+		      u8 protocol,
+		      u16 port,
+		      u32 *out_sid)
+{
+	struct ocontext *c;
+	int rc = 0;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_PORT];
+	while (c) {
+		if (c-&gt;u.port.protocol == protocol &amp;&amp;
+		    c-&gt;u.port.low_port &lt;= port &amp;&amp;
+		    c-&gt;u.port.high_port &gt;= port)
+			break;
+		c = c-&gt;next;
+	}
+
+	if (c) {
+		if (!c-&gt;sid[0]) {
+			rc = sidtab_context_to_sid(&amp;sidtab,
+						   &amp;c-&gt;context[0],
+						   &amp;c-&gt;sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c-&gt;sid[0];
+	} else {
+		*out_sid = SECINITSID_PORT;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+/**
+ * security_netif_sid - Obtain the SID for a network interface.
+ * @name: interface name
+ * @if_sid: interface SID
+ * @msg_sid: default SID for received packets
+ */
+int security_netif_sid(char *name,
+		       u32 *if_sid,
+		       u32 *msg_sid)
+{
+	int rc = 0;
+	struct ocontext *c;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_NETIF];
+	while (c) {
+		if (strcmp(name, c-&gt;u.name) == 0)
+			break;
+		c = c-&gt;next;
+	}
+
+	if (c) {
+		if (!c-&gt;sid[0] || !c-&gt;sid[1]) {
+			rc = sidtab_context_to_sid(&amp;sidtab,
+						  &amp;c-&gt;context[0],
+						  &amp;c-&gt;sid[0]);
+			if (rc)
+				goto out;
+			rc = sidtab_context_to_sid(&amp;sidtab,
+						   &amp;c-&gt;context[1],
+						   &amp;c-&gt;sid[1]);
+			if (rc)
+				goto out;
+		}
+		*if_sid = c-&gt;sid[0];
+		*msg_sid = c-&gt;sid[1];
+	} else {
+		*if_sid = SECINITSID_NETIF;
+		*msg_sid = SECINITSID_NETMSG;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+
+/**
+ * security_node_sid - Obtain the SID for a node (host).
+ * @domain: communication domain aka address family
+ * @addrp: address
+ * @addrlen: address length in bytes
+ * @out_sid: security identifier
+ */
+int security_node_sid(u16 domain,
+		      void *addrp,
+		      u32 addrlen,
+		      u32 *out_sid)
+{
+	int rc = 0;
+	u32 addr;
+	struct ocontext *c;
+
+	POLICY_RDLOCK;
+
+	if (domain != AF_INET || addrlen != sizeof(u32)) {
+		*out_sid = SECINITSID_NODE;
+		goto out;
+	}
+	addr = *((u32 *)addrp);
+
+	c = policydb.ocontexts[OCON_NODE];
+	while (c) {
+		if (c-&gt;u.node.addr == (addr &amp; c-&gt;u.node.mask))
+			break;
+		c = c-&gt;next;
+	}
+
+	if (c) {
+		if (!c-&gt;sid[0]) {
+			rc = sidtab_context_to_sid(&amp;sidtab,
+						   &amp;c-&gt;context[0],
+						   &amp;c-&gt;sid[0]);
+			if (rc)
+				goto out;
+		}
+		*out_sid = c-&gt;sid[0];
+	} else {
+		*out_sid = SECINITSID_NODE;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+#define SIDS_NEL 25
+
+/**
+ * security_get_user_sids - Obtain reachable SIDs for a user.
+ * @fromsid: starting SID
+ * @username: username
+ * @sids: array of reachable SIDs for user
+ * @nel: number of elements in @sids
+ *
+ * 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(u32 fromsid,
+	                   char *username,
+			   u32 **sids,
+			   u32 *nel)
+{
+	struct context *fromcon, usercon;
+	u32 *mysids, *mysids2, sid;
+	u32 mynel = 0, maxnel = SIDS_NEL;
+	struct user_datum *user;
+	struct role_datum *role;
+	struct av_decision avd;
+	int rc = 0, i, j;
+
+	if (!ss_initialized) {
+		*sids = NULL;
+		*nel = 0;
+		goto out;
+	}
+
+	POLICY_RDLOCK;
+
+	fromcon = sidtab_search(&amp;sidtab, fromsid);
+	if (!fromcon) {
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+
+	user = hashtab_search(policydb.p_users.table, username);
+	if (!user) {
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+	usercon.user = user-&gt;value;
+
+	mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC);
+	if (!mysids) {
+		rc = -ENOMEM;
+		goto out_unlock;
+	}
+	memset(mysids, 0, maxnel*sizeof(*mysids));
+
+	for (i = ebitmap_startbit(&amp;user-&gt;roles); i &lt; ebitmap_length(&amp;user-&gt;roles); i++) {
+		if (!ebitmap_get_bit(&amp;user-&gt;roles, i))
+			continue;
+		role = policydb.role_val_to_struct[i];
+		usercon.role = i+1;
+		for (j = ebitmap_startbit(&amp;role-&gt;types); j &lt; ebitmap_length(&amp;role-&gt;types); j++) {
+			if (!ebitmap_get_bit(&amp;role-&gt;types, j))
+				continue;
+			usercon.type = j+1;
+			if (usercon.type == fromcon-&gt;type)
+				continue;
+			mls_for_user_ranges(user,usercon) {
+				rc = context_struct_compute_av(fromcon, &amp;usercon,
+							       SECCLASS_PROCESS,
+							       PROCESS__TRANSITION,
+							       &amp;avd);
+				if (rc ||  !(avd.allowed &amp; PROCESS__TRANSITION))
+					continue;
+				rc = sidtab_context_to_sid(&amp;sidtab, &amp;usercon, &amp;sid);
+				if (rc) {
+					kfree(mysids);
+					goto out_unlock;
+				}
+				if (mynel &lt; maxnel) {
+					mysids[mynel++] = sid;
+				} else {
+					maxnel += SIDS_NEL;
+					mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
+					if (!mysids2) {
+						rc = -ENOMEM;
+						kfree(mysids);
+						goto out_unlock;
+					}
+					memset(mysids2, 0, maxnel*sizeof(*mysids2));
+					memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
+					kfree(mysids);
+					mysids = mysids2;
+					mysids[mynel++] = sid;
+				}
+			}
+			mls_end_user_ranges;
+		}
+	}
+
+	*sids = mysids;
+	*nel = mynel;
+
+out_unlock:
+	POLICY_RDUNLOCK;
+out:
+	return rc;
+}
+
+/**
+ * security_genfs_sid - Obtain a SID for a file in a filesystem
+ * @fstype: filesystem type
+ * @path: path from root of mount
+ * @sclass: file security class
+ * @sid: SID for path
+ *
+ * Obtain a SID to use for a file in a filesystem that
+ * cannot support xattr or use a fixed labeling behavior like
+ * transition SIDs or task SIDs.
+ */
+int security_genfs_sid(const char *fstype,
+	               char *path,
+		       u16 sclass,
+		       u32 *sid)
+{
+	int len;
+	struct genfs *genfs;
+	struct ocontext *c;
+	int rc = 0, cmp = 0;
+
+	POLICY_RDLOCK;
+
+	for (genfs = policydb.genfs; genfs; genfs = genfs-&gt;next) {
+		cmp = strcmp(fstype, genfs-&gt;fstype);
+		if (cmp &lt;= 0)
+			break;
+	}
+
+	if (!genfs || cmp) {
+		*sid = SECINITSID_UNLABELED;
+		rc = -ENOENT;
+		goto out;
+	}
+
+	for (c = genfs-&gt;head; c; c = c-&gt;next) {
+		len = strlen(c-&gt;u.name);
+		if ((!c-&gt;v.sclass || sclass == c-&gt;v.sclass) &amp;&amp;
+		    (strncmp(c-&gt;u.name, path, len) == 0))
+			break;
+	}
+
+	if (!c) {
+		*sid = SECINITSID_UNLABELED;
+		rc = -ENOENT;
+		goto out;
+	}
+
+	if (!c-&gt;sid[0]) {
+		rc = sidtab_context_to_sid(&amp;sidtab,
+					   &amp;c-&gt;context[0],
+					   &amp;c-&gt;sid[0]);
+		if (rc)
+			goto out;
+	}
+
+	*sid = c-&gt;sid[0];
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+/**
+ * security_fs_use - Determine how to handle labeling for a filesystem.
+ * @fstype: filesystem type
+ * @behavior: labeling behavior
+ * @sid: SID for filesystem (superblock)
+ */
+int security_fs_use(
+	const char *fstype,
+	unsigned int *behavior,
+	u32 *sid)
+{
+	int rc = 0;
+	struct ocontext *c;
+
+	POLICY_RDLOCK;
+
+	c = policydb.ocontexts[OCON_FSUSE];
+	while (c) {
+		if (strcmp(fstype, c-&gt;u.name) == 0)
+			break;
+		c = c-&gt;next;
+	}
+
+	if (c) {
+		*behavior = c-&gt;v.behavior;
+		if (!c-&gt;sid[0]) {
+			rc = sidtab_context_to_sid(&amp;sidtab,
+						   &amp;c-&gt;context[0],
+						   &amp;c-&gt;sid[0]);
+			if (rc)
+				goto out;
+		}
+		*sid = c-&gt;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;
+}
diff -puN /dev/null security/selinux/ss/services.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/services.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,21 @@
+/*
+ * Implementation of the security services.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_SERVICES_H_
+#define _SS_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 struct sidtab sidtab;
+extern struct policydb policydb;
+
+#endif	/* _SS_SERVICES_H_ */
+
diff -puN /dev/null security/selinux/ss/sidtab.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/sidtab.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,329 @@
+/*
+ * Implementation of the SID table type.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "sidtab.h"
+
+#define SIDTAB_HASH(sid) \
+(sid &amp; SIDTAB_HASH_MASK)
+
+#define INIT_SIDTAB_LOCK(s) spin_lock_init(&amp;s-&gt;lock)
+#define SIDTAB_LOCK(s) spin_lock_irq(&amp;s-&gt;lock)
+#define SIDTAB_UNLOCK(s) spin_unlock_irq(&amp;s-&gt;lock)
+
+int sidtab_init(struct sidtab *s)
+{
+	int i;
+
+	s-&gt;htable = kmalloc(sizeof(*(s-&gt;htable)) * SIDTAB_SIZE, GFP_ATOMIC);
+	if (!s-&gt;htable)
+		return -ENOMEM;
+	for (i = 0; i &lt; SIDTAB_SIZE; i++)
+		s-&gt;htable[i] = NULL;
+	s-&gt;nel = 0;
+	s-&gt;next_sid = 1;
+	s-&gt;shutdown = 0;
+	INIT_SIDTAB_LOCK(s);
+	return 0;
+}
+
+int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
+{
+	int hvalue, rc = 0;
+	struct sidtab_node *prev, *cur, *newnode;
+
+	if (!s) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	hvalue = SIDTAB_HASH(sid);
+	prev = NULL;
+	cur = s-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; sid &gt; cur-&gt;sid) {
+		prev = cur;
+		cur = cur-&gt;next;
+	}
+
+	if (cur &amp;&amp; sid == cur-&gt;sid) {
+		rc = -EEXIST;
+		goto out;
+	}
+
+	newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC);
+	if (newnode == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	newnode-&gt;sid = sid;
+	if (context_cpy(&amp;newnode-&gt;context, context)) {
+		kfree(newnode);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	if (prev) {
+		newnode-&gt;next = prev-&gt;next;
+		wmb();
+		prev-&gt;next = newnode;
+	} else {
+		newnode-&gt;next = s-&gt;htable[hvalue];
+		wmb();
+		s-&gt;htable[hvalue] = newnode;
+	}
+
+	s-&gt;nel++;
+	if (sid &gt;= s-&gt;next_sid)
+		s-&gt;next_sid = sid + 1;
+out:
+	return rc;
+}
+
+int sidtab_remove(struct sidtab *s, u32 sid)
+{
+	int hvalue, rc = 0;
+	struct sidtab_node *cur, *last;
+
+	if (!s) {
+		rc = -ENOENT;
+		goto out;
+	}
+
+	hvalue = SIDTAB_HASH(sid);
+	last = NULL;
+	cur = s-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; sid &gt; cur-&gt;sid) {
+		last = cur;
+		cur = cur-&gt;next;
+	}
+
+	if (cur == NULL || sid != cur-&gt;sid) {
+		rc = -ENOENT;
+		goto out;
+	}
+
+	if (last == NULL)
+		s-&gt;htable[hvalue] = cur-&gt;next;
+	else
+		last-&gt;next = cur-&gt;next;
+
+	context_destroy(&amp;cur-&gt;context);
+
+	kfree(cur);
+	s-&gt;nel--;
+out:
+	return rc;
+}
+
+struct context *sidtab_search(struct sidtab *s, u32 sid)
+{
+	int hvalue;
+	struct sidtab_node *cur;
+
+	if (!s)
+		return NULL;
+
+	hvalue = SIDTAB_HASH(sid);
+	cur = s-&gt;htable[hvalue];
+	while (cur != NULL &amp;&amp; sid &gt; cur-&gt;sid)
+		cur = cur-&gt;next;
+
+	if (cur == NULL || sid != cur-&gt;sid) {
+		/* Remap invalid SIDs to the unlabeled SID. */
+		sid = SECINITSID_UNLABELED;
+		hvalue = SIDTAB_HASH(sid);
+		cur = s-&gt;htable[hvalue];
+		while (cur != NULL &amp;&amp; sid &gt; cur-&gt;sid)
+			cur = cur-&gt;next;
+		if (!cur || sid != cur-&gt;sid)
+			return NULL;
+	}
+
+	return &amp;cur-&gt;context;
+}
+
+int sidtab_map(struct sidtab *s,
+	       int (*apply) (u32 sid,
+			     struct context *context,
+			     void *args),
+	       void *args)
+{
+	int i, rc = 0;
+	struct sidtab_node *cur;
+
+	if (!s)
+		goto out;
+
+	for (i = 0; i &lt; SIDTAB_SIZE; i++) {
+		cur = s-&gt;htable[i];
+		while (cur != NULL) {
+			rc = apply(cur-&gt;sid, &amp;cur-&gt;context, args);
+			if (rc)
+				goto out;
+			cur = cur-&gt;next;
+		}
+	}
+out:
+	return rc;
+}
+
+void sidtab_map_remove_on_error(struct sidtab *s,
+				int (*apply) (u32 sid,
+					      struct context *context,
+					      void *args),
+				void *args)
+{
+	int i, ret;
+	struct sidtab_node *last, *cur, *temp;
+
+	if (!s)
+		return;
+
+	for (i = 0; i &lt; SIDTAB_SIZE; i++) {
+		last = NULL;
+		cur = s-&gt;htable[i];
+		while (cur != NULL) {
+			ret = apply(cur-&gt;sid, &amp;cur-&gt;context, args);
+			if (ret) {
+				if (last) {
+					last-&gt;next = cur-&gt;next;
+				} else {
+					s-&gt;htable[i] = cur-&gt;next;
+				}
+
+				temp = cur;
+				cur = cur-&gt;next;
+				context_destroy(&amp;temp-&gt;context);
+				kfree(temp);
+				s-&gt;nel--;
+			} else {
+				last = cur;
+				cur = cur-&gt;next;
+			}
+		}
+	}
+
+	return;
+}
+
+static inline u32 sidtab_search_context(struct sidtab *s,
+						  struct context *context)
+{
+	int i;
+	struct sidtab_node *cur;
+
+	for (i = 0; i &lt; SIDTAB_SIZE; i++) {
+		cur = s-&gt;htable[i];
+		while (cur != NULL) {
+			if (context_cmp(&amp;cur-&gt;context, context))
+				return cur-&gt;sid;
+			cur = cur-&gt;next;
+		}
+	}
+	return 0;
+}
+
+int sidtab_context_to_sid(struct sidtab *s,
+			  struct context *context,
+			  u32 *out_sid)
+{
+	u32 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-&gt;next_sid == UINT_MAX || s-&gt;shutdown) {
+			ret = -ENOMEM;
+			goto unlock_out;
+		}
+		sid = s-&gt;next_sid++;
+		ret = sidtab_insert(s, sid, context);
+		if (ret)
+			s-&gt;next_sid--;
+unlock_out:
+		SIDTAB_UNLOCK(s);
+	}
+
+	if (ret)
+		return ret;
+
+	*out_sid = sid;
+	return 0;
+}
+
+void sidtab_hash_eval(struct sidtab *h, char *tag)
+{
+	int i, chain_len, slots_used, max_chain_len;
+	struct sidtab_node *cur;
+
+	slots_used = 0;
+	max_chain_len = 0;
+	for (i = 0; i &lt; SIDTAB_SIZE; i++) {
+		cur = h-&gt;htable[i];
+		if (cur) {
+			slots_used++;
+			chain_len = 0;
+			while (cur) {
+				chain_len++;
+				cur = cur-&gt;next;
+			}
+
+			if (chain_len &gt; max_chain_len)
+				max_chain_len = chain_len;
+		}
+	}
+
+	printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
+	       "chain length %d\n", tag, h-&gt;nel, slots_used, SIDTAB_SIZE,
+	       max_chain_len);
+}
+
+void sidtab_destroy(struct sidtab *s)
+{
+	int i;
+	struct sidtab_node *cur, *temp;
+
+	if (!s)
+		return;
+
+	for (i = 0; i &lt; SIDTAB_SIZE; i++) {
+		cur = s-&gt;htable[i];
+		while (cur != NULL) {
+			temp = cur;
+			cur = cur-&gt;next;
+			context_destroy(&amp;temp-&gt;context);
+			kfree(temp);
+		}
+		s-&gt;htable[i] = NULL;
+	}
+	kfree(s-&gt;htable);
+	s-&gt;htable = NULL;
+	s-&gt;nel = 0;
+	s-&gt;next_sid = 1;
+}
+
+void sidtab_set(struct sidtab *dst, struct sidtab *src)
+{
+	SIDTAB_LOCK(src);
+	dst-&gt;htable = src-&gt;htable;
+	dst-&gt;nel = src-&gt;nel;
+	dst-&gt;next_sid = src-&gt;next_sid;
+	dst-&gt;shutdown = 0;
+	SIDTAB_UNLOCK(src);
+}
+
+void sidtab_shutdown(struct sidtab *s)
+{
+	SIDTAB_LOCK(s);
+	s-&gt;shutdown = 1;
+	SIDTAB_UNLOCK(s);
+}
diff -puN /dev/null security/selinux/ss/sidtab.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/sidtab.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,59 @@
+/*
+ * A security identifier table (sidtab) is a hash table
+ * of security context structures indexed by SID value.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_SIDTAB_H_
+#define _SS_SIDTAB_H_
+
+#include "context.h"
+
+struct sidtab_node {
+	u32 sid;		/* security identifier */
+	struct context context;	/* security context structure */
+	struct sidtab_node *next;
+};
+
+#define SIDTAB_HASH_BITS 7
+#define SIDTAB_HASH_BUCKETS (1 &lt;&lt; SIDTAB_HASH_BITS)
+#define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1)
+
+#define SIDTAB_SIZE SIDTAB_HASH_BUCKETS
+
+struct sidtab {
+	struct sidtab_node **htable;
+	unsigned int nel;	/* number of elements */
+	unsigned int next_sid;	/* next SID to allocate */
+	unsigned char shutdown;
+	spinlock_t lock;
+};
+
+int sidtab_init(struct sidtab *s);
+int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
+struct context *sidtab_search(struct sidtab *s, u32 sid);
+
+int sidtab_map(struct sidtab *s,
+	       int (*apply) (u32 sid,
+			     struct context *context,
+			     void *args),
+	       void *args);
+
+void sidtab_map_remove_on_error(struct sidtab *s,
+				int (*apply) (u32 sid,
+					      struct context *context,
+					      void *args),
+				void *args);
+
+int sidtab_context_to_sid(struct sidtab *s,
+			  struct context *context,
+			  u32 *sid);
+
+void sidtab_hash_eval(struct sidtab *h, char *tag);
+void sidtab_destroy(struct sidtab *s);
+void sidtab_set(struct sidtab *dst, struct sidtab *src);
+void sidtab_shutdown(struct sidtab *s);
+
+#endif	/* _SS_SIDTAB_H_ */
+
+
diff -puN /dev/null security/selinux/ss/symtab.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/symtab.c	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,40 @@
+/*
+ * Implementation of the symbol table type.
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#include "symtab.h"
+
+static unsigned int symhash(struct hashtab *h, void *key)
+{
+	char *p, *keyp;
+	unsigned int size;
+	unsigned int val;
+
+	val = 0;
+	keyp = key;
+	size = strlen(keyp);
+	for (p = keyp; (p - keyp) &lt; size; p++)
+		val = (val &lt;&lt; 4 | (val &gt;&gt; (8*sizeof(unsigned int)-4))) ^ (*p);
+	return val &amp; (h-&gt;size - 1);
+}
+
+static int symcmp(struct hashtab *h, void *key1, void *key2)
+{
+	char *keyp1, *keyp2;
+
+	keyp1 = key1;
+	keyp2 = key2;
+	return strcmp(keyp1, keyp2);
+}
+
+
+int symtab_init(struct symtab *s, unsigned int size)
+{
+	s-&gt;table = hashtab_create(symhash, symcmp, size);
+	if (!s-&gt;table)
+		return -1;
+	s-&gt;nprim = 0;
+	return 0;
+}
+
diff -puN /dev/null security/selinux/ss/symtab.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/security/selinux/ss/symtab.h	Thu Jul 17 09:38:01 2003
@@ -0,0 +1,23 @@
+/*
+ * 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).
+ *
+ * Author : Stephen Smalley, &lt;sds@epoch.ncsc.mil&gt;
+ */
+#ifndef _SS_SYMTAB_H_
+#define _SS_SYMTAB_H_
+
+#include "hashtab.h"
+
+struct symtab {
+	struct hashtab *table;	/* hash table (keyed on a string) */
+	u32 nprim;		/* number of primary names in table */
+};
+
+int symtab_init(struct symtab *s, unsigned int size);
+
+#endif	/* _SS_SYMTAB_H_ */
+
+

_
</pre></body></html>