changeset 7890:da5be6cc4191 fmac_alpha3

fmac-gate merge before push
author John Weeks <john.weeks@sun.com>
date Wed, 29 Oct 2008 11:52:47 -0700
parents a5fda081c83b (current diff) dc5a88b1d093 (diff)
children 15405b8c3bd3
files
diffstat 22 files changed, 473 insertions(+), 439 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libcmdutils/common/process_xattrs.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/lib/libcmdutils/common/process_xattrs.c	Wed Oct 29 11:52:47 2008 -0700
@@ -286,15 +286,16 @@
 		    cmd, fname);
 		return (NULL);
 	}
-	pair = NULL;
-	while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
+	pair = nvlist_next_nvpair(response, NULL);
+	while (pair != NULL) {
+		nvpair_t *next = nvlist_next_nvpair(response, pair);
 
 		name = nvpair_name(pair);
 
 		if (name != NULL)
 			fattr = name_to_attr(name);
 		else
-			return (response);
+			goto next;
 
 		type = nvpair_type(pair);
 		switch (type) {
@@ -305,22 +306,33 @@
 					    dgettext(TEXT_DOMAIN, "%s "
 					    "nvpair_value_boolean_value "
 					    "failed\n"), cmd);
-					continue;
+					goto next;
 				}
 				if (value && fattr != F_ARCHIVE &&
 				    fattr != F_AV_MODIFIED)
-					return (response);
+					goto next;
 				break;
 			case DATA_TYPE_UINT64_ARRAY:
 				if (fattr != F_CRTIME)
-					return (response);
+					goto next;
 				break;
 			case DATA_TYPE_NVLIST:
 			default:
-				return (response);
-				break;
+				goto next;
 		}
+
+		/* Remove any default attributes. */
+		(void) nvlist_remove(response, name, type);
+
+next:
+		pair = next;
 	}
+
+	/* If non-empty, return the response. */
+	pair = nvlist_next_nvpair(response, NULL);
+	if (pair)
+		return (response);
+
 	if (response != NULL)
 		nvlist_free(response);
 	return (NULL);
--- a/usr/src/uts/common/contract/process.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/contract/process.c	Wed Oct 29 11:52:47 2008 -0700
@@ -492,7 +492,7 @@
 	cankill = hasprocperm(tp->p_cred, ctp->conp_cred, PROCESS__SIGKILL);
 	mutex_exit(&tp->p_crlock);
 	if (cankill || (sp && prochasprocperm(tp, sp, CRED(),
-			    PROCESS__SIGKILL)))
+	    PROCESS__SIGKILL)))
 		return (1);
 
 	return (0);
--- a/usr/src/uts/common/disp/class.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/disp/class.c	Wed Oct 29 11:52:47 2008 -0700
@@ -261,7 +261,7 @@
 		 * Check basic permissions.
 		 */
 		if (!prochasprocperm(targpp, reqpp, reqpcredp,
-			PROCESS__SETSCHED)) {
+		    PROCESS__SETSCHED)) {
 			crfree(reqpcredp);
 			return (EPERM);
 		}
--- a/usr/src/uts/common/fmac/avc.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fmac/avc.c	Wed Oct 29 11:52:47 2008 -0700
@@ -49,6 +49,8 @@
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
 #include <sys/systm.h>
+#include <sys/kstat.h>
+#include <sys/atomic.h>
 #include <sys/note.h>
 #include <sys/fmac/fmac.h>
 #include <sys/fmac/avc.h>
@@ -58,7 +60,19 @@
 #include <sys/fmac/av_inherit.h>
 #include <sys/fmac/av_perm_to_string.h>
 
-static kmutex_t avc_lock;
+static krwlock_t avc_lock;
+static kmutex_t avc_audit_lock;
+
+/*
+ * An entry in the AVC.
+ */
+typedef struct avc_entry {
+	security_id_t		ssid;
+	security_id_t		tsid;
+	security_class_t	tclass;
+	struct av_decision	avd;
+	int			used;	 /* used recently */
+} avc_entry_t;
 
 typedef struct avc_node {
 	struct avc_entry ae;
@@ -85,39 +99,30 @@
 
 static char *avc_audit_buffer = NULL;
 
-unsigned avc_cache_stats[AVC_NSTATS];
-
-#ifdef AVC_CACHE_STATS
-#define	avc_cache_stats_incr(x) avc_cache_stats[(x)]++
-#define	avc_cache_stats_add(x, y) avc_cache_stats[(x)] += (y)
-#else
-#define	avc_cache_stats_incr(x)
-#define	avc_cache_stats_add(x, y)
-#endif /* AVC_CACHE_STATS */
-
 /*
- * Display the cache statistics
+ * AVC statistics
  */
-void
-avc_dump_stats(char *tag)
-{
-	printf("%s avc:  entry:  %d lookups == %d hits + %d misses "
-	    "(%d discards)\n",
-	    tag, avc_cache_stats[AVC_ENTRY_LOOKUPS],
-	    avc_cache_stats[AVC_ENTRY_HITS], avc_cache_stats[AVC_ENTRY_MISSES],
-	    avc_cache_stats[AVC_ENTRY_DISCARDS]);
+static struct {
+	kstat_named_t avclookups;
+	kstat_named_t avchits;
+	kstat_named_t avcprobes;
+	kstat_named_t avcmisses;
+} avcstats = {
+	{ "avclookups", KSTAT_DATA_UINT64 },
+	{ "avchits", KSTAT_DATA_UINT64 },
+	{ "avcprobes", KSTAT_DATA_UINT64 },
+	{ "avcmisses", KSTAT_DATA_UINT64 }
+};
 
-	printf("%s avc:  cav:  %d lookups == %d hits + %d misses\n",
-	    tag, avc_cache_stats[AVC_CAV_LOOKUPS],
-	    avc_cache_stats[AVC_CAV_HITS], avc_cache_stats[AVC_CAV_MISSES]);
+kstat_named_t *avcstats_ptr = (kstat_named_t *)&avcstats;
+uint_t avcstats_ndata = sizeof (avcstats) / sizeof (kstat_named_t);
 
-	printf("%s avc:  cav:  %d/%d probe/hit ratio\n",
-	    tag, avc_cache_stats[AVC_CAV_PROBES],
-	    avc_cache_stats[AVC_CAV_HITS]);
-}
+#define	avc_cache_stats_incr(stat) atomic_inc_64(&avcstats.stat.value.ui64)
+#define	avc_cache_stats_add(stat, x) atomic_add_64(&avcstats.stat.value.ui64, x)
 
 static void avc_audit_start(void)
 {
+	mutex_enter(&avc_audit_lock);
 	(void) memset(avc_audit_buffer, 0, PAGESIZE);
 }
 
@@ -136,12 +141,13 @@
 static void avc_audit_end(void)
 {
 	(void) printf("%s\n", avc_audit_buffer);
+	mutex_exit(&avc_audit_lock);
 }
 
 /*
  * Display an access vector in human-readable form.
  */
-void
+static void
 avc_dump_av(security_class_t tclass, access_vector_t av)
 {
 	char		**common_pts = 0;
@@ -182,7 +188,7 @@
 			}
 			if (i2 < AV_PERM_TO_STRING_SIZE)
 				avc_audit_append(" %s",
-					av_perm_to_string[i2].name);
+				    av_perm_to_string[i2].name);
 		}
 		i++;
 		perm <<= 1;
@@ -194,7 +200,7 @@
 /*
  * Display a SID pair and a class in human-readable form.
  */
