[PATCH] Allowing MLS->non-MLS and vice versa upon policy reload

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear Stephen,

I have created the patch for allowing runtime switch between different policy types, according to your advice and previous discussions on this mailing list. The patch obsoletes the small piece of documentation that I wrote a few days ago to help new users cope with the limitation.

I would be very grateful if you could review the patch so that, as soon as it is reviewed, it can be posted to the kernel mailing list. I have done some basic testing and it works on one of my systems, although sometimes I get the following side-effect:

/dev/pts/0 changed labels.
Unable to restore tty label...

which however doesn't affect the system. I am not sure where that comes from (perhaps bash)...

Regards,

Guido Trentalancia

Author: Guido Trentalancia <guido@xxxxxxxxxxxxxxxx>
Date:   Sun Jan 31 22:10:22 2010 +0100

    Allow runtime switching between different policy types (e.g. from a MLS/MCS
    policy to a non-MLS/non-MCS policy or viceversa).

    Signed-off-by: Guido Trentalancia <guido@xxxxxxxxxxxxxxxx>

diff -pruN security-testing-2.6/security/selinux/Makefile security-testing-2.6-new/security/selinux/Makefile
--- security-testing-2.6/security/selinux/Makefile	2010-01-29 01:06:42.132070393 +0100
+++ security-testing-2.6-new/security/selinux/Makefile	2010-01-29 02:13:42.497044862 +0100
@@ -18,7 +18,7 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM)

 selinux-$(CONFIG_NETLABEL) += netlabel.o

-EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
+EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/ss -Isecurity/selinux/include

 $(obj)/avc.o: $(obj)/flask.h

diff -pruN security-testing-2.6/security/selinux/include/security.h security-testing-2.6-new/security/selinux/include/security.h
--- security-testing-2.6/security/selinux/include/security.h	2010-01-29 02:02:47.737045258 +0100
+++ security-testing-2.6-new/security/selinux/include/security.h	2010-01-29 02:13:59.641064788 +0100
@@ -57,7 +57,6 @@
 struct netlbl_lsm_secattr;

 extern int selinux_enabled;
