All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
@ 2006-05-15 16:35 Stephen Smalley
  2006-05-15 17:41 ` Stephen Smalley
                   ` (3 more replies)
  0 siblings, 4 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-15 16:35 UTC (permalink / raw)
  To: selinux; +Cc: Thomas Bleher, Daniel J Walsh, SELinux-dev, James Morris

Hi,

During the earlier thread on splitting policy into individual packages
(using policy modules), it was requested that SELinux provide a way for
a privileged process (like a package manager) to label an inode with a
not-yet-defined security context (treating it as having the unlabeled
SID until defined in the policy) and then automatically update the
in-memory state when a policy that defines the security context is
loaded such that the inode immediately becomes accessible under the
rules governing access to that context in the new policy.  More
generally, the same behavior is desired for any case where a security
context that was once valid becomes invalid and then becomes valid again
through a series of policy reloads, to address issues in the past where
removing and re-adding types or other context components has caused
problems when inodes are labeled with those context components.  This is
a RFC and patch for the SELinux kernel "module" changes required to
support that functionality.

With this patch applied, the following sequence is possible, subject to
policy, which must allow <domain> security_t:security labelpriv; and
allow unlabeled_t fs_t:filesystem associate; in order for this to work
in enforcing mode.  Note that unconfined_t implicitly picks up all
security permissions at present due to the use of a wildcard for the
permission set in its rule.  However, you still need the second allow
rule as well in order for this to succeed in enforcing mode.  

# touch foo
# chcon -t foo_exec_t foo
# ls -Z foo
-rw-r--r--  root root system_u:object_r:unlabeled_t    foo
# semodule -i foo.pp # defines foo_exec_t
# ls -Z foo
-rw-r--r--  root root user_u:object_r:foo_exec_t       foo
# semodule -r foo
# ls -Z foo
-rw-r--r--  root root system_u:object_r:unlabeled_t    foo
# semodule -i foo.pp
# ls -Z foo
-rw-r--r--  root root user_u:object_r:foo_exec_t       foo

Logically, there are two separate changes here.  The first logical
change is to support deferred mapping of security contexts in the SID
table, storing their string representations when they cannot be mapped
under the current policy, and treating them the same as the unlabeled
SID while they are in this state.  Upon policy reloads, if a valid
context becomes invalid under the new policy, rather than removing it
from the SID table, we convert it to its string representation under the
old policy and store that in the SID table until such a time as it
becomes valid again, and if an invalid context becomes valid, we map it
to its internal structure representation.  This change alone is
worthwhile irrespective of the second change, as it addresses the
longstanding issue with removing and re-adding types to policy when they
are assigned to inodes.  The second logical change introduces the
support for setting invalid contexts by privileged processes, both via
setxattr() and via /proc/self/attr/fscreate, which is the more
controversial aspect.  Note that contrary to my earlier expectations, no
walking of the inode security structs is required, as the SIDs
themselves remain invariant under such changes.

---<snip>---

Introduce support for deferring mapping of security contexts in the
SID table upon policy reload, and use this support for inode security
contexts when the context is not yet valid under the current policy.
Only processes with 'labelpriv' permission to the 'security' class can
set such invalid security contexts on inodes.  Inodes with such
invalid contexts are treated as having the unlabeled SID until the context 
becomes valid under a policy.  This support is for use by privileged processes
like rpm that need to set down files in the proper security contexts prior to 
loading the policy module that defines the context and its associated rules.

---

 security/selinux/hooks.c                  |   16 ++
 security/selinux/include/av_permissions.h |    1 
 security/selinux/include/objsec.h         |    3 
 security/selinux/include/security.h       |    2 
 security/selinux/selinuxfs.c              |    4 
 security/selinux/ss/context.h             |   27 ++++
 security/selinux/ss/mls.c                 |   11 -
 security/selinux/ss/mls.h                 |    3 
 security/selinux/ss/services.c            |  183 ++++++++++++++++++++----------
 security/selinux/ss/sidtab.c              |    4 
 10 files changed, 183 insertions(+), 71 deletions(-)

diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/hooks.c linux-2.6.17-rc3-mm1-x/security/selinux/hooks.c
--- linux-2.6.17-rc3-mm1/security/selinux/hooks.c	2006-05-04 14:08:36.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/hooks.c	2006-05-15 09:07:33.000000000 -0400
@@ -2160,6 +2160,11 @@ static int selinux_inode_setxattr(struct
 		return rc;
 
 	rc = security_context_to_sid(value, size, &newsid);
+	if (rc == -EINVAL) {
+		if (task_has_security(current, SECURITY__LABELPRIV))
+			return rc;
+		rc = security_context_to_sid_force(value, size, &newsid);
+	}
 	if (rc)
 		return rc;
 
@@ -2193,10 +2198,11 @@ static void selinux_inode_post_setxattr(
 		return;
 	}
 
-	rc = security_context_to_sid(value, size, &newsid);
+	rc = security_context_to_sid_force(value, size, &newsid);
 	if (rc) {
 		printk(KERN_WARNING "%s:  unable to obtain SID for context "
-		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
+		       "%s on (%s, %lu), rc=%d\n", __FUNCTION__, (char*)value,
+		       inode->i_sb->s_id, inode->i_ino, -rc);
 		return;
 	}
 
@@ -4158,6 +4164,12 @@ static int selinux_setprocattr(struct ta
 			size--;
 		}
 		error = security_context_to_sid(value, size, &sid);
+		if (error == -EINVAL && !strcmp(name, "fscreate")) {
+			if (task_has_security(current, SECURITY__LABELPRIV))
+				return error;
+			error = security_context_to_sid_force(value, size,
+							      &sid);
+		}
 		if (error)
 			return error;
 	}
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/include/av_permissions.h linux-2.6.17-rc3-mm1-x/security/selinux/include/av_permissions.h
--- linux-2.6.17-rc3-mm1/security/selinux/include/av_permissions.h	2006-05-04 14:08:36.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/include/av_permissions.h	2006-05-12 09:48:56.000000000 -0400
@@ -526,6 +526,7 @@
 #define SECURITY__SETBOOL                         0x00000100UL
 #define SECURITY__SETSECPARAM                     0x00000200UL
 #define SECURITY__SETCHECKREQPROT                 0x00000400UL