-void
+static void
 avc_dump_query(
 	security_id_t ssid,		/* IN */
 	security_id_t tsid,		/* IN */
@@ -228,14 +234,23 @@
 void
 avc_init(void)
 {
+	kstat_t *ksp;
 	avc_node_t	*new;
 	int		i;
 
 	if (!fmac_enabled)
 		return;
 
-	for (i = 0; i < AVC_NSTATS; i++)
-		avc_cache_stats[i] = 0;
+	rw_init(&avc_lock, NULL, RW_DEFAULT, NULL);
+	mutex_init(&avc_audit_lock, NULL, MUTEX_DEFAULT, NULL);
+
+	ksp = kstat_create("avc", 0, "avcstats", "misc", KSTAT_TYPE_NAMED,
+	    avcstats_ndata, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
+
+	if (ksp) {
+		ksp->ks_data = avcstats_ptr;
+		kstat_install(ksp);
+	}
 
 	for (i = 0; i < AVC_CACHE_SLOTS; i++)
 		avc_cache.slots[i] = 0;
@@ -244,7 +259,7 @@
 	avc_cache.latest_notif = 0;
 
 	for (i = 0; i < AVC_CACHE_MAXNODES; i++) {
-		new = (avc_node_t *) kmem_zalloc(sizeof (avc_node_t), KM_SLEEP);
+		new = (avc_node_t *)kmem_zalloc(sizeof (avc_node_t), KM_SLEEP);
 		if (!new) {
 			cmn_err(CE_WARN,
 			    "avc:  only able to allocate %d entries\n", i);
@@ -271,7 +286,7 @@
 	int		slots_used;
 	avc_node_t	*node;
 
-	mutex_enter(&avc_lock);
+	rw_enter(&avc_lock, RW_READER);
 
 	slots_used = 0;
 	max_chain_len = 0;
@@ -289,7 +304,7 @@
 		}
 	}
 
-	mutex_exit(&avc_lock);
+	rw_exit(&avc_lock);
 
 	printf("\n%s avc:  %d entries and %d/%d buckets used, longest "
 	    "chain length %d\n",
@@ -312,8 +327,6 @@
 	int		slots_used;
 	avc_node_t	*node;
 
-	avc_dump_stats(tag);
-
 	slots_used = 0;
 	max_chain_len = 0;
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
@@ -463,32 +476,31 @@
  * `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
+ * then this function copies the av_decision into `avd'
+ * and returns 0. Otherwise, this function
  * returns ENOENT.
  */
-int
-avc_lookup(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested,	/* IN */
-	avc_entry_ref_t *aeref)	/* OUT */
+static int
+avc_lookup(security_id_t ssid, security_id_t tsid, security_class_t tclass,
+    access_vector_t requested, struct av_decision *avd)
 {
 	avc_node_t	*node;
 	int		probes;
 
-	avc_cache_stats_incr(AVC_CAV_LOOKUPS);
+	avc_cache_stats_incr(avclookups);
+
+	rw_enter(&avc_lock, RW_READER);
 	node = avc_search_node(ssid, tsid, tclass, &probes);
-
 	if (node && ((node->ae.avd.decided & requested) == requested)) {
-		avc_cache_stats_incr(AVC_CAV_HITS);
-		avc_cache_stats_add(AVC_CAV_PROBES, probes);
-		aeref->ae = &node->ae;
+		(void) memcpy(avd, &node->ae.avd, sizeof (*avd));
+		rw_exit(&avc_lock);
+		avc_cache_stats_incr(avchits);
+		avc_cache_stats_add(avcprobes, probes);
 		return (0);
 	}
+	rw_exit(&avc_lock);
 
-	avc_cache_stats_incr(AVC_CAV_MISSES);
+	avc_cache_stats_incr(avcmisses);
 	return (ENOENT);
 }
 
@@ -504,54 +516,43 @@
  * `aeref' to refer to the entry, and returns 0.
  * Otherwise, this function returns EAGAIN.
  */
-int
-avc_insert(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	struct avc_entry *ae,		/* IN */
-	avc_entry_ref_t *aeref)		/* OUT */
+static int
+avc_insert(security_id_t ssid, security_id_t tsid, security_class_t tclass,
+    struct av_decision *avd)
 {
 	avc_node_t	*node;
 
-	if (ae->avd.seqno < avc_cache.latest_notif) {
-		printf("avc:  seqno %d < latest_notif %d\n", ae->avd.seqno,
+	rw_enter(&avc_lock, RW_WRITER);
+	if (avd->seqno < avc_cache.latest_notif) {
+		printf("avc:  seqno %d < latest_notif %d\n", avd->seqno,
 		    avc_cache.latest_notif);
+		rw_exit(&avc_lock);
 		return (EAGAIN);
 	}
 
 	node = avc_claim_node(ssid, tsid, tclass);
 	if (!node) {
+		rw_exit(&avc_lock);
 		return (ENOMEM);
 	}
 
-	node->ae.avd.allowed = ae->avd.allowed;
-	node->ae.avd.decided = ae->avd.decided;
-	node->ae.avd.auditallow = ae->avd.auditallow;
-	node->ae.avd.auditdeny = ae->avd.auditdeny;
-	node->ae.avd.seqno = ae->avd.seqno;
-	aeref->ae = &node->ae;
+	(void) memcpy(&node->ae.avd, avd, sizeof (*avd));
+	rw_exit(&avc_lock);
 	return (0);
 }
 
 /*
  * Audit the granting or denial of permissions.
  */
-void
-avc_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t audited,	/* IN */
-	struct avc_entry *ae,		/* IN */
-	uint32_t denied,		/* IN */
-	avc_audit_data_t *a)		/* IN */
+#define	AVC_AUDITALLOW	0
+#define	AVC_AUDITDENY	1
+static void
+avc_audit(security_id_t ssid, security_id_t tsid, security_class_t tclass,
+    access_vector_t audited, uint32_t denied, avc_audit_data_t *a)
 {
 	struct proc *p = curproc;
 	struct vnode *vp;
 
-	_NOTE(ARGUNUSED(ae));
-
 	if (a && a->type == AVC_AUDIT_DATA_DONTAUDIT)
 		return;
 
@@ -608,7 +609,7 @@
 {
 	avc_callback_node_t *c;
 
-	c = (avc_callback_node_t *) kmem_alloc(sizeof (avc_callback_node_t),
+	c = (avc_callback_node_t *)kmem_alloc(sizeof (avc_callback_node_t),
 	    KM_SLEEP);
 
 	c->callback = callback;
@@ -664,17 +665,13 @@
  * `perms'.
  */
 static int
-avc_update_cache(
-	uint32_t event, 		/* IN */
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t perms)		/* IN */
+avc_update_cache(uint32_t event, security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, access_vector_t perms)
 {
 	avc_node_t	*node;
 	int		i;
 
-	mutex_enter(&avc_lock);
+	rw_enter(&avc_lock, RW_WRITER);
 
 	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
 		/* apply to all matching nodes */
@@ -696,7 +693,7 @@
 		}
 	}
 
-	mutex_exit(&avc_lock);
+	rw_exit(&avc_lock);
 
 	return (0);
 }
@@ -754,10 +751,10 @@
 		*out_retained = tretained;
 	}
 
-	mutex_enter(&avc_lock);
+	rw_enter(&avc_lock, RW_WRITER);
 	if (seqno > avc_cache.latest_notif)
 		avc_cache.latest_notif = seqno;
-	mutex_exit(&avc_lock);
+	rw_exit(&avc_lock);
 
 	return (0);
 }
@@ -823,7 +820,7 @@
 
 	avc_hash_eval("reset");
 
-	mutex_enter(&avc_lock);
+	rw_enter(&avc_lock, RW_WRITER);
 
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
 		node = avc_cache.slots[i];
@@ -843,24 +840,21 @@
 	}
 	avc_cache.lru_hint = 0;
 
-	mutex_exit(&avc_lock);
-
-	for (i = 0; i < AVC_NSTATS; i++)
-		avc_cache_stats[i] = 0;
+	rw_exit(&avc_lock);
 
 	for (c = avc_callbacks; c; c = c->next) {
 		if (c->events & AVC_CALLBACK_RESET) {
 			rc = c->callback(AVC_CALLBACK_RESET,
-				0, 0, 0, 0, 0);
+			    0, 0, 0, 0, 0);
 			if (rc)
 				return (rc);
 		}
 	}
 
-	mutex_enter(&avc_lock);
+	rw_enter(&avc_lock, RW_WRITER);
 	if (seqno > avc_cache.latest_notif)
 		avc_cache.latest_notif = seqno;
-	mutex_exit(&avc_lock);
+	rw_exit(&avc_lock);
 
 	return (0);
 }
@@ -877,10 +871,10 @@
 {
 	if (enable)
 		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
-			ssid, tsid, tclass, perms, seqno, 0);
+		    ssid, tsid, tclass, perms, seqno, 0);
 	else
 		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
-			ssid, tsid, tclass, perms, seqno, 0);
+		    ssid, tsid, tclass, perms, seqno, 0);
 }
 
 /* Enable or disable auditing of denied permissions */
@@ -895,107 +889,69 @@
 {
 	if (enable)
 		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
-			ssid, tsid, tclass, perms, seqno, 0);
+		    ssid, tsid, tclass, perms, seqno, 0);
 	else
 		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
-			ssid, tsid, tclass, perms, seqno, 0);
+		    ssid, tsid, tclass, perms, seqno, 0);
 }
 
 /*
- * Check permissions using an AVC entry ref.
- *
- * If the ref is null or the underlying AVC entry has been invalidated
- * or the underlying AVC entry does not contain all the requested
- * decisions, then this code falls through to avc_lookup.  In
- * this case, the AVC entry ref will be updated appropriately.
+ * Compute an entire access vector.
  */
 int