-extern int selinux_mls_enabled;

 /* Policy capabilities */
 enum {
diff -pruN security-testing-2.6/security/selinux/selinuxfs.c security-testing-2.6-new/security/selinux/selinuxfs.c
--- security-testing-2.6/security/selinux/selinuxfs.c	2010-01-29 02:02:47.738046835 +0100
+++ security-testing-2.6-new/security/selinux/selinuxfs.c	2010-01-31 23:17:44.494329730 +0100
@@ -38,6 +38,10 @@
 #include "security.h"
 #include "objsec.h"
 #include "conditional.h"
+#include "services.h"
+#include "policydb.h"
+
+extern struct policydb policydb;

 /* Policy capability filenames */
 static char *policycap_names[] = {
@@ -282,7 +286,8 @@ static ssize_t sel_read_mls(struct file
 	char tmpbuf[TMPBUFLEN];
 	ssize_t length;

-	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
+		policydb.selinux_mls_enabled);
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }

diff -pruN security-testing-2.6/security/selinux/ss/Makefile security-testing-2.6-new/security/selinux/ss/Makefile
--- security-testing-2.6/security/selinux/ss/Makefile	2010-01-29 01:06:42.157062028 +0100
+++ security-testing-2.6-new/security/selinux/ss/Makefile	2010-01-29 02:15:52.319045091 +0100
@@ -5,5 +5,5 @@
 EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
 obj-y := ss.o

-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
+ss-y := context.o ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o mls_types.o

diff -pruN security-testing-2.6/security/selinux/ss/context.c security-testing-2.6-new/security/selinux/ss/context.c
--- security-testing-2.6/security/selinux/ss/context.c	1970-01-01 01:00:00.000000000 +0100
+++ security-testing-2.6-new/security/selinux/ss/context.c	2010-01-31 21:39:01.293500739 +0100
@@ -0,0 +1,131 @@
+/*
+ * Security context auxiliary functions
+ *
+ * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx>
+ */
+
+#include "context.h"
+#include "ebitmap.h"
+#include "mls_types.h"
+#include "security.h"
+#include "policydb.h"
+
+inline void mls_context_init(struct context *c)
+{
+	memset(&c->range, 0, sizeof(c->range));
+}
+
+inline int mls_context_cpy(struct context *dst, struct context *src)
+{
+	int rc;
+
+	if (!policydb.selinux_mls_enabled)
+		return 0;
+
+	dst->range.level[0].sens = src->range.level[0].sens;
+	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
+	if (rc)
+		goto out;
+
+	dst->range.level[1].sens = src->range.level[1].sens;
+	rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
+	if (rc)
+		ebitmap_destroy(&dst->range.level[0].cat);
+out:
+	return rc;
+}
+
+/*
+ * Sets both levels in the MLS range of 'dst' to the low level of 'src'.
+ */
+inline int mls_context_cpy_low(struct context *dst, struct context *src)
+{
+	int rc;
+
+	if (!policydb.selinux_mls_enabled)
+		return 0;
+
+	dst->range.level[0].sens = src->range.level[0].sens;
+	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
+	if (rc)
+		goto out;
+
+	dst->range.level[1].sens = src->range.level[0].sens;
+	rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat);
+	if (rc)
+		ebitmap_destroy(&dst->range.level[0].cat);
+out:
+	return rc;
+}
+
+inline int mls_context_cmp(struct context *c1, struct context *c2)
+{
+	if (!policydb.selinux_mls_enabled)
+		return 1;
+
+	return c1->range.level[0].sens == c2->range.level[0].sens &&
+		ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
+		c1->range.level[1].sens == c2->range.level[1].sens &&
+		ebitmap_cmp(&c1->range.level[1].cat, &c2->range.level[1].cat);
+}
+
+inline void mls_context_destroy(struct policydb *p, struct context *c)
+{
+	if (!p->selinux_mls_enabled)
+		return;
+
+	ebitmap_destroy(&c->range.level[0].cat);
+	ebitmap_destroy(&c->range.level[1].cat);
+	mls_context_init(c);
+}
+
+inline void context_init(struct context *c)
+{
+	memset(c, 0, sizeof(*c));
+}
+
+inline int context_cpy(struct context *dst, struct context *src)
+{
+	int rc;
+
+	dst->user = src->user;
+	dst->role = src->role;
+	dst->type = src->type;
+	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;
+}
+
+inline void context_destroy(struct policydb *p, struct context *c)
+{
+	c->user = c->role = c->type = 0;
+	kfree(c->str);
+	c->str = NULL;
+	c->len = 0;
+	mls_context_destroy(p, c);
+}
+
+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) &&
+		mls_context_cmp(c1, c2));
+}
+
diff -pruN security-testing-2.6/security/selinux/ss/context.h security-testing-2.6-new/security/selinux/ss/context.h
--- security-testing-2.6/security/selinux/ss/context.h	2010-01-29 01:06:42.160060332 +0100
+++ security-testing-2.6-new/security/selinux/ss/context.h	2010-01-31 21:38:06.517349464 +0100
@@ -12,6 +12,7 @@
  *
  * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx>
  */
+
 #ifndef _SS_CONTEXT_H_
 #define _SS_CONTEXT_H_

@@ -19,6 +20,8 @@
 #include "mls_types.h"
 #include "security.h"

+extern struct policydb policydb;
+
 /*
  * A security context consists of an authenticated user
  * identity, a role, a type and a MLS range.
@@ -32,124 +35,15 @@ struct context {
 	char *str;	/* string representation if context cannot be mapped. */
 };