+#define SECURITY__LABELPRIV                       0x00000800UL
 
 #define SYSTEM__IPC_INFO                          0x00000001UL
 #define SYSTEM__SYSLOG_READ                       0x00000002UL
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/include/objsec.h linux-2.6.17-rc3-mm1-x/security/selinux/include/objsec.h
--- linux-2.6.17-rc3-mm1/security/selinux/include/objsec.h	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc3-mm1-x/security/selinux/include/objsec.h	2006-05-12 09:48:56.000000000 -0400
@@ -101,4 +101,7 @@ struct sk_security_struct {
 
 extern unsigned int selinux_checkreqprot;
 
+extern int task_has_security(struct task_struct *tsk,
+			     u32 perms);
+
 #endif /* _SELINUX_OBJSEC_H_ */
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/include/security.h linux-2.6.17-rc3-mm1-x/security/selinux/include/security.h
--- linux-2.6.17-rc3-mm1/security/selinux/include/security.h	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc3-mm1-x/security/selinux/include/security.h	2006-05-12 09:46:19.000000000 -0400
@@ -68,6 +68,8 @@ int security_context_to_sid(char *sconte
 
 int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *out_sid, u32 def_sid);
 
+int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid);
+
 int security_get_user_sids(u32 callsid, char *username,
 			   u32 **sids, u32 *nel);
 
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/selinuxfs.c linux-2.6.17-rc3-mm1-x/security/selinux/selinuxfs.c
--- linux-2.6.17-rc3-mm1/security/selinux/selinuxfs.c	2006-05-02 08:06:00.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/selinuxfs.c	2006-05-12 09:48:56.000000000 -0400
@@ -56,8 +56,8 @@ static int *bool_pending_values = NULL;
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
-static int task_has_security(struct task_struct *tsk,
-			     u32 perms)
+int task_has_security(struct task_struct *tsk,
+		      u32 perms)
 {
 	struct task_security_struct *tsec;
 
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/ss/context.h linux-2.6.17-rc3-mm1-x/security/selinux/ss/context.h
--- linux-2.6.17-rc3-mm1/security/selinux/ss/context.h	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc3-mm1-x/security/selinux/ss/context.h	2006-05-15 08:39:39.000000000 -0400
@@ -28,6 +28,8 @@ struct context {
 	u32 role;
 	u32 type;
 	struct mls_range range;
+	char *str;	/* string representation if context cannot be mapped. */
+	u32 len;        /* length of string in bytes */
 };
 
 static inline void mls_context_init(struct context *c)
@@ -83,20 +85,43 @@ static inline void context_init(struct c
 
 static inline int context_cpy(struct context *dst, struct context *src)
 {
+	int rc;
+
 	dst->user = src->user;
 	dst->role = src->role;
 	dst->type = src->type;
-	return mls_context_cpy(dst, src);
+	if (src->str) {
+		dst->str = kstrdup(src->str, GFP_ATOMIC);
+		if (!dst->str)
+			return -ENOMEM;
+		dst->len = src->len;
+	} else {
+		dst->str = NULL;
+		dst->len = 0;
+	}
+	rc = mls_context_cpy(dst, src);
+	if (rc) {
+		kfree(dst->str);
+		return rc;
+	}
+	return 0;
 }
 
 static inline void context_destroy(struct context *c)
 {
 	c->user = c->role = c->type = 0;
+	kfree(c->str);
+	c->str = NULL;
+	c->len = 0;
 	mls_context_destroy(c);
 }
 
 static inline int context_cmp(struct context *c1, struct context *c2)
 {
+	if (c1->len && c2->len)
+		return (c1->len == c2->len && !strcmp(c1->str, c2->str));
+	if (c1->len || c2->len)
+		return 0;
 	return ((c1->user == c2->user) &&
 		(c1->role == c2->role) &&
 		(c1->type == c2->type) &&
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/ss/mls.c linux-2.6.17-rc3-mm1-x/security/selinux/ss/mls.c
--- linux-2.6.17-rc3-mm1/security/selinux/ss/mls.c	2006-05-02 08:47:04.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/ss/mls.c	2006-05-12 10:08:35.000000000 -0400
@@ -249,7 +249,8 @@ static inline int mls_copy_context(struc
  * Policy read-lock must be held for sidtab lookup.
  *
  */
-int mls_context_to_sid(char oldc,
+int mls_context_to_sid(struct policydb *pol,
+		       char oldc,
 		       char **scontext,
 		       struct context *context,
 		       struct sidtab *s,
@@ -296,7 +297,7 @@ int mls_context_to_sid(char oldc,
 		*p++ = 0;
 
 	for (l = 0; l < 2; l++) {
-		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
+		levdatum = hashtab_search(pol->p_levels.table, scontextp);
 		if (!levdatum) {
 			rc = -EINVAL;
 			goto out;
@@ -320,7 +321,7 @@ int mls_context_to_sid(char oldc,
 					*rngptr++ = 0;
 				}
 
-				catdatum = hashtab_search(policydb.p_cats.table,
+				catdatum = hashtab_search(pol->p_cats.table,
 				                          scontextp);
 				if (!catdatum) {
 					rc = -EINVAL;
@@ -336,7 +337,7 @@ int mls_context_to_sid(char oldc,
 				if (rngptr) {
 					int i;
 
-					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+					rngdatum = hashtab_search(pol->p_cats.table, rngptr);
 					if (!rngdatum) {
 						rc = -EINVAL;
 						goto out;
@@ -404,7 +405,7 @@ int mls_from_string(char *str, struct co
 	if (!tmpstr) {
 		rc = -ENOMEM;
 	} else {
-		rc = mls_context_to_sid(':', &tmpstr, context,
+		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
 		                        NULL, SECSID_NULL);
 		kfree(freestr);
 	}
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/ss/mls.h linux-2.6.17-rc3-mm1-x/security/selinux/ss/mls.h
--- linux-2.6.17-rc3-mm1/security/selinux/ss/mls.h	2006-05-02 08:47:04.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/ss/mls.h	2006-05-12 09:03:23.000000000 -0400
@@ -21,7 +21,8 @@ int mls_compute_context_len(struct conte
 void 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,
+int mls_context_to_sid(struct policydb *p,
+		       char oldc,
 	               char **scontext,
 		       struct context *context,
 		       struct sidtab *s,
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/ss/services.c linux-2.6.17-rc3-mm1-x/security/selinux/ss/services.c
--- linux-2.6.17-rc3-mm1/security/selinux/ss/services.c	2006-05-02 08:47:04.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/ss/services.c	2006-05-15 10:01:01.000000000 -0400
@@ -619,36 +619,24 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
+static int string_to_context_struct(struct policydb *pol,
+				    struct sidtab *sidtabp,
+				    char *scontext,
+				    u32 scontext_len,
+				    struct context *ctx,
+				    u32 def_sid)
 {
-	char *scontext2;
-	struct context context;
+	char *scontext2 = NULL;
 	struct role_datum *role;
 	struct type_datum *typdatum;
 	struct user_datum *usrdatum;
 	char *scontextp, *p, oldc;
 	int rc = 0;
 
-	if (!ss_initialized) {
-		int i;
+	context_init(ctx);
 
-		for (i = 1; i < SECINITSID_NUM; i++) {
-			if (!strcmp(initial_sid_to_string[i], scontext)) {
-				*sid = i;
-				goto out;
-			}
-		}
-		*sid = SECINITSID_KERNEL;
-		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);
+	/* Copy the string so that we can modify the copy as we parse it. */
+	scontext2 = kmalloc(scontext_len+1, GFP_ATOMIC);
 	if (!scontext2) {
 		rc = -ENOMEM;
 		goto out;
@@ -656,11 +644,6 @@ static int security_context_to_sid_core(
 	memcpy(scontext2, scontext, scontext_len);
 	scontext2[scontext_len] = 0;
 
-	context_init(&context);
-	*sid = SECSID_NULL;
-
-	POLICY_RDLOCK;
-
 	/* Parse the security context. */
 
 	rc = -EINVAL;
@@ -672,15 +655,15 @@ static int security_context_to_sid_core(
 		p++;
 
 	if (*p == 0)
-		goto out_unlock;
+		goto out;
 
 	*p++ = 0;
 
-	usrdatum = hashtab_search(policydb.p_users.table, scontextp);
+	usrdatum = hashtab_search(pol->p_users.table, scontextp);
 	if (!usrdatum)
-		goto out_unlock;
+		goto out;
 
-	context.user = usrdatum->value;
+	ctx->user = usrdatum->value;
 
 	/* Extract role. */
 	scontextp = p;
@@ -688,14 +671,14 @@ static int security_context_to_sid_core(
 		p++;
 
 	if (*p == 0)
-		goto out_unlock;
+		goto out;
 
 	*p++ = 0;
 
-	role = hashtab_search(policydb.p_roles.table, scontextp);
+	role = hashtab_search(pol->p_roles.table, scontextp);
 	if (!role)
-		goto out_unlock;
-	context.role = role->value;
+		goto out;
+	ctx->role = role->value;
 
 	/* Extract type. */
 	scontextp = p;
@@ -704,33 +687,72 @@ static int security_context_to_sid_core(
 	oldc = *p;
 	*p++ = 0;
 
-	typdatum = hashtab_search(policydb.p_types.table, scontextp);
+	typdatum = hashtab_search(pol->p_types.table, scontextp);
 	if (!typdatum)
-		goto out_unlock;
+		goto out;
 
-	context.type = typdatum->value;
+	ctx->type = typdatum->value;
 
-	rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
+	rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid);
 	if (rc)
-		goto out_unlock;
+		goto out;
 
 	if ((p - scontext2) < scontext_len) {
 		rc = -EINVAL;
-		goto out_unlock;
+		goto out;
 	}
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &context)) {
+	if (!policydb_context_isvalid(pol, ctx)) {
 		rc = -EINVAL;
-		goto out_unlock;
+		context_destroy(ctx);
+		goto out;
 	}
-	/* Obtain the new sid. */
-	rc = sidtab_context_to_sid(&sidtab, &context, sid);
-out_unlock:
-	POLICY_RDUNLOCK;
-	context_destroy(&context);
+	rc = 0;
+out:
 	kfree(scontext2);
+	return rc;
+}
+
+static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid, int force)
+{
+	struct context context;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		int i;
+
+		for (i = 1; i < SECINITSID_NUM; i++) {
+			if (!strcmp(initial_sid_to_string[i], scontext)) {
+				*sid = i;
+				goto out;
+			}
+		}
+		*sid = SECINITSID_KERNEL;
+		goto out;
+	}
+	*sid = SECSID_NULL;
+
+	POLICY_RDLOCK;
+	rc = string_to_context_struct(&policydb, &sidtab,
+				      scontext, scontext_len,
+				      &context, def_sid);
+	if (rc == -EINVAL && force) {
+		context.str = kmalloc(scontext_len+1,GFP_ATOMIC);
+		if (!context.str) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		memcpy(context.str, scontext, scontext_len);
+		context.str[scontext_len] = 0;
+		context.len = scontext_len;
+	} else if (rc)
+		goto out;
+	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	if (rc)
+		context_destroy(&context);
 out:
+	POLICY_RDUNLOCK;
 	return rc;
 }
 
@@ -748,7 +770,7 @@ out:
 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-	                                    sid, SECSID_NULL);
+	                                    sid, SECSID_NULL, 0);
 }
 
 /**
@@ -765,13 +787,20 @@ int security_context_to_sid(char *sconte
  * The default SID is passed to the MLS layer to be used to allow
  * kernel labeling of the MLS field if the MLS field is not present
  * (for upgrading to MLS without full relabel).
+ * Implicitly forces adding of the context even if it cannot be mapped yet.
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
 int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-	                                    sid, def_sid);
+	                                    sid, def_sid, 1);
+}
+
+int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid)
+{
+	return security_context_to_sid_core(scontext, scontext_len,
+	                                    sid, SECSID_NULL, 1);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -1108,9 +1137,10 @@ static inline int convert_context_handle
 		char *s;
 		u32 len;
 
-		context_struct_to_string(context, &s, &len);
-		printk(KERN_ERR "security:  context %s is invalid\n", s);
-		kfree(s);
+		if (!context_struct_to_string(context, &s, &len)) {
+			printk(KERN_WARNING "SELinux:  Context %s would be invalid if enforcing\n", s);
+			kfree(s);
+		}
 	}
 	return rc;
 }
@@ -1142,6 +1172,27 @@ static int convert_context(u32 key,
 
 	args = p;
 
+	if (c->str) {
+		struct context ctx;
+		rc = string_to_context_struct(args->newp, NULL, c->str,
+					      c->len, &ctx, SECSID_NULL);
+		if (!rc) {
+			printk(KERN_INFO "SELinux:  Context %s became valid under new policy.\n", c->str);
+			/* Replace string with mapped representation. */
+			kfree(c->str);
+			memcpy(c, &ctx, sizeof(*c));
+			goto out;
+		} else if (rc == -EINVAL) {
+			/* Retain string representation for later mapping. */
+			rc = 0;
+			goto out;
+		} else {
+			/* Other error condition, e.g. ENOMEM. */
+			printk(KERN_ERR "SELinux:   Failed trying to map context %s (rc %d) under new policy, leaving unmapped.\n", c->str, -rc);
+			goto out;
+		}
+	}
+
 	rc = context_cpy(&oldc, c);
 	if (rc)
 		goto out;
@@ -1184,13 +1235,19 @@ static int convert_context(u32 key,
 	}
 
 	context_destroy(&oldc);
+	rc = 0;
 out:
 	return rc;
 bad:
-	context_struct_to_string(&oldc, &s, &len);
+	/* Map old representation to string and save it. */
+	if (context_struct_to_string(&oldc, &s, &len))
+		return -ENOMEM;
 	context_destroy(&oldc);
-	printk(KERN_ERR "security:  invalidating context %s\n", s);
-	kfree(s);
+	context_destroy(c);
+	c->str = s;
+	c->len = len;
+	printk(KERN_INFO "SELinux:  Context %s became invalid under new policy.\n", c->str);
+	rc = 0;
 	goto out;
 }
 
@@ -1249,7 +1306,11 @@ int security_load_policy(void *data, siz
 		return -EINVAL;
 	}
 
-	sidtab_init(&newsidtab);
+	if (sidtab_init(&newsidtab)) {
+		LOAD_UNLOCK;
+		policydb_destroy(&newpolicydb);
+		return -ENOMEM;
+	}
 
 	/* Verify that the existing classes did not change. */
 	if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
@@ -1267,10 +1328,12 @@ int security_load_policy(void *data, siz
 	}
 
 	/* Convert the internal representations of contexts
-	   in the new SID table and remove invalid SIDs. */
+	   in the new SID table. */
 	args.oldp = &policydb;
 	args.newp = &newpolicydb;
-	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
+	rc = sidtab_map(&newsidtab, convert_context, &args);
+	if (rc)
+		goto err;
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(&oldpolicydb, &policydb, sizeof policydb);
@@ -1520,6 +1583,8 @@ int security_get_user_sids(u32 fromsid,
 
 	POLICY_RDLOCK;
 
+	context_init(&usercon);
+
 	fromcon = sidtab_search(&sidtab, fromsid);
 	if (!fromcon) {
 		rc = -EINVAL;
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/ss/sidtab.c linux-2.6.17-rc3-mm1-x/security/selinux/ss/sidtab.c
--- linux-2.6.17-rc3-mm1/security/selinux/ss/sidtab.c	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc3-mm1-x/security/selinux/ss/sidtab.c	2006-05-15 10:20:08.000000000 -0400
@@ -100,7 +100,7 @@ struct context *sidtab_search(struct sid
 	while (cur != NULL && sid > cur->sid)
 		cur = cur->next;
 
-	if (cur == NULL || sid != cur->sid) {
+	if (cur == NULL || sid != cur->sid || cur->context.len) {
 		/* Remap invalid SIDs to the unlabeled SID. */
 		sid = SECINITSID_UNLABELED;
 		hvalue = SIDTAB_HASH(sid);
@@ -218,6 +218,8 @@ int sidtab_context_to_sid(struct sidtab 
 			goto unlock_out;
 		}
 		sid = s->next_sid++;
+		if (context->len)
+			printk(KERN_INFO "SELinux:  Context %s is not valid under current policy, adding as unmapped value.\n", context->str);
 		ret = sidtab_insert(s, sid, context);
 		if (ret)
 			s->next_sid--;

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-15 16:35 [RFC][PATCH] selinux: introduce support for deferred mapping of inode security contexts Stephen Smalley
@ 2006-05-15 17:41 ` Stephen Smalley
  2006-05-16 12:15 ` Stephen Smalley
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-15 17:41 UTC (permalink / raw)
  To: selinux; +Cc: Thomas Bleher, Daniel J Walsh, SELinux-dev, James Morris

On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
> Introduce support for deferring mapping of security contexts in the
> SID table upon policy reload, and use this support for inode security
> contexts when the context is not yet valid under the current policy.
> Only processes with 'labelpriv' permission to the 'security' class can
> set such invalid security contexts on inodes.  Inodes with such
> invalid contexts are treated as having the unlabeled SID until the context 
> becomes valid under a policy.  This support is for use by privileged processes
> like rpm that need to set down files in the proper security contexts prior to 
> loading the policy module that defines the context and its associated rules.

Also requires this diff on top of the other one to map labelpriv to a
string in avc messages:

diff -X /home/sds/dontdiff -rup linux-2.6.17-rc3-mm1/security/selinux/include/av_perm_to_string.h linux-2.6.17-rc3-mm1-x/security/selinux/include/av_perm_to_string.h
--- linux-2.6.17-rc3-mm1/security/selinux/include/av_perm_to_string.h	2006-05-15 13:22:03.000000000 -0400
+++ linux-2.6.17-rc3-mm1-x/security/selinux/include/av_perm_to_string.h	2006-05-15 12:26:56.000000000 -0400
@@ -87,6 +87,7 @@
    S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
    S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
    S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
+   S_(SECCLASS_SECURITY, SECURITY__LABELPRIV, "labelpriv")
    S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-15 16:35 [RFC][PATCH] selinux: introduce support for deferred mapping of inode security contexts Stephen Smalley
  2006-05-15 17:41 ` Stephen Smalley
@ 2006-05-16 12:15 ` Stephen Smalley
  2006-05-17  7:54 ` Thomas Bleher
  2006-05-19 13:44 ` Stephen Smalley
  3 siblings, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-16 12:15 UTC (permalink / raw)
  To: selinux; +Cc: Thomas Bleher, Daniel J Walsh, SELinux-dev, James Morris

On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
> # touch foo
> # chcon -t foo_exec_t foo
> # ls -Z foo
> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo

Note that an alternative would be to modify security_sid_to_context() to
return the unmapped string representation if it exists rather than just
falling through to the unlabeled SID's context.  In that case,
getxattr() would return the unmapped string, and userspace would see
user_u:object_r:foo_exec_t throughout the example even though the kernel
would internally be applying access checks based on the unlabeled SID's
context.  That seems useful for programs that want to check the
attributes (e.g. restore), but prevents rpm from easily checking whether
the attribute has been validated by a subsequent policy load (although
it could use security_check_context(3) for that purpose).  Likewise, if
an audit message is generated for a SID that has been invalidated,
having security_sid_to_context() return the unmapped string
representation would preserve the original string label in the audit
message rather than degenerating to the unlabeled SID's context.
Thoughts?

> # semodule -i foo.pp # defines foo_exec_t
> # ls -Z foo
> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> # semodule -r foo
> # ls -Z foo
> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> # semodule -i foo.pp
> # ls -Z foo
> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> 
> Logically, there are two separate changes here.  The first logical
> change is to support deferred mapping of security contexts in the SID
> table, storing their string representations when they cannot be mapped
> under the current policy, and treating them the same as the unlabeled
> SID while they are in this state.  Upon policy reloads, if a valid
> context becomes invalid under the new policy, rather than removing it
> from the SID table, we convert it to its string representation under the
> old policy and store that in the SID table until such a time as it
> becomes valid again, and if an invalid context becomes valid, we map it
> to its internal structure representation.  This change alone is
> worthwhile irrespective of the second change, as it addresses the
> longstanding issue with removing and re-adding types to policy when they
> are assigned to inodes.  The second logical change introduces the
> support for setting invalid contexts by privileged processes, both via
> setxattr() and via /proc/self/attr/fscreate, which is the more
> controversial aspect.  Note that contrary to my earlier expectations, no
> walking of the inode security structs is required, as the SIDs
> themselves remain invariant under such changes.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-15 16:35 [RFC][PATCH] selinux: introduce support for deferred mapping of inode security contexts Stephen Smalley
  2006-05-15 17:41 ` Stephen Smalley
  2006-05-16 12:15 ` Stephen Smalley
@ 2006-05-17  7:54 ` Thomas Bleher
  2006-05-17 17:52   ` Karl MacMillan
  2006-05-17 18:26   ` Stephen Smalley
  2006-05-19 13:44 ` Stephen Smalley
  3 siblings, 2 replies; 33+ messages in thread
From: Thomas Bleher @ 2006-05-17  7:54 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: selinux, Daniel J Walsh, SELinux-dev, James Morris, Jeremy Katz,
	Paul Nasrat, James Antill

[-- Attachment #1: Type: text/plain, Size: 2141 bytes --]

[Added CCs from earlier thread]

* Stephen Smalley <sds@tycho.nsa.gov> [2006-05-15 18:31]:
> During the earlier thread on splitting policy into individual packages
> (using policy modules), it was requested that SELinux provide a way for
> a privileged process (like a package manager) to label an inode with a
> not-yet-defined security context (treating it as having the unlabeled
> SID until defined in the policy) and then automatically update the
> in-memory state when a policy that defines the security context is
> loaded such that the inode immediately becomes accessible under the
> rules governing access to that context in the new policy.
[...]
> The second logical change introduces the
> support for setting invalid contexts by privileged processes, both via
> setxattr() and via /proc/self/attr/fscreate, which is the more
> controversial aspect.

I am still not convinced that we actually need this second change.

In http://marc.theaimsgroup.com/?l=selinux&m=114677075207486&w=2, I
outlined how rpm could work with the current kernel. I think this scheme
is preferable to changing the kernel, mainly because of two points:

* It makes it possible to later confine rpm more strictly:
  If you load policy before installing the package, you can use the
  policy server to prevent rpm from loading certain policies; rpm will
  only be able to put labels on disk it is allowed to by policy.
  If you load policy after package installation, rpm needs the labelpriv
  privilege, so you can't confine rpm in any meaningful sense.

* It allows rpm to know beforehand if the policy module will actually 
  apply on top of the current system policy (which is important if you 
  think of the differences between strict and targeted policy). It is
  better to abort install before than to have invalid labels on disk
  later.

As I didn't receive any response regarding my posting, I'd like to ask:
What prevents you from implementing it in a way similar to what I
described?
RPM already has trigger scripts so from the outside it looks like it
shouldn't be that hard to implement.

Thomas


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 191 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17  7:54 ` Thomas Bleher
@ 2006-05-17 17:52   ` Karl MacMillan
  2006-05-17 19:01     ` Stephen Smalley
  2006-05-18 18:14     ` Thomas Bleher
  2006-05-17 18:26   ` Stephen Smalley
  1 sibling, 2 replies; 33+ messages in thread
From: Karl MacMillan @ 2006-05-17 17:52 UTC (permalink / raw)
  To: Thomas Bleher
  Cc: Stephen Smalley, selinux, Daniel J Walsh, SELinux-dev,
	James Morris, Jeremy Katz, Paul Nasrat, James Antill

On Wed, 2006-05-17 at 09:54 +0200, Thomas Bleher wrote:
> [Added CCs from earlier thread]
> 
> * Stephen Smalley <sds@tycho.nsa.gov> [2006-05-15 18:31]:
> > During the earlier thread on splitting policy into individual packages
> > (using policy modules), it was requested that SELinux provide a way for
> > a privileged process (like a package manager) to label an inode with a
> > not-yet-defined security context (treating it as having the unlabeled
> > SID until defined in the policy) and then automatically update the
> > in-memory state when a policy that defines the security context is
> > loaded such that the inode immediately becomes accessible under the
> > rules governing access to that context in the new policy.
> [...]
> > The second logical change introduces the
> > support for setting invalid contexts by privileged processes, both via
> > setxattr() and via /proc/self/attr/fscreate, which is the more
> > controversial aspect.
> 
> I am still not convinced that we actually need this second change.
> 
> In http://marc.theaimsgroup.com/?l=selinux&m=114677075207486&w=2, I
> outlined how rpm could work with the current kernel. I think this scheme
> is preferable to changing the kernel, mainly because of two points:
> 
> * It makes it possible to later confine rpm more strictly:
>   If you load policy before installing the package, you can use the
>   policy server to prevent rpm from loading certain policies; rpm will
>   only be able to put labels on disk it is allowed to by policy.
>   If you load policy after package installation, rpm needs the labelpriv
>   privilege, so you can't confine rpm in any meaningful sense.
> 
> * It allows rpm to know beforehand if the policy module will actually 
>   apply on top of the current system policy (which is important if you 
>   think of the differences between strict and targeted policy). It is
>   better to abort install before than to have invalid labels on disk
>   later.
> 
> As I didn't receive any response regarding my posting, I'd like to ask:
> What prevents you from implementing it in a way similar to what I
> described?
> RPM already has trigger scripts so from the outside it looks like it
> shouldn't be that hard to implement.
> 

To get some realtime discussion going on this issue a telecon was held
with Red Hat, Tresys, and Steve participating. I'll try to summarize the
problems with the approaches that you, Josh, and I were pushing that
came out during that telecom. This is in the context of rpm, but I
believe that the problems are more general.

There are two basic ways to ensure that the policy needed by an rpm is
installed before that rpm: use package dependencies to make certain that
separate policy rpms are installed before rpms that require them or, as
you suggest, collect and install all of the policies from all of the
rpms at the start of the transaction.

The first solution does not work because it is not possible to order rpm
installation within a transaction based on dependencies because of
mutual and circular dependencies. There is _no_ general solution to
sorting packages so that dependencies are met at every step of the
transaction in the face of circular or mutual dependencies. Basically,
topological sorting only works for directed _acyclic_ graphs (see
http://en.wikipedia.org/wiki/Topological_sorting). Instead, rpm makes a
more general guarantee that the dependencies will be met at the end of
the transaction, which is not sufficient for our needs.

The second solution, which you describe, has two problems. As rpm works
now there are many circumstances, like network installations, where a
transaction begins without all of the rpms. Changing this would not only
be difficult, it is not clear that it would be desirable.

Even if all of the rpms were available, there are many potential
problems when a policy upgrade depends on a library or tool upgrade
(e.g., libsepol or semodule). This leads directly back to the dependency
problems.

This leads me to conclude that package managers may need to be able to
set raw contexts that are not currently valid. It is not a pleasant
trade-off, but it does have potential side benefits for backup and
restore tools.

Karl

-- 
Karl MacMillan
Tresys Technology
www.tresys.com

> Thomas
> 


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17  7:54 ` Thomas Bleher
  2006-05-17 17:52   ` Karl MacMillan
@ 2006-05-17 18:26   ` Stephen Smalley
  2006-05-17 18:28     ` Karl MacMillan
  1 sibling, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-17 18:26 UTC (permalink / raw)
  To: Thomas Bleher
  Cc: selinux, Daniel J Walsh, SELinux-dev, James Morris, Jeremy Katz,
	Paul Nasrat, James Antill

On Wed, 2006-05-17 at 09:54 +0200, Thomas Bleher wrote:
> In http://marc.theaimsgroup.com/?l=selinux&m=114677075207486&w=2, I
> outlined how rpm could work with the current kernel. I think this scheme
> is preferable to changing the kernel, mainly because of two points:
> 
> * It makes it possible to later confine rpm more strictly:
>   If you load policy before installing the package, you can use the
>   policy server to prevent rpm from loading certain policies; rpm will
>   only be able to put labels on disk it is allowed to by policy.
>   If you load policy after package installation, rpm needs the labelpriv
>   privilege, so you can't confine rpm in any meaningful sense.

>From the policy's perspective, rpm is being allowed to create/label
files with unlabeled_t (as the files are treated as such while the
labels are invalid) and to insert a policy module.  Access control on
what the policy module can contain (what types it may define and what
rules it may add) is the key to confining rpm (or rather, confining the
particular process spawned by rpm in a suitable domain for the package
being installed if rpm ever does that), and that is true regardless of
whether rpm loads policy before or after setting down the files.  To
close the loop between the undefined file labels and the policy module
that was checked, it is important that rpm verify that all of the file
labels set down by rpm became valid upon the policy load, and either
warn the admin or take some corrective action (whether that means
relabeling those files to truly be unlabeled_t, removing those files, or
reverting the package install altogether) if they are not.  I suppose
calling security_check_context() on each context from the header would
suffice, followed by either a warning or corrective action if it fails
on any of them.

> * It allows rpm to know beforehand if the policy module will actually 
>   apply on top of the current system policy (which is important if you 
>   think of the differences between strict and targeted policy). It is
>   better to abort install before than to have invalid labels on disk
>   later.

I agree that rpm shouldn't leave invalid labels around on disk.  This is
similar to the above problem.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17 18:26   ` Stephen Smalley
@ 2006-05-17 18:28     ` Karl MacMillan
  2006-05-17 18:43       ` Stephen Smalley
  0 siblings, 1 reply; 33+ messages in thread
From: Karl MacMillan @ 2006-05-17 18:28 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Thomas Bleher, selinux, Daniel J Walsh, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Wed, 2006-05-17 at 14:26 -0400, Stephen Smalley wrote:
> On Wed, 2006-05-17 at 09:54 +0200, Thomas Bleher wrote:
> > In http://marc.theaimsgroup.com/?l=selinux&m=114677075207486&w=2, I
> > outlined how rpm could work with the current kernel. I think this scheme
> > is preferable to changing the kernel, mainly because of two points:
> > 
> > * It makes it possible to later confine rpm more strictly:
> >   If you load policy before installing the package, you can use the
> >   policy server to prevent rpm from loading certain policies; rpm will
> >   only be able to put labels on disk it is allowed to by policy.
> >   If you load policy after package installation, rpm needs the labelpriv
> >   privilege, so you can't confine rpm in any meaningful sense.
> 
> >From the policy's perspective, rpm is being allowed to create/label
> files with unlabeled_t (as the files are treated as such while the
> labels are invalid) and to insert a policy module.  Access control on
> what the policy module can contain (what types it may define and what
> rules it may add) is the key to confining rpm (or rather, confining the
> particular process spawned by rpm in a suitable domain for the package
> being installed if rpm ever does that), and that is true regardless of
> whether rpm loads policy before or after setting down the files.  To
> close the loop between the undefined file labels and the policy module
> that was checked, it is important that rpm verify that all of the file
> labels set down by rpm became valid upon the policy load, and either
> warn the admin or take some corrective action (whether that means
> relabeling those files to truly be unlabeled_t, removing those files, or
> reverting the package install altogether) if they are not.  I suppose
> calling security_check_context() on each context from the header would
> suffice, followed by either a warning or corrective action if it fails
> on any of them.
> 

Only checking the contexts in the header would protect against malicious
packages but not a subverted rpm, right?

Karl

-- 
Karl MacMillan
Tresys Technology
www.tresys.com

> > * It allows rpm to know beforehand if the policy module will actually 
> >   apply on top of the current system policy (which is important if you 
> >   think of the differences between strict and targeted policy). It is
> >   better to abort install before than to have invalid labels on disk
> >   later.
> 
> I agree that rpm shouldn't leave invalid labels around on disk.  This is
> similar to the above problem.
> 


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17 18:28     ` Karl MacMillan
@ 2006-05-17 18:43       ` Stephen Smalley
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-17 18:43 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Thomas Bleher, selinux, Daniel J Walsh, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Wed, 2006-05-17 at 14:28 -0400, Karl MacMillan wrote:
> On Wed, 2006-05-17 at 14:26 -0400, Stephen Smalley wrote:
> > close the loop between the undefined file labels and the policy module
> > that was checked, it is important that rpm verify that all of the file
> > labels set down by rpm became valid upon the policy load, and either
> > warn the admin or take some corrective action (whether that means
> > relabeling those files to truly be unlabeled_t, removing those files, or
> > reverting the package install altogether) if they are not.  I suppose
> > calling security_check_context() on each context from the header would
> > suffice, followed by either a warning or corrective action if it fails
> > on any of them.
> > 
> 
> Only checking the contexts in the header would protect against malicious
> packages but not a subverted rpm, right?

Yes, unless rpm itself is decomposed, with one rpm process in one domain
performing the checking and one rpm process in another domain performing
the install and module insertion (which you need anyway if you want to
mediate policy module insertions based on package trustworthiness).  

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17 17:52   ` Karl MacMillan
@ 2006-05-17 19:01     ` Stephen Smalley
  2006-05-18 18:14     ` Thomas Bleher
  1 sibling, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-17 19:01 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Thomas Bleher, selinux, Daniel J Walsh, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Wed, 2006-05-17 at 13:52 -0400, Karl MacMillan wrote:
> This leads me to conclude that package managers may need to be able to
> set raw contexts that are not currently valid. It is not a pleasant
> trade-off, but it does have potential side benefits for backup and
> restore tools.

I don't think it is useful for restore(8), as lgetxattr() will show it
as unlabeled_t and compares will still fail.  Per the earlier discussion
on this thread.

It might have some utility in creating filesystems for a system running
a different policy than the build/host system.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-17 17:52   ` Karl MacMillan
  2006-05-17 19:01     ` Stephen Smalley
@ 2006-05-18 18:14     ` Thomas Bleher
  2006-05-19 12:59       ` Stephen Smalley
  1 sibling, 1 reply; 33+ messages in thread
From: Thomas Bleher @ 2006-05-18 18:14 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Stephen Smalley, selinux, Daniel J Walsh, SELinux-dev,
	James Morris, Jeremy Katz, Paul Nasrat, James Antill

[-- Attachment #1: Type: text/plain, Size: 5436 bytes --]

* Karl MacMillan <kmacmillan@tresys.com> [2006-05-17 19:55]:
> On Wed, 2006-05-17 at 09:54 +0200, Thomas Bleher wrote:
> > [Added CCs from earlier thread]
> > 
> > * Stephen Smalley <sds@tycho.nsa.gov> [2006-05-15 18:31]:
> > > During the earlier thread on splitting policy into individual packages
> > > (using policy modules), it was requested that SELinux provide a way for
> > > a privileged process (like a package manager) to label an inode with a
> > > not-yet-defined security context (treating it as having the unlabeled
> > > SID until defined in the policy) and then automatically update the
> > > in-memory state when a policy that defines the security context is
> > > loaded such that the inode immediately becomes accessible under the
> > > rules governing access to that context in the new policy.
> > [...]
> > > The second logical change introduces the
> > > support for setting invalid contexts by privileged processes, both via
> > > setxattr() and via /proc/self/attr/fscreate, which is the more
> > > controversial aspect.
> > 
> > I am still not convinced that we actually need this second change.
> > 
> > In http://marc.theaimsgroup.com/?l=selinux&m=114677075207486&w=2, I
> > outlined how rpm could work with the current kernel. I think this scheme
> > is preferable to changing the kernel, mainly because of two points:
> > 
> > * It makes it possible to later confine rpm more strictly:
> >   If you load policy before installing the package, you can use the
> >   policy server to prevent rpm from loading certain policies; rpm will
> >   only be able to put labels on disk it is allowed to by policy.
> >   If you load policy after package installation, rpm needs the labelpriv
> >   privilege, so you can't confine rpm in any meaningful sense.
> > 
> > * It allows rpm to know beforehand if the policy module will actually 
> >   apply on top of the current system policy (which is important if you 
> >   think of the differences between strict and targeted policy). It is
> >   better to abort install before than to have invalid labels on disk
> >   later.
> > 
> > As I didn't receive any response regarding my posting, I'd like to ask:
> > What prevents you from implementing it in a way similar to what I
> > described?
> > RPM already has trigger scripts so from the outside it looks like it
> > shouldn't be that hard to implement.
> > 
> 
> To get some realtime discussion going on this issue a telecon was held
> with Red Hat, Tresys, and Steve participating. I'll try to summarize the
> problems with the approaches that you, Josh, and I were pushing that
> came out during that telecom. This is in the context of rpm, but I
> believe that the problems are more general.
> 
> There are two basic ways to ensure that the policy needed by an rpm is
> installed before that rpm: use package dependencies to make certain that
> separate policy rpms are installed before rpms that require them or, as
> you suggest, collect and install all of the policies from all of the
> rpms at the start of the transaction.
> 
> The first solution does not work because it is not possible to order rpm
> installation within a transaction based on dependencies because of
> mutual and circular dependencies. There is _no_ general solution to
> sorting packages so that dependencies are met at every step of the
> transaction in the face of circular or mutual dependencies. Basically,
> topological sorting only works for directed _acyclic_ graphs (see
> http://en.wikipedia.org/wiki/Topological_sorting). Instead, rpm makes a
> more general guarantee that the dependencies will be met at the end of
> the transaction, which is not sufficient for our needs.
> 
> The second solution, which you describe, has two problems. As rpm works
> now there are many circumstances, like network installations, where a
> transaction begins without all of the rpms. Changing this would not only
> be difficult, it is not clear that it would be desirable.
> 
> Even if all of the rpms were available, there are many potential
> problems when a policy upgrade depends on a library or tool upgrade
> (e.g., libsepol or semodule). This leads directly back to the dependency
> problems.
> 
> This leads me to conclude that package managers may need to be able to
> set raw contexts that are not currently valid. It is not a pleasant
> trade-off, but it does have potential side benefits for backup and
> restore tools.

Thank you for your explanation.
I see that these are very difficult issues, but I must admit that I
still feel very uneasy about the proposed changes.

So let me suggest one more possibility:
rpm installs the package, puts the labels on disk and afterwards
installs the policy (like Dan proposed originally). 
EXCEPT: Whenever rpm finds that the label it wants to put on disk is not
valid in the current policy, it labels the file as unlabeled_t (or some
other special label). After rpm has installed the policy, it relabels
the guilty files. This adds no overhead - rpm already knows the paths and
the labels, and it would have had to visit the files anyway to verify
their labels -, looks exactly the same from the outside, doesn't require
kernel changes and makes it possible to later restrict rpm.

Now, you can't decline such an offer, can you? ;-)

Or am I missing something fundamental here?

Thomas


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 191 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-18 18:14     ` Thomas Bleher
@ 2006-05-19 12:59       ` Stephen Smalley
  2006-05-19 13:18         ` Joshua Brindle
  2006-05-19 13:18         ` Karl MacMillan
  0 siblings, 2 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-19 12:59 UTC (permalink / raw)
  To: Thomas Bleher
  Cc: Karl MacMillan, selinux, Daniel J Walsh, SELinux-dev,
	James Morris, Jeremy Katz, Paul Nasrat, James Antill

On Thu, 2006-05-18 at 20:14 +0200, Thomas Bleher wrote:
> Thank you for your explanation.
> I see that these are very difficult issues, but I must admit that I
> still feel very uneasy about the proposed changes.
> 
> So let me suggest one more possibility:
> rpm installs the package, puts the labels on disk and afterwards
> installs the policy (like Dan proposed originally). 
> EXCEPT: Whenever rpm finds that the label it wants to put on disk is not
> valid in the current policy, it labels the file as unlabeled_t (or some
> other special label). After rpm has installed the policy, it relabels
> the guilty files. This adds no overhead - rpm already knows the paths and
> the labels, and it would have had to visit the files anyway to verify
> their labels -, looks exactly the same from the outside, doesn't require
> kernel changes and makes it possible to later restrict rpm.
> 
> Now, you can't decline such an offer, can you? ;-)
> 
> Or am I missing something fundamental here?

In the labelpriv model, rpm doesn't have to visit the individual files
afterward in the common case; it just calls security_check_context(3) on
each distinct context stored in the rpm header (once per context, not
per file) after the module insertion phase, and if any of them are still
invalid (the uncommon case), rpm then takes corrective action (whether
that means relabeling files that had those invalid labels to truly be
unlabeled_t, removing those files, or reverting the install altogether -
the latter seems cleanest to me).  If we can't get a guarantee that rpm
will perform such checking and take corrective action, then I'd agree
that the kernel change is a no-go.

With regard to restricting rpm, under both models, rpm is being allowed
to set down unlabeled_t files and to insert policy modules.  Restricting
rpm meaningfully under either model requires fine-grained mediation of
what those policy modules may contain, which requires the use of the
policy management server as the libsemanage back end to enforce such
mediation.  Restricting rpm meaningfully under either model also
requires decomposition of rpm, so that not all of rpm has to run with
the same rights and the core rpm processing can run with different
rights depending on the package characteristics.  Given such mediation
and decomposition, having a small rpm helper in its own domain that
verifies that the header contexts are valid after module insertion,
taking corrective action if necessary, would address the linkage between
the header contexts and the module contents.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 12:59       ` Stephen Smalley
@ 2006-05-19 13:18         ` Joshua Brindle
  2006-05-19 13:18         ` Karl MacMillan
  1 sibling, 0 replies; 33+ messages in thread
From: Joshua Brindle @ 2006-05-19 13:18 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Thomas Bleher, Karl MacMillan, selinux, Daniel J Walsh,
	SELinux-dev, James Morris, Jeremy Katz, Paul Nasrat, James Antill

Stephen Smalley wrote:
> On Thu, 2006-05-18 at 20:14 +0200, Thomas Bleher wrote:
>   
>> Thank you for your explanation.
>> I see that these are very difficult issues, but I must admit that I
>> still feel very uneasy about the proposed changes.
>>
>> So let me suggest one more possibility:
>> rpm installs the package, puts the labels on disk and afterwards
>> installs the policy (like Dan proposed originally). 
>> EXCEPT: Whenever rpm finds that the label it wants to put on disk is not
>> valid in the current policy, it labels the file as unlabeled_t (or some
>> other special label). After rpm has installed the policy, it relabels
>> the guilty files. This adds no overhead - rpm already knows the paths and
>> the labels, and it would have had to visit the files anyway to verify
>> their labels -, looks exactly the same from the outside, doesn't require
>> kernel changes and makes it possible to later restrict rpm.
>>
>> Now, you can't decline such an offer, can you? ;-)
>>
>> Or am I missing something fundamental here?
>>     
> In the labelpriv model, rpm doesn't have to visit the individual files
> afterward in the common case; it just calls security_check_context(3) on
> each distinct context stored in the rpm header (once per context, not
> per file) after the module insertion phase, and if any of them are still
> invalid (the uncommon case), rpm then takes corrective action (whether
> that means relabeling files that had those invalid labels to truly be
> unlabeled_t, removing those files, or reverting the install altogether -
> the latter seems cleanest to me).  If we can't get a guarantee that rpm
> will perform such checking and take corrective action, then I'd agree
> that the kernel change is a no-go.
>   
Or just use matchpathcon() to label it. The installed file contexts are 
implicitly trusted anyway, I don't see how it could hurt to revert to 
defaults. Then again, an unlabeled file after the reload could indicate 
an error in the package, policy, etc. On this note, how do you expect 
this helper to work? I don't think that rpm maintains a list of files 
per-transaction and since the post-script order can't be guaranteed you 
never know when a particular policy has been reloaded (mutual dependency 
problem, mta policy declares sendmail_t but sendmail package puts down 
the file). There are probably other cases where this is problematic.

> With regard to restricting rpm, under both models, rpm is being allowed
> to set down unlabeled_t files and to insert policy modules.  Restricting
> rpm meaningfully under either model requires fine-grained mediation of
> what those policy modules may contain, which requires the use of the
> policy management server as the libsemanage back end to enforce such
> mediation.  Restricting rpm meaningfully under either model also
> requires decomposition of rpm, so that not all of rpm has to run with
> the same rights and the core rpm processing can run with different
> rights depending on the package characteristics.  Given such mediation
> and decomposition, having a small rpm helper in its own domain that
> verifies that the header contexts are valid after module insertion,
> taking corrective action if necessary, would address the linkage between
> the header contexts and the module contents.
>   
Right, unfortunately it looks like rpm will have this capability long 
before the policy management server is ready to be dropped in. We also 
haven't solved the hierarchal -policy-in-refpolicy problem which is 
necessary for any meaningful policy enforcement.

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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 12:59       ` Stephen Smalley
  2006-05-19 13:18         ` Joshua Brindle
@ 2006-05-19 13:18         ` Karl MacMillan
  2006-05-23 17:15           ` Stephen Smalley
  1 sibling, 1 reply; 33+ messages in thread
From: Karl MacMillan @ 2006-05-19 13:18 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Thomas Bleher, selinux, Daniel J Walsh, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Fri, 2006-05-19 at 08:59 -0400, Stephen Smalley wrote:
> On Thu, 2006-05-18 at 20:14 +0200, Thomas Bleher wrote:
> > Thank you for your explanation.
> > I see that these are very difficult issues, but I must admit that I
> > still feel very uneasy about the proposed changes.
> > 
> > So let me suggest one more possibility:
> > rpm installs the package, puts the labels on disk and afterwards
> > installs the policy (like Dan proposed originally). 
> > EXCEPT: Whenever rpm finds that the label it wants to put on disk is not
> > valid in the current policy, it labels the file as unlabeled_t (or some
> > other special label). After rpm has installed the policy, it relabels
> > the guilty files. This adds no overhead - rpm already knows the paths and
> > the labels, and it would have had to visit the files anyway to verify
> > their labels -, looks exactly the same from the outside, doesn't require
> > kernel changes and makes it possible to later restrict rpm.
> > 
> > Now, you can't decline such an offer, can you? ;-)
> > 
> > Or am I missing something fundamental here?
> 
> In the labelpriv model, rpm doesn't have to visit the individual files
> afterward in the common case; it just calls security_check_context(3) on
> each distinct context stored in the rpm header (once per context, not
> per file) after the module insertion phase, and if any of them are still
> invalid (the uncommon case), rpm then takes corrective action (whether
> that means relabeling files that had those invalid labels to truly be
> unlabeled_t, removing those files, or reverting the install altogether -
> the latter seems cleanest to me).  If we can't get a guarantee that rpm
> will perform such checking and take corrective action, then I'd agree
> that the kernel change is a no-go.
> 

The question is when the labels will become valid.

Thinking through this more I realized that if we cannot guarantee
ordering within a transaction we cannot commit any policy modules until
the end of the transaction. Otherwise it will not be possible to have
_any_ dependencies between policy modules, which doesn't seem likely
based on my recent investigations into refpolicy dependencies.

If policy modules are only committed at the end of the transaction,
verification of the rpms will require going back through the headers of
every rpm in the transaction.

Dan, Jeremy, Paul, any thoughts about when the policy modules will be
committed?

Karl

-- 
Karl MacMillan
Tresys Technology
www.tresys.com

> With regard to restricting rpm, under both models, rpm is being allowed
> to set down unlabeled_t files and to insert policy modules.  Restricting
> rpm meaningfully under either model requires fine-grained mediation of
> what those policy modules may contain, which requires the use of the
> policy management server as the libsemanage back end to enforce such
> mediation.  Restricting rpm meaningfully under either model also
> requires decomposition of rpm, so that not all of rpm has to run with
> the same rights and the core rpm processing can run with different
> rights depending on the package characteristics.  Given such mediation
> and decomposition, having a small rpm helper in its own domain that
> verifies that the header contexts are valid after module insertion,
> taking corrective action if necessary, would address the linkage between
> the header contexts and the module contents.
> 


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-15 16:35 [RFC][PATCH] selinux: introduce support for deferred mapping of inode security contexts Stephen Smalley
                   ` (2 preceding siblings ...)
  2006-05-17  7:54 ` Thomas Bleher
@ 2006-05-19 13:44 ` Stephen Smalley
  2006-05-19 13:59   ` Daniel J Walsh
  3 siblings, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-19 13:44 UTC (permalink / raw)
  To: selinux; +Cc: Thomas Bleher, Daniel J Walsh, SELinux-dev, James Morris

On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
> With this patch applied, the following sequence is possible, subject to
> policy, which must allow <domain> security_t:security labelpriv; and
> allow unlabeled_t fs_t:filesystem associate; in order for this to work
> in enforcing mode.  Note that unconfined_t implicitly picks up all
> security permissions at present due to the use of a wildcard for the
> permission set in its rule.  However, you still need the second allow
> rule as well in order for this to succeed in enforcing mode.  
> 
> # touch foo
> # chcon -t foo_exec_t foo
> # ls -Z foo
> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> # semodule -i foo.pp # defines foo_exec_t
> # ls -Z foo
> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> # semodule -r foo
> # ls -Z foo
> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> # semodule -i foo.pp
> # ls -Z foo
> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo

Eric Paris pointed out that the above behavior violates the principle of
least surprise for users (chcon appears to succeed but leaves the file
with unlabeled_t).  So to clarify:  The intent would be to exclude
labelpriv permission from even unconfined_t and to only allow it to
specific program domains (initially only package manager domains) where
the program expects such behavior and performs some verification
separately once the file context is expected to be valid.  Of course,
this requires that rpm_t not be an alias of unconfined_t, which is true
in FC5 (but not in FC4).

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 13:44 ` Stephen Smalley
@ 2006-05-19 13:59   ` Daniel J Walsh
  2006-05-19 14:14     ` Stephen Smalley
  0 siblings, 1 reply; 33+ messages in thread
From: Daniel J Walsh @ 2006-05-19 13:59 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, Thomas Bleher, SELinux-dev, James Morris

Stephen Smalley wrote:
> On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
>   
>> With this patch applied, the following sequence is possible, subject to
>> policy, which must allow <domain> security_t:security labelpriv; and
>> allow unlabeled_t fs_t:filesystem associate; in order for this to work
>> in enforcing mode.  Note that unconfined_t implicitly picks up all
>> security permissions at present due to the use of a wildcard for the
>> permission set in its rule.  However, you still need the second allow
>> rule as well in order for this to succeed in enforcing mode.  
>>
>> # touch foo
>> # chcon -t foo_exec_t foo
>> # ls -Z foo
>> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
>> # semodule -i foo.pp # defines foo_exec_t
>> # ls -Z foo
>> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
>> # semodule -r foo
>> # ls -Z foo
>> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
>> # semodule -i foo.pp
>> # ls -Z foo
>> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
>>     
>
> Eric Paris pointed out that the above behavior violates the principle of
> least surprise for users (chcon appears to succeed but leaves the file
> with unlabeled_t).  So to clarify:  The intent would be to exclude
> labelpriv permission from even unconfined_t and to only allow it to
> specific program domains (initially only package manager domains) where
> the program expects such behavior and performs some verification
> separately once the file context is expected to be valid.  Of course,
> this requires that rpm_t not be an alias of unconfined_t, which is true
> in FC5 (but not in FC4).
>
>   
We already have this problem in targeted with aliases.

Try
# ls -lZ /lib/libselinux.so.1
-rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1
# chcon -t shlib_t /lib/libselinux.so.1
# ls -lZ /lib/libselinux.so.1
-rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1






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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
@ 2006-05-19 14:05 Joshua Brindle
  2006-05-19 14:18 ` Stephen Smalley
  0 siblings, 1 reply; 33+ messages in thread
From: Joshua Brindle @ 2006-05-19 14:05 UTC (permalink / raw)
  To: Daniel J Walsh, Stephen Smalley
  Cc: selinux, Thomas Bleher, selinux-dev, James Morris

> From: Daniel J Walsh [mailto:dwalsh@redhat.com] 
> 
> Stephen Smalley wrote:
> > On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
> >   
> >> With this patch applied, the following sequence is 
> possible, subject 
> >> to policy, which must allow <domain> security_t:security 
> labelpriv; 
> >> and allow unlabeled_t fs_t:filesystem associate; in order 
> for this to 
> >> work in enforcing mode.  Note that unconfined_t implicitly 
> picks up 
> >> all security permissions at present due to the use of a 
> wildcard for 
> >> the permission set in its rule.  However, you still need 
> the second 
> >> allow rule as well in order for this to succeed in enforcing mode.
> >>
> >> # touch foo
> >> # chcon -t foo_exec_t foo
> >> # ls -Z foo
> >> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> >> # semodule -i foo.pp # defines foo_exec_t # ls -Z foo
> >> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> >> # semodule -r foo
> >> # ls -Z foo
> >> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> >> # semodule -i foo.pp
> >> # ls -Z foo
> >> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> >>     
> >
> > Eric Paris pointed out that the above behavior violates the 
> principle 
> > of least surprise for users (chcon appears to succeed but 
> leaves the 
> > file with unlabeled_t).  So to clarify:  The intent would be to 
> > exclude labelpriv permission from even unconfined_t and to 
> only allow 
> > it to specific program domains (initially only package manager 
> > domains) where the program expects such behavior and performs some 
> > verification separately once the file context is expected 
> to be valid.  
> > Of course, this requires that rpm_t not be an alias of 
> unconfined_t, 
> > which is true in FC5 (but not in FC4).
> >
> >   
> We already have this problem in targeted with aliases.
> 
> Try
> # ls -lZ /lib/libselinux.so.1
> -rwxr-xr-x  root root system_u:object_r:lib_t          
> /lib/libselinux.so.1
> # chcon -t shlib_t /lib/libselinux.so.1
> # ls -lZ /lib/libselinux.so.1
> -rwxr-xr-x  root root system_u:object_r:lib_t          
> /lib/libselinux.so.1
> 

Another reason why canonicalizing the paths on getxattr() is non-ideal.
Why can't we use an alternate interface for canonicalizing paths
(optionally, if the client wants it).


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 13:59   ` Daniel J Walsh
@ 2006-05-19 14:14     ` Stephen Smalley
  2006-05-19 14:20       ` Daniel J Walsh
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-19 14:14 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: selinux, Thomas Bleher, SELinux-dev, James Morris

On Fri, 2006-05-19 at 09:59 -0400, Daniel J Walsh wrote:
> Stephen Smalley wrote:
> > On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
> >   
> >> With this patch applied, the following sequence is possible, subject to
> >> policy, which must allow <domain> security_t:security labelpriv; and
> >> allow unlabeled_t fs_t:filesystem associate; in order for this to work
> >> in enforcing mode.  Note that unconfined_t implicitly picks up all
> >> security permissions at present due to the use of a wildcard for the
> >> permission set in its rule.  However, you still need the second allow
> >> rule as well in order for this to succeed in enforcing mode.  
> >>
> >> # touch foo
> >> # chcon -t foo_exec_t foo
> >> # ls -Z foo
> >> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> >> # semodule -i foo.pp # defines foo_exec_t
> >> # ls -Z foo
> >> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> >> # semodule -r foo
> >> # ls -Z foo
> >> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
> >> # semodule -i foo.pp
> >> # ls -Z foo
> >> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
> >>     
> >
> > Eric Paris pointed out that the above behavior violates the principle of
> > least surprise for users (chcon appears to succeed but leaves the file
> > with unlabeled_t).  So to clarify:  The intent would be to exclude
> > labelpriv permission from even unconfined_t and to only allow it to
> > specific program domains (initially only package manager domains) where
> > the program expects such behavior and performs some verification
> > separately once the file context is expected to be valid.  Of course,
> > this requires that rpm_t not be an alias of unconfined_t, which is true
> > in FC5 (but not in FC4).
> >
> >   
> We already have this problem in targeted with aliases.
> 
> Try
> # ls -lZ /lib/libselinux.so.1
> -rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1
> # chcon -t shlib_t /lib/libselinux.so.1
> # ls -lZ /lib/libselinux.so.1
> -rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1

Not quite the same issue.  In that case, shlib_t is a valid type; it
just happens to be aliased to lib_t in targeted policy.  So the user
gets the expected behavior, i.e. the file becomes accessible under the
rules associated with that type.  And if the user enters a type that is
completely undefined by the policy, he still gets an error.

With labelpriv, if user has a simple typo (e.g. http_sys_content_t
instead of httpd_sys_content_t), he gets no error from chcon, and that
string is stored with the file, but the file is treated internally as
unlabeled_t.  Thus it is _not_ accessible under the rules associated
with the type he meant to apply.

In any event, as long as we exclude this permission (via ~labelpriv or
by explicitly enumerating the allowed security permissions) from
unconfined_t going forward, it shouldn't be a problem.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 14:05 Joshua Brindle
@ 2006-05-19 14:18 ` Stephen Smalley
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-19 14:18 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: Daniel J Walsh, selinux, Thomas Bleher, selinux-dev, James Morris

On Fri, 2006-05-19 at 10:05 -0400, Joshua Brindle wrote:
> > We already have this problem in targeted with aliases.
> > 
> > Try
> > # ls -lZ /lib/libselinux.so.1
> > -rwxr-xr-x  root root system_u:object_r:lib_t          
> > /lib/libselinux.so.1
> > # chcon -t shlib_t /lib/libselinux.so.1
> > # ls -lZ /lib/libselinux.so.1
> > -rwxr-xr-x  root root system_u:object_r:lib_t          
> > /lib/libselinux.so.1
> > 
> 
> Another reason why canonicalizing the paths on getxattr() is non-ideal.
> Why can't we use an alternate interface for canonicalizing paths
> (optionally, if the client wants it).

The original motivation for the getxattr canonicalization was to make
the transition to MCS (MLS-enabled) transparent.  Which required it to
be transparently applied to all callers, not just a few.
It also solved our longstanding problem with not being able to see the
effective MAC label of e.g. mountpoint-labeled filesystems, genfs
filesystems, /proc nodes, etc.  It wasn't so much about canonicalization
as it was about getting the incore inode label of a given inode.
Canonicalization just happens automatically when converting back and
forth between SIDs and contexts because sid_to_context always returns
the primary names.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 14:14     ` Stephen Smalley
@ 2006-05-19 14:20       ` Daniel J Walsh
  0 siblings, 0 replies; 33+ messages in thread
From: Daniel J Walsh @ 2006-05-19 14:20 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, Thomas Bleher, SELinux-dev, James Morris

Stephen Smalley wrote:
> On Fri, 2006-05-19 at 09:59 -0400, Daniel J Walsh wrote:
>   
>> Stephen Smalley wrote:
>>     
>>> On Mon, 2006-05-15 at 12:35 -0400, Stephen Smalley wrote:
>>>   
>>>       
>>>> With this patch applied, the following sequence is possible, subject to
>>>> policy, which must allow <domain> security_t:security labelpriv; and
>>>> allow unlabeled_t fs_t:filesystem associate; in order for this to work
>>>> in enforcing mode.  Note that unconfined_t implicitly picks up all
>>>> security permissions at present due to the use of a wildcard for the
>>>> permission set in its rule.  However, you still need the second allow
>>>> rule as well in order for this to succeed in enforcing mode.  
>>>>
>>>> # touch foo
>>>> # chcon -t foo_exec_t foo
>>>> # ls -Z foo
>>>> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
>>>> # semodule -i foo.pp # defines foo_exec_t
>>>> # ls -Z foo
>>>> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
>>>> # semodule -r foo
>>>> # ls -Z foo
>>>> -rw-r--r--  root root system_u:object_r:unlabeled_t    foo
>>>> # semodule -i foo.pp
>>>> # ls -Z foo
>>>> -rw-r--r--  root root user_u:object_r:foo_exec_t       foo
>>>>     
>>>>         
>>> Eric Paris pointed out that the above behavior violates the principle of
>>> least surprise for users (chcon appears to succeed but leaves the file
>>> with unlabeled_t).  So to clarify:  The intent would be to exclude
>>> labelpriv permission from even unconfined_t and to only allow it to
>>> specific program domains (initially only package manager domains) where
>>> the program expects such behavior and performs some verification
>>> separately once the file context is expected to be valid.  Of course,
>>> this requires that rpm_t not be an alias of unconfined_t, which is true
>>> in FC5 (but not in FC4).
>>>
>>>   
>>>       
>> We already have this problem in targeted with aliases.
>>
>> Try
>> # ls -lZ /lib/libselinux.so.1
>> -rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1
>> # chcon -t shlib_t /lib/libselinux.so.1
>> # ls -lZ /lib/libselinux.so.1
>> -rwxr-xr-x  root root system_u:object_r:lib_t          /lib/libselinux.so.1
>>     
>  
> Not quite the same issue.  In that case, shlib_t is a valid type; it
> just happens to be aliased to lib_t in targeted policy.  So the user
> gets the expected behavior, i.e. the file becomes accessible under the
> rules associated with that type.  And if the user enters a type that is
> completely undefined by the policy, he still gets an error.
>
> With labelpriv, if user has a simple typo (e.g. http_sys_content_t
> instead of httpd_sys_content_t), he gets no error from chcon, and that
> string is stored with the file, but the file is treated internally as
> unlabeled_t.  Thus it is _not_ accessible under the rules associated
> with the type he meant to apply.
>
> In any event, as long as we exclude this permission (via ~labelpriv or
> by explicitly enumerating the allowed security permissions) from
> unconfined_t going forward, it shouldn't be a problem.
>
>   
Yes the only app that should have labelpriv is the installer.  (rpm_t)  
I am not sure if
other installers would need this.

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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-19 13:18         ` Karl MacMillan
@ 2006-05-23 17:15           ` Stephen Smalley
  2006-05-23 18:23             ` Daniel J Walsh
  2006-05-24 17:24             ` Jeremy Katz
  0 siblings, 2 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-23 17:15 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Thomas Bleher, selinux, Daniel J Walsh, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Fri, 2006-05-19 at 09:18 -0400, Karl MacMillan wrote:
> On Fri, 2006-05-19 at 08:59 -0400, Stephen Smalley wrote:
> > In the labelpriv model, rpm doesn't have to visit the individual files
> > afterward in the common case; it just calls security_check_context(3) on
> > each distinct context stored in the rpm header (once per context, not
> > per file) after the module insertion phase, and if any of them are still
> > invalid (the uncommon case), rpm then takes corrective action (whether
> > that means relabeling files that had those invalid labels to truly be
> > unlabeled_t, removing those files, or reverting the install altogether -
> > the latter seems cleanest to me).  If we can't get a guarantee that rpm
> > will perform such checking and take corrective action, then I'd agree
> > that the kernel change is a no-go.
> > 
> 
> The question is when the labels will become valid.
> 
> Thinking through this more I realized that if we cannot guarantee
> ordering within a transaction we cannot commit any policy modules until
> the end of the transaction. Otherwise it will not be possible to have
> _any_ dependencies between policy modules, which doesn't seem likely
> based on my recent investigations into refpolicy dependencies.
> 
> If policy modules are only committed at the end of the transaction,
> verification of the rpms will require going back through the headers of
> every rpm in the transaction.
> 
> Dan, Jeremy, Paul, any thoughts about when the policy modules will be
> committed?

Below is an updated version of the kernel patch to support rpm labeling
of files before policy load, with a couple of bug fixes and a re-base to
2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
resolve the issues of how rpm will check file label validity after
policy load (e.g. calling security_check_context(3) on each label from
the header), what corrective action rpm will take if a file label is
invalid (options suggested include relabeling to unlabeled_t, relabeling
to the context returned by the system policy via matchpathcon, or
reverting the install), and the issues raised by Karl above (as they
also affect the ability of rpm to perform such verification and
correction sanely).

---<snip>---

Introduce support for deferring mapping of security contexts in the
SID table upon policy reload, and use this support for inode security
contexts when the context is not yet valid under the current policy.
Only processes with 'labelpriv' permission to the 'security' class can
set such invalid security contexts on inodes.  Inodes with such
invalid contexts are treated as having the unlabeled SID until the context 
becomes valid under a policy.  This support is for use by privileged processes
like rpm that need to set down files in the proper security contexts prior to 
loading the policy module that defines the context and its associated rules.

---

 security/selinux/hooks.c                     |   16 +-
 security/selinux/include/av_perm_to_string.h |    1 
 security/selinux/include/av_permissions.h    |    1 
 security/selinux/include/objsec.h            |    3 
 security/selinux/include/security.h          |    2 
 security/selinux/selinuxfs.c                 |    4 
 security/selinux/ss/context.h                |   17 ++
 security/selinux/ss/mls.c                    |   11 -
 security/selinux/ss/mls.h                    |    3 
 security/selinux/ss/services.c               |  213 +++++++++++++++++----------
 security/selinux/ss/sidtab.c                 |    4 
 11 files changed, 189 insertions(+), 86 deletions(-)

diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/hooks.c linux-2.6.17-rc4-mm3-x/security/selinux/hooks.c
--- linux-2.6.17-rc4-mm3/security/selinux/hooks.c	2006-05-22 09:09:46.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/hooks.c	2006-05-23 08:57:55.000000000 -0400
@@ -2165,6 +2165,11 @@ static int selinux_inode_setxattr(struct
 		return rc;
 
 	rc = security_context_to_sid(value, size, &newsid);
+	if (rc == -EINVAL) {
+		if (task_has_security(current, SECURITY__LABELPRIV))
+			return rc;
+		rc = security_context_to_sid_force(value, size, &newsid);
+	}
 	if (rc)
 		return rc;
 
@@ -2198,10 +2203,11 @@ static void selinux_inode_post_setxattr(
 		return;
 	}
 
-	rc = security_context_to_sid(value, size, &newsid);
+	rc = security_context_to_sid_force(value, size, &newsid);
 	if (rc) {
 		printk(KERN_WARNING "%s:  unable to obtain SID for context "
-		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
+		       "%s on (%s, %lu), rc=%d\n", __FUNCTION__, (char*)value,
+		       inode->i_sb->s_id, inode->i_ino, -rc);
 		return;
 	}
 
@@ -4186,6 +4192,12 @@ static int selinux_setprocattr(struct ta
 			size--;
 		}
 		error = security_context_to_sid(value, size, &sid);
+		if (error == -EINVAL && !strcmp(name, "fscreate")) {
+			if (task_has_security(current, SECURITY__LABELPRIV))
+				return error;
+			error = security_context_to_sid_force(value, size,
+							      &sid);
+		}
 		if (error)
 			return error;
 	}
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/av_permissions.h linux-2.6.17-rc4-mm3-x/security/selinux/include/av_permissions.h
--- linux-2.6.17-rc4-mm3/security/selinux/include/av_permissions.h	2006-05-22 09:09:46.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/include/av_permissions.h	2006-05-23 08:57:55.000000000 -0400
@@ -526,6 +526,7 @@
 #define SECURITY__SETBOOL                         0x00000100UL
 #define SECURITY__SETSECPARAM                     0x00000200UL
 #define SECURITY__SETCHECKREQPROT                 0x00000400UL
+#define SECURITY__LABELPRIV                       0x00000800UL
 
 #define SYSTEM__IPC_INFO                          0x00000001UL
 #define SYSTEM__SYSLOG_READ                       0x00000002UL
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/av_perm_to_string.h linux-2.6.17-rc4-mm3-x/security/selinux/include/av_perm_to_string.h
--- linux-2.6.17-rc4-mm3/security/selinux/include/av_perm_to_string.h	2006-05-22 09:09:46.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/include/av_perm_to_string.h	2006-05-23 08:57:55.000000000 -0400
@@ -87,6 +87,7 @@
    S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
    S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
    S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
+   S_(SECCLASS_SECURITY, SECURITY__LABELPRIV, "labelpriv")
    S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/objsec.h linux-2.6.17-rc4-mm3-x/security/selinux/include/objsec.h
--- linux-2.6.17-rc4-mm3/security/selinux/include/objsec.h	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc4-mm3-x/security/selinux/include/objsec.h	2006-05-23 08:57:55.000000000 -0400
@@ -101,4 +101,7 @@ struct sk_security_struct {
 
 extern unsigned int selinux_checkreqprot;
 
+extern int task_has_security(struct task_struct *tsk,
+			     u32 perms);
+
 #endif /* _SELINUX_OBJSEC_H_ */
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/security.h linux-2.6.17-rc4-mm3-x/security/selinux/include/security.h
--- linux-2.6.17-rc4-mm3/security/selinux/include/security.h	2006-05-22 09:09:22.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/include/security.h	2006-05-23 08:57:55.000000000 -0400
@@ -63,6 +63,8 @@ int security_context_to_sid(char *sconte
 
 int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *out_sid, u32 def_sid);
 
+int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid);
+
 int security_get_user_sids(u32 callsid, char *username,
 			   u32 **sids, u32 *nel);
 
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/selinuxfs.c linux-2.6.17-rc4-mm3-x/security/selinux/selinuxfs.c
--- linux-2.6.17-rc4-mm3/security/selinux/selinuxfs.c	2006-05-22 09:09:46.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/selinuxfs.c	2006-05-23 08:57:55.000000000 -0400
@@ -71,8 +71,8 @@ static int *bool_pending_values = NULL;
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
-static int task_has_security(struct task_struct *tsk,
-			     u32 perms)
+int task_has_security(struct task_struct *tsk,
+		      u32 perms)
 {
 	struct task_security_struct *tsec;
 
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/context.h linux-2.6.17-rc4-mm3-x/security/selinux/ss/context.h
--- linux-2.6.17-rc4-mm3/security/selinux/ss/context.h	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/context.h	2006-05-23 12:16:28.000000000 -0400
@@ -28,6 +28,8 @@ struct context {
 	u32 role;
 	u32 type;
 	struct mls_range range;
+	char *str;	/* string representation if context cannot be mapped. */
+	u32 len;        /* length of string in bytes, including NUL byte. */
 };
 
 static inline void mls_context_init(struct context *c)
@@ -83,6 +85,14 @@ static inline void context_init(struct c
 
 static inline int context_cpy(struct context *dst, struct context *src)
 {
+	context_init(dst);
+	if (src->len) {
+		dst->str = kstrdup(src->str, GFP_ATOMIC);
+		if (!dst->str)
+			return -ENOMEM;
+		dst->len = src->len;
+		return 0;
+	}
 	dst->user = src->user;
 	dst->role = src->role;
 	dst->type = src->type;
@@ -91,12 +101,17 @@ static inline int context_cpy(struct con
 
 static inline void context_destroy(struct context *c)
 {
-	c->user = c->role = c->type = 0;
+	kfree(c->str);
 	mls_context_destroy(c);
+	context_init(c);
 }
 
 static inline int context_cmp(struct context *c1, struct context *c2)
 {
+	if (c1->len && c2->len)
+		return (c1->len == c2->len && !memcmp(c1->str, c2->str, c1->len));
+	if (c1->len || c2->len)
+		return 0;
 	return ((c1->user == c2->user) &&
 		(c1->role == c2->role) &&
 		(c1->type == c2->type) &&
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/mls.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.c
--- linux-2.6.17-rc4-mm3/security/selinux/ss/mls.c	2006-05-22 09:09:22.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.c	2006-05-23 08:57:55.000000000 -0400
@@ -249,7 +249,8 @@ static inline int mls_copy_context(struc
  * Policy read-lock must be held for sidtab lookup.
  *
  */
-int mls_context_to_sid(char oldc,
+int mls_context_to_sid(struct policydb *pol,
+		       char oldc,
 		       char **scontext,
 		       struct context *context,
 		       struct sidtab *s,
@@ -296,7 +297,7 @@ int mls_context_to_sid(char oldc,
 		*p++ = 0;
 
 	for (l = 0; l < 2; l++) {
-		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
+		levdatum = hashtab_search(pol->p_levels.table, scontextp);
 		if (!levdatum) {
 			rc = -EINVAL;
 			goto out;
@@ -320,7 +321,7 @@ int mls_context_to_sid(char oldc,
 					*rngptr++ = 0;
 				}
 
-				catdatum = hashtab_search(policydb.p_cats.table,
+				catdatum = hashtab_search(pol->p_cats.table,
 				                          scontextp);
 				if (!catdatum) {
 					rc = -EINVAL;
@@ -336,7 +337,7 @@ int mls_context_to_sid(char oldc,
 				if (rngptr) {
 					int i;
 
-					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+					rngdatum = hashtab_search(pol->p_cats.table, rngptr);
 					if (!rngdatum) {
 						rc = -EINVAL;
 						goto out;
@@ -404,7 +405,7 @@ int mls_from_string(char *str, struct co
 	if (!tmpstr) {
 		rc = -ENOMEM;
 	} else {
-		rc = mls_context_to_sid(':', &tmpstr, context,
+		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
 		                        NULL, SECSID_NULL);
 		kfree(freestr);
 	}
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/mls.h linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.h
--- linux-2.6.17-rc4-mm3/security/selinux/ss/mls.h	2006-05-22 09:09:22.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.h	2006-05-23 08:57:55.000000000 -0400
@@ -21,7 +21,8 @@ int mls_compute_context_len(struct conte
 void 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,
+int mls_context_to_sid(struct policydb *p,
+		       char oldc,
 	               char **scontext,
 		       struct context *context,
 		       struct sidtab *s,
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/services.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/services.c
--- linux-2.6.17-rc4-mm3/security/selinux/ss/services.c	2006-05-22 09:09:46.000000000 -0400
+++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/services.c	2006-05-23 12:17:26.000000000 -0400
@@ -623,48 +623,31 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
+static int string_to_context_struct(struct policydb *pol,
+				    struct sidtab *sidtabp,
+				    char *scontext,
+				    u32 scontext_len,
+				    struct context *ctx,
+				    u32 def_sid)
 {
-	char *scontext2;
-	struct context context;
+	char *scontext2 = NULL;
 	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 < SECINITSID_NUM; i++) {
-			if (!strcmp(initial_sid_to_string[i], scontext)) {
-				*sid = i;
-				goto out;
-			}
-		}
-		*sid = SECINITSID_KERNEL;
-		goto out;
-	}
-	*sid = SECSID_NULL;
+	context_init(ctx);
 
-	/* 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);
+	/* Copy the string so that we can modify the copy as we parse it. */
+	scontext2 = kmalloc(scontext_len+1, GFP_ATOMIC);
 	if (!scontext2) {
 		rc = -ENOMEM;
-		goto out;
+		goto err;
 	}
 	memcpy(scontext2, scontext, scontext_len);
 	scontext2[scontext_len] = 0;
 
-	context_init(&context);
-	*sid = SECSID_NULL;
-
-	POLICY_RDLOCK;
-
 	/* Parse the security context. */
 
 	rc = -EINVAL;
@@ -676,15 +659,15 @@ static int security_context_to_sid_core(
 		p++;
 
 	if (*p == 0)
-		goto out_unlock;
+		goto err;
 
 	*p++ = 0;
 
-	usrdatum = hashtab_search(policydb.p_users.table, scontextp);
+	usrdatum = hashtab_search(pol->p_users.table, scontextp);
 	if (!usrdatum)
-		goto out_unlock;
+		goto err;
 
-	context.user = usrdatum->value;
+	ctx->user = usrdatum->value;
 
 	/* Extract role. */
 	scontextp = p;
@@ -692,14 +675,14 @@ static int security_context_to_sid_core(
 		p++;
 
 	if (*p == 0)
-		goto out_unlock;
+		goto err;
 
 	*p++ = 0;
 
-	role = hashtab_search(policydb.p_roles.table, scontextp);
+	role = hashtab_search(pol->p_roles.table, scontextp);
 	if (!role)
-		goto out_unlock;
-	context.role = role->value;
+		goto err;
+	ctx->role = role->value;
 
 	/* Extract type. */
 	scontextp = p;
@@ -708,32 +691,74 @@ static int security_context_to_sid_core(
 	oldc = *p;
 	*p++ = 0;
 
-	typdatum = hashtab_search(policydb.p_types.table, scontextp);
+	typdatum = hashtab_search(pol->p_types.table, scontextp);
 	if (!typdatum)
-		goto out_unlock;
+		goto err;
 
-	context.type = typdatum->value;
+	ctx->type = typdatum->value;
 
-	rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
+	rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid);
 	if (rc)
-		goto out_unlock;
+		goto err;
 
-	if ((p - scontext2) < scontext_len) {
-		rc = -EINVAL;
-		goto out_unlock;
-	}
+	rc = -EINVAL;
+	if ((p - scontext2) < scontext_len)
+		goto err;
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &context)) {
-		rc = -EINVAL;
-		goto out_unlock;
+	if (!policydb_context_isvalid(pol, ctx))
+		goto err;
+
+	rc = 0;
+out:
+	kfree(scontext2);
+	return rc;
+err:
+	context_destroy(ctx);
+	goto out;
+}
+
+static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid, int force)
+{
+	struct context context;
+	int rc = 0;
+
+	if (!ss_initialized) {
+		int i;
+
+		for (i = 1; i < SECINITSID_NUM; i++) {
+			if (!strcmp(initial_sid_to_string[i], scontext)) {
+				*sid = i;
+				goto out;
+			}
+		}
+		*sid = SECINITSID_KERNEL;
+		goto out;
 	}
-	/* Obtain the new sid. */
+	*sid = SECSID_NULL;
+
+	POLICY_RDLOCK;
+	rc = string_to_context_struct(&policydb, &sidtab,
+				      scontext, scontext_len,
+				      &context, def_sid);
+	if (rc == -EINVAL && force && scontext_len) {
+		context_init(&context);
+		context.len = scontext_len;
+		if (scontext[scontext_len-1])
+			context.len++; /* extend for NUL. */
+		context.str = kmalloc(context.len, GFP_ATOMIC);
+		if (!context.str) {
+			rc = -ENOMEM;
+			goto out_unlock;
+		}
+		memcpy(context.str, scontext, scontext_len);
+		context.str[context.len-1] = 0;
+	} else if (rc)
+		goto out_unlock;
 	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	context_destroy(&context);
 out_unlock:
 	POLICY_RDUNLOCK;
-	context_destroy(&context);
-	kfree(scontext2);
 out:
 	return rc;
 }
@@ -752,7 +777,7 @@ out:
 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-	                                    sid, SECSID_NULL);
+	                                    sid, SECSID_NULL, 0);
 }
 
 /**
@@ -769,13 +794,21 @@ int security_context_to_sid(char *sconte
  * The default SID is passed to the MLS layer to be used to allow
  * kernel labeling of the MLS field if the MLS field is not present
  * (for upgrading to MLS without full relabel).
+ * Adds the string representation if the context cannot be mapped under
+ * current policy.
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
 int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-	                                    sid, def_sid);
+	                                    sid, def_sid, 1);
+}
+
+int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid)
+{
+	return security_context_to_sid_core(scontext, scontext_len,
+	                                    sid, SECSID_NULL, 1);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -1112,9 +1145,10 @@ static inline int convert_context_handle
 		char *s;
 		u32 len;
 
-		context_struct_to_string(context, &s, &len);
-		printk(KERN_ERR "security:  context %s is invalid\n", s);
-		kfree(s);
+		if (!context_struct_to_string(context, &s, &len)) {
+			printk(KERN_WARNING "SELinux:  Context %s would be invalid if enforcing\n", s);
+			kfree(s);
+		}
 	}
 	return rc;
 }
@@ -1146,6 +1180,27 @@ static int convert_context(u32 key,
 
 	args = p;
 
+	if (c->str) {
+		struct context ctx;
+		rc = string_to_context_struct(args->newp, NULL, c->str,
+					      c->len, &ctx, SECSID_NULL);
+		if (!rc) {
+			printk(KERN_INFO "SELinux:  Context %s became valid under new policy.\n", c->str);
+			/* Replace string with mapped representation. */
+			kfree(c->str);
+			memcpy(c, &ctx, sizeof(*c));
+			goto out;
+		} else if (rc == -EINVAL) {
+			/* Retain string representation for later mapping. */
+			rc = 0;
+			goto out;
+		} else {
+			/* Other error condition, e.g. ENOMEM. */
+			printk(KERN_ERR "SELinux:   Failed trying to map context %s (rc %d) under new policy, leaving unmapped.\n", c->str, -rc);
+			goto out;
+		}
+	}
+
 	rc = context_cpy(&oldc, c);
 	if (rc)
 		goto out;
@@ -1155,46 +1210,48 @@ static int convert_context(u32 key,
 	/* Convert the user. */
 	usrdatum = hashtab_search(args->newp->p_users.table,
 	                          args->oldp->p_user_val_to_name[c->user - 1]);
-	if (!usrdatum) {
-		goto bad;
-	}
+	if (!usrdatum)
+		goto map;
 	c->user = usrdatum->value;
 
 	/* Convert the role. */
 	role = hashtab_search(args->newp->p_roles.table,
 	                      args->oldp->p_role_val_to_name[c->role - 1]);
-	if (!role) {
-		goto bad;
-	}
+	if (!role)
+		goto map;
 	c->role = role->value;
 
 	/* Convert the type. */
 	typdatum = hashtab_search(args->newp->p_types.table,
 	                          args->oldp->p_type_val_to_name[c->type - 1]);
-	if (!typdatum) {
-		goto bad;
-	}
+	if (!typdatum)
+		goto map;
 	c->type = typdatum->value;
 
 	rc = mls_convert_context(args->oldp, args->newp, c);
 	if (rc)
-		goto bad;
+		goto map;
 
 	/* Check the validity of the new context. */
 	if (!policydb_context_isvalid(args->newp, c)) {
 		rc = convert_context_handle_invalid_context(&oldc);
 		if (rc)
-			goto bad;
+			goto map;
 	}
 
 	context_destroy(&oldc);
 out:
 	return rc;
-bad:
-	context_struct_to_string(&oldc, &s, &len);
+map:
+	/* Map old representation to string and save it. */
+	if (context_struct_to_string(&oldc, &s, &len))
+		return -ENOMEM;
 	context_destroy(&oldc);
-	printk(KERN_ERR "security:  invalidating context %s\n", s);
-	kfree(s);
+	context_destroy(c);
+	c->str = s;
+	c->len = len;
+	printk(KERN_INFO "SELinux:  Context %s became invalid under new policy.\n", c->str);
+	rc = 0;
 	goto out;
 }
 
@@ -1253,7 +1310,11 @@ int security_load_policy(void *data, siz
 		return -EINVAL;
 	}
 
-	sidtab_init(&newsidtab);
+	if (sidtab_init(&newsidtab)) {
+		LOAD_UNLOCK;
+		policydb_destroy(&newpolicydb);
+		return -ENOMEM;
+	}
 
 	/* Verify that the existing classes did not change. */
 	if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
@@ -1271,10 +1332,12 @@ int security_load_policy(void *data, siz
 	}
 
 	/* Convert the internal representations of contexts
-	   in the new SID table and remove invalid SIDs. */
+	   in the new SID table. */
 	args.oldp = &policydb;
 	args.newp = &newpolicydb;
-	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
+	rc = sidtab_map(&newsidtab, convert_context, &args);
+	if (rc)
+		goto err;
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(&oldpolicydb, &policydb, sizeof policydb);
@@ -1524,6 +1587,8 @@ int security_get_user_sids(u32 fromsid,
 
 	POLICY_RDLOCK;
 
+	context_init(&usercon);
+
 	fromcon = sidtab_search(&sidtab, fromsid);
 	if (!fromcon) {
 		rc = -EINVAL;
diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/sidtab.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/sidtab.c
--- linux-2.6.17-rc4-mm3/security/selinux/ss/sidtab.c	2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/sidtab.c	2006-05-23 08:57:55.000000000 -0400
@@ -100,7 +100,7 @@ struct context *sidtab_search(struct sid
 	while (cur != NULL && sid > cur->sid)
 		cur = cur->next;
 
-	if (cur == NULL || sid != cur->sid) {
+	if (cur == NULL || sid != cur->sid || cur->context.len) {
 		/* Remap invalid SIDs to the unlabeled SID. */
 		sid = SECINITSID_UNLABELED;
 		hvalue = SIDTAB_HASH(sid);
@@ -218,6 +218,8 @@ int sidtab_context_to_sid(struct sidtab 
 			goto unlock_out;
 		}
 		sid = s->next_sid++;
+		if (context->len)
+			printk(KERN_INFO "SELinux:  Context %s is not valid under current policy, adding as unmapped value.\n", context->str);
 		ret = sidtab_insert(s, sid, context);
 		if (ret)
 			s->next_sid--;

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 17:15           ` Stephen Smalley
@ 2006-05-23 18:23             ` Daniel J Walsh
  2006-05-23 18:50               ` Stephen Smalley
  2006-05-24 17:24             ` Jeremy Katz
  1 sibling, 1 reply; 33+ messages in thread
From: Daniel J Walsh @ 2006-05-23 18:23 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Karl MacMillan, Thomas Bleher, selinux, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

Stephen Smalley wrote:
> On Fri, 2006-05-19 at 09:18 -0400, Karl MacMillan wrote:
>   
>> On Fri, 2006-05-19 at 08:59 -0400, Stephen Smalley wrote:
>>     
>>> In the labelpriv model, rpm doesn't have to visit the individual files
>>> afterward in the common case; it just calls security_check_context(3) on
>>> each distinct context stored in the rpm header (once per context, not
>>> per file) after the module insertion phase, and if any of them are still
>>> invalid (the uncommon case), rpm then takes corrective action (whether
>>> that means relabeling files that had those invalid labels to truly be
>>> unlabeled_t, removing those files, or reverting the install altogether -
>>> the latter seems cleanest to me).  If we can't get a guarantee that rpm
>>> will perform such checking and take corrective action, then I'd agree
>>> that the kernel change is a no-go.
>>>
>>>       
>> The question is when the labels will become valid.
>>
>> Thinking through this more I realized that if we cannot guarantee
>> ordering within a transaction we cannot commit any policy modules until
>> the end of the transaction. Otherwise it will not be possible to have
>> _any_ dependencies between policy modules, which doesn't seem likely
>> based on my recent investigations into refpolicy dependencies.
>>
>> If policy modules are only committed at the end of the transaction,
>> verification of the rpms will require going back through the headers of
>> every rpm in the transaction.
>>
>> Dan, Jeremy, Paul, any thoughts about when the policy modules will be
>> committed?
>>     
>
> Below is an updated version of the kernel patch to support rpm labeling
> of files before policy load, with a couple of bug fixes and a re-base to
> 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> resolve the issues of how rpm will check file label validity after
> policy load (e.g. calling security_check_context(3) on each label from
> the header), what corrective action rpm will take if a file label is
> invalid (options suggested include relabeling to unlabeled_t, relabeling
> to the context returned by the system policy via matchpathcon, or
> reverting the install), and the issues raised by Karl above (as they
> also affect the ability of rpm to perform such verification and
> correction sanely).
>
>   
As far as I understand it, rpm will not go back and check the whether 
the context are sane.  If the
postinstall of policy fails, the context on disk will be incorrect and 
treated like unlabeled_t.

Jeremy and Paul is that your understanding?

Dan
> ---<snip>---
>
> Introduce support for deferring mapping of security contexts in the
> SID table upon policy reload, and use this support for inode security
> contexts when the context is not yet valid under the current policy.
> Only processes with 'labelpriv' permission to the 'security' class can
> set such invalid security contexts on inodes.  Inodes with such
> invalid contexts are treated as having the unlabeled SID until the context 
> becomes valid under a policy.  This support is for use by privileged processes
> like rpm that need to set down files in the proper security contexts prior to 
> loading the policy module that defines the context and its associated rules.
>
> ---
>
>  security/selinux/hooks.c                     |   16 +-
>  security/selinux/include/av_perm_to_string.h |    1 
>  security/selinux/include/av_permissions.h    |    1 
>  security/selinux/include/objsec.h            |    3 
>  security/selinux/include/security.h          |    2 
>  security/selinux/selinuxfs.c                 |    4 
>  security/selinux/ss/context.h                |   17 ++
>  security/selinux/ss/mls.c                    |   11 -
>  security/selinux/ss/mls.h                    |    3 
>  security/selinux/ss/services.c               |  213 +++++++++++++++++----------
>  security/selinux/ss/sidtab.c                 |    4 
>  11 files changed, 189 insertions(+), 86 deletions(-)
>
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/hooks.c linux-2.6.17-rc4-mm3-x/security/selinux/hooks.c
> --- linux-2.6.17-rc4-mm3/security/selinux/hooks.c	2006-05-22 09:09:46.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/hooks.c	2006-05-23 08:57:55.000000000 -0400
> @@ -2165,6 +2165,11 @@ static int selinux_inode_setxattr(struct
>  		return rc;
>  
>  	rc = security_context_to_sid(value, size, &newsid);
> +	if (rc == -EINVAL) {
> +		if (task_has_security(current, SECURITY__LABELPRIV))
> +			return rc;
> +		rc = security_context_to_sid_force(value, size, &newsid);
> +	}
>  	if (rc)
>  		return rc;
>  
> @@ -2198,10 +2203,11 @@ static void selinux_inode_post_setxattr(
>  		return;
>  	}
>  
> -	rc = security_context_to_sid(value, size, &newsid);
> +	rc = security_context_to_sid_force(value, size, &newsid);
>  	if (rc) {
>  		printk(KERN_WARNING "%s:  unable to obtain SID for context "
> -		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
> +		       "%s on (%s, %lu), rc=%d\n", __FUNCTION__, (char*)value,
> +		       inode->i_sb->s_id, inode->i_ino, -rc);
>  		return;
>  	}
>  
> @@ -4186,6 +4192,12 @@ static int selinux_setprocattr(struct ta
>  			size--;
>  		}
>  		error = security_context_to_sid(value, size, &sid);
> +		if (error == -EINVAL && !strcmp(name, "fscreate")) {
> +			if (task_has_security(current, SECURITY__LABELPRIV))
> +				return error;
> +			error = security_context_to_sid_force(value, size,
> +							      &sid);
> +		}
>  		if (error)
>  			return error;
>  	}
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/av_permissions.h linux-2.6.17-rc4-mm3-x/security/selinux/include/av_permissions.h
> --- linux-2.6.17-rc4-mm3/security/selinux/include/av_permissions.h	2006-05-22 09:09:46.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/include/av_permissions.h	2006-05-23 08:57:55.000000000 -0400
> @@ -526,6 +526,7 @@
>  #define SECURITY__SETBOOL                         0x00000100UL
>  #define SECURITY__SETSECPARAM                     0x00000200UL
>  #define SECURITY__SETCHECKREQPROT                 0x00000400UL
> +#define SECURITY__LABELPRIV                       0x00000800UL
>  
>  #define SYSTEM__IPC_INFO                          0x00000001UL
>  #define SYSTEM__SYSLOG_READ                       0x00000002UL
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/av_perm_to_string.h linux-2.6.17-rc4-mm3-x/security/selinux/include/av_perm_to_string.h
> --- linux-2.6.17-rc4-mm3/security/selinux/include/av_perm_to_string.h	2006-05-22 09:09:46.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/include/av_perm_to_string.h	2006-05-23 08:57:55.000000000 -0400
> @@ -87,6 +87,7 @@
>     S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
>     S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
>     S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
> +   S_(SECCLASS_SECURITY, SECURITY__LABELPRIV, "labelpriv")
>     S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
>     S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
>     S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/objsec.h linux-2.6.17-rc4-mm3-x/security/selinux/include/objsec.h
> --- linux-2.6.17-rc4-mm3/security/selinux/include/objsec.h	2006-03-20 00:53:29.000000000 -0500
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/include/objsec.h	2006-05-23 08:57:55.000000000 -0400
> @@ -101,4 +101,7 @@ struct sk_security_struct {
>  
>  extern unsigned int selinux_checkreqprot;
>  
> +extern int task_has_security(struct task_struct *tsk,
> +			     u32 perms);
> +
>  #endif /* _SELINUX_OBJSEC_H_ */
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/include/security.h linux-2.6.17-rc4-mm3-x/security/selinux/include/security.h
> --- linux-2.6.17-rc4-mm3/security/selinux/include/security.h	2006-05-22 09:09:22.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/include/security.h	2006-05-23 08:57:55.000000000 -0400
> @@ -63,6 +63,8 @@ int security_context_to_sid(char *sconte
>  
>  int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *out_sid, u32 def_sid);
>  
> +int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid);
> +
>  int security_get_user_sids(u32 callsid, char *username,
>  			   u32 **sids, u32 *nel);
>  
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/selinuxfs.c linux-2.6.17-rc4-mm3-x/security/selinux/selinuxfs.c
> --- linux-2.6.17-rc4-mm3/security/selinux/selinuxfs.c	2006-05-22 09:09:46.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/selinuxfs.c	2006-05-23 08:57:55.000000000 -0400
> @@ -71,8 +71,8 @@ static int *bool_pending_values = NULL;
>  extern void selnl_notify_setenforce(int val);
>  
>  /* Check whether a task is allowed to use a security operation. */
> -static int task_has_security(struct task_struct *tsk,
> -			     u32 perms)
> +int task_has_security(struct task_struct *tsk,
> +		      u32 perms)
>  {
>  	struct task_security_struct *tsec;
>  
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/context.h linux-2.6.17-rc4-mm3-x/security/selinux/ss/context.h
> --- linux-2.6.17-rc4-mm3/security/selinux/ss/context.h	2006-03-20 00:53:29.000000000 -0500
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/context.h	2006-05-23 12:16:28.000000000 -0400
> @@ -28,6 +28,8 @@ struct context {
>  	u32 role;
>  	u32 type;
>  	struct mls_range range;
> +	char *str;	/* string representation if context cannot be mapped. */
> +	u32 len;        /* length of string in bytes, including NUL byte. */
>  };
>  
>  static inline void mls_context_init(struct context *c)
> @@ -83,6 +85,14 @@ static inline void context_init(struct c
>  
>  static inline int context_cpy(struct context *dst, struct context *src)
>  {
> +	context_init(dst);
> +	if (src->len) {
> +		dst->str = kstrdup(src->str, GFP_ATOMIC);
> +		if (!dst->str)
> +			return -ENOMEM;
> +		dst->len = src->len;
> +		return 0;
> +	}
>  	dst->user = src->user;
>  	dst->role = src->role;
>  	dst->type = src->type;
> @@ -91,12 +101,17 @@ static inline int context_cpy(struct con
>  
>  static inline void context_destroy(struct context *c)
>  {
> -	c->user = c->role = c->type = 0;
> +	kfree(c->str);
>  	mls_context_destroy(c);
> +	context_init(c);
>  }
>  
>  static inline int context_cmp(struct context *c1, struct context *c2)
>  {
> +	if (c1->len && c2->len)
> +		return (c1->len == c2->len && !memcmp(c1->str, c2->str, c1->len));
> +	if (c1->len || c2->len)
> +		return 0;
>  	return ((c1->user == c2->user) &&
>  		(c1->role == c2->role) &&
>  		(c1->type == c2->type) &&
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/mls.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.c
> --- linux-2.6.17-rc4-mm3/security/selinux/ss/mls.c	2006-05-22 09:09:22.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.c	2006-05-23 08:57:55.000000000 -0400
> @@ -249,7 +249,8 @@ static inline int mls_copy_context(struc
>   * Policy read-lock must be held for sidtab lookup.
>   *
>   */
> -int mls_context_to_sid(char oldc,
> +int mls_context_to_sid(struct policydb *pol,
> +		       char oldc,
>  		       char **scontext,
>  		       struct context *context,
>  		       struct sidtab *s,
> @@ -296,7 +297,7 @@ int mls_context_to_sid(char oldc,
>  		*p++ = 0;
>  
>  	for (l = 0; l < 2; l++) {
> -		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
> +		levdatum = hashtab_search(pol->p_levels.table, scontextp);
>  		if (!levdatum) {
>  			rc = -EINVAL;
>  			goto out;
> @@ -320,7 +321,7 @@ int mls_context_to_sid(char oldc,
>  					*rngptr++ = 0;
>  				}
>  
> -				catdatum = hashtab_search(policydb.p_cats.table,
> +				catdatum = hashtab_search(pol->p_cats.table,
>  				                          scontextp);
>  				if (!catdatum) {
>  					rc = -EINVAL;
> @@ -336,7 +337,7 @@ int mls_context_to_sid(char oldc,
>  				if (rngptr) {
>  					int i;
>  
> -					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
> +					rngdatum = hashtab_search(pol->p_cats.table, rngptr);
>  					if (!rngdatum) {
>  						rc = -EINVAL;
>  						goto out;
> @@ -404,7 +405,7 @@ int mls_from_string(char *str, struct co
>  	if (!tmpstr) {
>  		rc = -ENOMEM;
>  	} else {
> -		rc = mls_context_to_sid(':', &tmpstr, context,
> +		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
>  		                        NULL, SECSID_NULL);
>  		kfree(freestr);
>  	}
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/mls.h linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.h
> --- linux-2.6.17-rc4-mm3/security/selinux/ss/mls.h	2006-05-22 09:09:22.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/mls.h	2006-05-23 08:57:55.000000000 -0400
> @@ -21,7 +21,8 @@ int mls_compute_context_len(struct conte
>  void 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,
> +int mls_context_to_sid(struct policydb *p,
> +		       char oldc,
>  	               char **scontext,
>  		       struct context *context,
>  		       struct sidtab *s,
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/services.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/services.c
> --- linux-2.6.17-rc4-mm3/security/selinux/ss/services.c	2006-05-22 09:09:46.000000000 -0400
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/services.c	2006-05-23 12:17:26.000000000 -0400
> @@ -623,48 +623,31 @@ out:
>  
>  }
>  
> -static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
> +static int string_to_context_struct(struct policydb *pol,
> +				    struct sidtab *sidtabp,
> +				    char *scontext,
> +				    u32 scontext_len,
> +				    struct context *ctx,
> +				    u32 def_sid)
>  {
> -	char *scontext2;
> -	struct context context;
> +	char *scontext2 = NULL;
>  	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 < SECINITSID_NUM; i++) {
> -			if (!strcmp(initial_sid_to_string[i], scontext)) {
> -				*sid = i;
> -				goto out;
> -			}
> -		}
> -		*sid = SECINITSID_KERNEL;
> -		goto out;
> -	}
> -	*sid = SECSID_NULL;
> +	context_init(ctx);
>  
> -	/* 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);
> +	/* Copy the string so that we can modify the copy as we parse it. */
> +	scontext2 = kmalloc(scontext_len+1, GFP_ATOMIC);
>  	if (!scontext2) {
>  		rc = -ENOMEM;
> -		goto out;
> +		goto err;
>  	}
>  	memcpy(scontext2, scontext, scontext_len);
>  	scontext2[scontext_len] = 0;
>  
> -	context_init(&context);
> -	*sid = SECSID_NULL;
> -
> -	POLICY_RDLOCK;
> -
>  	/* Parse the security context. */
>  
>  	rc = -EINVAL;
> @@ -676,15 +659,15 @@ static int security_context_to_sid_core(
>  		p++;
>  
>  	if (*p == 0)
> -		goto out_unlock;
> +		goto err;
>  
>  	*p++ = 0;
>  
> -	usrdatum = hashtab_search(policydb.p_users.table, scontextp);
> +	usrdatum = hashtab_search(pol->p_users.table, scontextp);
>  	if (!usrdatum)
> -		goto out_unlock;
> +		goto err;
>  
> -	context.user = usrdatum->value;
> +	ctx->user = usrdatum->value;
>  
>  	/* Extract role. */
>  	scontextp = p;
> @@ -692,14 +675,14 @@ static int security_context_to_sid_core(
>  		p++;
>  
>  	if (*p == 0)
> -		goto out_unlock;
> +		goto err;
>  
>  	*p++ = 0;
>  
> -	role = hashtab_search(policydb.p_roles.table, scontextp);
> +	role = hashtab_search(pol->p_roles.table, scontextp);
>  	if (!role)
> -		goto out_unlock;
> -	context.role = role->value;
> +		goto err;
> +	ctx->role = role->value;
>  
>  	/* Extract type. */
>  	scontextp = p;
> @@ -708,32 +691,74 @@ static int security_context_to_sid_core(
>  	oldc = *p;
>  	*p++ = 0;
>  
> -	typdatum = hashtab_search(policydb.p_types.table, scontextp);
> +	typdatum = hashtab_search(pol->p_types.table, scontextp);
>  	if (!typdatum)
> -		goto out_unlock;
> +		goto err;
>  
> -	context.type = typdatum->value;
> +	ctx->type = typdatum->value;
>  
> -	rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
> +	rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid);
>  	if (rc)
> -		goto out_unlock;
> +		goto err;
>  
> -	if ((p - scontext2) < scontext_len) {
> -		rc = -EINVAL;
> -		goto out_unlock;
> -	}
> +	rc = -EINVAL;
> +	if ((p - scontext2) < scontext_len)
> +		goto err;
>  
>  	/* Check the validity of the new context. */
> -	if (!policydb_context_isvalid(&policydb, &context)) {
> -		rc = -EINVAL;
> -		goto out_unlock;
> +	if (!policydb_context_isvalid(pol, ctx))
> +		goto err;
> +
> +	rc = 0;
> +out:
> +	kfree(scontext2);
> +	return rc;
> +err:
> +	context_destroy(ctx);
> +	goto out;
> +}
> +
> +static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid, int force)
> +{
> +	struct context context;
> +	int rc = 0;
> +
> +	if (!ss_initialized) {
> +		int i;
> +
> +		for (i = 1; i < SECINITSID_NUM; i++) {
> +			if (!strcmp(initial_sid_to_string[i], scontext)) {
> +				*sid = i;
> +				goto out;
> +			}
> +		}
> +		*sid = SECINITSID_KERNEL;
> +		goto out;
>  	}
> -	/* Obtain the new sid. */
> +	*sid = SECSID_NULL;
> +
> +	POLICY_RDLOCK;
> +	rc = string_to_context_struct(&policydb, &sidtab,
> +				      scontext, scontext_len,
> +				      &context, def_sid);
> +	if (rc == -EINVAL && force && scontext_len) {
> +		context_init(&context);
> +		context.len = scontext_len;
> +		if (scontext[scontext_len-1])
> +			context.len++; /* extend for NUL. */
> +		context.str = kmalloc(context.len, GFP_ATOMIC);
> +		if (!context.str) {
> +			rc = -ENOMEM;
> +			goto out_unlock;
> +		}
> +		memcpy(context.str, scontext, scontext_len);
> +		context.str[context.len-1] = 0;
> +	} else if (rc)
> +		goto out_unlock;
>  	rc = sidtab_context_to_sid(&sidtab, &context, sid);
> +	context_destroy(&context);
>  out_unlock:
>  	POLICY_RDUNLOCK;
> -	context_destroy(&context);
> -	kfree(scontext2);
>  out:
>  	return rc;
>  }
> @@ -752,7 +777,7 @@ out:
>  int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
>  {
>  	return security_context_to_sid_core(scontext, scontext_len,
> -	                                    sid, SECSID_NULL);
> +	                                    sid, SECSID_NULL, 0);
>  }
>  
>  /**
> @@ -769,13 +794,21 @@ int security_context_to_sid(char *sconte
>   * The default SID is passed to the MLS layer to be used to allow
>   * kernel labeling of the MLS field if the MLS field is not present
>   * (for upgrading to MLS without full relabel).
> + * Adds the string representation if the context cannot be mapped under
> + * current policy.
>   * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
>   * memory is available, or 0 on success.
>   */
>  int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
>  {
>  	return security_context_to_sid_core(scontext, scontext_len,
> -	                                    sid, def_sid);
> +	                                    sid, def_sid, 1);
> +}
> +
> +int security_context_to_sid_force(char *scontext, u32 scontext_len, u32 *sid)
> +{
> +	return security_context_to_sid_core(scontext, scontext_len,
> +	                                    sid, SECSID_NULL, 1);
>  }
>  
>  static int compute_sid_handle_invalid_context(
> @@ -1112,9 +1145,10 @@ static inline int convert_context_handle
>  		char *s;
>  		u32 len;
>  
> -		context_struct_to_string(context, &s, &len);
> -		printk(KERN_ERR "security:  context %s is invalid\n", s);
> -		kfree(s);
> +		if (!context_struct_to_string(context, &s, &len)) {
> +			printk(KERN_WARNING "SELinux:  Context %s would be invalid if enforcing\n", s);
> +			kfree(s);
> +		}
>  	}
>  	return rc;
>  }
> @@ -1146,6 +1180,27 @@ static int convert_context(u32 key,
>  
>  	args = p;
>  
> +	if (c->str) {
> +		struct context ctx;
> +		rc = string_to_context_struct(args->newp, NULL, c->str,
> +					      c->len, &ctx, SECSID_NULL);
> +		if (!rc) {
> +			printk(KERN_INFO "SELinux:  Context %s became valid under new policy.\n", c->str);
> +			/* Replace string with mapped representation. */
> +			kfree(c->str);
> +			memcpy(c, &ctx, sizeof(*c));
> +			goto out;
> +		} else if (rc == -EINVAL) {
> +			/* Retain string representation for later mapping. */
> +			rc = 0;
> +			goto out;
> +		} else {
> +			/* Other error condition, e.g. ENOMEM. */
> +			printk(KERN_ERR "SELinux:   Failed trying to map context %s (rc %d) under new policy, leaving unmapped.\n", c->str, -rc);
> +			goto out;
> +		}
> +	}
> +
>  	rc = context_cpy(&oldc, c);
>  	if (rc)
>  		goto out;
> @@ -1155,46 +1210,48 @@ static int convert_context(u32 key,
>  	/* Convert the user. */
>  	usrdatum = hashtab_search(args->newp->p_users.table,
>  	                          args->oldp->p_user_val_to_name[c->user - 1]);
> -	if (!usrdatum) {
> -		goto bad;
> -	}
> +	if (!usrdatum)
> +		goto map;
>  	c->user = usrdatum->value;
>  
>  	/* Convert the role. */
>  	role = hashtab_search(args->newp->p_roles.table,
>  	                      args->oldp->p_role_val_to_name[c->role - 1]);
> -	if (!role) {
> -		goto bad;
> -	}
> +	if (!role)
> +		goto map;
>  	c->role = role->value;
>  
>  	/* Convert the type. */
>  	typdatum = hashtab_search(args->newp->p_types.table,
>  	                          args->oldp->p_type_val_to_name[c->type - 1]);
> -	if (!typdatum) {
> -		goto bad;
> -	}
> +	if (!typdatum)
> +		goto map;
>  	c->type = typdatum->value;
>  
>  	rc = mls_convert_context(args->oldp, args->newp, c);
>  	if (rc)
> -		goto bad;
> +		goto map;
>  
>  	/* Check the validity of the new context. */
>  	if (!policydb_context_isvalid(args->newp, c)) {
>  		rc = convert_context_handle_invalid_context(&oldc);
>  		if (rc)
> -			goto bad;
> +			goto map;
>  	}
>  
>  	context_destroy(&oldc);
>  out:
>  	return rc;
> -bad:
> -	context_struct_to_string(&oldc, &s, &len);
> +map:
> +	/* Map old representation to string and save it. */
> +	if (context_struct_to_string(&oldc, &s, &len))
> +		return -ENOMEM;
>  	context_destroy(&oldc);
> -	printk(KERN_ERR "security:  invalidating context %s\n", s);
> -	kfree(s);
> +	context_destroy(c);
> +	c->str = s;
> +	c->len = len;
> +	printk(KERN_INFO "SELinux:  Context %s became invalid under new policy.\n", c->str);
> +	rc = 0;
>  	goto out;
>  }
>  
> @@ -1253,7 +1310,11 @@ int security_load_policy(void *data, siz
>  		return -EINVAL;
>  	}
>  
> -	sidtab_init(&newsidtab);
> +	if (sidtab_init(&newsidtab)) {
> +		LOAD_UNLOCK;
> +		policydb_destroy(&newpolicydb);
> +		return -ENOMEM;
> +	}
>  
>  	/* Verify that the existing classes did not change. */
>  	if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
> @@ -1271,10 +1332,12 @@ int security_load_policy(void *data, siz
>  	}
>  
>  	/* Convert the internal representations of contexts
> -	   in the new SID table and remove invalid SIDs. */
> +	   in the new SID table. */
>  	args.oldp = &policydb;
>  	args.newp = &newpolicydb;
> -	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
> +	rc = sidtab_map(&newsidtab, convert_context, &args);
> +	if (rc)
> +		goto err;
>  
>  	/* Save the old policydb and SID table to free later. */
>  	memcpy(&oldpolicydb, &policydb, sizeof policydb);
> @@ -1524,6 +1587,8 @@ int security_get_user_sids(u32 fromsid,
>  
>  	POLICY_RDLOCK;
>  
> +	context_init(&usercon);
> +
>  	fromcon = sidtab_search(&sidtab, fromsid);
>  	if (!fromcon) {
>  		rc = -EINVAL;
> diff -X /home/sds/dontdiff -rup linux-2.6.17-rc4-mm3/security/selinux/ss/sidtab.c linux-2.6.17-rc4-mm3-x/security/selinux/ss/sidtab.c
> --- linux-2.6.17-rc4-mm3/security/selinux/ss/sidtab.c	2006-03-20 00:53:29.000000000 -0500
> +++ linux-2.6.17-rc4-mm3-x/security/selinux/ss/sidtab.c	2006-05-23 08:57:55.000000000 -0400
> @@ -100,7 +100,7 @@ struct context *sidtab_search(struct sid
>  	while (cur != NULL && sid > cur->sid)
>  		cur = cur->next;
>  
> -	if (cur == NULL || sid != cur->sid) {
> +	if (cur == NULL || sid != cur->sid || cur->context.len) {
>  		/* Remap invalid SIDs to the unlabeled SID. */
>  		sid = SECINITSID_UNLABELED;
>  		hvalue = SIDTAB_HASH(sid);
> @@ -218,6 +218,8 @@ int sidtab_context_to_sid(struct sidtab 
>  			goto unlock_out;
>  		}
>  		sid = s->next_sid++;
> +		if (context->len)
> +			printk(KERN_INFO "SELinux:  Context %s is not valid under current policy, adding as unmapped value.\n", context->str);
>  		ret = sidtab_insert(s, sid, context);
>  		if (ret)
>  			s->next_sid--;
>
>   


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 18:23             ` Daniel J Walsh
@ 2006-05-23 18:50               ` Stephen Smalley
  2006-05-23 20:11                 ` Stephen Smalley
  2006-05-24 17:24                 ` Jeremy Katz
  0 siblings, 2 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-23 18:50 UTC (permalink / raw)
  To: Daniel J Walsh
  Cc: Karl MacMillan, Thomas Bleher, selinux, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Tue, 2006-05-23 at 14:23 -0400, Daniel J Walsh wrote:
> Stephen Smalley wrote:
> > Below is an updated version of the kernel patch to support rpm labeling
> > of files before policy load, with a couple of bug fixes and a re-base to
> > 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> > resolve the issues of how rpm will check file label validity after
> > policy load (e.g. calling security_check_context(3) on each label from
> > the header), what corrective action rpm will take if a file label is
> > invalid (options suggested include relabeling to unlabeled_t, relabeling
> > to the context returned by the system policy via matchpathcon, or
> > reverting the install), and the issues raised by Karl above (as they
> > also affect the ability of rpm to perform such verification and
> > correction sanely).
> >
> >   
> As far as I understand it, rpm will not go back and check the whether 
> the context are sane.  If the
> postinstall of policy fails, the context on disk will be incorrect and 
> treated like unlabeled_t.

I don't think that is really a viable option.  It is undesirable from
both a robustness POV and a security POV.  rpm shouldn't leave the
filesystem littered with files that have invalid contexts (which could
later be turned into valid contexts by another package's policy module,
suddenly granting access to those files or permissions to those
executables unexpectedly), nor should it leave the system littered with
packages whose policy couldn't be installed, as the package software may
then run with the wrong permissions.

> Jeremy and Paul is that your understanding?

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 18:50               ` Stephen Smalley
@ 2006-05-23 20:11                 ` Stephen Smalley
  2006-05-24 17:24                   ` Jeremy Katz
  2006-05-24 17:24                 ` Jeremy Katz
  1 sibling, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-23 20:11 UTC (permalink / raw)
  To: Daniel J Walsh
  Cc: Karl MacMillan, Thomas Bleher, selinux, SELinux-dev, James Morris,
	Jeremy Katz, Paul Nasrat, James Antill

On Tue, 2006-05-23 at 14:50 -0400, Stephen Smalley wrote:
> On Tue, 2006-05-23 at 14:23 -0400, Daniel J Walsh wrote:
> > Stephen Smalley wrote:
> > > Below is an updated version of the kernel patch to support rpm labeling
> > > of files before policy load, with a couple of bug fixes and a re-base to
> > > 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> > > resolve the issues of how rpm will check file label validity after
> > > policy load (e.g. calling security_check_context(3) on each label from
> > > the header), what corrective action rpm will take if a file label is
> > > invalid (options suggested include relabeling to unlabeled_t, relabeling
> > > to the context returned by the system policy via matchpathcon, or
> > > reverting the install), and the issues raised by Karl above (as they
> > > also affect the ability of rpm to perform such verification and
> > > correction sanely).
> > >
> > >   
> > As far as I understand it, rpm will not go back and check the whether 
> > the context are sane.  If the
> > postinstall of policy fails, the context on disk will be incorrect and 
> > treated like unlabeled_t.
> 
> I don't think that is really a viable option.  It is undesirable from
> both a robustness POV and a security POV.  rpm shouldn't leave the
> filesystem littered with files that have invalid contexts (which could
> later be turned into valid contexts by another package's policy module,
> suddenly granting access to those files or permissions to those
> executables unexpectedly), nor should it leave the system littered with
> packages whose policy couldn't be installed, as the package software may
> then run with the wrong permissions.

By the way, reverting the install altogether makes the most sense to me
as a recovery action, i.e. either the package is installed with policy
successfully loaded and all files with valid labels or the package is
not installed at all.

> > Jeremy and Paul is that your understanding?

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 17:15           ` Stephen Smalley
  2006-05-23 18:23             ` Daniel J Walsh
@ 2006-05-24 17:24             ` Jeremy Katz
  2006-05-24 17:48               ` Stephen Smalley
  2006-05-25 15:19               ` Stephen Smalley
  1 sibling, 2 replies; 33+ messages in thread
From: Jeremy Katz @ 2006-05-24 17:24 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, SELinux-dev, Paul Nasrat

On Tue, 2006-05-23 at 13:15 -0400, Stephen Smalley wrote:
> Below is an updated version of the kernel patch to support rpm labeling
> of files before policy load, with a couple of bug fixes and a re-base to
> 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> resolve the issues of how rpm will check file label validity after
> policy load (e.g. calling security_check_context(3) on each label from
> the header), what corrective action rpm will take if a file label is
> invalid (options suggested include relabeling to unlabeled_t, relabeling
> to the context returned by the system policy via matchpathcon, or
> reverting the install), and the issues raised by Karl above (as they
> also affect the ability of rpm to perform such verification and
> correction sanely).

Well, given that the only labels that will end up in a header will be
from a policy in that package, I'm still not really convinced what
adding a verification step _really_ accomplishes.  

Sure, it helps in the case of someone crafting a malicious package which
has random things in the header (by hand, not from rpmbuild[1]) but if
someone is crafting a malicious package and getting it signed by someone
you trust, then you have far larger concerns.

Jeremy

[1] Maybe it's just the clarification on what ends up happening that is
really needed.  In the case where a package contains no policy modules
the behavior will be exactly what it is today.  If a package contains a
policy module, at rpmbuild time, we'll map contexts into the header for
*only* the files covered explicitly by that policy module.  So the only
contexts that could end up in the header will be ones that will then be
installed by the policy module.  For the other files, we'll continue to
just set the file contexts based on the policy as today.



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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 20:11                 ` Stephen Smalley
@ 2006-05-24 17:24                   ` Jeremy Katz
  0 siblings, 0 replies; 33+ messages in thread
From: Jeremy Katz @ 2006-05-24 17:24 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, SELinux-dev, Paul Nasrat

On Tue, 2006-05-23 at 16:11 -0400, Stephen Smalley wrote:
> On Tue, 2006-05-23 at 14:50 -0400, Stephen Smalley wrote:
> > On Tue, 2006-05-23 at 14:23 -0400, Daniel J Walsh wrote:
> > > Stephen Smalley wrote:
> > > > Below is an updated version of the kernel patch to support rpm labeling
> > > > of files before policy load, with a couple of bug fixes and a re-base to
> > > > 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> > > > resolve the issues of how rpm will check file label validity after
> > > > policy load (e.g. calling security_check_context(3) on each label from
> > > > the header), what corrective action rpm will take if a file label is
> > > > invalid (options suggested include relabeling to unlabeled_t, relabeling
> > > > to the context returned by the system policy via matchpathcon, or
> > > > reverting the install), and the issues raised by Karl above (as they
> > > > also affect the ability of rpm to perform such verification and
> > > > correction sanely).
> > > >
> > > >   
> > > As far as I understand it, rpm will not go back and check the whether 
> > > the context are sane.  If the
> > > postinstall of policy fails, the context on disk will be incorrect and 
> > > treated like unlabeled_t.
> > 
> > I don't think that is really a viable option.  It is undesirable from
> > both a robustness POV and a security POV.  rpm shouldn't leave the
> > filesystem littered with files that have invalid contexts (which could
> > later be turned into valid contexts by another package's policy module,
> > suddenly granting access to those files or permissions to those
> > executables unexpectedly), nor should it leave the system littered with
> > packages whose policy couldn't be installed, as the package software may
> > then run with the wrong permissions.
> 
> By the way, reverting the install altogether makes the most sense to me
> as a recovery action, i.e. either the package is installed with policy
> successfully loaded and all files with valid labels or the package is
> not installed at all.

There is no way to just "revert" a package install -- the scriptlets can
do arbitrary things and so there isn't a way to just revert that

Jeremy


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-23 18:50               ` Stephen Smalley
  2006-05-23 20:11                 ` Stephen Smalley
@ 2006-05-24 17:24                 ` Jeremy Katz
  2006-05-24 18:01                   ` Stephen Smalley
  1 sibling, 1 reply; 33+ messages in thread
From: Jeremy Katz @ 2006-05-24 17:24 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, SELinux-dev, Paul Nasrat

On Tue, 2006-05-23 at 14:50 -0400, Stephen Smalley wrote:
> On Tue, 2006-05-23 at 14:23 -0400, Daniel J Walsh wrote:
> > Stephen Smalley wrote:
> > > Below is an updated version of the kernel patch to support rpm labeling
> > > of files before policy load, with a couple of bug fixes and a re-base to
> > > 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> > > resolve the issues of how rpm will check file label validity after
> > > policy load (e.g. calling security_check_context(3) on each label from
> > > the header), what corrective action rpm will take if a file label is
> > > invalid (options suggested include relabeling to unlabeled_t, relabeling
> > > to the context returned by the system policy via matchpathcon, or
> > > reverting the install), and the issues raised by Karl above (as they
> > > also affect the ability of rpm to perform such verification and
> > > correction sanely).
> > >
> > >   
> > As far as I understand it, rpm will not go back and check the whether 
> > the context are sane.  If the
> > postinstall of policy fails, the context on disk will be incorrect and 
> > treated like unlabeled_t.
> 
> I don't think that is really a viable option.  It is undesirable from
> both a robustness POV and a security POV.  rpm shouldn't leave the
> filesystem littered with files that have invalid contexts (which could
> later be turned into valid contexts by another package's policy module,
> suddenly granting access to those files or permissions to those
> executables unexpectedly), nor should it leave the system littered with
> packages whose policy couldn't be installed, as the package software may
> then run with the wrong permissions.

So the thing not covered in my other mail is "policy couldn't be
installed" -- but what would cause that to be the case?  I'd rather make
it so that we don't hit that (via dependencies, as I'm guessing that's
the likely culprit) rather than trying to hack around it.

Jeremy


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-24 17:24             ` Jeremy Katz
@ 2006-05-24 17:48               ` Stephen Smalley
  2006-05-25 15:19               ` Stephen Smalley
  1 sibling, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-24 17:48 UTC (permalink / raw)
  To: Jeremy Katz; +Cc: selinux, SELinux-dev, Paul Nasrat

On Wed, 2006-05-24 at 13:24 -0400, Jeremy Katz wrote:
> On Tue, 2006-05-23 at 13:15 -0400, Stephen Smalley wrote:
> > Below is an updated version of the kernel patch to support rpm labeling
> > of files before policy load, with a couple of bug fixes and a re-base to
> > 2.6.17-rc4-mm3.  Note that before we can upstream this, we need to
> > resolve the issues of how rpm will check file label validity after
> > policy load (e.g. calling security_check_context(3) on each label from
> > the header), what corrective action rpm will take if a file label is
> > invalid (options suggested include relabeling to unlabeled_t, relabeling
> > to the context returned by the system policy via matchpathcon, or
> > reverting the install), and the issues raised by Karl above (as they
> > also affect the ability of rpm to perform such verification and
> > correction sanely).
> 
> Well, given that the only labels that will end up in a header will be
> from a policy in that package, I'm still not really convinced what
> adding a verification step _really_ accomplishes.
>   
> 
> Sure, it helps in the case of someone crafting a malicious package which
> has random things in the header (by hand, not from rpmbuild[1]) but if
> someone is crafting a malicious package and getting it signed by someone
> you trust, then you have far larger concerns.

One would like to be able to go beyond a simple binary decision on trust
and instead constrain what a package can do at finer granularity based
both on the trustworthiness of the source and the function/purpose of
the package (e.g. httpd has no business replacing the base policy
module, nor does it need to add a policy module that adds allow rules
giving access to the policy store to httpd_t or any other domain,
regardless of the fact that it comes from Red Hat with suitable
signature).

> [1] Maybe it's just the clarification on what ends up happening that is
> really needed.  In the case where a package contains no policy modules
> the behavior will be exactly what it is today.  If a package contains a
> policy module, at rpmbuild time, we'll map contexts into the header for
> *only* the files covered explicitly by that policy module.  So the only
> contexts that could end up in the header will be ones that will then be
> installed by the policy module.  For the other files, we'll continue to
> just set the file contexts based on the policy as today.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-24 17:24                 ` Jeremy Katz
@ 2006-05-24 18:01                   ` Stephen Smalley
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Smalley @ 2006-05-24 18:01 UTC (permalink / raw)
  To: Jeremy Katz; +Cc: selinux, SELinux-dev, Paul Nasrat

On Wed, 2006-05-24 at 13:24 -0400, Jeremy Katz wrote:
> On Tue, 2006-05-23 at 14:50 -0400, Stephen Smalley wrote:
> > I don't think that is really a viable option.  It is undesirable from
> > both a robustness POV and a security POV.  rpm shouldn't leave the
> > filesystem littered with files that have invalid contexts (which could
> > later be turned into valid contexts by another package's policy module,
> > suddenly granting access to those files or permissions to those
> > executables unexpectedly), nor should it leave the system littered with
> > packages whose policy couldn't be installed, as the package software may
> > then run with the wrong permissions.
> 
> So the thing not covered in my other mail is "policy couldn't be
> installed" -- but what would cause that to be the case?  I'd rather make
> it so that we don't hit that (via dependencies, as I'm guessing that's
> the likely culprit) rather than trying to hack around it.

I don't think you can prevent it in general; there are many possible
failure points here, from dependency issues to policy denials to
conflicts with local policy modules created by users or third party
policy modules to resource failures (inadequate disk space for the new
policy module to be installed).  It isn't within the distro's control to
really guarantee that it will work.  I suppose a somewhat parallel
question might be how rpm handles other kinds of failures, not just from
the post scriptlets, but in setting down the files and establishing
their ownerships and modes normally.  However, that may not be a good
example, as there is no current attempt to provide a spectrum of trust
vs. an all-or-nothing situation.

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-24 17:24             ` Jeremy Katz
  2006-05-24 17:48               ` Stephen Smalley
@ 2006-05-25 15:19               ` Stephen Smalley
  2006-05-25 15:28                 ` Stephen Smalley
  1 sibling, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-25 15:19 UTC (permalink / raw)
  To: Jeremy Katz; +Cc: selinux, SELinux-dev, Paul Nasrat

On Wed, 2006-05-24 at 13:24 -0400, Jeremy Katz wrote:
> Well, given that the only labels that will end up in a header will be
> from a policy in that package, I'm still not really convinced what
> adding a verification step _really_ accomplishes.  

In addition to the security aspects, think about it just from the
perspective of robustness and error reporting.  At present (w/o
labelpriv support), programs get an immediate indication if they attempt
to set a file label that is not defined by the policy, so they know when
they have tried to use an invalid label.  With labelpriv support, some
programs (like rpm) are going to get no indications of invalid file
labels when they are set, nor will they get any indication when the
policy is loaded that those file labels were never made valid.  Hence,
if they don't perform any separate verification, they'll never know that
an error occurred, and just leave the system in an inconsistent state.

Compare with chown/chmod with symbolic values rather than raw integers,
and note that those programs certainly report when the symbolic value is
invalid.  Eric Paris pointed out that if we gave user domains (i.e.
unconfined_t in targeted policy) the new labelpriv permission, then they
would certainly be unhappy to find that a seemingly successful chcon
command actually left the file in an unlabeled state without any warning
or error.  If rpm doesn't do any verification/checking, then it is in
the same situation - it violates the principle of least surprise.

The alternative model to post checking after policy load would be to
either:
1) Precheck the file contexts from the header against the .pp file in
some manner at install time (in which case rpm can abort early), or
2) Have load_policy fail if any of these labelpriv-created contexts were
not made valid by the new policy, reverting to the old policy and
returning an error all the way back to rpm (in which case rpm still has
to take some corrective action).

-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-25 15:19               ` Stephen Smalley
@ 2006-05-25 15:28                 ` Stephen Smalley
  2006-05-26 18:54                   ` Jeremy Katz
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-25 15:28 UTC (permalink / raw)
  To: Jeremy Katz; +Cc: selinux, SELinux-dev, Paul Nasrat

On Thu, 2006-05-25 at 11:19 -0400, Stephen Smalley wrote:
> The alternative model to post checking after policy load would be to
> either:
> 1) Precheck the file contexts from the header against the .pp file in
> some manner at install time (in which case rpm can abort early), or

And as I suspect that you'll say that since those contexts were
generated from the .pp file in the first place, no such checking is
required, let me note that:
a) the contexts will have been generated from the file contexts part of
the .pp, not from the policy module itself, so there could be an
inconsistency between the two that leaves the context invalid under the
new policy, and
b) having rpm recheck at install time provides us with both greater
robustness (in the event of a bug in rpmbuild or a package corrupted in
some manner along the way) and security (in the event of a maliciously
constructed package).

> 2) Have load_policy fail if any of these labelpriv-created contexts were
> not made valid by the new policy, reverting to the old policy and
> returning an error all the way back to rpm (in which case rpm still has
> to take some corrective action).


-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-25 15:28                 ` Stephen Smalley
@ 2006-05-26 18:54                   ` Jeremy Katz
  2006-05-26 20:13                     ` Stephen Smalley
  0 siblings, 1 reply; 33+ messages in thread
From: Jeremy Katz @ 2006-05-26 18:54 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, SELinux-dev, Paul Nasrat

On Thu, 2006-05-25 at 11:28 -0400, Stephen Smalley wrote:
> On Thu, 2006-05-25 at 11:19 -0400, Stephen Smalley wrote:
> > The alternative model to post checking after policy load would be to
> > either:
> > 1) Precheck the file contexts from the header against the .pp file in
> > some manner at install time (in which case rpm can abort early), or
> 
> And as I suspect that you'll say that since those contexts were
> generated from the .pp file in the first place, no such checking is
> required, let me note that:
> a) the contexts will have been generated from the file contexts part of
> the .pp, not from the policy module itself, so there could be an
> inconsistency between the two that leaves the context invalid under the
> new policy, and

I still think that it's somewhat important to try to ensure that this
doesn't happen before you get to installing the package, just because at
that point, you're basically putting the user in the "you're hosed, do
not pass go, do not collect $200" position.  So I still hope that we
don't end up with this being a common occurrence :-)

> b) having rpm recheck at install time provides us with both greater
> robustness (in the event of a bug in rpmbuild or a package corrupted in
> some manner along the way) and security (in the event of a maliciously
> constructed package).

But I'm willing to concede that adding some form of checking here may
well make sense.  But I'm not convinced it will necessarily belong in
rpm itself -- it may make more sense to have it in the
policy_module_loader_helper which is going to end up being needed to
avoid stupid scriptlet errors.  But that's in the realm of it not really
mattering who's checking in that it's being checked.  Does that seem
reasonable?

Jeremy


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-26 18:54                   ` Jeremy Katz
@ 2006-05-26 20:13                     ` Stephen Smalley
  2006-05-26 20:16                       ` Jeremy Katz
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2006-05-26 20:13 UTC (permalink / raw)
  To: Jeremy Katz; +Cc: selinux, SELinux-dev, Paul Nasrat

On Fri, 2006-05-26 at 14:54 -0400, Jeremy Katz wrote:
> On Thu, 2006-05-25 at 11:28 -0400, Stephen Smalley wrote:
> > On Thu, 2006-05-25 at 11:19 -0400, Stephen Smalley wrote:
> > > The alternative model to post checking after policy load would be to
> > > either:
> > > 1) Precheck the file contexts from the header against the .pp file in
> > > some manner at install time (in which case rpm can abort early), or
> > 
> > And as I suspect that you'll say that since those contexts were
> > generated from the .pp file in the first place, no such checking is
> > required, let me note that:
> > a) the contexts will have been generated from the file contexts part of
> > the .pp, not from the policy module itself, so there could be an
> > inconsistency between the two that leaves the context invalid under the
> > new policy, and
> 
> I still think that it's somewhat important to try to ensure that this
> doesn't happen before you get to installing the package, just because at
> that point, you're basically putting the user in the "you're hosed, do
> not pass go, do not collect $200" position.  So I still hope that we
> don't end up with this being a common occurrence :-)

Agreed, we want to maximize build-time checking to catch problems in
advance, but we can't guarantee that it will catch all problems and we
don't want to have to fully trust it.

> > b) having rpm recheck at install time provides us with both greater
> > robustness (in the event of a bug in rpmbuild or a package corrupted in
> > some manner along the way) and security (in the event of a maliciously
> > constructed package).
> 
> But I'm willing to concede that adding some form of checking here may
> well make sense.  But I'm not convinced it will necessarily belong in
> rpm itself -- it may make more sense to have it in the
> policy_module_loader_helper which is going to end up being needed to
> avoid stupid scriptlet errors.  But that's in the realm of it not really
> mattering who's checking in that it's being checked.  Does that seem
> reasonable?

Only issue here is the error path in rpm if that helper fails (or
whether the helper gets enough information from rpm to take corrective
action itself).
 
-- 
Stephen Smalley
National Security Agency


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC][PATCH] selinux:  introduce support for deferred mapping of inode security contexts
  2006-05-26 20:13                     ` Stephen Smalley
@ 2006-05-26 20:16                       ` Jeremy Katz
  0 siblings, 0 replies; 33+ messages in thread
From: Jeremy Katz @ 2006-05-26 20:16 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, SELinux-dev, Paul Nasrat

On Fri, 2006-05-26 at 16:13 -0400, Stephen Smalley wrote:
> On Fri, 2006-05-26 at 14:54 -0400, Jeremy Katz wrote:
> > On Thu, 2006-05-25 at 11:28 -0400, Stephen Smalley wrote:
> > > On Thu, 2006-05-25 at 11:19 -0400, Stephen Smalley wrote:
> > > b) having rpm recheck at install time provides us with both greater
> > > robustness (in the event of a bug in rpmbuild or a package corrupted in
> > > some manner along the way) and security (in the event of a maliciously
> > > constructed package).
> > 
> > But I'm willing to concede that adding some form of checking here may
> > well make sense.  But I'm not convinced it will necessarily belong in
> > rpm itself -- it may make more sense to have it in the
> > policy_module_loader_helper which is going to end up being needed to
> > avoid stupid scriptlet errors.  But that's in the realm of it not really
> > mattering who's checking in that it's being checked.  Does that seem
> > reasonable?
> 
> Only issue here is the error path in rpm if that helper fails (or
> whether the helper gets enough information from rpm to take corrective
> action itself).

We'll make sure that the helper has enough information to fallback to
relabeling as unlabeled (it might even make sense for it to be able to
fall back to what the loaded policy would give so that, eg, shared libs
at least end up as lib_t)

Jeremy


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

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2006-05-26 20:16 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-15 16:35 [RFC][PATCH] selinux: introduce support for deferred mapping of inode security contexts Stephen Smalley
2006-05-15 17:41 ` Stephen Smalley
2006-05-16 12:15 ` Stephen Smalley
2006-05-17  7:54 ` Thomas Bleher
2006-05-17 17:52   ` Karl MacMillan
2006-05-17 19:01     ` Stephen Smalley
2006-05-18 18:14     ` Thomas Bleher
2006-05-19 12:59       ` Stephen Smalley
2006-05-19 13:18         ` Joshua Brindle
2006-05-19 13:18         ` Karl MacMillan
2006-05-23 17:15           ` Stephen Smalley
2006-05-23 18:23             ` Daniel J Walsh
2006-05-23 18:50               ` Stephen Smalley
2006-05-23 20:11                 ` Stephen Smalley
2006-05-24 17:24                   ` Jeremy Katz
2006-05-24 17:24                 ` Jeremy Katz
2006-05-24 18:01                   ` Stephen Smalley
2006-05-24 17:24             ` Jeremy Katz
2006-05-24 17:48               ` Stephen Smalley
2006-05-25 15:19               ` Stephen Smalley
2006-05-25 15:28                 ` Stephen Smalley
2006-05-26 18:54                   ` Jeremy Katz
2006-05-26 20:13                     ` Stephen Smalley
2006-05-26 20:16                       ` Jeremy Katz
2006-05-17 18:26   ` Stephen Smalley
2006-05-17 18:28     ` Karl MacMillan
2006-05-17 18:43       ` Stephen Smalley
2006-05-19 13:44 ` Stephen Smalley
2006-05-19 13:59   ` Daniel J Walsh
2006-05-19 14:14     ` Stephen Smalley
2006-05-19 14:20       ` Daniel J Walsh
  -- strict thread matches above, loose matches on Subject: below --
2006-05-19 14:05 Joshua Brindle
2006-05-19 14:18 ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.