-avc_has_perm_ref_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested,	/* IN */
-	avc_entry_ref_t *aeref,		/* IN */
-	avc_audit_data_t *auditdata)	/* IN */
+avc_compute_av(security_id_t ssid, security_id_t tsid, security_class_t tclass,
+    access_vector_t requested, struct av_decision *avd)
 {
-	struct avc_entry	*ae;
 	int			rc;
-	struct avc_entry	entry;
-	access_vector_t		denied;
 
 	if (!fmac_enabled)
 		return (0);
 
-	mutex_enter(&avc_lock);
-	avc_cache_stats_incr(AVC_ENTRY_LOOKUPS);
-	ae = aeref->ae;
-	if (ae) {
-		if (ae->ssid == ssid &&
-		    ae->tsid == tsid &&
-		    ae->tclass == tclass &&
-		    ((ae->avd.decided & requested) == requested)) {
-			avc_cache_stats_incr(AVC_ENTRY_HITS);
-			ae->used = 1;
-		} else {
-			avc_cache_stats_incr(AVC_ENTRY_DISCARDS);
-			ae = 0;
-		}
+	rc = avc_lookup(ssid, tsid, tclass, requested, avd);
+	if (rc) {
+		rc = security_compute_av(ssid, tsid, tclass, requested, avd);
+		if (rc)
+			return (rc);
+		rc = avc_insert(ssid, tsid, tclass, avd);
+		if (rc)
+			return (rc);
 	}
 
-	if (!ae) {
-		avc_cache_stats_incr(AVC_ENTRY_MISSES);
-		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
-		if (rc) {
-			mutex_exit(&avc_lock);
-			rc = security_compute_av(ssid, tsid, tclass, requested,
-			    &entry.avd);
-			if (rc)
-				return (rc);
-			mutex_enter(&avc_lock);
-			rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
-			if (rc) {
-				mutex_exit(&avc_lock);
-				return (rc);
-			}
-		}
-		ae = aeref->ae;
-	}
+	return (0);
+}
+
+int
+avc_has_perm(security_id_t ssid, security_id_t tsid, security_class_t tclass,
+    access_vector_t requested, avc_audit_data_t *auditdata)
+{
+	struct av_decision avd;
+	access_vector_t	denied;
+	int rc;
 
-	denied = requested & ~(ae->avd.allowed);
+	ASSERT(requested);
+
+	rc = avc_compute_av(ssid, tsid, tclass, requested, &avd);
+	if (rc)
+		return (rc);
 
-	if (!requested || denied) {
-		if (!requested || (denied & ae->avd.auditdeny))
-			avc_audit(ssid, tsid, tclass, denied, ae, AVC_AUDITDENY,
+	denied = requested & ~avd.allowed;
+
+	if (denied) {
+		if (denied & avd.auditdeny)
+			avc_audit(ssid, tsid, tclass, denied, AVC_AUDITDENY,
 			    auditdata);
 		if (fmac_enforcing) {
-			mutex_exit(&avc_lock);
 			return (EACCES);
 		} else {
-			ae->avd.allowed |= requested;
-			mutex_exit(&avc_lock);
+			(void) avc_update_cache(AVC_CALLBACK_GRANT, ssid, tsid,
+			    tclass, requested);
 			return (0);
 		}
 	}
 
-	if (requested & ae->avd.auditallow)
-		avc_audit(ssid, tsid, tclass, requested, ae, AVC_AUDITALLOW,
+	if (requested & avd.auditallow)
+		avc_audit(ssid, tsid, tclass, requested, AVC_AUDITALLOW,
 		    auditdata);
 
-	mutex_exit(&avc_lock);
 	return (0);
 }
-
-/* Check permissions */
-int
-avc_has_perm_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested, 	/* IN */
-	avc_audit_data_t *auditdata)	/* IN */
-{
-	avc_entry_ref_t ref;
-	AVC_ENTRY_REF_INIT(&ref);
-	return (avc_has_perm_ref_audit(ssid, tsid, tclass, requested, &ref,
-	    auditdata));
-}
--- a/usr/src/uts/common/fmac/fmac.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fmac/fmac.c	Wed Oct 29 11:52:47 2008 -0700
@@ -35,6 +35,7 @@
 #include <sys/param.h>
 #include <sys/kobj.h>
 #include <sys/vfs.h>
+#include <sys/acl.h>
 #include <sys/fmac/security.h>
 #include <sys/fmac/fmac.h>
 #include <sys/fmac/avc.h>
@@ -174,6 +175,8 @@
 		return (0);
 	if (vp->v_secid != SECINITSID_UNLABELED)
 		return (0); /* already set */
+	if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0)
+		return (0);
 
 	xva_init(&xvattr);
 	if ((xoap = xva_getxoptattr(&xvattr)) == NULL)
@@ -186,7 +189,7 @@
 
 	if (XVA_ISSET_RTN(&xvattr, XAT_SECCTX)) {
 		error = security_context_to_sid(xoap->xoa_secctx,
-			strlen(xoap->xoa_secctx), &secid);
+		    strlen(xoap->xoa_secctx), &secid);
 		if (error)
 			return (error);
 	} else {
@@ -202,6 +205,23 @@
 	return (0);
 }
 
+void
+fmac_vnode_init_secid(vnode_t *vp, char *secctx)
+{
+	security_id_t secid;
+
+	if (!fmac_enabled)
+		return;
+
+	/*
+	 * Called before vp is put in dnlc, so no need to hold v_lock.
+	 */
+	if (security_context_to_sid(secctx, strlen(secctx), &secid))
+		vp->v_secid = SECINITSID_UNLABELED;
+	else
+		vp->v_secid = secid;
+}
+
 int
 fmac_vfs_root(vfs_t *vfsp, vnode_t *vp)
 {
@@ -215,6 +235,7 @@
 	security_id_t cr_secid, old_secid, new_secid;
 	security_class_t sclass;
 	int error;
+	avc_audit_data_t ad;
 
 	if (!fmac_enabled)
 		return (EINVAL);
@@ -235,24 +256,60 @@
 		 */
 		mutex_enter(&(vp->v_lock));
 		old_secid = vp->v_secid;
+		AVC_AUDIT_DATA_INIT(&ad, FS);
+		ad.u.fs.vp = vp;
 		error = avc_has_perm(cr_secid, old_secid, sclass,
-		    FILE__RELABELFROM);
+		    FILE__RELABELFROM, &ad);
 		if (!error)
 			error = avc_has_perm(cr_secid, new_secid, sclass,
-			    FILE__RELABELTO);
+			    FILE__RELABELTO, &ad);
 		if (!error)
 			vp->v_secid = new_secid;
 		mutex_exit(&(vp->v_lock));
 	} else {
 		/* Creating a new file. */
 		error = avc_has_perm(cr_secid, new_secid, sclass,
-		    FILE__CREATE);
+		    FILE__CREATE, NULL);
 	}
 
 	return (error);
 }
 
 int
+fmac_vnode_get_secctx(vnode_t *vp, vattr_t *vap)
+{
+	xvattr_t *xvap = (xvattr_t *)vap;
+	xoptattr_t *xoap;
+	security_context_t scontext;
+	uint32_t scontext_len;
+	int error;
+
+	if (!fmac_enabled)
+		return (0);
+
+	xoap = xva_getxoptattr(xvap);
+	if (!xoap)
+		return (0);
+
+	if (!XVA_ISSET_REQ(xvap, XAT_SECCTX))
+		return (0);
+
+	error = security_sid_to_context(vp->v_secid, &scontext, &scontext_len);
+	if (error)
+		return (error);
+
+	if (scontext_len > sizeof (xoap->xoa_secctx)) {
+		security_context_free(scontext);
+		return (EINVAL);
+	}
+
+	(void) strncpy(xoap->xoa_secctx, scontext, sizeof (xoap->xoa_secctx));
+	XVA_SET_RTN(xvap, XAT_SECCTX);
+	security_context_free(scontext);
+	return (0);
+}
+
+int
 fmac_vnode_create(vnode_t *dvp, char *name, xvattr_t *xvap, vattr_t **vapp,
     cred_t *cr, security_id_t *secidp)
 {
@@ -260,6 +317,7 @@
 	security_class_t sclass;
 	security_context_t scontext;
 	uint32_t scontext_len;
+	vattr_t *vap = *vapp;
 	xoptattr_t *xoap;
 	int error;
 	avc_audit_data_t ad;
@@ -277,7 +335,7 @@
 	if (vfs_has_feature(dvp->v_vfsp, VFSFT_XVATTR) == 0)
 		return (0);
 
-	sclass = fmac_vtype_to_sclass((*vapp)->va_type);
+	sclass = fmac_vtype_to_sclass(vap->va_type);
 	if (!sclass)
 		return (0);
 
@@ -292,42 +350,46 @@
 	ad.u.fs.vp = dvp;
 	ad.u.fs.name = name;
 
-	error = avc_has_perm_audit(cr_secid, dvp->v_secid, SECCLASS_DIR,
+	error = avc_has_perm(cr_secid, dvp->v_secid, SECCLASS_DIR,
 	    DIR__ADD_NAME, &ad);
 	if (error)
 		return (error);
 
-	error = avc_has_perm_audit(cr_secid, secid, sclass, FILE__CREATE, &ad);
+	error = avc_has_perm(cr_secid, secid, sclass, FILE__CREATE, &ad);
 	if (error)
 		return (error);
 
-	/*
-	 * Wrap the vattr with an xvattr so we can pass the
-	 * secctx to the fs code.
-	 */
-	xva_init(xvap);
-	(void) memcpy(&xvap->xva_vattr, *vapp, sizeof (vattr_t));
-	xvap->xva_vattr.va_mask |= AT_XVATTR; /* reset after memcpy */
-	XVA_SET_REQ(xvap, XAT_SECCTX);
+	if (!xvap) {
+		/*
+		 * Caller only wants the secid, not an xvattr w/ secctx.
+		 * tmpfs is one such example.
+		 */
+		*secidp = secid;
+		return (0);
+	}
+
+	if (!(vap->va_mask & AT_XVATTR)) {
+		/*
+		 * If the vattr is not already an xvattr, then wrap the
+		 * vattr with an xvattr so we can pass the secctx to
+		 * the fs code.
+		 */
+		xva_from_va(xvap, vap);
+		*vapp = &xvap->xva_vattr;
+	} else {
+		xvap = (xvattr_t *)vap;
+	}
 
 	error = security_sid_to_context(secid, &scontext, &scontext_len);
 	if (error)
 		return (error);
 
-	if (scontext_len > sizeof (xoap->xoa_secctx))
-		goto inval;
-
 	xoap = xva_getxoptattr(xvap);
-	if (!xoap)
+	if (!xoap || scontext_len > sizeof (xoap->xoa_secctx))
 		goto inval;
 	(void) strncpy(xoap->xoa_secctx, scontext, sizeof (xoap->xoa_secctx));
+	XVA_SET_REQ(xvap, XAT_SECCTX);
 
-	/*
-	 * Switch the vap pointer to the newly populated xvattr.
-	 * fop_create/fop_mkdir will then pass the xvattr along to
-	 * the underlying fs code.  The original vattr is not mutated.
-	 */
-	*vapp = &xvap->xva_vattr;
 	*secidp = secid;
 	security_context_free(scontext);
 	return (0);
@@ -347,13 +409,11 @@
 }
 
 int
-fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
-    caller_context_t *ct)
+fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr)
 {
 	security_id_t cr_secid;
 	security_class_t sclass;
 	int error;
-	vnode_t *realvp;
 	avc_audit_data_t ad;
 
 	if (!fmac_enabled)
@@ -363,22 +423,19 @@
 	if (!sclass)
 		return (0);
 
-	if (VOP_REALVP(svp, &realvp, ct) == 0)
-		svp = realvp;
-
 	cr_secid = crgetsecid(cr);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.vp = tdvp;
 	ad.u.fs.name = name;
-	error = avc_has_perm_audit(cr_secid, tdvp->v_secid, SECCLASS_DIR,
+	error = avc_has_perm(cr_secid, tdvp->v_secid, SECCLASS_DIR,
 	    DIR__ADD_NAME, &ad);
 	if (error)
 		return (error);
 
 	ad.u.fs.vp = svp;
-	return (avc_has_perm_audit(cr_secid, svp->v_secid, sclass,
-		    FILE__LINK, &ad));
+	return (avc_has_perm(cr_secid, svp->v_secid, sclass,
+	    FILE__LINK, &ad));
 }
 
 int
@@ -402,7 +459,7 @@
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.vp = dvp;
 	ad.u.fs.name = name;
-	error = avc_has_perm_audit(cr_secid, dvp->v_secid, SECCLASS_DIR,
+	error = avc_has_perm(cr_secid, dvp->v_secid, SECCLASS_DIR,
 	    DIR__REMOVE_NAME, &ad);
 	if (error)
 		return (error);
@@ -412,7 +469,7 @@
 		av = DIR__RMDIR;
 	else
 		av = FILE__UNLINK;
-	return (avc_has_perm_audit(cr_secid, vp->v_secid, sclass, av, &ad));
+	return (avc_has_perm(cr_secid, vp->v_secid, sclass, av, &ad));
 }
 
 int
@@ -437,19 +494,19 @@
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 
 	ad.u.fs.vp = sdvp;
-	error = avc_has_perm_audit(cr_secid, sdvp->v_secid, SECCLASS_DIR,
+	error = avc_has_perm(cr_secid, sdvp->v_secid, SECCLASS_DIR,
 	    DIR__REMOVE_NAME, &ad);
 	if (error)
 		return (error);
 
 	ad.u.fs.vp = svp;
-	error = avc_has_perm_audit(cr_secid, svp->v_secid, sclass,
+	error = avc_has_perm(cr_secid, svp->v_secid, sclass,
 	    FILE__RENAME, &ad);
 	if (error)
 		return (error);
 
 	ad.u.fs.vp = tdvp;
-	error = avc_has_perm_audit(cr_secid, tdvp->v_secid, SECCLASS_DIR,
+	error = avc_has_perm(cr_secid, tdvp->v_secid, SECCLASS_DIR,
 	    DIR__ADD_NAME, &ad);
 	if (error)
 		return (error);
@@ -465,7 +522,7 @@
 			av = FILE__UNLINK;
 
 		ad.u.fs.vp = tvp;
-		error = avc_has_perm_audit(cr_secid, tvp->v_secid, tclass, av,
+		error = avc_has_perm(cr_secid, tvp->v_secid, tclass, av,
 		    &ad);
 		if (error)
 			return (error);
@@ -492,8 +549,8 @@
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.vp = vp;
-	return (avc_has_perm_audit(cr_secid, vp->v_secid, sclass,
-		    FILE__SETATTR, &ad));
+	return (avc_has_perm(cr_secid, vp->v_secid, sclass,
+	    FILE__SETATTR, &ad));
 }
 
 int
@@ -516,32 +573,32 @@
 			return (error);
 	}
 
+	AVC_AUDIT_DATA_INIT(&ad, FS);
+	ad.u.fs.vp = vp;
+
 	if (prev_secid == secid) {
-		AVC_AUDIT_DATA_INIT(&ad, FS);
-		ad.u.fs.vp = vp;
-		error = avc_has_perm_audit(prev_secid, vp->v_secid,
+		error = avc_has_perm(prev_secid, vp->v_secid,
 		    SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
 		if (error)
 			return (error);
 		*execsetid = B_FALSE;
 		*setsecid = B_FALSE;
+		*prev_secidp = *secidp = secid;
 		return (0);
 	}
 
 	error = avc_has_perm(prev_secid, secid, SECCLASS_PROCESS,
-	    PROCESS__TRANSITION);
+	    PROCESS__TRANSITION, &ad);
 	if (error)
 		return (error);
 
-	AVC_AUDIT_DATA_INIT(&ad, FS);
-	ad.u.fs.vp = vp;
-	error = avc_has_perm_audit(secid, vp->v_secid, SECCLASS_FILE,
+	error = avc_has_perm(secid, vp->v_secid, SECCLASS_FILE,
 	    FILE__ENTRYPOINT, &ad);
 	if (error)
 		return (error);
 
 	error = avc_has_perm(prev_secid, secid, SECCLASS_PROCESS,
-	    PROCESS__EXECSETID);
+	    PROCESS__EXECSETID, &ad);
 	if (error)
 		*execsetid = B_TRUE;
 	else
@@ -553,6 +610,17 @@
 	return (0);
 }
 
+#define	fmac_ace_to_av(mask, perm) \
+	if (mode & (mask)) { \
+		mode &= ~(mask); \
+		av |= (perm); \
+	}
+
+#define	ACE_GETATTR_MASK (ACE_READ_NAMED_ATTRS | ACE_READ_ATTRIBUTES | \
+    ACE_READ_ACL)
+#define	ACE_SETATTR_MASK (ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ATTRIBUTES | \
+    ACE_WRITE_ACL | ACE_WRITE_OWNER)
+
 int
 fmac_vnode_access(vnode_t *vp, int mode, int flags, cred_t *cr,
     boolean_t audit)
@@ -572,17 +640,43 @@
 		return (0);
 
 	av = 0;
-	if (mode & VREAD)
-		av |= FILE__READ;
-	if (flags & V_APPEND)
-		av |= FILE__APPEND;
-	else if (mode & VWRITE)
-		av |= FILE__WRITE;
-	if (mode & VEXEC) {
-		if (sclass == SECCLASS_DIR)
-			av |= DIR__SEARCH;
-		else
-			av |= FILE__EXECUTE;
+
+	if (flags & V_ACE_MASK) {
+		mode &= ~ACE_SYNCHRONIZE; /* ignore synchronize bit */
+		fmac_ace_to_av(ACE_READ_DATA, FILE__READ);
+		fmac_ace_to_av(ACE_GETATTR_MASK, FILE__GETATTR);
+		fmac_ace_to_av(ACE_SETATTR_MASK, FILE__SETATTR);
+		if (sclass == SECCLASS_DIR) {
+			fmac_ace_to_av((ACE_ADD_FILE | ACE_ADD_SUBDIRECTORY),
+			    DIR__ADD_NAME);
+			fmac_ace_to_av(ACE_DELETE_CHILD, DIR__REMOVE_NAME);
+			fmac_ace_to_av(ACE_DELETE, DIR__RMDIR);
+			fmac_ace_to_av(ACE_EXECUTE, DIR__SEARCH);
+		} else {
+			fmac_ace_to_av(ACE_APPEND_DATA, FILE__APPEND);
+			fmac_ace_to_av(ACE_WRITE_DATA, (flags & V_APPEND) ?
+			    FILE__APPEND : FILE__WRITE);
+			fmac_ace_to_av(ACE_EXECUTE, FILE__EXECUTE);
+			fmac_ace_to_av(ACE_DELETE, FILE__UNLINK);
+		}
+		if (mode) {
+			cmn_err(CE_WARN, "FMAC:  Unknown ACE mask 0x%x\n",
+			    mode);
+			return (EACCES);
+		}
+	} else {
+		if (mode & VREAD)
+			av |= FILE__READ;
+		if (flags & V_APPEND)
+			av |= FILE__APPEND;
+		else if (mode & VWRITE)
+			av |= FILE__WRITE;
+		if (mode & VEXEC) {
+			if (sclass == SECCLASS_DIR)
+				av |= DIR__SEARCH;
+			else
+				av |= FILE__EXECUTE;
+		}
 	}
 
 	if (!av)
@@ -593,7 +687,7 @@
 		ad.u.fs.vp = vp;
 	} else
 		AVC_AUDIT_DATA_INIT(&ad, DONTAUDIT);
-	return (avc_has_perm_audit(cr_secid, vp->v_secid, sclass, av, &ad));
+	return (avc_has_perm(cr_secid, vp->v_secid, sclass, av, &ad));
 }
 
 int
@@ -604,7 +698,7 @@
 	if (!fmac_enabled)
 		return (0);
 	return (avc_has_perm(crgetsecid((cred_t *)scr), crgetsecid(tcr),
-		    SECCLASS_PROCESS, PROCESS__PTRACE));
+	    SECCLASS_PROCESS, PROCESS__PTRACE, NULL));
 }
 
 access_vector_t
@@ -632,5 +726,5 @@
 
 	tsecid = crgetsecid((cred_t *)tcrp);
 	ssecid = crgetsecid((cred_t *)scrp);
-	return (avc_has_perm(ssecid, tsecid, SECCLASS_PROCESS, perms));
+	return (avc_has_perm(ssecid, tsecid, SECCLASS_PROCESS, perms, NULL));
 }
--- a/usr/src/uts/common/fs/tmpfs/tmp_subr.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/tmpfs/tmp_subr.c	Wed Oct 29 11:52:47 2008 -0700
@@ -42,6 +42,7 @@
 #include <sys/kmem.h>
 #include <sys/atomic.h>
 #include <sys/policy.h>
+#include <sys/fmac/fmac.h>
 #include <sys/fs/tmp.h>
 #include <sys/fs/tmpnode.h>
 
@@ -52,6 +53,8 @@
 {
 	struct tmpnode *tp = vtp;
 	int shift = 0;
+	int error = 0;
+
 	/*
 	 * Check access based on owner, group and
 	 * public permissions in tmpnode.
@@ -65,10 +68,14 @@
 	/* compute missing mode bits */
 	mode &= ~(tp->tn_mode << shift);
 
-	if (mode == 0)
-		return (0);
+	if (mode)
+		error = secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid,
+		    mode);
 
-	return (secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid, mode));
+	if (!error)
+		error = fmac_vnode_access(TNTOV(tp), mode, 0, cred, B_TRUE);
+
+	return (error);
 }
 
 /*
@@ -86,15 +93,19 @@
 	struct cred *cr)
 {
 	uid_t uid = crgetuid(cr);
+	int error = 0;
 
 	if ((dir->tn_mode & S_ISVTX) &&
 	    uid != dir->tn_uid &&
 	    uid != entry->tn_uid &&
 	    (entry->tn_type != VREG ||
 	    tmp_taccess(entry, VWRITE, cr) != 0))
-		return (secpolicy_vnode_remove(cr));
+		error = secpolicy_vnode_remove(cr);
 
-	return (0);
+	if (!error)
+		error = fmac_vnode_remove(TNTOV(dir), TNTOV(entry), NULL, cr);
+
+	return (error);
 }
 
 /*
--- a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c	Wed Oct 29 11:52:47 2008 -0700
@@ -342,6 +342,7 @@
 
 	rw_enter(&tp->tn_rwlock, RW_WRITER);
 	TNTOV(tp)->v_flag |= VROOT;
+	TNTOV(tp)->v_secid = mvp->v_secid;
 
 	/*
 	 * If the getattr succeeded, use its results.  Otherwise allow
--- a/usr/src/uts/common/fs/tmpfs/tmp_vnops.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/tmpfs/tmp_vnops.c	Wed Oct 29 11:52:47 2008 -0700
@@ -64,6 +64,7 @@
 #include <sys/vm.h>
 #include <sys/vtrace.h>
 #include <sys/policy.h>
+#include <sys/fmac/fmac.h>
 #include <fs/fs_subr.h>
 
 static int	tmp_getapage(struct vnode *, u_offset_t, size_t, uint_t *,
@@ -702,7 +703,8 @@
 	 */
 	vap->va_nblocks = (fsblkcnt64_t)btodb(ptob(btopr(vap->va_size)));
 	mutex_exit(&tp->tn_tlock);
-	return (0);
+
+	return (fmac_vnode_get_secctx(vp, vap));
 }
 
 /*ARGSUSED4*/
@@ -718,14 +720,38 @@
 	struct tmpnode *tp = (struct tmpnode *)VTOTN(vp);
 	int error = 0;
 	struct vattr *get;
+	xvattr_t *xvap = (xvattr_t *)vap;
 	long mask;
 
 	/*
 	 * Cannot set these attributes
 	 */
-	if ((vap->va_mask & AT_NOSET) || (vap->va_mask & AT_XVATTR))
+	if (vap->va_mask & AT_NOSET)
 		return (EINVAL);
 
+	/*
+	 * Only support XAT_SECCTX presently.
+	 */
+	if (vap->va_mask & AT_XVATTR) {
+		if (XVA_ISSET_REQ(xvap, XAT_CREATETIME) ||
+		    XVA_ISSET_REQ(xvap, XAT_ARCHIVE) ||
+		    XVA_ISSET_REQ(xvap, XAT_SYSTEM) ||
+		    XVA_ISSET_REQ(xvap, XAT_READONLY) ||
+		    XVA_ISSET_REQ(xvap, XAT_HIDDEN) ||
+		    XVA_ISSET_REQ(xvap, XAT_NOUNLINK) ||
+		    XVA_ISSET_REQ(xvap, XAT_IMMUTABLE) ||
+		    XVA_ISSET_REQ(xvap, XAT_APPENDONLY) ||
+		    XVA_ISSET_REQ(xvap, XAT_NODUMP) ||
+		    XVA_ISSET_REQ(xvap, XAT_OPAQUE) ||
+		    XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED) ||
+		    XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
+			return (EINVAL);
+	}
+
+	error = fmac_vnode_setattr(vp, cred);
+	if (error)
+		return (error);
+
 	mutex_enter(&tp->tn_tlock);
 
 	get = &tp->tn_attr;
@@ -741,6 +767,11 @@
 
 	mask = vap->va_mask;
 
+	if ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_SECCTX)) {
+		/* vnode secid was updated during the secpolicy call. */
+		XVA_SET_RTN(xvap, XAT_SECCTX);
+	}
+
 	if (mask & AT_MODE) {
 		get->va_mode &= S_IFMT;
 		get->va_mode |= vap->va_mode & ~S_IFMT;
@@ -937,6 +968,7 @@
 	struct tmpnode *self;
 	int error;
 	struct tmpnode *oldtp;
+	security_id_t	secid;
 
 again:
 	parent = (struct tmpnode *)VTOTN(dvp);
@@ -1021,6 +1053,10 @@
 	if (error != ENOENT)
 		return (error);
 
+	error = fmac_vnode_create(dvp, nm, NULL, &vap, cred, &secid);
+	if (error)
+		return (error);
+
 	rw_enter(&parent->tn_rwlock, RW_WRITER);
 	error = tdirenter(tm, parent, nm, DE_CREATE,
 	    (struct tmpnode *)NULL, (struct tmpnode *)NULL,
@@ -1057,6 +1093,8 @@
 			return (ENOSYS);
 		*vpp = newvp;
 	}
+
+	fmac_vnode_post_create(*vpp, secid);
 	TRACE_3(TR_FAC_TMPFS, TR_TMPFS_CREATE,
 	    "tmpfs create:dvp %p nm %s vpp %p", dvp, nm, vpp);
 	return (0);
@@ -1117,6 +1155,10 @@
 	if (VOP_REALVP(srcvp, &realvp, ct) == 0)
 		srcvp = realvp;
 
+	error = fmac_vnode_link(dvp, srcvp, tnm, cred);
+	if (error)
+		return (error);
+
 	parent = (struct tmpnode *)VTOTN(dvp);
 	from = (struct tmpnode *)VTOTN(srcvp);
 
@@ -1300,6 +1342,11 @@
 	struct tmpnode *self = NULL;
 	struct tmount *tm = (struct tmount *)VTOTM(dvp);
 	int error;
+	security_id_t	secid;
+
+	error = fmac_vnode_create(dvp, nm, NULL, &va, cred, &secid);
+	if (error)
+		return (error);
 
 	/* no new dirs allowed in xattr dirs */
 	if (parent->tn_flags & ISXATTR)
@@ -1333,6 +1380,7 @@
 	}
 	rw_exit(&parent->tn_rwlock);
 	*vpp = TNTOV(self);
+	fmac_vnode_post_create(*vpp, secid);
 	return (0);
 }
 
--- a/usr/src/uts/common/fs/vnode.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/vnode.c	Wed Oct 29 11:52:47 2008 -0700
@@ -381,6 +381,18 @@
 }
 
 /*
+ * Populate an xvattr from a vattr.
+ */
+void
+xva_from_va(xvattr_t *xvap, vattr_t *vap)
+{
+	ASSERT(!(vap->va_mask & AT_XVATTR));
+	xva_init(xvap);
+	(void) memcpy(&xvap->xva_vattr, vap, sizeof (vattr_t));
+	xvap->xva_vattr.va_mask |= AT_XVATTR;
+}
+
+/*
  * If AT_XVATTR is set, returns a pointer to the embedded xoptattr_t
  * structure.  Otherwise, returns NULL.
  */
@@ -3275,10 +3287,6 @@
 		return (EINVAL);
 	}
 
-	err = fmac_vnode_setattr(vp, cr);
-	if (err)
-		return (err);
-
 	err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct);
 	VOPSTATS_UPDATE(vp, setattr);
 	return (err);
@@ -3303,9 +3311,7 @@
 
 	err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr, ct);
 	VOPSTATS_UPDATE(vp, access);
-	if (err)
-		return (err);
-	return (fmac_vnode_access(vp, mode, flags, cr, B_TRUE));
+	return (err);
 }
 
 int
@@ -3367,8 +3373,6 @@
 	vsecattr_t *vsecp)	/* ACL to set during create */
 {
 	int ret;
-	xvattr_t xvattr;
-	security_id_t secid;
 
 	if (vsecp != NULL &&
 	    vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) {
@@ -3383,16 +3387,11 @@
 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
 		return (EINVAL);
 
-	ret = fmac_vnode_create(dvp, name, &xvattr, &vap, cr, &secid);
-	if (ret)
-		return (ret);
-
 	VOPXID_MAP_CR(dvp, cr);
 
 	ret = (*(dvp)->v_op->vop_create)
 	    (dvp, name, vap, excl, mode, vpp, cr, flags, ct, vsecp);
 	if (ret == 0 && *vpp) {
-		fmac_vnode_post_create(*vpp, secid);
 		VOPSTATS_UPDATE(*vpp, create);
 		if ((*vpp)->v_path == NULL) {
 			vn_setpath(rootdir, dvp, *vpp, name, strlen(name));
@@ -3450,10 +3449,6 @@
 
 	VOPXID_MAP_CR(tdvp, cr);
 
-	err = fmac_vnode_link(tdvp, svp, tnm, cr, ct);
-	if (err)
-		return (err);
-
 	err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr, ct, flags);
 	VOPSTATS_UPDATE(tdvp, link);
 	return (err);
@@ -3499,8 +3494,6 @@
 	int flags,
 	vsecattr_t *vsecp)	/* ACL to set during create */
 {
-	xvattr_t xvattr;
-	security_id_t secid;
 	int ret;
 
 	if (vsecp != NULL &&
@@ -3516,16 +3509,11 @@
 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
 		return (EINVAL);
 
-	ret = fmac_vnode_create(dvp, dirname, &xvattr, &vap, cr, &secid);
-	if (ret)
-		return (ret);
-
 	VOPXID_MAP_CR(dvp, cr);
 
 	ret = (*(dvp)->v_op->vop_mkdir)
 	    (dvp, dirname, vap, vpp, cr, ct, flags, vsecp);
 	if (ret == 0 && *vpp) {
-		fmac_vnode_post_create(*vpp, secid);
 		VOPSTATS_UPDATE(*vpp, mkdir);
 		if ((*vpp)->v_path == NULL) {
 			vn_setpath(rootdir, dvp, *vpp, dirname,
@@ -4075,10 +4063,6 @@
 		return (EINVAL);
 	}
 
-	err = fmac_vnode_setattr(vp, cr);
-	if (err)
-		return (err);
-
 	err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr, ct);
 	VOPSTATS_UPDATE(vp, setsecattr);
 	return (err);
--- a/usr/src/uts/common/fs/xattr.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/xattr.c	Wed Oct 29 11:52:47 2008 -0700
@@ -683,13 +683,13 @@
 			break;
 		case F_SECCTX:
 			if (!secctx ||
-				strlen(secctx) >= sizeof (xoap->xoa_secctx)) {
+			    strlen(secctx) >= sizeof (xoap->xoa_secctx)) {
 				nvlist_free(nvp);
 				return (EINVAL);
 			}
 			XVA_SET_REQ(&xvattr, XAT_SECCTX);
 			(void) strncpy(xoap->xoa_secctx, secctx,
-				sizeof (xoap->xoa_secctx));
+			    sizeof (xoap->xoa_secctx));
 			break;
 		default:
 			break;
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c	Wed Oct 29 11:52:47 2008 -0700
@@ -42,6 +42,7 @@
 #include <sys/fs/zfs.h>
 #include <sys/mode.h>
 #include <sys/policy.h>
+#include <sys/fmac/fmac.h>
 #include <sys/zfs_znode.h>
 #include <sys/zfs_fuid.h>
 #include <sys/zfs_acl.h>
@@ -2353,11 +2354,8 @@
 	}
 
 	if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,
-	    &check_privs, skipaclchk, cr)) == 0) {
-		if (is_attr)
-			VN_RELE(ZTOV(xzp));
-		return (0);
-	}
+	    &check_privs, skipaclchk, cr)) == 0)
+		goto out;
 
 	if (error && !check_privs) {
 		if (is_attr)
@@ -2424,6 +2422,11 @@
 		}
 	}
 
+out:
+	if (!error)
+		error = fmac_vnode_access(ZTOV(check_zp), mode,
+		    flags|V_ACE_MASK, cr, B_TRUE);
+
 	if (is_attr)
 		VN_RELE(ZTOV(xzp));
 
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 29 11:52:47 2008 -0700
@@ -1159,6 +1159,8 @@
 	int		error;
 	zfs_acl_t	*aclp = NULL;
 	zfs_fuid_info_t *fuidp = NULL;
+	xvattr_t	xvattr;
+	security_id_t	secid;
 
 	/*
 	 * If we have an ephemeral id, ACL, or XVATTR then
@@ -1241,6 +1243,11 @@
 			goto out;
 		}
 
+		error = fmac_vnode_create(dvp, name, &xvattr, &vap, cr,
+		    &secid);
+		if (error)
+			goto out;
+
 		/*
 		 * We only support the creation of regular files in
 		 * extended attribute directories.
@@ -1298,6 +1305,7 @@
 		if (fuidp)
 			zfs_fuid_info_free(fuidp);
 		dmu_tx_commit(tx);
+		fmac_vnode_post_create(ZTOV(zp), secid);
 	} else {
 		int aflags = (flag & FAPPEND) ? V_APPEND : 0;
 
@@ -1610,6 +1618,8 @@
 	zfs_acl_t	*aclp = NULL;
 	zfs_fuid_info_t	*fuidp = NULL;
 	int		zf = ZNEW;
+	xvattr_t	xvattr;
+	security_id_t	secid;
 
 	ASSERT(vap->va_type == VDIR);
 
@@ -1665,6 +1675,13 @@
 		return (error);
 	}
 
+	error = fmac_vnode_create(dvp, dirname, &xvattr, &vap, cr, &secid);
+	if (error) {
+		zfs_dirent_unlock(dl);
+		ZFS_EXIT(zfsvfs);
+		return (error);
+	}
+
 	if (vsecp && aclp == NULL) {
 		error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, &aclp);
 		if (error) {
@@ -1734,6 +1751,8 @@
 		zfs_fuid_info_free(fuidp);
 	dmu_tx_commit(tx);
 
+	fmac_vnode_post_create(ZTOV(zp), secid);
+
 	zfs_dirent_unlock(dl);
 
 	ZFS_EXIT(zfsvfs);
@@ -2499,6 +2518,13 @@
 	 * First validate permissions
 	 */
 
+
+	err = fmac_vnode_setattr(vp, cr);
+	if (err) {
+		ZFS_EXIT(zfsvfs);
+		return (err);
+	}
+
 	if (mask & AT_SIZE) {
 		err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr);
 		if (err) {
@@ -3455,6 +3481,12 @@
 	if (VOP_REALVP(svp, &realvp, ct) == 0)
 		svp = realvp;
 
+	error = fmac_vnode_link(tdvp, svp, name, cr);
+	if (error) {
+		ZFS_EXIT(zfsvfs);
+		return (error);
+	}
+
 	if (svp->v_vfsp != tdvp->v_vfsp) {
 		ZFS_EXIT(zfsvfs);
 		return (EXDEV);
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c	Wed Oct 29 11:52:47 2008 -0700
@@ -56,6 +56,7 @@
 #include <sys/zfs_fuid.h>
 #include <sys/fs/zfs.h>
 #include <sys/kidmap.h>
+#include <sys/fmac/fmac.h>
 #endif /* _KERNEL */
 
 #include <sys/dmu.h>
@@ -968,6 +969,7 @@
 	dmu_object_info_t doi;
 	dmu_buf_t	*db;
 	znode_t		*zp;
+	znode_phys_t	*pzp;
 	int err;
 
 	*zpp = NULL;
@@ -1016,6 +1018,13 @@
 	 * Not found create new znode/vnode
 	 */
 	zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size);
+
+	/*
+	 * Compute FMAC security identifier
+	 */
+	pzp = zp->z_phys;
+	if (ZTOV(zp)->v_type != VLNK && pzp->zp_flags & ZFS_BONUS_SECCTX)
+		fmac_vnode_init_secid(ZTOV(zp), (char *)(pzp + 1));
 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
 	*zpp = zp;
 	return (0);
--- a/usr/src/uts/common/os/cpu.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/os/cpu.c	Wed Oct 29 11:52:47 2008 -0700
@@ -2505,7 +2505,7 @@
 	 * or hasprocperm() fails.
 	 */
 	if (tp->t_cid == 0 || !hasprocperm(tp->t_cred, CRED(),
-		PROCESS__SETSCHED)) {
+	    PROCESS__SETSCHED)) {
 		*error = EPERM;
 		thread_unlock(tp);
 		return (0);
--- a/usr/src/uts/common/os/exec.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/os/exec.c	Wed Oct 29 11:52:47 2008 -0700
@@ -580,8 +580,8 @@
 	if (level == 0 && privflags != 0) {
 		newcred = cred = crdup(cred);
 
+		cred->cr_prev_secid = prev_secid;
 		if (setsecid) {
-			cred->cr_prev_secid = prev_secid;
 			cred->cr_secid = secid;
 			cred->cr_exec_secid = SECSID_NULL;
 		}
@@ -623,6 +623,9 @@
 			CR_EPRIV(cred) = CR_PPRIV(cred) = CR_IPRIV(cred);
 			priv_adjust_PA(cred);
 		}
+	} else if (level == 0 && cred->cr_prev_secid != prev_secid) {
+		newcred = cred = crdup(cred);
+		cred->cr_prev_secid = prev_secid;
 	}
 
 	/* SunOS 4.x buy-back */
--- a/usr/src/uts/common/os/klpd.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/os/klpd.c	Wed Oct 29 11:52:47 2008 -0700
@@ -550,7 +550,7 @@
 		mutex_enter(&pidlock);
 		p = prfind(pid);
 		if (p == NULL || !prochasprocperm(p, curproc, CRED(),
-			PROCESS__PTRACE)) {
+		    PROCESS__PTRACE)) {
 			mutex_exit(&pidlock);
 			klpd_rele(kpd);
 			return (set_errno(p == NULL ? ESRCH : EPERM));
--- a/usr/src/uts/common/sys/fmac/avc.h	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/sys/fmac/avc.h	Wed Oct 29 11:52:47 2008 -0700
@@ -45,32 +45,6 @@
 #include <sys/fmac/av_permissions.h>
 #include <sys/fmac/security.h>
 
-/*
- * An entry in the AVC.
- */
-typedef struct avc_entry {
-	security_id_t		ssid;
-	security_id_t		tsid;
-	security_class_t	tclass;
-	struct av_decision	avd;
-	int			used;	 /* used recently */
-} avc_entry_t;
-
-
-/*
- * A reference to an AVC entry.
- */
-typedef struct avc_entry_ref {
-	avc_entry_t *ae;
-} avc_entry_ref_t;
-
-#define	AVC_ENTRY_REF_NULL { NULL }
-
-/* Initialize an AVC entry reference before first use. */
-#define	AVC_ENTRY_REF_INIT(h) { (h)->ae = NULL; }
-
-#define	AVC_ENTRY_REF_CPY(dst, src) (dst)->ae = (src)->ae
-
 struct vnode;
 
 typedef struct avc_audit_data {
@@ -96,36 +70,6 @@
 }
 
 /*
- * AVC statistics
- */
-#define	AVC_ENTRY_LOOKUPS	0
-#define	AVC_ENTRY_HITS		1
-#define	AVC_ENTRY_MISSES	2
-#define	AVC_ENTRY_DISCARDS	3
-#define	AVC_CAV_LOOKUPS		4
-#define	AVC_CAV_HITS		5
-#define	AVC_CAV_PROBES		6
-#define	AVC_CAV_MISSES		7
-#define	AVC_NSTATS		8
-extern unsigned avc_cache_stats[AVC_NSTATS];
-void avc_dump_stats(char *tag);
-
-/*
- * AVC display support
- */
-void avc_dump_av(
-	security_class_t tclass,	/* IN */
-	access_vector_t av);		/* IN */
-
-void avc_dump_query(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass);	/* IN */
-
-void avc_dump_cache(char *tag);
-
-
-/*
  * AVC operations
  */
 
@@ -133,84 +77,16 @@
 void avc_init(void);
 
 /*
- * Look up an AVC entry that is valid for the
- * `requested' permissions between the SID pair
- * (`ssid', `tsid'), interpreting the permissions
- * based on `tclass'.  If a valid AVC entry exists,
- * then this function updates `aeref' to refer to the
- * entry and returns 0. Otherwise, this function
- * returns -ENOENT.
+ * Compute an entire access vector.
  */
-int avc_lookup(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested,	/* IN */
-	avc_entry_ref_t *aeref);	/* OUT */
-
-/*
- * Insert an AVC entry for the SID pair
- * (`ssid', `tsid') and class `tclass'.
- * The access vectors and the sequence number are
- * normally provided by the security server in
- * response to a security_compute_av call.  If the
- * sequence number `ae->avd.seqno' is not less than the latest
- * revocation notification, then the function copies
- * the access vectors into a cache entry, updates
- * `aeref' to refer to the entry, and returns 0.
- * Otherwise, this function returns -EAGAIN.
- */
-int avc_insert(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	struct avc_entry *ae,		/* IN */
-	avc_entry_ref_t *out_aeref);	/* OUT */
-
+extern int avc_compute_av(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, access_vector_t requested,
+    struct av_decision *avd);
 
-/* Audit the checking of permissions */
-#define	AVC_AUDITALLOW	0
-#define	AVC_AUDITDENY	1
-void avc_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t perms,		/* IN */
-	struct avc_entry *ae,		/* IN */
-	uint32_t denied,		/* IN */
-	avc_audit_data_t *auditdata);   /* IN */
-
-/*
- * Check permissions using an AVC entry ref.
- *
- * If the ref is null or the underlying AVC entry has been invalidated
- * or the underlying AVC entry does not contain all the requested
- * decisions, then this code falls through to avc_lookup.  In
- * this case, the AVC entry ref will be updated appropriately.
- */
-int avc_has_perm_ref_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested, 	/* IN */
-	avc_entry_ref_t *aeref,		/* IN */
-	avc_audit_data_t *auditdata);	/* IN */
-
-#define	avc_has_perm_ref(ssid, tsid, tclass, requested, aeref)		\
-	avc_has_perm_ref_audit(ssid, tsid, tclass, requested, aeref, 0)
-
-
-/* Check permissions */
-int
-avc_has_perm_audit(
-	security_id_t ssid,		/* IN */
-	security_id_t tsid,		/* IN */
-	security_class_t tclass,	/* IN */
-	access_vector_t requested,	/* IN */
-	avc_audit_data_t *auditdata);	/* IN */
-
-#define	avc_has_perm(ssid, tsid, tclass, requested) \
-	avc_has_perm_audit(ssid, tsid, tclass, requested, 0)
+/* Check requested permissions. */
+extern int avc_has_perm(security_id_t ssid, security_id_t tsid,
+    security_class_t tclass, access_vector_t requested,
+    avc_audit_data_t *auditdata);
 
 #define	AVC_CALLBACK_GRANT		1
 #define	AVC_CALLBACK_TRY_REVOKE		2