-static inline void mls_context_init(struct context *c)
-{
-	memset(&c->range, 0, sizeof(c->range));
-}
-
-static inline int mls_context_cpy(struct context *dst, struct context *src)
-{
-	int rc;
-
-	if (!selinux_mls_enabled)
-		return 0;
-
-	dst->range.level[0].sens = src->range.level[0].sens;
-	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
-	if (rc)
-		goto out;
-
-	dst->range.level[1].sens = src->range.level[1].sens;
-	rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
-	if (rc)
-		ebitmap_destroy(&dst->range.level[0].cat);
-out:
-	return rc;
-}
-
-/*
- * Sets both levels in the MLS range of 'dst' to the low level of 'src'.
- */
-static inline int mls_context_cpy_low(struct context *dst, struct context *src)
-{
-	int rc;
-
-	if (!selinux_mls_enabled)
-		return 0;
-
-	dst->range.level[0].sens = src->range.level[0].sens;
-	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
-	if (rc)
-		goto out;
-
-	dst->range.level[1].sens = src->range.level[0].sens;
-	rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat);
-	if (rc)
-		ebitmap_destroy(&dst->range.level[0].cat);
-out:
-	return rc;
-}
-
-static inline int mls_context_cmp(struct context *c1, struct context *c2)
-{
-	if (!selinux_mls_enabled)
-		return 1;
-
-	return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
-		ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
-		(c1->range.level[1].sens == c2->range.level[1].sens) &&
-		ebitmap_cmp(&c1->range.level[1].cat, &c2->range.level[1].cat));
-}
-
-static inline void mls_context_destroy(struct context *c)
-{
-	if (!selinux_mls_enabled)
-		return;
-
-	ebitmap_destroy(&c->range.level[0].cat);
-	ebitmap_destroy(&c->range.level[1].cat);
-	mls_context_init(c);
-}
-
-static inline void context_init(struct context *c)
-{
-	memset(c, 0, sizeof(*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;
-	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) &&
-		mls_context_cmp(c1, c2));
-}
+inline void mls_context_init(struct context *c);
+inline int mls_context_cpy(struct context *dst, struct context *src);
+inline int mls_context_cpy_low(struct context *dst, struct context *src);
+inline int mls_context_cmp(struct context *c1, struct context *c2);
+inline void mls_context_destroy(struct policydb *p, struct context *c);
+inline void context_init(struct context *c);
+inline int context_cpy(struct context *dst, struct context *src);
+inline void context_destroy(struct policydb *p, struct context *c);
+inline int context_cmp(struct context *c1, struct context *c2);

 #endif	/* _SS_CONTEXT_H_ */