@@ -240,6 +116,9 @@
 	security_class_t tclass,
 	access_vector_t perms);
 
+/* Dump cache contents. */
+extern void avc_dump_cache(char *tag);
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/uts/common/sys/fmac/fmac.h	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/sys/fmac/fmac.h	Wed Oct 29 11:52:47 2008 -0700
@@ -86,13 +86,14 @@
 void fmac_init(void);
 int fmac_load_policy(char *file);
 int fmac_vnode_lookup(vnode_t *, cred_t *, caller_context_t *);
+void fmac_vnode_init_secid(vnode_t *vp, char *secctx);
 int fmac_vfs_root(vfs_t *, vnode_t *);
 int fmac_vnode_set_secctx(char *, cred_t *, vtype_t, vnode_t *);
+int fmac_vnode_get_secctx(vnode_t *vp, vattr_t *vap);
 int fmac_vnode_create(vnode_t *, char *, xvattr_t *, vattr_t **, cred_t *,
     security_id_t *);
 void fmac_vnode_post_create(vnode_t *, security_id_t);
-int fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
-    caller_context_t *ct);
+int fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr);
 int fmac_vnode_remove(vnode_t *dvp, vnode_t *vp, char *name, cred_t *cr);
 int fmac_vnode_rename(vnode_t *sdvp, vnode_t *svp, vnode_t *tdvp, vnode_t *tvp,
     cred_t *cr);
--- a/usr/src/uts/common/sys/vnode.h	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/sys/vnode.h	Wed Oct 29 11:52:47 2008 -0700
@@ -1259,6 +1259,7 @@
  * xva_getxoptattr() returns a ponter to the xoptattr_t section of xvattr_t
  */
 void		xva_init(xvattr_t *);
+void		xva_from_va(xvattr_t *, vattr_t *);
 xoptattr_t	*xva_getxoptattr(xvattr_t *);	/* Get ptr to xoptattr_t */
 
 void xattr_init(void);		/* Initialize vnodeops for xattrs */
--- a/usr/src/uts/common/syscall/corectl.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/syscall/corectl.c	Wed Oct 29 11:52:47 2008 -0700
@@ -287,7 +287,7 @@
 				mutex_exit(&pidlock);
 				mutex_enter(&p->p_crlock);
 				if (!hasprocperm(p->p_cred, CRED(),
-					PROCESS__GETCORE))
+				    PROCESS__GETCORE))
 					error = EPERM;
 				else if (p->p_corefile != NULL)
 					rp = corectl_path_value(p->p_corefile);
@@ -437,7 +437,7 @@
 	mutex_enter(&p->p_crlock);
 
 	if (!(p->p_flag & SSYS) && hasprocperm(p->p_cred, CRED(),
-		PROCESS__SETCORE)) {
+	    PROCESS__SETCORE)) {
 		mutex_exit(&p->p_crlock);
 		counterp->cc_count++;
 		if (counterp->cc_path != NULL) {
--- a/usr/src/uts/common/syscall/fmacsys.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/syscall/fmacsys.c	Wed Oct 29 11:52:47 2008 -0700
@@ -59,7 +59,7 @@
 		return (set_errno(EINVAL));
 
 	if (err = avc_has_perm(crgetsecid(CRED()), SECINITSID_SECURITY,
-	    SECCLASS_SECURITY, SECURITY__SETENFORCE))
+	    SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL))
 		return (set_errno(err));
 
 	switch (mode) {
@@ -92,7 +92,7 @@
 		return (set_errno(EINVAL));
 
 	if (err = avc_has_perm(crgetsecid(CRED()), SECINITSID_SECURITY,
-	    SECCLASS_SECURITY, SECURITY__LOAD_POLICY))
+	    SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL))
 		return (set_errno(err));
 
 	kpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
@@ -136,7 +136,7 @@
 	int			err;
 
 	if (err = avc_has_perm(crgetsecid(CRED()), SECINITSID_SECURITY,
-	    SECCLASS_SECURITY, SECURITY__COMPUTE_AV))
+	    SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL))
 		return (set_errno(err));
 
 	kscontext = kmem_alloc(FMAC_MAX_CONTEXT_LEN, KM_SLEEP);
@@ -183,7 +183,7 @@
 	int			err;
 
 	if (err = avc_has_perm(crgetsecid(CRED()), SECINITSID_SECURITY,
-	    SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT))
+	    SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL))
 		return (set_errno(err));
 
 	kscontext = kmem_alloc(FMAC_MAX_CONTEXT_LEN, KM_SLEEP);
@@ -227,7 +227,7 @@
 	}
 
 	if (err = avc_has_perm(crgetsecid(CRED()), sid, SECCLASS_PROCESS,
-	    PROCESS__GETATTR))
+	    PROCESS__GETATTR, NULL))
 		return (set_errno(err));
 
 	if ((err = security_sid_to_context(sid, &pcontext,
@@ -285,7 +285,7 @@
 	int			err;
 
 	if (err = avc_has_perm(crgetsecid(CRED()), crgetsecid(CRED()),
-	    SECCLASS_PROCESS, PROCESS__SETEXEC))
+	    SECCLASS_PROCESS, PROCESS__SETEXEC, NULL))
 		return (set_errno(err));
 
 	if (scontext == 0) {
--- a/usr/src/uts/common/syscall/lgrpsys.c	Wed Oct 29 08:20:16 2008 -0700
+++ b/usr/src/uts/common/syscall/lgrpsys.c	Wed Oct 29 11:52:47 2008 -0700
@@ -345,7 +345,7 @@
 			 * affinity for LWP
 			 */
 			if (t->t_cid == 0 || !hasprocperm(t->t_cred, CRED(),
-				PROCESS__SETSCHED)) {
+			    PROCESS__SETSCHED)) {
 				thread_unlock(t);
 				return (set_errno(EPERM));
 			}
@@ -588,7 +588,7 @@
 	 * thread
 	 */
 	if (t->t_cid == 0 || !hasprocperm(t->t_cred, CRED(),
-		PROCESS__SETSCHED)) {
+	    PROCESS__SETSCHED)) {
 		thread_unlock(t);
 		return (set_errno(EPERM));
 	}
@@ -960,7 +960,7 @@
 	 * thread
 	 */
 	if (t->t_cid == 0 || !hasprocperm(t->t_cred, CRED(),
-		PROCESS__SETSCHED)) {
+	    PROCESS__SETSCHED)) {
 		thread_unlock(t);
 		return (set_errno(EPERM));
 	}