diff -pruN security-testing-2.6/security/selinux/ss/mls.c security-testing-2.6-new/security/selinux/ss/mls.c
--- security-testing-2.6/security/selinux/ss/mls.c	2010-01-29 02:02:47.739046177 +0100
+++ security-testing-2.6-new/security/selinux/ss/mls.c	2010-01-31 21:49:38.704348310 +0100
@@ -39,7 +39,7 @@ int mls_compute_context_len(struct conte
 	struct ebitmap *e;
 	struct ebitmap_node *node;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return 0;

 	len = 1; /* for the beginning ":" */
@@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *
 	struct ebitmap *e;
 	struct ebitmap_node *node;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return;

 	scontextp = *scontext;
@@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb
 {
 	struct user_datum *usrdatum;

-	if (!selinux_mls_enabled)
+	if (!p->selinux_mls_enabled)
 		return 1;

 	if (!mls_range_isvalid(p, &c->range))
@@ -253,7 +253,7 @@ int mls_context_to_sid(struct policydb *
 	struct cat_datum *catdatum, *rngdatum;
 	int l, rc = -EINVAL;

-	if (!selinux_mls_enabled) {
+	if (!pol->selinux_mls_enabled) {
 		if (def_sid != SECSID_NULL && oldc)
 			*scontext += strlen(*scontext)+1;
 		return 0;
@@ -387,7 +387,7 @@ int mls_from_string(char *str, struct co
 	char *tmpstr, *freestr;
 	int rc;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return -EINVAL;

 	/* we need freestr because mls_context_to_sid will change
@@ -407,7 +407,7 @@ int mls_from_string(char *str, struct co
 /*
  * Copies the MLS range `range' into `context'.
  */
-static inline int mls_range_set(struct context *context,
+inline int mls_range_set(struct context *context,
 				struct mls_range *range)
 {
 	int l, rc = 0;
@@ -427,7 +427,7 @@ static inline int mls_range_set(struct c
 int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
 			 struct context *usercon)
 {
-	if (selinux_mls_enabled) {
+	if (policydb.selinux_mls_enabled) {
 		struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
 		struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
 		struct mls_level *user_low = &(user->range.level[0]);
@@ -477,7 +477,7 @@ int mls_convert_context(struct policydb
 	struct ebitmap_node *node;
 	int l, i;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return 0;

 	for (l = 0; l < 2; l++) {
@@ -516,7 +516,7 @@ int mls_compute_sid(struct context *scon
 	struct range_trans rtr;
 	struct mls_range *r;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return 0;

 	switch (specified) {
@@ -559,7 +559,7 @@ int mls_compute_sid(struct context *scon
 void mls_export_netlbl_lvl(struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return;

 	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -579,7 +579,7 @@ void mls_export_netlbl_lvl(struct contex
 void mls_import_netlbl_lvl(struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return;

 	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -601,7 +601,7 @@ int mls_export_netlbl_cat(struct context
 {
 	int rc;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return 0;

 	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -629,7 +629,7 @@ int mls_import_netlbl_cat(struct context
 {
 	int rc;

-	if (!selinux_mls_enabled)
+	if (!policydb.selinux_mls_enabled)
 		return 0;

 	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff -pruN security-testing-2.6/security/selinux/ss/mls.h security-testing-2.6-new/security/selinux/ss/mls.h
--- security-testing-2.6/security/selinux/ss/mls.h	2010-01-29 01:06:42.168051431 +0100
+++ security-testing-2.6-new/security/selinux/ss/mls.h	2010-01-31 21:50:17.923330980 +0100
@@ -24,6 +24,8 @@
 #include "context.h"
 #include "policydb.h"

+extern struct policydb policydb;
+
 int mls_compute_context_len(struct context *context);
 void mls_sid_to_context(struct context *context, char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
@@ -39,6 +41,8 @@ int mls_context_to_sid(struct policydb *

 int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);

+inline int mls_range_set(struct context *context, struct mls_range *range);
+
 int mls_convert_context(struct policydb *oldp,
 			struct policydb *newp,
 			struct context *context);
diff -pruN security-testing-2.6/security/selinux/ss/mls_types.c security-testing-2.6-new/security/selinux/ss/mls_types.c
--- security-testing-2.6/security/selinux/ss/mls_types.c	1970-01-01 01:00:00.000000000 +0100
+++ security-testing-2.6-new/security/selinux/ss/mls_types.c	2010-01-29 02:36:49.528045041 +0100
@@ -0,0 +1,27 @@
+/*
+ * Auxiliary functions for the multi-level security (MLS) policy.
+ *
+ * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx>
+ */
+
+#include "mls_types.h"
+#include "policydb.h"
+
+inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
+{
+	if (!policydb.selinux_mls_enabled)
+		return 1;
+
+	return ((l1->sens == l2->sens) &&
+		ebitmap_cmp(&l1->cat, &l2->cat));
+}
+
+inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+{
+	if (!policydb.selinux_mls_enabled)
+		return 1;
+
+	return ((l1->sens >= l2->sens) &&
+		ebitmap_contains(&l1->cat, &l2->cat));
+}
+
diff -pruN security-testing-2.6/security/selinux/ss/mls_types.h security-testing-2.6-new/security/selinux/ss/mls_types.h
--- security-testing-2.6/security/selinux/ss/mls_types.h	2010-01-29 01:06:42.168051431 +0100
+++ security-testing-2.6-new/security/selinux/ss/mls_types.h	2010-01-29 02:23:39.017044387 +0100
@@ -14,7 +14,9 @@
 #ifndef _SS_MLS_TYPES_H_
 #define _SS_MLS_TYPES_H_

-#include "security.h"
+#include "ebitmap.h"
+
+extern struct policydb policydb;

 struct mls_level {
 	u32 sens;		/* sensitivity */
@@ -25,23 +27,8 @@ struct mls_range {
 	struct mls_level level[2]; /* low == level[0], high == level[1] */
 };

-static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
-{
-	if (!selinux_mls_enabled)
-		return 1;
-
-	return ((l1->sens == l2->sens) &&
-		ebitmap_cmp(&l1->cat, &l2->cat));
-}
-
-static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
-{
-	if (!selinux_mls_enabled)
-		return 1;
-
-	return ((l1->sens >= l2->sens) &&
-		ebitmap_contains(&l1->cat, &l2->cat));
-}
+inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2);
+inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2);

 #define mls_level_incomp(l1, l2)
 (!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
diff -pruN security-testing-2.6/security/selinux/ss/policydb.c security-testing-2.6-new/security/selinux/ss/policydb.c
--- security-testing-2.6/security/selinux/ss/policydb.c	2010-01-29 02:02:47.740046077 +0100
+++ security-testing-2.6-new/security/selinux/ss/policydb.c	2010-01-31 21:41:44.306327882 +0100
@@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = {
 };
 #endif

-int selinux_mls_enabled;
-
 static unsigned int symtab_sizes[SYM_NUM] = {
 	2,
 	32,
@@ -455,7 +453,7 @@ static int policydb_index_others(struct

 	printk(KERN_DEBUG "SELinux:  %d users, %d roles, %d types, %d bools",
 	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
-	if (selinux_mls_enabled)
+	if (p->selinux_mls_enabled)
 		printk(", %d sens, %d cats", p->p_levels.nprim,
 		       p->p_cats.nprim);
 	printk("n");
@@ -656,10 +654,10 @@ static int range_tr_destroy(void *key, v
 	return 0;
 }

-static void ocontext_destroy(struct ocontext *c, int i)
+static void ocontext_destroy(struct policydb *p, struct ocontext *c, int i)
 {
-	context_destroy(&c->context[0]);
-	context_destroy(&c->context[1]);
+	context_destroy(p, &c->context[0]);
+	context_destroy(p, &c->context[1]);
 	if (i == OCON_ISID || i == OCON_FS ||
 	    i == OCON_NETIF || i == OCON_FSUSE)
 		kfree(c->u.name);
@@ -699,7 +697,7 @@ void policydb_destroy(struct policydb *p
 		while (c) {
 			ctmp = c;
 			c = c->next;
-			ocontext_destroy(ctmp, i);
+			ocontext_destroy(p, ctmp, i);
 		}
 		p->ocontexts[i] = NULL;
 	}
@@ -712,7 +710,7 @@ void policydb_destroy(struct policydb *p
 		while (c) {
 			ctmp = c;
 			c = c->next;
-			ocontext_destroy(ctmp, OCON_FSUSE);
+			ocontext_destroy(p, ctmp, OCON_FSUSE);
 		}
 		gtmp = g;
 		g = g->next;
@@ -942,7 +940,7 @@ static int context_read_and_validate(str

 	if (!policydb_context_isvalid(p, c)) {
 		printk(KERN_ERR "SELinux:  invalid security contextn");
-		context_destroy(c);
+		context_destroy(p, c);
 		rc = -EINVAL;
 	}
 out:
@@ -1787,12 +1785,7 @@ int policydb_read(struct policydb *p, vo
 	}

 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
-		if (ss_initialized && !selinux_mls_enabled) {
-			printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
-				" and MLS policiesn");
-			goto bad;
-		}
-		selinux_mls_enabled = 1;
+		p->selinux_mls_enabled = 1;
 		config |= POLICYDB_CONFIG_MLS;

 		if (p->policyvers < POLICYDB_VERSION_MLS) {
@@ -1801,12 +1794,6 @@ int policydb_read(struct policydb *p, vo
 				p->policyvers);
 			goto bad;
 		}
-	} else {
-		if (ss_initialized && selinux_mls_enabled) {
-			printk(KERN_ERR "SELinux: Cannot switch between MLS and"
-				" non-MLS policiesn");
-			goto bad;
-		}
 	}
 	p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
 	p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
@@ -2234,7 +2221,7 @@ int policydb_read(struct policydb *p, vo
 out:
 	return rc;
 bad_newc:
-	ocontext_destroy(newc, OCON_FSUSE);
+	ocontext_destroy(p, newc, OCON_FSUSE);
 bad:
 	if (!rc)
 		rc = -EINVAL;
diff -pruN security-testing-2.6/security/selinux/ss/policydb.h security-testing-2.6-new/security/selinux/ss/policydb.h
--- security-testing-2.6/security/selinux/ss/policydb.h	2010-01-29 02:02:47.740046077 +0100
+++ security-testing-2.6-new/security/selinux/ss/policydb.h	2010-01-29 02:33:01.393045934 +0100
@@ -185,6 +185,8 @@ struct genfs {

 /* The policy database */
 struct policydb {
+	int selinux_mls_enabled;
+
 	/* symbol tables */
 	struct symtab symtab[SYM_NUM];
 #define p_commons symtab[SYM_COMMONS]
diff -pruN security-testing-2.6/security/selinux/ss/services.c security-testing-2.6-new/security/selinux/ss/services.c
--- security-testing-2.6/security/selinux/ss/services.c	2010-01-29 02:02:47.742042805 +0100
+++ security-testing-2.6-new/security/selinux/ss/services.c	2010-01-31 23:28:26.440336638 +0100
@@ -26,6 +26,10 @@
  *
  *  Added support for bounds domain and audit messaged on masked permissions
  *
+ * Updated: Guido Trentalancia <guido@xxxxxxxxxxxxxxxx>
+ *
+ *  Added support for runtime switching of the policy type
+ *
  * Copyright (C) 2008, 2009 NEC Corporation
  * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
@@ -1145,7 +1149,7 @@ static int string_to_context_struct(stru
 	rc = 0;
 out:
 	if (rc)
-		context_destroy(ctx);
+		context_destroy(pol, ctx);
 	return rc;
 }

@@ -1198,7 +1202,7 @@ static int security_context_to_sid_core(
 	} else if (rc)
 		goto out;
 	rc = sidtab_context_to_sid(&sidtab, &context, sid);
-	context_destroy(&context);
+	context_destroy(&policydb, &context);
 out:
 	read_unlock(&policy_rwlock);
 	kfree(scontext2);
@@ -1419,7 +1423,7 @@ static int security_compute_sid(u32 ssid
 	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
-	context_destroy(&newcontext);
+	context_destroy(&policydb, &newcontext);
 out:
 	return rc;
 }
@@ -1547,6 +1551,8 @@ static int convert_context(u32 key,
 {
 	struct convert_context_args *args;
 	struct context oldc;
+	struct ocontext *oc;
+	struct mls_range *range;
 	struct role_datum *role;
 	struct type_datum *typdatum;
 	struct user_datum *usrdatum;
@@ -1614,9 +1620,29 @@ static int convert_context(u32 key,
 		goto bad;
 	c->type = typdatum->value;

-	rc = mls_convert_context(args->oldp, args->newp, c);
-	if (rc)
-		goto bad;
+	/* Convert the MLS/MCS fields or deal with policy type switch */
+	if (args->oldp->selinux_mls_enabled
+	    && args->newp->selinux_mls_enabled) {
+		rc = mls_convert_context(args->oldp, args->newp, c);
+		if (rc)
+			goto bad;
+	} else if (args->oldp->selinux_mls_enabled
+		   && !args->newp->selinux_mls_enabled)
+	/* Switching between MLS/MCS and non-MLS/non-MCS policy: */
+	/* free any storage used by the MLS fields in the        */
+	/* context for all existing entries in the sidtab.       */
+		mls_context_destroy(args->oldp, c);
+	else if (!args->oldp->selinux_mls_enabled
+		 && args->newp->selinux_mls_enabled) {
+	/* Switching between non-MLS/non-MCS and MLS/MCS policy:  */
+	/* ensure that the MLS fields of the context for all      */
+	/* existing entries in the sidtab are filled in with a    */
+	/* suitable default value, likely taken from one of the   */
+	/* initial SIDs.                                          */
+		oc = args->newp->ocontexts[OCON_ISID];
+		range = &oc->context[0].range;
+		mls_range_set(c, range);
+	}

 	/* Check the validity of the new context. */
 	if (!policydb_context_isvalid(args->newp, c)) {
@@ -1625,7 +1651,7 @@ static int convert_context(u32 key,
 			goto bad;
 	}

-	context_destroy(&oldc);
+	context_destroy(args->oldp, &oldc);
 	rc = 0;
 out:
 	return rc;
@@ -1633,8 +1659,8 @@ bad:
 	/* Map old representation to string and save it. */
 	if (context_struct_to_string(&oldc, &s, &len))
 		return -ENOMEM;
-	context_destroy(&oldc);
-	context_destroy(c);
+	context_destroy(args->oldp, &oldc);
+	context_destroy(args->newp, c);
 	c->str = s;
 	c->len = len;
 	printk(KERN_INFO
@@ -1712,6 +1738,15 @@ int security_load_policy(void *data, siz
 	if (policydb_read(&newpolicydb, fp))
 		return -EINVAL;

+	/* If switching between different policy types, log it */
+	if (policydb.selinux_mls_enabled && newpolicydb.selinux_mls_enabled)
+		printk(KERN_INFO "SELinux: Switching between MLS/MCS"
+			" and standard policy...n");
+	else if (!policydb.selinux_mls_enabled
+	  && newpolicydb.selinux_mls_enabled)
+		printk(KERN_INFO "SELinux: Switching between standard"
+			" and MLS/MCS policy...n");
+
 	if (sidtab_init(&newsidtab)) {
 		policydb_destroy(&newpolicydb);
 		return -ENOMEM;
@@ -1741,8 +1776,12 @@ int security_load_policy(void *data, siz
 	args.oldp = &policydb;
 	args.newp = &newpolicydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR "SELinux:  unable to convert the internal"
+			" representation of contexts in the new SID"
+			" tablen");
 		goto err;
+	}

 	/* Save the old policydb and SID table to free later. */
 	memcpy(&oldpolicydb, &policydb, sizeof policydb);
@@ -1761,7 +1800,7 @@ int security_load_policy(void *data, siz

 	/* Free the old policydb and SID table. */
 	policydb_destroy(&oldpolicydb);
-	sidtab_destroy(&oldsidtab);
+	sidtab_destroy(&oldpolicydb, &oldsidtab);
 	kfree(oldmap);

 	avc_ss_reset(seqno);
@@ -1773,7 +1812,7 @@ int security_load_policy(void *data, siz

 err:
 	kfree(map);
-	sidtab_destroy(&newsidtab);
+	sidtab_destroy(&newpolicydb, &newsidtab);
 	policydb_destroy(&newpolicydb);
 	return rc;

@@ -2338,7 +2377,7 @@ int security_sid_mls_copy(u32 sid, u32 m
 	u32 len;
 	int rc = 0;

-	if (!ss_initialized || !selinux_mls_enabled) {
+	if (!ss_initialized || !policydb.selinux_mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -2388,7 +2427,7 @@ bad:

 out_unlock:
 	read_unlock(&policy_rwlock);
-	context_destroy(&newcon);
+	context_destroy(&policydb, &newcon);
 out:
 	return rc;
 }
@@ -2439,7 +2478,7 @@ int security_net_peersid_resolve(u32 nlb
 	/* we don't need to check ss_initialized here since the only way both
 	 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
 	 * security server was initialized and ss_initialized was true */
-	if (!selinux_mls_enabled) {
+	if (!policydb.selinux_mls_enabled) {
 		*peer_sid = SECSID_NULL;
 		return 0;
 	}
@@ -2612,7 +2651,7 @@ void selinux_audit_rule_free(void *vrule
 	struct selinux_audit_rule *rule = vrule;

 	if (rule) {
-		context_destroy(&rule->au_ctxt);
+		context_destroy(&policydb, &rule->au_ctxt);
 		kfree(rule);
 	}
 }
diff -pruN security-testing-2.6/security/selinux/ss/services.h security-testing-2.6-new/security/selinux/ss/services.h
--- security-testing-2.6/security/selinux/ss/services.h	2010-01-29 01:06:42.174044406 +0100
+++ security-testing-2.6-new/security/selinux/ss/services.h	2010-01-31 23:24:36.677347711 +0100
@@ -3,6 +3,7 @@
  *
  * Author : Stephen Smalley, <sds@xxxxxxxxxxxxxx>
  */
+
 #ifndef _SS_SERVICES_H_
 #define _SS_SERVICES_H_

@@ -11,5 +12,51 @@

 extern struct policydb policydb;

+int security_bounded_transition(u32 old_sid, u32 new_sid);
+void security_compute_av(u32 ssid, u32 tsid, u16 orig_tclass,
+			 struct av_decision *avd);
+void security_compute_av_user(u32 ssid, u32 tsid, u16 tclass,
+			      struct av_decision *avd);
+const char *security_get_initial_sid_context(u32 sid);
+int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
+int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
+int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid);
+int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+				    u32 *sid, u32 def_sid, gfp_t gfp_flags);
+int security_context_to_sid_force(const char *scontext, u32 scontext_len,
+				  u32 *sid);
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
+int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
+int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
+int security_load_policy(void *data, size_t len);
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
+int security_netif_sid(char *name, u32 *if_sid);
+int security_node_sid(u16 domain, void *addrp, u32 addrlen, u32 *out_sid);
+int security_get_user_sids(u32 fromsid, char *username, u32 **sids, u32 *nel);
+int security_genfs_sid(const char *fstype, char *path, u16 orig_sclass,
+		       u32 *sid);
+int security_fs_use(const char *fstype, unsigned int *behavior, u32 *sid);
+int security_get_bools(int *len, char ***names, int **values);
+int security_set_bools(int len, int *values);
+int security_get_bool_value(int bool);
+int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
+int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, u32 xfrm_sid,
+				 u32 *peer_sid);
+int security_get_classes(char ***classes, int *nclasses);
+int security_get_permissions(char *class, char ***perms, int *nperms);
+int security_get_reject_unknown(void);
+int security_get_allow_unknown(void);
+int security_policycap_supported(unsigned int req_cap);
+void selinux_audit_rule_free(void *vrule);
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule);
+int selinux_audit_rule_known(struct audit_krule *rule);
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+			     struct audit_context *actx);
+int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
+				   u32 *sid);
+int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr);
+
+
 #endif	/* _SS_SERVICES_H_ */

diff -pruN security-testing-2.6/security/selinux/ss/sidtab.c security-testing-2.6-new/security/selinux/ss/sidtab.c
--- security-testing-2.6/security/selinux/ss/sidtab.c	2010-01-29 01:06:42.174044406 +0100
+++ security-testing-2.6-new/security/selinux/ss/sidtab.c	2010-01-31 21:42:55.649896349 +0100
@@ -232,7 +232,7 @@ void sidtab_hash_eval(struct sidtab *h,
 	       max_chain_len);
 }

-void sidtab_destroy(struct sidtab *s)
+void sidtab_destroy(struct policydb *p, struct sidtab *s)
 {
 	int i;
 	struct sidtab_node *cur, *temp;
@@ -245,7 +245,7 @@ void sidtab_destroy(struct sidtab *s)
 		while (cur) {
 			temp = cur;
 			cur = cur->next;
-			context_destroy(&temp->context);
+			context_destroy(p, &temp->context);
 			kfree(temp);
 		}
 		s->htable[i] = NULL;
diff -pruN security-testing-2.6/security/selinux/ss/sidtab.h security-testing-2.6-new/security/selinux/ss/sidtab.h
--- security-testing-2.6/security/selinux/ss/sidtab.h	2010-01-29 01:06:42.175047659 +0100
+++ security-testing-2.6-new/security/selinux/ss/sidtab.h	2010-01-31 21:42:31.052348740 +0100
@@ -45,7 +45,7 @@ int sidtab_context_to_sid(struct sidtab
 			  u32 *sid);

 void sidtab_hash_eval(struct sidtab *h, char *tag);
-void sidtab_destroy(struct sidtab *s);
+void sidtab_destroy(struct policydb *p, struct sidtab *s);
 void sidtab_set(struct sidtab *dst, struct sidtab *src);
 void sidtab_shutdown(struct sidtab *s);

Attachment: switch-policy.patch
Description: Binary data


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux