All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds
@ 2018-01-26 14:32 ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn

Holding the preempt_disable is very bad for low latency tasks
as audio and therefore we need to break out the rule-set dependent
part from this disable. By using a RCU instead of rwlock we
have an efficient locking and less preemption interference.

Selinux uses a lot of read_locks. This patch replaces the rwlock
with RCY that does not hold preempt_disable.

Intel Xeon W3520 2.67 Ghz running FC27 with 4.15.0-rc9git (+measurement)
I get preempt_disable in worst case for 1.2ms in security_compute_av().
With the patch I get 960us as the longest security_compute_av()
without preempt disabeld. It very much noise in the measurement
but it is not likely a degrade.

And the preempt_disable times is also very dependent on the selinux
rule-set.

In security_get_user_sids() we have two nested for-loops and the
inner part calls sittab_context_to_sid() that calls
sidtab_search_context() that has a for loop() over a while() where
the loops is dependent on the rules.

On the test system the average lookup time is 60us and does
not change with the RCU usage.

To use RCU the structure of policydb has to be accesses through a pointer.
We need 4 patches to get there.

  [PATCH v2 1/5] selinux:Remove direct references to policydb.
  We remove direct references and pass it through function arguments.

  [PATCH v2 2/5] selinux: Move policydb to pointer structure
  Move the policydb to dynamic allocated structure.

  [PATCH v2 3/5] selinux: Move sidtab to pointer structure
  Same as for policydb but for sidtab. They are closly related
  and should be switched at the same time.
  
  [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  Now we can switch rules by switching pointers.

  [PATCH v2 5/5] selinux: Switch locking to RCU.
  We are now ready to use RCU.
  
History: V1 rwsem

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

* [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds
@ 2018-01-26 14:32 ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

Holding the preempt_disable is very bad for low latency tasks
as audio and therefore we need to break out the rule-set dependent
part from this disable. By using a RCU instead of rwlock we
have an efficient locking and less preemption interference.

Selinux uses a lot of read_locks. This patch replaces the rwlock
with RCY that does not hold preempt_disable.

Intel Xeon W3520 2.67 Ghz running FC27 with 4.15.0-rc9git (+measurement)
I get preempt_disable in worst case for 1.2ms in security_compute_av().
With the patch I get 960us as the longest security_compute_av()
without preempt disabeld. It very much noise in the measurement
but it is not likely a degrade.

And the preempt_disable times is also very dependent on the selinux
rule-set.

In security_get_user_sids() we have two nested for-loops and the
inner part calls sittab_context_to_sid() that calls
sidtab_search_context() that has a for loop() over a while() where
the loops is dependent on the rules.

On the test system the average lookup time is 60us and does
not change with the RCU usage.

To use RCU the structure of policydb has to be accesses through a pointer.
We need 4 patches to get there.

  [PATCH v2 1/5] selinux:Remove direct references to policydb.
  We remove direct references and pass it through function arguments.

  [PATCH v2 2/5] selinux: Move policydb to pointer structure
  Move the policydb to dynamic allocated structure.

  [PATCH v2 3/5] selinux: Move sidtab to pointer structure
  Same as for policydb but for sidtab. They are closly related
  and should be switched at the same time.
  
  [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  Now we can switch rules by switching pointers.

  [PATCH v2 5/5] selinux: Switch locking to RCU.
  We are now ready to use RCU.
  
History: V1 rwsem
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds
@ 2018-01-26 14:32 ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn

Holding the preempt_disable is very bad for low latency tasks
as audio and therefore we need to break out the rule-set dependent
part from this disable. By using a RCU instead of rwlock we
have an efficient locking and less preemption interference.

Selinux uses a lot of read_locks. This patch replaces the rwlock
with RCY that does not hold preempt_disable.

Intel Xeon W3520 2.67 Ghz running FC27 with 4.15.0-rc9git (+measurement)
I get preempt_disable in worst case for 1.2ms in security_compute_av().
With the patch I get 960us as the longest security_compute_av()
without preempt disabeld. It very much noise in the measurement
but it is not likely a degrade.

And the preempt_disable times is also very dependent on the selinux
rule-set.

In security_get_user_sids() we have two nested for-loops and the
inner part calls sittab_context_to_sid() that calls
sidtab_search_context() that has a for loop() over a while() where
the loops is dependent on the rules.

On the test system the average lookup time is 60us and does
not change with the RCU usage.

To use RCU the structure of policydb has to be accesses through a pointer.
We need 4 patches to get there.

  [PATCH v2 1/5] selinux:Remove direct references to policydb.
  We remove direct references and pass it through function arguments.

  [PATCH v2 2/5] selinux: Move policydb to pointer structure
  Move the policydb to dynamic allocated structure.

  [PATCH v2 3/5] selinux: Move sidtab to pointer structure
  Same as for policydb but for sidtab. They are closly related
  and should be switched at the same time.
  
  [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  Now we can switch rules by switching pointers.

  [PATCH v2 5/5] selinux: Switch locking to RCU.
  We are now ready to use RCU.
  
History: V1 rwsem

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-01-26 14:32 ` peter.enderborg at sony.com
  (?)
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  -1 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This preparation removes the export of the
policydb and send pointers to it through parameter agruments.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
 security/selinux/ss/mls.h      | 37 +++++++++--------
 security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++---------------
 security/selinux/ss/services.h |  3 --
 4 files changed, 114 insertions(+), 85 deletions(-)

diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index ad982ce..b1f35d3 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -33,20 +33,20 @@
  * Return the length in bytes for the MLS fields of the
  * security context string representation of `context'.
  */
-int mls_compute_context_len(struct context *context)
+int mls_compute_context_len(struct policydb *p, struct context *context)
 {
 	int i, l, len, head, prev;
 	char *nm;
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	len = 1; /* for the beginning ":" */
 	for (l = 0; l < 2; l++) {
 		int index_sens = context->range.level[l].sens;
-		len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
+		len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
 
 		/* categories */
 		head = -2;
@@ -56,17 +56,17 @@ int mls_compute_context_len(struct context *context)
 			if (i - prev > 1) {
 				/* one or more negative bits are skipped */
 				if (head != prev) {
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					len += strlen(nm) + 1;
 				}
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				len += strlen(nm) + 1;
 				head = i;
 			}
 			prev = i;
 		}
 		if (prev != head) {
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			len += strlen(nm) + 1;
 		}
 		if (l == 0) {
@@ -86,7 +86,7 @@ int mls_compute_context_len(struct context *context)
  * the MLS fields of `context' into the string `*scontext'.
  * Update `*scontext' to point to the end of the MLS fields.
  */
-void mls_sid_to_context(struct context *context,
+void mls_sid_to_context(struct policydb *p, struct context *context,
 			char **scontext)
 {
 	char *scontextp, *nm;
@@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	scontextp = *scontext;
@@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
 	scontextp++;
 
 	for (l = 0; l < 2; l++) {
-		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
+		strcpy(scontextp, sym_name(p, SYM_LEVELS,
 					   context->range.level[l].sens - 1));
 		scontextp += strlen(scontextp);
 
@@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
 						*scontextp++ = '.';
 					else
 						*scontextp++ = ',';
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					strcpy(scontextp, nm);
 					scontextp += strlen(nm);
 				}
@@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
 					*scontextp++ = ':';
 				else
 					*scontextp++ = ',';
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				strcpy(scontextp, nm);
 				scontextp += strlen(nm);
 				head = i;
@@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
 				*scontextp++ = '.';
 			else
 				*scontextp++ = ',';
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			strcpy(scontextp, nm);
 			scontextp += strlen(nm);
 		}
@@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
  * the string `str'.  This function will allocate temporary memory with the
  * given constraints of gfp_mask.
  */
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask)
 {
 	char *tmpstr, *freestr;
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return -EINVAL;
 
 	/* we need freestr because mls_context_to_sid will change
@@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
 	if (!tmpstr) {
 		rc = -ENOMEM;
 	} else {
-		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
+		rc = mls_context_to_sid(p, ':', &tmpstr, context,
 					NULL, SECSID_NULL);
 		kfree(freestr);
 	}
@@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
 	return rc;
 }
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon)
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon)
 {
-	if (policydb.mls_enabled) {
+	if (p->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]);
@@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
  * structure `c' from the values specified in the
  * policy `oldp' to the values specified in the policy `newp'.
  */
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *c)
 {
@@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
 	struct ebitmap_node *node;
 	int l, i;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	for (l = 0; l < 2; l++) {
@@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
 	return 0;
 }
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
@@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
 	struct class_datum *cladatum;
 	int default_range = 0;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	switch (specified) {
@@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
 		rtr.source_type = scontext->type;
 		rtr.target_type = tcontext->type;
 		rtr.target_class = tclass;
-		r = hashtab_search(policydb.range_tr, &rtr);
+		r = hashtab_search(p->range_tr, &rtr);
 		if (r)
 			return mls_range_set(newcontext, r);
 
-		if (tclass && tclass <= policydb.p_classes.nprim) {
-			cladatum = policydb.class_val_to_struct[tclass - 1];
+		if (tclass && tclass <= p->p_classes.nprim) {
+			cladatum = p->class_val_to_struct[tclass - 1];
 			if (cladatum)
 				default_range = cladatum->default_range;
 		}
@@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
 
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == p->process_class) || (sock == true))
 			/* Use the process MLS attributes. */
 			return mls_context_cpy(newcontext, scontext);
 		else
@@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
  * NetLabel MLS sensitivity level field.
  *
  */
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context *context,
  * NetLabel MLS sensitivity level into the context.
  *
  */
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context *context,
  * MLS category field.  Returns zero on success, negative values on failure.
  *
  */
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context *context,
  * negative values on failure.
  *
  */
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 131d762..cb039c0 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -25,8 +25,9 @@
 #include "context.h"
 #include "policydb.h"
 
-int mls_compute_context_len(struct context *context);
-void mls_sid_to_context(struct context *context, char **scontext);
+int mls_compute_context_len(struct policydb *p, struct context *context);
+void mls_sid_to_context(struct policydb *p, struct context *context,
+			char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
 int mls_range_isvalid(struct policydb *p, struct mls_range *r);
 int mls_level_isvalid(struct policydb *p, struct mls_level *l);
@@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
 		       struct sidtab *s,
 		       u32 def_sid);
 
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask);
 
 int mls_range_set(struct context *context, struct mls_range *range);
 
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *context);
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
 		    struct context *newcontext,
 		    bool sock);
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon);
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon);
 
 #ifdef CONFIG_NETLABEL
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
 #else
-static inline void mls_export_netlbl_lvl(struct context *context,
+static inline void mls_export_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline void mls_import_netlbl_lvl(struct context *context,
+static inline void mls_import_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline int mls_export_netlbl_cat(struct context *context,
+static inline int mls_export_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
 }
-static inline int mls_import_netlbl_cat(struct context *context,
+static inline int mls_import_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
@@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct context *context,
 #endif
 
 #endif	/* _SS_MLS_H */
-
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 33cfe5d..47d8030 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-struct policydb policydb;
+static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -117,8 +117,12 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-static struct selinux_mapping *current_mapping;
-static u16 current_mapping_size;
+struct shared_current_mapping {
+	struct selinux_mapping *current_mapping;
+	u16 current_mapping_size;
+};
+
+static struct shared_current_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb *pol,
 
 static u16 unmap_class(u16 tclass)
 {
-	if (tclass < current_mapping_size)
-		return current_mapping[tclass].value;
+	if (tclass < crm->current_mapping_size)
+		return crm->current_mapping[tclass].value;
 
 	return tclass;
 }
@@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
 {
 	u16 i;
 
-	for (i = 1; i < current_mapping_size; i++) {
-		if (current_mapping[i].value == pol_value)
+	for (i = 1; i < crm->current_mapping_size; i++) {
+		if (crm->current_mapping[i].value == pol_value)
 			return i;
 	}
 
@@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
-	if (tclass < current_mapping_size) {
-		unsigned i, n = current_mapping[tclass].num_perms;
+	if (tclass < crm->current_mapping_size) {
+		unsigned int i, n = crm->current_mapping[tclass].num_perms;
 		u32 result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->allowed & current_mapping[tclass].perms[i])
+			if (avd->allowed &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (allow_unknown && !current_mapping[tclass].perms[i])
+			if (allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		avd->allowed = result;
 
 		for (i = 0, result = 0; i < n; i++)
-			if (avd->auditallow & current_mapping[tclass].perms[i])
+			if (avd->auditallow &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		avd->auditallow = result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->auditdeny & current_mapping[tclass].perms[i])
+			if (avd->auditdeny &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (!allow_unknown && !current_mapping[tclass].perms[i])
+			if (!allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		/*
@@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(context);
+	*scontext_len += mls_compute_context_len(&policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 		sym_name(&policydb, SYM_ROLES, context->role - 1),
 		sym_name(&policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(context, &scontextp);
+	mls_sid_to_context(&policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
 			     &newcontext, sock);
 	if (rc)
 		goto out_unlock;
@@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(args->oldp, args->newp, c);
+		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t len)
 {
 	struct policydb *oldpolicydb, *newpolicydb;
 	struct sidtab oldsidtab, newsidtab;
-	struct selinux_mapping *oldmap, *map = NULL;
+	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
+	struct shared_current_mapping *new_mapping;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t len)
 		rc = -ENOMEM;
 		goto out;
 	}
+	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+	if (!new_mapping) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	newpolicydb = oldpolicydb + 1;
 
 	if (!ss_initialized) {
+		crm = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+		if (!crm) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t len)
 
 		policydb.len = len;
 		rc = selinux_set_mapping(&policydb, secclass_map,
-					 &current_mapping,
-					 &current_mapping_size);
+					 &crm->current_mapping,
+					 &crm->current_mapping_size);
 		if (rc) {
 			policydb_destroy(&policydb);
 			avtab_cache_destroy();
@@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t len)
 	memcpy(&policydb, newpolicydb, sizeof(policydb));
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
-	oldmap = current_mapping;
-	current_mapping = map;
-	current_mapping_size = map_size;
+	oldmap = crm->current_mapping;
+	crm->current_mapping = map;
+	crm->current_mapping_size = map_size;
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
 
@@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(fromcon, user, &usercon))
+			if (mls_setup_user_range(&policydb, fromcon,
+						 user, &usercon))
 				continue;
 
 			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
@@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
  * cannot support xattr or use a fixed labeling behavior like
  * transition SIDs or task SIDs.
  *
- * The caller must acquire the policy_rwlock before calling this function.
+ * The caller must hold rcu before calling this function.
  */
 static inline int __security_genfs_sid(const char *fstype,
 				       char *path,
@@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const char *fstype,
  * @sclass: file security class
  * @sid: SID for path
  *
- * Acquire policy_rwlock before calling __security_genfs_sid() and release
+ * Hold rcu before calling __security_genfs_sid() and release
  * it afterward.
  */
 int security_genfs_sid(const char *fstype,
@@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
+				     GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&ctx_new, secattr);
+		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&ctx_new, secattr);
+			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+						   secattr);
 			if (rc)
 				goto out;
 		}
@@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(ctx, secattr);
-	rc = mls_export_netlbl_cat(ctx, secattr);
+	mls_export_netlbl_lvl(&policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index 356bdd3..50c7ceb 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -10,8 +10,6 @@
 #include "policydb.h"
 #include "sidtab.h"
 
-extern struct policydb policydb;
-
 void services_compute_xperms_drivers(struct extended_perms *xperms,
 				struct avtab_node *node);
 
@@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
 					struct avtab_node *node);
 
 #endif	/* _SS_SERVICES_H_ */
-
-- 
2.7.4

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This preparation removes the export of the
policydb and send pointers to it through parameter agruments.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
 security/selinux/ss/mls.h      | 37 +++++++++--------
 security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++---------------
 security/selinux/ss/services.h |  3 --
 4 files changed, 114 insertions(+), 85 deletions(-)

diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index ad982ce..b1f35d3 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -33,20 +33,20 @@
  * Return the length in bytes for the MLS fields of the
  * security context string representation of `context'.
  */
-int mls_compute_context_len(struct context *context)
+int mls_compute_context_len(struct policydb *p, struct context *context)
 {
 	int i, l, len, head, prev;
 	char *nm;
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	len = 1; /* for the beginning ":" */
 	for (l = 0; l < 2; l++) {
 		int index_sens = context->range.level[l].sens;
-		len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
+		len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
 
 		/* categories */
 		head = -2;
@@ -56,17 +56,17 @@ int mls_compute_context_len(struct context *context)
 			if (i - prev > 1) {
 				/* one or more negative bits are skipped */
 				if (head != prev) {
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					len += strlen(nm) + 1;
 				}
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				len += strlen(nm) + 1;
 				head = i;
 			}
 			prev = i;
 		}
 		if (prev != head) {
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			len += strlen(nm) + 1;
 		}
 		if (l == 0) {
@@ -86,7 +86,7 @@ int mls_compute_context_len(struct context *context)
  * the MLS fields of `context' into the string `*scontext'.
  * Update `*scontext' to point to the end of the MLS fields.
  */
-void mls_sid_to_context(struct context *context,
+void mls_sid_to_context(struct policydb *p, struct context *context,
 			char **scontext)
 {
 	char *scontextp, *nm;
@@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	scontextp = *scontext;
@@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
 	scontextp++;
 
 	for (l = 0; l < 2; l++) {
-		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
+		strcpy(scontextp, sym_name(p, SYM_LEVELS,
 					   context->range.level[l].sens - 1));
 		scontextp += strlen(scontextp);
 
@@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
 						*scontextp++ = '.';
 					else
 						*scontextp++ = ',';
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					strcpy(scontextp, nm);
 					scontextp += strlen(nm);
 				}
@@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
 					*scontextp++ = ':';
 				else
 					*scontextp++ = ',';
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				strcpy(scontextp, nm);
 				scontextp += strlen(nm);
 				head = i;
@@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
 				*scontextp++ = '.';
 			else
 				*scontextp++ = ',';
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			strcpy(scontextp, nm);
 			scontextp += strlen(nm);
 		}
@@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
  * the string `str'.  This function will allocate temporary memory with the
  * given constraints of gfp_mask.
  */
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask)
 {
 	char *tmpstr, *freestr;
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return -EINVAL;
 
 	/* we need freestr because mls_context_to_sid will change
@@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
 	if (!tmpstr) {
 		rc = -ENOMEM;
 	} else {
-		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
+		rc = mls_context_to_sid(p, ':', &tmpstr, context,
 					NULL, SECSID_NULL);
 		kfree(freestr);
 	}
@@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
 	return rc;
 }
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon)
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon)
 {
-	if (policydb.mls_enabled) {
+	if (p->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]);
@@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
  * structure `c' from the values specified in the
  * policy `oldp' to the values specified in the policy `newp'.
  */
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *c)
 {
@@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
 	struct ebitmap_node *node;
 	int l, i;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	for (l = 0; l < 2; l++) {
@@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
 	return 0;
 }
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
@@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
 	struct class_datum *cladatum;
 	int default_range = 0;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	switch (specified) {
@@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
 		rtr.source_type = scontext->type;
 		rtr.target_type = tcontext->type;
 		rtr.target_class = tclass;
-		r = hashtab_search(policydb.range_tr, &rtr);
+		r = hashtab_search(p->range_tr, &rtr);
 		if (r)
 			return mls_range_set(newcontext, r);
 
-		if (tclass && tclass <= policydb.p_classes.nprim) {
-			cladatum = policydb.class_val_to_struct[tclass - 1];
+		if (tclass && tclass <= p->p_classes.nprim) {
+			cladatum = p->class_val_to_struct[tclass - 1];
 			if (cladatum)
 				default_range = cladatum->default_range;
 		}
@@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
 
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == p->process_class) || (sock == true))
 			/* Use the process MLS attributes. */
 			return mls_context_cpy(newcontext, scontext);
 		else
@@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
  * NetLabel MLS sensitivity level field.
  *
  */
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context *context,
  * NetLabel MLS sensitivity level into the context.
  *
  */
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context *context,
  * MLS category field.  Returns zero on success, negative values on failure.
  *
  */
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context *context,
  * negative values on failure.
  *
  */
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 131d762..cb039c0 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -25,8 +25,9 @@
 #include "context.h"
 #include "policydb.h"
 
-int mls_compute_context_len(struct context *context);
-void mls_sid_to_context(struct context *context, char **scontext);
+int mls_compute_context_len(struct policydb *p, struct context *context);
+void mls_sid_to_context(struct policydb *p, struct context *context,
+			char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
 int mls_range_isvalid(struct policydb *p, struct mls_range *r);
 int mls_level_isvalid(struct policydb *p, struct mls_level *l);
@@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
 		       struct sidtab *s,
 		       u32 def_sid);
 
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask);
 
 int mls_range_set(struct context *context, struct mls_range *range);
 
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *context);
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
 		    struct context *newcontext,
 		    bool sock);
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon);
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon);
 
 #ifdef CONFIG_NETLABEL
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
 #else
-static inline void mls_export_netlbl_lvl(struct context *context,
+static inline void mls_export_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline void mls_import_netlbl_lvl(struct context *context,
+static inline void mls_import_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline int mls_export_netlbl_cat(struct context *context,
+static inline int mls_export_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
 }
-static inline int mls_import_netlbl_cat(struct context *context,
+static inline int mls_import_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
@@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct context *context,
 #endif
 
 #endif	/* _SS_MLS_H */
-
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 33cfe5d..47d8030 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-struct policydb policydb;
+static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -117,8 +117,12 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-static struct selinux_mapping *current_mapping;
-static u16 current_mapping_size;
+struct shared_current_mapping {
+	struct selinux_mapping *current_mapping;
+	u16 current_mapping_size;
+};
+
+static struct shared_current_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb *pol,
 
 static u16 unmap_class(u16 tclass)
 {
-	if (tclass < current_mapping_size)
-		return current_mapping[tclass].value;
+	if (tclass < crm->current_mapping_size)
+		return crm->current_mapping[tclass].value;
 
 	return tclass;
 }
@@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
 {
 	u16 i;
 
-	for (i = 1; i < current_mapping_size; i++) {
-		if (current_mapping[i].value == pol_value)
+	for (i = 1; i < crm->current_mapping_size; i++) {
+		if (crm->current_mapping[i].value == pol_value)
 			return i;
 	}
 
@@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
-	if (tclass < current_mapping_size) {
-		unsigned i, n = current_mapping[tclass].num_perms;
+	if (tclass < crm->current_mapping_size) {
+		unsigned int i, n = crm->current_mapping[tclass].num_perms;
 		u32 result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->allowed & current_mapping[tclass].perms[i])
+			if (avd->allowed &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (allow_unknown && !current_mapping[tclass].perms[i])
+			if (allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		avd->allowed = result;
 
 		for (i = 0, result = 0; i < n; i++)
-			if (avd->auditallow & current_mapping[tclass].perms[i])
+			if (avd->auditallow &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		avd->auditallow = result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->auditdeny & current_mapping[tclass].perms[i])
+			if (avd->auditdeny &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (!allow_unknown && !current_mapping[tclass].perms[i])
+			if (!allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		/*
@@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(context);
+	*scontext_len += mls_compute_context_len(&policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 		sym_name(&policydb, SYM_ROLES, context->role - 1),
 		sym_name(&policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(context, &scontextp);
+	mls_sid_to_context(&policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
 			     &newcontext, sock);
 	if (rc)
 		goto out_unlock;
@@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(args->oldp, args->newp, c);
+		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t len)
 {
 	struct policydb *oldpolicydb, *newpolicydb;
 	struct sidtab oldsidtab, newsidtab;
-	struct selinux_mapping *oldmap, *map = NULL;
+	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
+	struct shared_current_mapping *new_mapping;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t len)
 		rc = -ENOMEM;
 		goto out;
 	}
+	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+	if (!new_mapping) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	newpolicydb = oldpolicydb + 1;
 
 	if (!ss_initialized) {
+		crm = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+		if (!crm) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t len)
 
 		policydb.len = len;
 		rc = selinux_set_mapping(&policydb, secclass_map,
-					 &current_mapping,
-					 &current_mapping_size);
+					 &crm->current_mapping,
+					 &crm->current_mapping_size);
 		if (rc) {
 			policydb_destroy(&policydb);
 			avtab_cache_destroy();
@@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t len)
 	memcpy(&policydb, newpolicydb, sizeof(policydb));
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
-	oldmap = current_mapping;
-	current_mapping = map;
-	current_mapping_size = map_size;
+	oldmap = crm->current_mapping;
+	crm->current_mapping = map;
+	crm->current_mapping_size = map_size;
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
 
@@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(fromcon, user, &usercon))
+			if (mls_setup_user_range(&policydb, fromcon,
+						 user, &usercon))
 				continue;
 
 			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
@@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
  * cannot support xattr or use a fixed labeling behavior like
  * transition SIDs or task SIDs.
  *
- * The caller must acquire the policy_rwlock before calling this function.
+ * The caller must hold rcu before calling this function.
  */
 static inline int __security_genfs_sid(const char *fstype,
 				       char *path,
@@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const char *fstype,
  * @sclass: file security class
  * @sid: SID for path
  *
- * Acquire policy_rwlock before calling __security_genfs_sid() and release
+ * Hold rcu before calling __security_genfs_sid() and release
  * it afterward.
  */
 int security_genfs_sid(const char *fstype,
@@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
+				     GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&ctx_new, secattr);
+		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&ctx_new, secattr);
+			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+						   secattr);
 			if (rc)
 				goto out;
 		}
@@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(ctx, secattr);
-	rc = mls_export_netlbl_cat(ctx, secattr);
+	mls_export_netlbl_lvl(&policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index 356bdd3..50c7ceb 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -10,8 +10,6 @@
 #include "policydb.h"
 #include "sidtab.h"
 
-extern struct policydb policydb;
-
 void services_compute_xperms_drivers(struct extended_perms *xperms,
 				struct avtab_node *node);
 
@@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
 					struct avtab_node *node);
 
 #endif	/* _SS_SERVICES_H_ */
-
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This preparation removes the export of the
policydb and send pointers to it through parameter agruments.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
 security/selinux/ss/mls.h      | 37 +++++++++--------
 security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++---------------
 security/selinux/ss/services.h |  3 --
 4 files changed, 114 insertions(+), 85 deletions(-)

diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index ad982ce..b1f35d3 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -33,20 +33,20 @@
  * Return the length in bytes for the MLS fields of the
  * security context string representation of `context'.
  */
-int mls_compute_context_len(struct context *context)
+int mls_compute_context_len(struct policydb *p, struct context *context)
 {
 	int i, l, len, head, prev;
 	char *nm;
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	len = 1; /* for the beginning ":" */
 	for (l = 0; l < 2; l++) {
 		int index_sens = context->range.level[l].sens;
-		len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
+		len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
 
 		/* categories */
 		head = -2;
@@ -56,17 +56,17 @@ int mls_compute_context_len(struct context *context)
 			if (i - prev > 1) {
 				/* one or more negative bits are skipped */
 				if (head != prev) {
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					len += strlen(nm) + 1;
 				}
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				len += strlen(nm) + 1;
 				head = i;
 			}
 			prev = i;
 		}
 		if (prev != head) {
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			len += strlen(nm) + 1;
 		}
 		if (l == 0) {
@@ -86,7 +86,7 @@ int mls_compute_context_len(struct context *context)
  * the MLS fields of `context' into the string `*scontext'.
  * Update `*scontext' to point to the end of the MLS fields.
  */
-void mls_sid_to_context(struct context *context,
+void mls_sid_to_context(struct policydb *p, struct context *context,
 			char **scontext)
 {
 	char *scontextp, *nm;
@@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	scontextp = *scontext;
@@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
 	scontextp++;
 
 	for (l = 0; l < 2; l++) {
-		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
+		strcpy(scontextp, sym_name(p, SYM_LEVELS,
 					   context->range.level[l].sens - 1));
 		scontextp += strlen(scontextp);
 
@@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
 						*scontextp++ = '.';
 					else
 						*scontextp++ = ',';
-					nm = sym_name(&policydb, SYM_CATS, prev);
+					nm = sym_name(p, SYM_CATS, prev);
 					strcpy(scontextp, nm);
 					scontextp += strlen(nm);
 				}
@@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
 					*scontextp++ = ':';
 				else
 					*scontextp++ = ',';
-				nm = sym_name(&policydb, SYM_CATS, i);
+				nm = sym_name(p, SYM_CATS, i);
 				strcpy(scontextp, nm);
 				scontextp += strlen(nm);
 				head = i;
@@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
 				*scontextp++ = '.';
 			else
 				*scontextp++ = ',';
-			nm = sym_name(&policydb, SYM_CATS, prev);
+			nm = sym_name(p, SYM_CATS, prev);
 			strcpy(scontextp, nm);
 			scontextp += strlen(nm);
 		}
@@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
  * the string `str'.  This function will allocate temporary memory with the
  * given constraints of gfp_mask.
  */
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask)
 {
 	char *tmpstr, *freestr;
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return -EINVAL;
 
 	/* we need freestr because mls_context_to_sid will change
@@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
 	if (!tmpstr) {
 		rc = -ENOMEM;
 	} else {
-		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
+		rc = mls_context_to_sid(p, ':', &tmpstr, context,
 					NULL, SECSID_NULL);
 		kfree(freestr);
 	}
@@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
 	return rc;
 }
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon)
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon)
 {
-	if (policydb.mls_enabled) {
+	if (p->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]);
@@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
  * structure `c' from the values specified in the
  * policy `oldp' to the values specified in the policy `newp'.
  */
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *c)
 {
@@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
 	struct ebitmap_node *node;
 	int l, i;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	for (l = 0; l < 2; l++) {
@@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
 	return 0;
 }
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
@@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
 	struct class_datum *cladatum;
 	int default_range = 0;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	switch (specified) {
@@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
 		rtr.source_type = scontext->type;
 		rtr.target_type = tcontext->type;
 		rtr.target_class = tclass;
-		r = hashtab_search(policydb.range_tr, &rtr);
+		r = hashtab_search(p->range_tr, &rtr);
 		if (r)
 			return mls_range_set(newcontext, r);
 
-		if (tclass && tclass <= policydb.p_classes.nprim) {
-			cladatum = policydb.class_val_to_struct[tclass - 1];
+		if (tclass && tclass <= p->p_classes.nprim) {
+			cladatum = p->class_val_to_struct[tclass - 1];
 			if (cladatum)
 				default_range = cladatum->default_range;
 		}
@@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
 
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == p->process_class) || (sock == true))
 			/* Use the process MLS attributes. */
 			return mls_context_cpy(newcontext, scontext);
 		else
@@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
  * NetLabel MLS sensitivity level field.
  *
  */
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context *context,
  * NetLabel MLS sensitivity level into the context.
  *
  */
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return;
 
 	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context *context,
  * MLS category field.  Returns zero on success, negative values on failure.
  *
  */
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context *context,
  * negative values on failure.
  *
  */
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr)
 {
 	int rc;
 
-	if (!policydb.mls_enabled)
+	if (!p->mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 131d762..cb039c0 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -25,8 +25,9 @@
 #include "context.h"
 #include "policydb.h"
 
-int mls_compute_context_len(struct context *context);
-void mls_sid_to_context(struct context *context, char **scontext);
+int mls_compute_context_len(struct policydb *p, struct context *context);
+void mls_sid_to_context(struct policydb *p, struct context *context,
+			char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
 int mls_range_isvalid(struct policydb *p, struct mls_range *r);
 int mls_level_isvalid(struct policydb *p, struct mls_level *l);
@@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
 		       struct sidtab *s,
 		       u32 def_sid);
 
-int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
+int mls_from_string(struct policydb *p, char *str, struct context *context,
+		    gfp_t gfp_mask);
 
 int mls_range_set(struct context *context, struct mls_range *range);
 
-int mls_convert_context(struct policydb *oldp,
+int mls_convert_context(struct policydb *p, struct policydb *oldp,
 			struct policydb *newp,
 			struct context *context);
 
-int mls_compute_sid(struct context *scontext,
+int mls_compute_sid(struct policydb *p, struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
 		    struct context *newcontext,
 		    bool sock);
 
-int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
-			 struct context *usercon);
+int mls_setup_user_range(struct policydb *p, struct context *fromcon,
+			 struct user_datum *user, struct context *usercon);
 
 #ifdef CONFIG_NETLABEL
-void mls_export_netlbl_lvl(struct context *context,
+void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-void mls_import_netlbl_lvl(struct context *context,
+void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
 			   struct netlbl_lsm_secattr *secattr);
-int mls_export_netlbl_cat(struct context *context,
+int mls_export_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
-int mls_import_netlbl_cat(struct context *context,
+int mls_import_netlbl_cat(struct policydb *p, struct context *context,
 			  struct netlbl_lsm_secattr *secattr);
 #else
-static inline void mls_export_netlbl_lvl(struct context *context,
+static inline void mls_export_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline void mls_import_netlbl_lvl(struct context *context,
+static inline void mls_import_netlbl_lvl(struct policydb *p,
+					 struct context *context,
 					 struct netlbl_lsm_secattr *secattr)
 {
 	return;
 }
-static inline int mls_export_netlbl_cat(struct context *context,
+static inline int mls_export_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
 }
-static inline int mls_import_netlbl_cat(struct context *context,
+static inline int mls_import_netlbl_cat(struct policydb *p,
+					struct context *context,
 					struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOMEM;
@@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct context *context,
 #endif
 
 #endif	/* _SS_MLS_H */
-
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 33cfe5d..47d8030 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-struct policydb policydb;
+static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -117,8 +117,12 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-static struct selinux_mapping *current_mapping;
-static u16 current_mapping_size;
+struct shared_current_mapping {
+	struct selinux_mapping *current_mapping;
+	u16 current_mapping_size;
+};
+
+static struct shared_current_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb *pol,
 
 static u16 unmap_class(u16 tclass)
 {
-	if (tclass < current_mapping_size)
-		return current_mapping[tclass].value;
+	if (tclass < crm->current_mapping_size)
+		return crm->current_mapping[tclass].value;
 
 	return tclass;
 }
@@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
 {
 	u16 i;
 
-	for (i = 1; i < current_mapping_size; i++) {
-		if (current_mapping[i].value == pol_value)
+	for (i = 1; i < crm->current_mapping_size; i++) {
+		if (crm->current_mapping[i].value == pol_value)
 			return i;
 	}
 
@@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
-	if (tclass < current_mapping_size) {
-		unsigned i, n = current_mapping[tclass].num_perms;
+	if (tclass < crm->current_mapping_size) {
+		unsigned int i, n = crm->current_mapping[tclass].num_perms;
 		u32 result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->allowed & current_mapping[tclass].perms[i])
+			if (avd->allowed &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (allow_unknown && !current_mapping[tclass].perms[i])
+			if (allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		avd->allowed = result;
 
 		for (i = 0, result = 0; i < n; i++)
-			if (avd->auditallow & current_mapping[tclass].perms[i])
+			if (avd->auditallow &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		avd->auditallow = result;
 
 		for (i = 0, result = 0; i < n; i++) {
-			if (avd->auditdeny & current_mapping[tclass].perms[i])
+			if (avd->auditdeny &
+			    crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
-			if (!allow_unknown && !current_mapping[tclass].perms[i])
+			if (!allow_unknown &&
+			    !crm->current_mapping[tclass].perms[i])
 				result |= 1<<i;
 		}
 		/*
@@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
 	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(context);
+	*scontext_len += mls_compute_context_len(&policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 		sym_name(&policydb, SYM_ROLES, context->role - 1),
 		sym_name(&policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(context, &scontextp);
+	mls_sid_to_context(&policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
 			     &newcontext, sock);
 	if (rc)
 		goto out_unlock;
@@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(args->oldp, args->newp, c);
+		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t len)
 {
 	struct policydb *oldpolicydb, *newpolicydb;
 	struct sidtab oldsidtab, newsidtab;
-	struct selinux_mapping *oldmap, *map = NULL;
+	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
+	struct shared_current_mapping *new_mapping;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t len)
 		rc = -ENOMEM;
 		goto out;
 	}
+	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+	if (!new_mapping) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	newpolicydb = oldpolicydb + 1;
 
 	if (!ss_initialized) {
+		crm = kzalloc(sizeof(struct shared_current_mapping),
+			      GFP_KERNEL);
+		if (!crm) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t len)
 
 		policydb.len = len;
 		rc = selinux_set_mapping(&policydb, secclass_map,
-					 &current_mapping,
-					 &current_mapping_size);
+					 &crm->current_mapping,
+					 &crm->current_mapping_size);
 		if (rc) {
 			policydb_destroy(&policydb);
 			avtab_cache_destroy();
@@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t len)
 	memcpy(&policydb, newpolicydb, sizeof(policydb));
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
-	oldmap = current_mapping;
-	current_mapping = map;
-	current_mapping_size = map_size;
+	oldmap = crm->current_mapping;
+	crm->current_mapping = map;
+	crm->current_mapping_size = map_size;
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
 
@@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(fromcon, user, &usercon))
+			if (mls_setup_user_range(&policydb, fromcon,
+						 user, &usercon))
 				continue;
 
 			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
@@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
  * cannot support xattr or use a fixed labeling behavior like
  * transition SIDs or task SIDs.
  *
- * The caller must acquire the policy_rwlock before calling this function.
+ * The caller must hold rcu before calling this function.
  */
 static inline int __security_genfs_sid(const char *fstype,
 				       char *path,
@@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const char *fstype,
  * @sclass: file security class
  * @sid: SID for path
  *
- * Acquire policy_rwlock before calling __security_genfs_sid() and release
+ * Hold rcu before calling __security_genfs_sid() and release
  * it afterward.
  */
 int security_genfs_sid(const char *fstype,
@@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
+				     GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&ctx_new, secattr);
+		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&ctx_new, secattr);
+			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+						   secattr);
 			if (rc)
 				goto out;
 		}
@@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(ctx, secattr);
-	rc = mls_export_netlbl_cat(ctx, secattr);
+	mls_export_netlbl_lvl(&policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index 356bdd3..50c7ceb 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -10,8 +10,6 @@
 #include "policydb.h"
 #include "sidtab.h"
 
-extern struct policydb policydb;
-
 void services_compute_xperms_drivers(struct extended_perms *xperms,
 				struct avtab_node *node);
 
@@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
 					struct avtab_node *node);
 
 #endif	/* _SS_SERVICES_H_ */
-
-- 
2.7.4


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

* [PATCH v2 2/5] selinux: Move policydb to pointer structure
  2018-01-26 14:32 ` peter.enderborg at sony.com
  (?)
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  -1 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This patch adds a pointer structure to
repleace the static policydb.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 274 ++++++++++++++++++++++-------------------
 1 file changed, 149 insertions(+), 125 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 47d8030..21400bd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,6 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct selinux_mapping {
 struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
+	struct policydb policydb;
 };
 
 static struct shared_current_mapping *crm;
@@ -277,7 +277,7 @@ static void map_decision(u16 tclass, struct av_decision *avd,
 
 int security_mls_enabled(void)
 {
-	return policydb.mls_enabled;
+	return crm->policydb.mls_enabled;
 }
 
 /*
@@ -335,8 +335,8 @@ static int constraint_expr_eval(struct context *scontext,
 			case CEXPR_ROLE:
 				val1 = scontext->role;
 				val2 = tcontext->role;
-				r1 = policydb.role_val_to_struct[val1 - 1];
-				r2 = policydb.role_val_to_struct[val2 - 1];
+				r1 = crm->policydb.role_val_to_struct[val1 - 1];
+				r2 = crm->policydb.role_val_to_struct[val2 - 1];
 				switch (e->op) {
 				case CEXPR_DOM:
 					s[++sp] = ebitmap_get_bit(&r1->dominates,
@@ -501,8 +501,8 @@ static void security_dump_masked_av(struct context *scontext,
 	if (!permissions)
 		return;
 
-	tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
-	tclass_dat = policydb.class_val_to_struct[tclass - 1];
+	tclass_name = sym_name(&crm->policydb, SYM_CLASSES, tclass - 1);
+	tclass_dat = crm->policydb.class_val_to_struct[tclass - 1];
 	common_dat = tclass_dat->comdatum;
 
 	/* init permission_names */
@@ -571,14 +571,14 @@ static void type_attribute_bounds_av(struct context *scontext,
 	struct type_datum *target;
 	u32 masked = 0;
 
-	source = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	source = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    scontext->type - 1);
 	BUG_ON(!source);
 
 	if (!source->bounds)
 		return;
 
-	target = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	target = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    tcontext->type - 1);
 	BUG_ON(!target);
 
@@ -664,13 +664,13 @@ static void context_struct_compute_av(struct context *scontext,
 		xperms->len = 0;
 	}
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "SELinux:  Invalid class %hu\n", tclass);
 		return;
 	}
 
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/*
 	 * If a specific type enforcement rule was defined for
@@ -678,15 +678,18 @@ static void context_struct_compute_av(struct context *scontext,
 	 */
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_AV | AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified)) {
 				if (node->key.specified == AVTAB_ALLOWED)
@@ -700,7 +703,7 @@ static void context_struct_compute_av(struct context *scontext,
 			}
 
 			/* Check conditional av table for additional permissions */
-			cond_compute_av(&policydb.te_cond_avtab, &avkey,
+			cond_compute_av(&crm->policydb.te_cond_avtab, &avkey,
 					avd, xperms);
 
 		}
@@ -725,16 +728,16 @@ static void context_struct_compute_av(struct context *scontext,
 	 * role is changing, then check the (current_role, new_role)
 	 * pair.
 	 */
-	if (tclass == policydb.process_class &&
-	    (avd->allowed & policydb.process_trans_perms) &&
+	if (tclass == crm->policydb.process_class &&
+	    (avd->allowed & crm->policydb.process_trans_perms) &&
 	    scontext->role != tcontext->role) {
-		for (ra = policydb.role_allow; ra; ra = ra->next) {
+		for (ra = crm->policydb.role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
 			    tcontext->role == ra->new_role)
 				break;
 		}
 		if (!ra)
-			avd->allowed &= ~policydb.process_trans_perms;
+			avd->allowed &= ~crm->policydb.process_trans_perms;
 	}
 
 	/*
@@ -763,7 +766,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
 	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
 		  "op=security_validate_transition seresult=denied"
 		  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
-		  o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  o, n, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(o);
 	kfree(n);
@@ -795,11 +798,11 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	else
 		tclass = orig_tclass;
 
-	if (!tclass || tclass > policydb.p_classes.nprim) {
+	if (!tclass || tclass > crm->policydb.p_classes.nprim) {
 		rc = -EINVAL;
 		goto out;
 	}
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	ocontext = sidtab_search(&sidtab, oldsid);
 	if (!ocontext) {
@@ -901,7 +904,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 
 	index = new_context->type;
 	while (true) {
-		type = flex_array_get_ptr(policydb.type_val_to_struct_array,
+		type = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 					  index - 1);
 		BUG_ON(!type);
 
@@ -1046,35 +1049,36 @@ void security_compute_xperms_decision(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		pr_warn_ratelimited("SELinux:  Invalid class %hu\n", tclass);
 		goto out;
 	}
 
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array,
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
 				scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array,
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
 				tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified))
 				services_compute_xperms_decision(xpermd, node);
 
-			cond_compute_xperms(&policydb.te_cond_avtab,
+			cond_compute_xperms(&crm->policydb.te_cond_avtab,
 						&avkey, xpermd);
 		}
 	}
@@ -1120,7 +1124,7 @@ void security_compute_av(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1132,12 +1136,12 @@ void security_compute_av(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
-	map_decision(orig_tclass, avd, policydb.allow_unknown);
+	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
 	read_unlock(&policy_rwlock);
 	return;
@@ -1166,7 +1170,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1177,7 +1181,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	if (unlikely(!tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
@@ -1217,10 +1221,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	}
 
 	/* Compute the size of the context. */
-	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(&policydb, context);
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_USERS,
+					 context->user - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_ROLES,
+					 context->role - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_TYPES,
+					 context->type - 1)) + 1;
+	*scontext_len += mls_compute_context_len(&crm->policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1235,11 +1242,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	 * Copy the user name, role name and type name into the context.
 	 */
 	scontextp += sprintf(scontextp, "%s:%s:%s",
-		sym_name(&policydb, SYM_USERS, context->user - 1),
-		sym_name(&policydb, SYM_ROLES, context->role - 1),
-		sym_name(&policydb, SYM_TYPES, context->type - 1));
+		sym_name(&crm->policydb, SYM_USERS, context->user - 1),
+		sym_name(&crm->policydb, SYM_ROLES, context->role - 1),
+		sym_name(&crm->policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(&policydb, context, &scontextp);
+	mls_sid_to_context(&crm->policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1452,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1546,7 +1553,7 @@ static int compute_sid_handle_invalid_context(
 		  " scontext=%s"
 		  " tcontext=%s"
 		  " tclass=%s",
-		  n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  n, s, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(s);
 	kfree(t);
@@ -1638,8 +1645,8 @@ static int security_compute_sid(u32 ssid,
 		goto out_unlock;
 	}
 
-	if (tclass && tclass <= policydb.p_classes.nprim)
-		cladatum = policydb.class_val_to_struct[tclass - 1];
+	if (tclass && tclass <= crm->policydb.p_classes.nprim)
+		cladatum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/* Set the user identity. */
 	switch (specified) {
@@ -1665,7 +1672,7 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
 		newcontext.role = tcontext->role;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == crm->policydb.process_class) || (sock == true))
 			newcontext.role = scontext->role;
 		else
 			newcontext.role = OBJECT_R_VAL;
@@ -1677,7 +1684,8 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
 		newcontext.type = tcontext->type;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true)) {
+		if ((tclass == crm->policydb.process_class) ||
+		    (sock == true)) {
 			/* Use the type of process. */
 			newcontext.type = scontext->type;
 		} else {
@@ -1691,11 +1699,12 @@ static int security_compute_sid(u32 ssid,
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
 	avkey.specified = specified;
-	avdatum = avtab_search(&policydb.te_avtab, &avkey);
+	avdatum = avtab_search(&crm->policydb.te_avtab, &avkey);
 
 	/* If no permanent rule, also check for enabled conditional rules */
 	if (!avdatum) {
-		node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+		node = avtab_search_node(&crm->policydb.te_cond_avtab,
+					 &avkey);
 		for (; node; node = avtab_search_node_next(node, specified)) {
 			if (node->key.specified & AVTAB_ENABLED) {
 				avdatum = &node->datum;
@@ -1711,13 +1720,16 @@ static int security_compute_sid(u32 ssid,
 
 	/* if we have a objname this is a file trans check so check those rules */
 	if (objname)
-		filename_compute_type(&policydb, &newcontext, scontext->type,
-				      tcontext->type, tclass, objname);
+		filename_compute_type(&crm->policydb, &newcontext,
+				      scontext->type, tcontext->type,
+				      tclass, objname);
 
 	/* Check for class-specific changes. */
 	if (specified & AVTAB_TRANSITION) {
 		/* Look for a role transition rule. */
-		for (roletr = policydb.role_tr; roletr; roletr = roletr->next) {
+		for (roletr = crm->policydb.role_tr;
+		     roletr;
+		     roletr = roletr->next) {
 			if ((roletr->role == scontext->role) &&
 			    (roletr->type == tcontext->type) &&
 			    (roletr->tclass == tclass)) {
@@ -1730,13 +1742,13 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
-			     &newcontext, sock);
+	rc = mls_compute_sid(&crm->policydb, scontext, tcontext, tclass,
+			     specified, &newcontext, sock);
 	if (rc)
 		goto out_unlock;
 
 	/* Check the validity of the context. */
-	if (!policydb_context_isvalid(&policydb, &newcontext)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcontext)) {
 		rc = compute_sid_handle_invalid_context(scontext,
 							tcontext,
 							tclass,
@@ -1944,7 +1956,8 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
+		rc = mls_convert_context(&crm->policydb, args->oldp,
+					 args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2009,27 +2022,31 @@ static void security_load_policycaps(void)
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps,
-					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
-	selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_ALWAYSNETWORK);
+	selinux_policycap_netpeer =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+			  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_alwaysnetwork =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&policydb.policycaps, i));
+			ebitmap_get_bit(&crm->policydb.policycaps, i));
 
-	ebitmap_for_each_positive_bit(&policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2084,7 +2101,7 @@ int security_load_policy(void *data, size_t len)
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&policydb, fp);
+		rc = policydb_read(&crm->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
@@ -2092,21 +2109,21 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		policydb.len = len;
-		rc = selinux_set_mapping(&policydb, secclass_map,
+		crm->policydb.len = len;
+		rc = selinux_set_mapping(&crm->policydb, secclass_map,
 					 &crm->current_mapping,
 					 &crm->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
 			goto out;
 		}
 
-		rc = policydb_load_isids(&policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &sidtab);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
@@ -2135,9 +2152,9 @@ int security_load_policy(void *data, size_t len)
 
 	newpolicydb->len = len;
 	/* If switching between different policy types, log MLS status */
-	if (policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
 	rc = policydb_load_isids(newpolicydb, &newsidtab);
@@ -2168,7 +2185,7 @@ int security_load_policy(void *data, size_t len)
 	 * Convert the internal representations of contexts
 	 * in the new SID table.
 	 */
-	args.oldp = &policydb;
+	args.oldp = &crm->policydb;
 	args.newp = newpolicydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
@@ -2179,12 +2196,13 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Save the old policydb and SID table to free later. */
-	memcpy(oldpolicydb, &policydb, sizeof(policydb));
+	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
 	sidtab_set(&oldsidtab, &sidtab);
 
 	/* Install the new policydb and SID table. */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&policydb, newpolicydb, sizeof(policydb));
+	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
+
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
 	oldmap = crm->current_mapping;
@@ -2222,7 +2240,7 @@ size_t security_policydb_len(void)
 	size_t len;
 
 	read_lock(&policy_rwlock);
-	len = policydb.len;
+	len = crm->policydb.len;
 	read_unlock(&policy_rwlock);
 
 	return len;
@@ -2241,7 +2259,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_PORT];
+	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
 		if (c->u.port.protocol == protocol &&
 		    c->u.port.low_port <= port &&
@@ -2281,7 +2299,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBPKEY];
+	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
 		if (c->u.ibpkey.low_pkey <= pkey_num &&
 		    c->u.ibpkey.high_pkey >= pkey_num &&
@@ -2321,7 +2339,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBENDPORT];
+	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
 		if (c->u.ibendport.port == port_num &&
 		    !strncmp(c->u.ibendport.dev_name,
@@ -2361,7 +2379,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_NETIF];
+	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
 		if (strcmp(name, c->u.name) == 0)
 			break;
@@ -2430,7 +2448,7 @@ int security_node_sid(u16 domain,
 
 		addr = *((u32 *)addrp);
 
-		c = policydb.ocontexts[OCON_NODE];
+		c = crm->policydb.ocontexts[OCON_NODE];
 		while (c) {
 			if (c->u.node.addr == (addr & c->u.node.mask))
 				break;
@@ -2443,7 +2461,7 @@ int security_node_sid(u16 domain,
 		rc = -EINVAL;
 		if (addrlen != sizeof(u64) * 2)
 			goto out;
-		c = policydb.ocontexts[OCON_NODE6];
+		c = crm->policydb.ocontexts[OCON_NODE6];
 		while (c) {
 			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
 						c->u.node6.mask))
@@ -2522,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	rc = -EINVAL;
-	user = hashtab_search(policydb.p_users.table, username);
+	user = hashtab_search(crm->policydb.p_users.table, username);
 	if (!user)
 		goto out_unlock;
 
@@ -2534,12 +2552,12 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
-		role = policydb.role_val_to_struct[i];
+		role = crm->policydb.role_val_to_struct[i];
 		usercon.role = i + 1;
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(&policydb, fromcon,
+			if (mls_setup_user_range(&crm->policydb, fromcon,
 						 user, &usercon))
 				continue;
 
@@ -2623,7 +2641,7 @@ static inline int __security_genfs_sid(const char *fstype,
 	sclass = unmap_class(orig_sclass);
 	*sid = SECINITSID_UNLABELED;
 
-	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+	for (genfs = crm->policydb.genfs; genfs; genfs = genfs->next) {
 		cmp = strcmp(fstype, genfs->fstype);
 		if (cmp <= 0)
 			break;
@@ -2692,7 +2710,7 @@ int security_fs_use(struct super_block *sb)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_FSUSE];
+	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
 		if (strcmp(fstype, c->u.name) == 0)
 			break;
@@ -2733,7 +2751,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	*values = NULL;
 
 	rc = 0;
-	*len = policydb.p_bools.nprim;
+	*len = crm->policydb.p_bools.nprim;
 	if (!*len)
 		goto out;
 
@@ -2748,10 +2766,11 @@ int security_get_bools(int *len, char ***names, int **values)
 		goto err;
 
 	for (i = 0; i < *len; i++) {
-		(*values)[i] = policydb.bool_val_to_struct[i]->state;
+		(*values)[i] = crm->policydb.bool_val_to_struct[i]->state;
 
 		rc = -ENOMEM;
-		(*names)[i] = kstrdup(sym_name(&policydb, SYM_BOOLS, i), GFP_ATOMIC);
+		(*names)[i] = kstrdup(sym_name(&crm->policydb, SYM_BOOLS, i),
+				      GFP_ATOMIC);
 		if (!(*names)[i])
 			goto err;
 	}
@@ -2778,29 +2797,30 @@ int security_set_bools(int len, int *values)
 	write_lock_irq(&policy_rwlock);
 
 	rc = -EFAULT;
-	lenp = policydb.p_bools.nprim;
+	lenp = crm->policydb.p_bools.nprim;
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
-		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+		if (!!values[i] !=
+		    crm->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&policydb, SYM_BOOLS, i),
+				sym_name(&crm->policydb, SYM_BOOLS, i),
 				!!values[i],
-				policydb.bool_val_to_struct[i]->state,
+				crm->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			policydb.bool_val_to_struct[i]->state = 1;
+			crm->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			policydb.bool_val_to_struct[i]->state = 0;
+			crm->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&policydb, cur);
+	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&crm->policydb, cur);
 		if (rc)
 			goto out;
 	}
@@ -2826,11 +2846,11 @@ int security_get_bool_value(int index)
 	read_lock(&policy_rwlock);
 
 	rc = -EFAULT;
-	len = policydb.p_bools.nprim;
+	len = crm->policydb.p_bools.nprim;
 	if (index >= len)
 		goto out;
 
-	rc = policydb.bool_val_to_struct[index]->state;
+	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -2881,7 +2901,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	int rc;
 
 	rc = 0;
-	if (!ss_initialized || !policydb.mls_enabled) {
+	if (!ss_initialized || !crm->policydb.mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -2914,7 +2934,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		goto out_unlock;
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &newcon)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcon)) {
 		rc = convert_context_handle_invalid_context(&newcon);
 		if (rc) {
 			if (!context_struct_to_string(&newcon, &s, &len)) {
@@ -2984,7 +3004,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	/* 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 (!policydb.mls_enabled)
+	if (!crm->policydb.mls_enabled)
 		return 0;
 
 	read_lock(&policy_rwlock);
@@ -3038,12 +3058,12 @@ int security_get_classes(char ***classes, int *nclasses)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOMEM;
-	*nclasses = policydb.p_classes.nprim;
+	*nclasses = crm->policydb.p_classes.nprim;
 	*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
 	if (!*classes)
 		goto out;
 
-	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+	rc = hashtab_map(crm->policydb.p_classes.table, get_classes_callback,
 			*classes);
 	if (rc) {
 		int i;
@@ -3078,7 +3098,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	match = hashtab_search(policydb.p_classes.table, class);
+	match = hashtab_search(crm->policydb.p_classes.table, class);
 	if (!match) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized class %s\n",
 			__func__, class);
@@ -3117,12 +3137,12 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 
 int security_get_reject_unknown(void)
 {
-	return policydb.reject_unknown;
+	return crm->policydb.reject_unknown;
 }
 
 int security_get_allow_unknown(void)
 {
-	return policydb.allow_unknown;
+	return crm->policydb.allow_unknown;
 }
 
 /**
@@ -3140,7 +3160,7 @@ int security_policycap_supported(unsigned int req_cap)
 	int rc;
 
 	read_lock(&policy_rwlock);
-	rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
+	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
 	read_unlock(&policy_rwlock);
 
 	return rc;
@@ -3213,7 +3233,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_USER:
 	case AUDIT_OBJ_USER:
 		rc = -EINVAL;
-		userdatum = hashtab_search(policydb.p_users.table, rulestr);
+		userdatum = hashtab_search(crm->policydb.p_users.table,
+					   rulestr);
 		if (!userdatum)
 			goto out;
 		tmprule->au_ctxt.user = userdatum->value;
@@ -3221,7 +3242,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_ROLE:
 	case AUDIT_OBJ_ROLE:
 		rc = -EINVAL;
-		roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+		roledatum = hashtab_search(crm->policydb.p_roles.table,
+					   rulestr);
 		if (!roledatum)
 			goto out;
 		tmprule->au_ctxt.role = roledatum->value;
@@ -3229,7 +3251,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_TYPE:
 	case AUDIT_OBJ_TYPE:
 		rc = -EINVAL;
-		typedatum = hashtab_search(policydb.p_types.table, rulestr);
+		typedatum = hashtab_search(crm->policydb.p_types.table,
+					   rulestr);
 		if (!typedatum)
 			goto out;
 		tmprule->au_ctxt.type = typedatum->value;
@@ -3238,8 +3261,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
-				     GFP_ATOMIC);
+		rc = mls_from_string(&crm->policydb, rulestr,
+				     &tmprule->au_ctxt, GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3489,15 +3512,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
+		mls_import_netlbl_lvl(&crm->policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+			rc = mls_import_netlbl_cat(&crm->policydb, &ctx_new,
 						   secattr);
 			if (rc)
 				goto out;
 		}
 		rc = -EIDRM;
-		if (!mls_context_isvalid(&policydb, &ctx_new))
+		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
 		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
@@ -3545,15 +3568,16 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 		goto out;
 
 	rc = -ENOMEM;
-	secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
+	secattr->domain = kstrdup(sym_name(&crm->policydb,
+					   SYM_TYPES, ctx->type - 1),
 				  GFP_ATOMIC);
 	if (secattr->domain == NULL)
 		goto out;
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(&policydb, ctx, secattr);
-	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
+	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -3584,7 +3608,7 @@ int security_read_policy(void **data, size_t *len)
 	fp.len = *len;
 
 	read_lock(&policy_rwlock);
-	rc = policydb_write(&policydb, &fp);
+	rc = policydb_write(&crm->policydb, &fp);
 	read_unlock(&policy_rwlock);
 
 	if (rc)
-- 
2.7.4

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

* [PATCH v2 2/5] selinux: Move policydb to pointer structure
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This patch adds a pointer structure to
repleace the static policydb.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 274 ++++++++++++++++++++++-------------------
 1 file changed, 149 insertions(+), 125 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 47d8030..21400bd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,6 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct selinux_mapping {
 struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
+	struct policydb policydb;
 };
 
 static struct shared_current_mapping *crm;
@@ -277,7 +277,7 @@ static void map_decision(u16 tclass, struct av_decision *avd,
 
 int security_mls_enabled(void)
 {
-	return policydb.mls_enabled;
+	return crm->policydb.mls_enabled;
 }
 
 /*
@@ -335,8 +335,8 @@ static int constraint_expr_eval(struct context *scontext,
 			case CEXPR_ROLE:
 				val1 = scontext->role;
 				val2 = tcontext->role;
-				r1 = policydb.role_val_to_struct[val1 - 1];
-				r2 = policydb.role_val_to_struct[val2 - 1];
+				r1 = crm->policydb.role_val_to_struct[val1 - 1];
+				r2 = crm->policydb.role_val_to_struct[val2 - 1];
 				switch (e->op) {
 				case CEXPR_DOM:
 					s[++sp] = ebitmap_get_bit(&r1->dominates,
@@ -501,8 +501,8 @@ static void security_dump_masked_av(struct context *scontext,
 	if (!permissions)
 		return;
 
-	tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
-	tclass_dat = policydb.class_val_to_struct[tclass - 1];
+	tclass_name = sym_name(&crm->policydb, SYM_CLASSES, tclass - 1);
+	tclass_dat = crm->policydb.class_val_to_struct[tclass - 1];
 	common_dat = tclass_dat->comdatum;
 
 	/* init permission_names */
@@ -571,14 +571,14 @@ static void type_attribute_bounds_av(struct context *scontext,
 	struct type_datum *target;
 	u32 masked = 0;
 
-	source = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	source = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    scontext->type - 1);
 	BUG_ON(!source);
 
 	if (!source->bounds)
 		return;
 
-	target = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	target = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    tcontext->type - 1);
 	BUG_ON(!target);
 
@@ -664,13 +664,13 @@ static void context_struct_compute_av(struct context *scontext,
 		xperms->len = 0;
 	}
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "SELinux:  Invalid class %hu\n", tclass);
 		return;
 	}
 
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/*
 	 * If a specific type enforcement rule was defined for
@@ -678,15 +678,18 @@ static void context_struct_compute_av(struct context *scontext,
 	 */
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_AV | AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified)) {
 				if (node->key.specified == AVTAB_ALLOWED)
@@ -700,7 +703,7 @@ static void context_struct_compute_av(struct context *scontext,
 			}
 
 			/* Check conditional av table for additional permissions */
-			cond_compute_av(&policydb.te_cond_avtab, &avkey,
+			cond_compute_av(&crm->policydb.te_cond_avtab, &avkey,
 					avd, xperms);
 
 		}
@@ -725,16 +728,16 @@ static void context_struct_compute_av(struct context *scontext,
 	 * role is changing, then check the (current_role, new_role)
 	 * pair.
 	 */
-	if (tclass == policydb.process_class &&
-	    (avd->allowed & policydb.process_trans_perms) &&
+	if (tclass == crm->policydb.process_class &&
+	    (avd->allowed & crm->policydb.process_trans_perms) &&
 	    scontext->role != tcontext->role) {
-		for (ra = policydb.role_allow; ra; ra = ra->next) {
+		for (ra = crm->policydb.role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
 			    tcontext->role == ra->new_role)
 				break;
 		}
 		if (!ra)
-			avd->allowed &= ~policydb.process_trans_perms;
+			avd->allowed &= ~crm->policydb.process_trans_perms;
 	}
 
 	/*
@@ -763,7 +766,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
 	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
 		  "op=security_validate_transition seresult=denied"
 		  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
-		  o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  o, n, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(o);
 	kfree(n);
@@ -795,11 +798,11 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	else
 		tclass = orig_tclass;
 
-	if (!tclass || tclass > policydb.p_classes.nprim) {
+	if (!tclass || tclass > crm->policydb.p_classes.nprim) {
 		rc = -EINVAL;
 		goto out;
 	}
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	ocontext = sidtab_search(&sidtab, oldsid);
 	if (!ocontext) {
@@ -901,7 +904,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 
 	index = new_context->type;
 	while (true) {
-		type = flex_array_get_ptr(policydb.type_val_to_struct_array,
+		type = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 					  index - 1);
 		BUG_ON(!type);
 
@@ -1046,35 +1049,36 @@ void security_compute_xperms_decision(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		pr_warn_ratelimited("SELinux:  Invalid class %hu\n", tclass);
 		goto out;
 	}
 
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array,
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
 				scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array,
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
 				tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified))
 				services_compute_xperms_decision(xpermd, node);
 
-			cond_compute_xperms(&policydb.te_cond_avtab,
+			cond_compute_xperms(&crm->policydb.te_cond_avtab,
 						&avkey, xpermd);
 		}
 	}
@@ -1120,7 +1124,7 @@ void security_compute_av(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1132,12 +1136,12 @@ void security_compute_av(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
-	map_decision(orig_tclass, avd, policydb.allow_unknown);
+	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
 	read_unlock(&policy_rwlock);
 	return;
@@ -1166,7 +1170,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1177,7 +1181,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	if (unlikely(!tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
@@ -1217,10 +1221,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	}
 
 	/* Compute the size of the context. */
-	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(&policydb, context);
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_USERS,
+					 context->user - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_ROLES,
+					 context->role - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_TYPES,
+					 context->type - 1)) + 1;
+	*scontext_len += mls_compute_context_len(&crm->policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1235,11 +1242,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	 * Copy the user name, role name and type name into the context.
 	 */
 	scontextp += sprintf(scontextp, "%s:%s:%s",
-		sym_name(&policydb, SYM_USERS, context->user - 1),
-		sym_name(&policydb, SYM_ROLES, context->role - 1),
-		sym_name(&policydb, SYM_TYPES, context->type - 1));
+		sym_name(&crm->policydb, SYM_USERS, context->user - 1),
+		sym_name(&crm->policydb, SYM_ROLES, context->role - 1),
+		sym_name(&crm->policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(&policydb, context, &scontextp);
+	mls_sid_to_context(&crm->policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1452,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1546,7 +1553,7 @@ static int compute_sid_handle_invalid_context(
 		  " scontext=%s"
 		  " tcontext=%s"
 		  " tclass=%s",
-		  n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  n, s, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(s);
 	kfree(t);
@@ -1638,8 +1645,8 @@ static int security_compute_sid(u32 ssid,
 		goto out_unlock;
 	}
 
-	if (tclass && tclass <= policydb.p_classes.nprim)
-		cladatum = policydb.class_val_to_struct[tclass - 1];
+	if (tclass && tclass <= crm->policydb.p_classes.nprim)
+		cladatum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/* Set the user identity. */
 	switch (specified) {
@@ -1665,7 +1672,7 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
 		newcontext.role = tcontext->role;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == crm->policydb.process_class) || (sock == true))
 			newcontext.role = scontext->role;
 		else
 			newcontext.role = OBJECT_R_VAL;
@@ -1677,7 +1684,8 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
 		newcontext.type = tcontext->type;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true)) {
+		if ((tclass == crm->policydb.process_class) ||
+		    (sock == true)) {
 			/* Use the type of process. */
 			newcontext.type = scontext->type;
 		} else {
@@ -1691,11 +1699,12 @@ static int security_compute_sid(u32 ssid,
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
 	avkey.specified = specified;
-	avdatum = avtab_search(&policydb.te_avtab, &avkey);
+	avdatum = avtab_search(&crm->policydb.te_avtab, &avkey);
 
 	/* If no permanent rule, also check for enabled conditional rules */
 	if (!avdatum) {
-		node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+		node = avtab_search_node(&crm->policydb.te_cond_avtab,
+					 &avkey);
 		for (; node; node = avtab_search_node_next(node, specified)) {
 			if (node->key.specified & AVTAB_ENABLED) {
 				avdatum = &node->datum;
@@ -1711,13 +1720,16 @@ static int security_compute_sid(u32 ssid,
 
 	/* if we have a objname this is a file trans check so check those rules */
 	if (objname)
-		filename_compute_type(&policydb, &newcontext, scontext->type,
-				      tcontext->type, tclass, objname);
+		filename_compute_type(&crm->policydb, &newcontext,
+				      scontext->type, tcontext->type,
+				      tclass, objname);
 
 	/* Check for class-specific changes. */
 	if (specified & AVTAB_TRANSITION) {
 		/* Look for a role transition rule. */
-		for (roletr = policydb.role_tr; roletr; roletr = roletr->next) {
+		for (roletr = crm->policydb.role_tr;
+		     roletr;
+		     roletr = roletr->next) {
 			if ((roletr->role == scontext->role) &&
 			    (roletr->type == tcontext->type) &&
 			    (roletr->tclass == tclass)) {
@@ -1730,13 +1742,13 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
-			     &newcontext, sock);
+	rc = mls_compute_sid(&crm->policydb, scontext, tcontext, tclass,
+			     specified, &newcontext, sock);
 	if (rc)
 		goto out_unlock;
 
 	/* Check the validity of the context. */
-	if (!policydb_context_isvalid(&policydb, &newcontext)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcontext)) {
 		rc = compute_sid_handle_invalid_context(scontext,
 							tcontext,
 							tclass,
@@ -1944,7 +1956,8 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
+		rc = mls_convert_context(&crm->policydb, args->oldp,
+					 args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2009,27 +2022,31 @@ static void security_load_policycaps(void)
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps,
-					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
-	selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_ALWAYSNETWORK);
+	selinux_policycap_netpeer =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+			  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_alwaysnetwork =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&policydb.policycaps, i));
+			ebitmap_get_bit(&crm->policydb.policycaps, i));
 
-	ebitmap_for_each_positive_bit(&policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2084,7 +2101,7 @@ int security_load_policy(void *data, size_t len)
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&policydb, fp);
+		rc = policydb_read(&crm->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
@@ -2092,21 +2109,21 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		policydb.len = len;
-		rc = selinux_set_mapping(&policydb, secclass_map,
+		crm->policydb.len = len;
+		rc = selinux_set_mapping(&crm->policydb, secclass_map,
 					 &crm->current_mapping,
 					 &crm->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
 			goto out;
 		}
 
-		rc = policydb_load_isids(&policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &sidtab);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
@@ -2135,9 +2152,9 @@ int security_load_policy(void *data, size_t len)
 
 	newpolicydb->len = len;
 	/* If switching between different policy types, log MLS status */
-	if (policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
 	rc = policydb_load_isids(newpolicydb, &newsidtab);
@@ -2168,7 +2185,7 @@ int security_load_policy(void *data, size_t len)
 	 * Convert the internal representations of contexts
 	 * in the new SID table.
 	 */
-	args.oldp = &policydb;
+	args.oldp = &crm->policydb;
 	args.newp = newpolicydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
@@ -2179,12 +2196,13 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Save the old policydb and SID table to free later. */
-	memcpy(oldpolicydb, &policydb, sizeof(policydb));
+	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
 	sidtab_set(&oldsidtab, &sidtab);
 
 	/* Install the new policydb and SID table. */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&policydb, newpolicydb, sizeof(policydb));
+	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
+
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
 	oldmap = crm->current_mapping;
@@ -2222,7 +2240,7 @@ size_t security_policydb_len(void)
 	size_t len;
 
 	read_lock(&policy_rwlock);
-	len = policydb.len;
+	len = crm->policydb.len;
 	read_unlock(&policy_rwlock);
 
 	return len;
@@ -2241,7 +2259,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_PORT];
+	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
 		if (c->u.port.protocol == protocol &&
 		    c->u.port.low_port <= port &&
@@ -2281,7 +2299,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBPKEY];
+	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
 		if (c->u.ibpkey.low_pkey <= pkey_num &&
 		    c->u.ibpkey.high_pkey >= pkey_num &&
@@ -2321,7 +2339,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBENDPORT];
+	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
 		if (c->u.ibendport.port == port_num &&
 		    !strncmp(c->u.ibendport.dev_name,
@@ -2361,7 +2379,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_NETIF];
+	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
 		if (strcmp(name, c->u.name) == 0)
 			break;
@@ -2430,7 +2448,7 @@ int security_node_sid(u16 domain,
 
 		addr = *((u32 *)addrp);
 
-		c = policydb.ocontexts[OCON_NODE];
+		c = crm->policydb.ocontexts[OCON_NODE];
 		while (c) {
 			if (c->u.node.addr == (addr & c->u.node.mask))
 				break;
@@ -2443,7 +2461,7 @@ int security_node_sid(u16 domain,
 		rc = -EINVAL;
 		if (addrlen != sizeof(u64) * 2)
 			goto out;
-		c = policydb.ocontexts[OCON_NODE6];
+		c = crm->policydb.ocontexts[OCON_NODE6];
 		while (c) {
 			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
 						c->u.node6.mask))
@@ -2522,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	rc = -EINVAL;
-	user = hashtab_search(policydb.p_users.table, username);
+	user = hashtab_search(crm->policydb.p_users.table, username);
 	if (!user)
 		goto out_unlock;
 
@@ -2534,12 +2552,12 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
-		role = policydb.role_val_to_struct[i];
+		role = crm->policydb.role_val_to_struct[i];
 		usercon.role = i + 1;
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(&policydb, fromcon,
+			if (mls_setup_user_range(&crm->policydb, fromcon,
 						 user, &usercon))
 				continue;
 
@@ -2623,7 +2641,7 @@ static inline int __security_genfs_sid(const char *fstype,
 	sclass = unmap_class(orig_sclass);
 	*sid = SECINITSID_UNLABELED;
 
-	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+	for (genfs = crm->policydb.genfs; genfs; genfs = genfs->next) {
 		cmp = strcmp(fstype, genfs->fstype);
 		if (cmp <= 0)
 			break;
@@ -2692,7 +2710,7 @@ int security_fs_use(struct super_block *sb)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_FSUSE];
+	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
 		if (strcmp(fstype, c->u.name) == 0)
 			break;
@@ -2733,7 +2751,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	*values = NULL;
 
 	rc = 0;
-	*len = policydb.p_bools.nprim;
+	*len = crm->policydb.p_bools.nprim;
 	if (!*len)
 		goto out;
 
@@ -2748,10 +2766,11 @@ int security_get_bools(int *len, char ***names, int **values)
 		goto err;
 
 	for (i = 0; i < *len; i++) {
-		(*values)[i] = policydb.bool_val_to_struct[i]->state;
+		(*values)[i] = crm->policydb.bool_val_to_struct[i]->state;
 
 		rc = -ENOMEM;
-		(*names)[i] = kstrdup(sym_name(&policydb, SYM_BOOLS, i), GFP_ATOMIC);
+		(*names)[i] = kstrdup(sym_name(&crm->policydb, SYM_BOOLS, i),
+				      GFP_ATOMIC);
 		if (!(*names)[i])
 			goto err;
 	}
@@ -2778,29 +2797,30 @@ int security_set_bools(int len, int *values)
 	write_lock_irq(&policy_rwlock);
 
 	rc = -EFAULT;
-	lenp = policydb.p_bools.nprim;
+	lenp = crm->policydb.p_bools.nprim;
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
-		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+		if (!!values[i] !=
+		    crm->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&policydb, SYM_BOOLS, i),
+				sym_name(&crm->policydb, SYM_BOOLS, i),
 				!!values[i],
-				policydb.bool_val_to_struct[i]->state,
+				crm->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			policydb.bool_val_to_struct[i]->state = 1;
+			crm->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			policydb.bool_val_to_struct[i]->state = 0;
+			crm->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&policydb, cur);
+	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&crm->policydb, cur);
 		if (rc)
 			goto out;
 	}
@@ -2826,11 +2846,11 @@ int security_get_bool_value(int index)
 	read_lock(&policy_rwlock);
 
 	rc = -EFAULT;
-	len = policydb.p_bools.nprim;
+	len = crm->policydb.p_bools.nprim;
 	if (index >= len)
 		goto out;
 
-	rc = policydb.bool_val_to_struct[index]->state;
+	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -2881,7 +2901,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	int rc;
 
 	rc = 0;
-	if (!ss_initialized || !policydb.mls_enabled) {
+	if (!ss_initialized || !crm->policydb.mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -2914,7 +2934,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		goto out_unlock;
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &newcon)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcon)) {
 		rc = convert_context_handle_invalid_context(&newcon);
 		if (rc) {
 			if (!context_struct_to_string(&newcon, &s, &len)) {
@@ -2984,7 +3004,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	/* 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 (!policydb.mls_enabled)
+	if (!crm->policydb.mls_enabled)
 		return 0;
 
 	read_lock(&policy_rwlock);
@@ -3038,12 +3058,12 @@ int security_get_classes(char ***classes, int *nclasses)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOMEM;
-	*nclasses = policydb.p_classes.nprim;
+	*nclasses = crm->policydb.p_classes.nprim;
 	*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
 	if (!*classes)
 		goto out;
 
-	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+	rc = hashtab_map(crm->policydb.p_classes.table, get_classes_callback,
 			*classes);
 	if (rc) {
 		int i;
@@ -3078,7 +3098,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	match = hashtab_search(policydb.p_classes.table, class);
+	match = hashtab_search(crm->policydb.p_classes.table, class);
 	if (!match) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized class %s\n",
 			__func__, class);
@@ -3117,12 +3137,12 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 
 int security_get_reject_unknown(void)
 {
-	return policydb.reject_unknown;
+	return crm->policydb.reject_unknown;
 }
 
 int security_get_allow_unknown(void)
 {
-	return policydb.allow_unknown;
+	return crm->policydb.allow_unknown;
 }
 
 /**
@@ -3140,7 +3160,7 @@ int security_policycap_supported(unsigned int req_cap)
 	int rc;
 
 	read_lock(&policy_rwlock);
-	rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
+	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
 	read_unlock(&policy_rwlock);
 
 	return rc;
@@ -3213,7 +3233,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_USER:
 	case AUDIT_OBJ_USER:
 		rc = -EINVAL;
-		userdatum = hashtab_search(policydb.p_users.table, rulestr);
+		userdatum = hashtab_search(crm->policydb.p_users.table,
+					   rulestr);
 		if (!userdatum)
 			goto out;
 		tmprule->au_ctxt.user = userdatum->value;
@@ -3221,7 +3242,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_ROLE:
 	case AUDIT_OBJ_ROLE:
 		rc = -EINVAL;
-		roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+		roledatum = hashtab_search(crm->policydb.p_roles.table,
+					   rulestr);
 		if (!roledatum)
 			goto out;
 		tmprule->au_ctxt.role = roledatum->value;
@@ -3229,7 +3251,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_TYPE:
 	case AUDIT_OBJ_TYPE:
 		rc = -EINVAL;
-		typedatum = hashtab_search(policydb.p_types.table, rulestr);
+		typedatum = hashtab_search(crm->policydb.p_types.table,
+					   rulestr);
 		if (!typedatum)
 			goto out;
 		tmprule->au_ctxt.type = typedatum->value;
@@ -3238,8 +3261,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
-				     GFP_ATOMIC);
+		rc = mls_from_string(&crm->policydb, rulestr,
+				     &tmprule->au_ctxt, GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3489,15 +3512,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
+		mls_import_netlbl_lvl(&crm->policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+			rc = mls_import_netlbl_cat(&crm->policydb, &ctx_new,
 						   secattr);
 			if (rc)
 				goto out;
 		}
 		rc = -EIDRM;
-		if (!mls_context_isvalid(&policydb, &ctx_new))
+		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
 		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
@@ -3545,15 +3568,16 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 		goto out;
 
 	rc = -ENOMEM;
-	secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
+	secattr->domain = kstrdup(sym_name(&crm->policydb,
+					   SYM_TYPES, ctx->type - 1),
 				  GFP_ATOMIC);
 	if (secattr->domain == NULL)
 		goto out;
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(&policydb, ctx, secattr);
-	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
+	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -3584,7 +3608,7 @@ int security_read_policy(void **data, size_t *len)
 	fp.len = *len;
 
 	read_lock(&policy_rwlock);
-	rc = policydb_write(&policydb, &fp);
+	rc = policydb_write(&crm->policydb, &fp);
 	read_unlock(&policy_rwlock);
 
 	if (rc)
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 2/5] selinux: Move policydb to pointer structure
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we seed to address the policydb
though a pointer. This patch adds a pointer structure to
repleace the static policydb.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 274 ++++++++++++++++++++++-------------------
 1 file changed, 149 insertions(+), 125 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 47d8030..21400bd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -90,7 +90,6 @@ int selinux_policycap_nnp_nosuid_transition;
 static DEFINE_RWLOCK(policy_rwlock);
 
 static struct sidtab sidtab;
-static struct policydb policydb;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct selinux_mapping {
 struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
+	struct policydb policydb;
 };
 
 static struct shared_current_mapping *crm;
@@ -277,7 +277,7 @@ static void map_decision(u16 tclass, struct av_decision *avd,
 
 int security_mls_enabled(void)
 {
-	return policydb.mls_enabled;
+	return crm->policydb.mls_enabled;
 }
 
 /*
@@ -335,8 +335,8 @@ static int constraint_expr_eval(struct context *scontext,
 			case CEXPR_ROLE:
 				val1 = scontext->role;
 				val2 = tcontext->role;
-				r1 = policydb.role_val_to_struct[val1 - 1];
-				r2 = policydb.role_val_to_struct[val2 - 1];
+				r1 = crm->policydb.role_val_to_struct[val1 - 1];
+				r2 = crm->policydb.role_val_to_struct[val2 - 1];
 				switch (e->op) {
 				case CEXPR_DOM:
 					s[++sp] = ebitmap_get_bit(&r1->dominates,
@@ -501,8 +501,8 @@ static void security_dump_masked_av(struct context *scontext,
 	if (!permissions)
 		return;
 
-	tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
-	tclass_dat = policydb.class_val_to_struct[tclass - 1];
+	tclass_name = sym_name(&crm->policydb, SYM_CLASSES, tclass - 1);
+	tclass_dat = crm->policydb.class_val_to_struct[tclass - 1];
 	common_dat = tclass_dat->comdatum;
 
 	/* init permission_names */
@@ -571,14 +571,14 @@ static void type_attribute_bounds_av(struct context *scontext,
 	struct type_datum *target;
 	u32 masked = 0;
 
-	source = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	source = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    scontext->type - 1);
 	BUG_ON(!source);
 
 	if (!source->bounds)
 		return;
 
-	target = flex_array_get_ptr(policydb.type_val_to_struct_array,
+	target = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 				    tcontext->type - 1);
 	BUG_ON(!target);
 
@@ -664,13 +664,13 @@ static void context_struct_compute_av(struct context *scontext,
 		xperms->len = 0;
 	}
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "SELinux:  Invalid class %hu\n", tclass);
 		return;
 	}
 
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/*
 	 * If a specific type enforcement rule was defined for
@@ -678,15 +678,18 @@ static void context_struct_compute_av(struct context *scontext,
 	 */
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_AV | AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
+			       tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified)) {
 				if (node->key.specified == AVTAB_ALLOWED)
@@ -700,7 +703,7 @@ static void context_struct_compute_av(struct context *scontext,
 			}
 
 			/* Check conditional av table for additional permissions */
-			cond_compute_av(&policydb.te_cond_avtab, &avkey,
+			cond_compute_av(&crm->policydb.te_cond_avtab, &avkey,
 					avd, xperms);
 
 		}
@@ -725,16 +728,16 @@ static void context_struct_compute_av(struct context *scontext,
 	 * role is changing, then check the (current_role, new_role)
 	 * pair.
 	 */
-	if (tclass == policydb.process_class &&
-	    (avd->allowed & policydb.process_trans_perms) &&
+	if (tclass == crm->policydb.process_class &&
+	    (avd->allowed & crm->policydb.process_trans_perms) &&
 	    scontext->role != tcontext->role) {
-		for (ra = policydb.role_allow; ra; ra = ra->next) {
+		for (ra = crm->policydb.role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
 			    tcontext->role == ra->new_role)
 				break;
 		}
 		if (!ra)
-			avd->allowed &= ~policydb.process_trans_perms;
+			avd->allowed &= ~crm->policydb.process_trans_perms;
 	}
 
 	/*
@@ -763,7 +766,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
 	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
 		  "op=security_validate_transition seresult=denied"
 		  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
-		  o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  o, n, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(o);
 	kfree(n);
@@ -795,11 +798,11 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	else
 		tclass = orig_tclass;
 
-	if (!tclass || tclass > policydb.p_classes.nprim) {
+	if (!tclass || tclass > crm->policydb.p_classes.nprim) {
 		rc = -EINVAL;
 		goto out;
 	}
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	ocontext = sidtab_search(&sidtab, oldsid);
 	if (!ocontext) {
@@ -901,7 +904,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 
 	index = new_context->type;
 	while (true) {
-		type = flex_array_get_ptr(policydb.type_val_to_struct_array,
+		type = flex_array_get_ptr(crm->policydb.type_val_to_struct_array,
 					  index - 1);
 		BUG_ON(!type);
 
@@ -1046,35 +1049,36 @@ void security_compute_xperms_decision(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 
 
-	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+	if (unlikely(!tclass || tclass > crm->policydb.p_classes.nprim)) {
 		pr_warn_ratelimited("SELinux:  Invalid class %hu\n", tclass);
 		goto out;
 	}
 
 	avkey.target_class = tclass;
 	avkey.specified = AVTAB_XPERMS;
-	sattr = flex_array_get(policydb.type_attr_map_array,
+	sattr = flex_array_get(crm->policydb.type_attr_map_array,
 				scontext->type - 1);
 	BUG_ON(!sattr);
-	tattr = flex_array_get(policydb.type_attr_map_array,
+	tattr = flex_array_get(crm->policydb.type_attr_map_array,
 				tcontext->type - 1);
 	BUG_ON(!tattr);
 	ebitmap_for_each_positive_bit(sattr, snode, i) {
 		ebitmap_for_each_positive_bit(tattr, tnode, j) {
 			avkey.source_type = i + 1;
 			avkey.target_type = j + 1;
-			for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+			for (node = avtab_search_node(&crm->policydb.te_avtab,
+						      &avkey);
 			     node;
 			     node = avtab_search_node_next(node, avkey.specified))
 				services_compute_xperms_decision(xpermd, node);
 
-			cond_compute_xperms(&policydb.te_cond_avtab,
+			cond_compute_xperms(&crm->policydb.te_cond_avtab,
 						&avkey, xpermd);
 		}
 	}
@@ -1120,7 +1124,7 @@ void security_compute_av(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1132,12 +1136,12 @@ void security_compute_av(u32 ssid,
 
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
-	map_decision(orig_tclass, avd, policydb.allow_unknown);
+	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
 	read_unlock(&policy_rwlock);
 	return;
@@ -1166,7 +1170,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
 	tcontext = sidtab_search(&sidtab, tsid);
@@ -1177,7 +1181,7 @@ void security_compute_av_user(u32 ssid,
 	}
 
 	if (unlikely(!tclass)) {
-		if (policydb.allow_unknown)
+		if (crm->policydb.allow_unknown)
 			goto allow;
 		goto out;
 	}
@@ -1217,10 +1221,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	}
 
 	/* Compute the size of the context. */
-	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
-	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
-	*scontext_len += mls_compute_context_len(&policydb, context);
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_USERS,
+					 context->user - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_ROLES,
+					 context->role - 1)) + 1;
+	*scontext_len += strlen(sym_name(&crm->policydb, SYM_TYPES,
+					 context->type - 1)) + 1;
+	*scontext_len += mls_compute_context_len(&crm->policydb, context);
 
 	if (!scontext)
 		return 0;
@@ -1235,11 +1242,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	 * Copy the user name, role name and type name into the context.
 	 */
 	scontextp += sprintf(scontextp, "%s:%s:%s",
-		sym_name(&policydb, SYM_USERS, context->user - 1),
-		sym_name(&policydb, SYM_ROLES, context->role - 1),
-		sym_name(&policydb, SYM_TYPES, context->type - 1));
+		sym_name(&crm->policydb, SYM_USERS, context->user - 1),
+		sym_name(&crm->policydb, SYM_ROLES, context->role - 1),
+		sym_name(&crm->policydb, SYM_TYPES, context->type - 1));
 
-	mls_sid_to_context(&policydb, context, &scontextp);
+	mls_sid_to_context(&crm->policydb, context, &scontextp);
 
 	*scontextp = 0;
 
@@ -1452,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1546,7 +1553,7 @@ static int compute_sid_handle_invalid_context(
 		  " scontext=%s"
 		  " tcontext=%s"
 		  " tclass=%s",
-		  n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+		  n, s, t, sym_name(&crm->policydb, SYM_CLASSES, tclass-1));
 out:
 	kfree(s);
 	kfree(t);
@@ -1638,8 +1645,8 @@ static int security_compute_sid(u32 ssid,
 		goto out_unlock;
 	}
 
-	if (tclass && tclass <= policydb.p_classes.nprim)
-		cladatum = policydb.class_val_to_struct[tclass - 1];
+	if (tclass && tclass <= crm->policydb.p_classes.nprim)
+		cladatum = crm->policydb.class_val_to_struct[tclass - 1];
 
 	/* Set the user identity. */
 	switch (specified) {
@@ -1665,7 +1672,7 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
 		newcontext.role = tcontext->role;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true))
+		if ((tclass == crm->policydb.process_class) || (sock == true))
 			newcontext.role = scontext->role;
 		else
 			newcontext.role = OBJECT_R_VAL;
@@ -1677,7 +1684,8 @@ static int security_compute_sid(u32 ssid,
 	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
 		newcontext.type = tcontext->type;
 	} else {
-		if ((tclass == policydb.process_class) || (sock == true)) {
+		if ((tclass == crm->policydb.process_class) ||
+		    (sock == true)) {
 			/* Use the type of process. */
 			newcontext.type = scontext->type;
 		} else {
@@ -1691,11 +1699,12 @@ static int security_compute_sid(u32 ssid,
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
 	avkey.specified = specified;
-	avdatum = avtab_search(&policydb.te_avtab, &avkey);
+	avdatum = avtab_search(&crm->policydb.te_avtab, &avkey);
 
 	/* If no permanent rule, also check for enabled conditional rules */
 	if (!avdatum) {
-		node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+		node = avtab_search_node(&crm->policydb.te_cond_avtab,
+					 &avkey);
 		for (; node; node = avtab_search_node_next(node, specified)) {
 			if (node->key.specified & AVTAB_ENABLED) {
 				avdatum = &node->datum;
@@ -1711,13 +1720,16 @@ static int security_compute_sid(u32 ssid,
 
 	/* if we have a objname this is a file trans check so check those rules */
 	if (objname)
-		filename_compute_type(&policydb, &newcontext, scontext->type,
-				      tcontext->type, tclass, objname);
+		filename_compute_type(&crm->policydb, &newcontext,
+				      scontext->type, tcontext->type,
+				      tclass, objname);
 
 	/* Check for class-specific changes. */
 	if (specified & AVTAB_TRANSITION) {
 		/* Look for a role transition rule. */
-		for (roletr = policydb.role_tr; roletr; roletr = roletr->next) {
+		for (roletr = crm->policydb.role_tr;
+		     roletr;
+		     roletr = roletr->next) {
 			if ((roletr->role == scontext->role) &&
 			    (roletr->type == tcontext->type) &&
 			    (roletr->tclass == tclass)) {
@@ -1730,13 +1742,13 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass, specified,
-			     &newcontext, sock);
+	rc = mls_compute_sid(&crm->policydb, scontext, tcontext, tclass,
+			     specified, &newcontext, sock);
 	if (rc)
 		goto out_unlock;
 
 	/* Check the validity of the context. */
-	if (!policydb_context_isvalid(&policydb, &newcontext)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcontext)) {
 		rc = compute_sid_handle_invalid_context(scontext,
 							tcontext,
 							tclass,
@@ -1944,7 +1956,8 @@ static int convert_context(u32 key,
 
 	/* Convert the MLS fields if dealing with MLS policies */
 	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
-		rc = mls_convert_context(&policydb, args->oldp, args->newp, c);
+		rc = mls_convert_context(&crm->policydb, args->oldp,
+					 args->newp, c);
 		if (rc)
 			goto bad;
 	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
@@ -2009,27 +2022,31 @@ static void security_load_policycaps(void)
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps,
-					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
-	selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
-						  POLICYDB_CAPABILITY_ALWAYSNETWORK);
+	selinux_policycap_netpeer =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+			  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_alwaysnetwork =
+		ebitmap_get_bit(&crm->policydb.policycaps,
+				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&policydb.policycaps,
+		ebitmap_get_bit(&crm->policydb.policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&policydb.policycaps, i));
+			ebitmap_get_bit(&crm->policydb.policycaps, i));
 
-	ebitmap_for_each_positive_bit(&policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2084,7 +2101,7 @@ int security_load_policy(void *data, size_t len)
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&policydb, fp);
+		rc = policydb_read(&crm->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
@@ -2092,21 +2109,21 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		policydb.len = len;
-		rc = selinux_set_mapping(&policydb, secclass_map,
+		crm->policydb.len = len;
+		rc = selinux_set_mapping(&crm->policydb, secclass_map,
 					 &crm->current_mapping,
 					 &crm->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
 			goto out;
 		}
 
-		rc = policydb_load_isids(&policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &sidtab);
 		if (rc) {
-			policydb_destroy(&policydb);
+			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
@@ -2135,9 +2152,9 @@ int security_load_policy(void *data, size_t len)
 
 	newpolicydb->len = len;
 	/* If switching between different policy types, log MLS status */
-	if (policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
 	rc = policydb_load_isids(newpolicydb, &newsidtab);
@@ -2168,7 +2185,7 @@ int security_load_policy(void *data, size_t len)
 	 * Convert the internal representations of contexts
 	 * in the new SID table.
 	 */
-	args.oldp = &policydb;
+	args.oldp = &crm->policydb;
 	args.newp = newpolicydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
@@ -2179,12 +2196,13 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Save the old policydb and SID table to free later. */
-	memcpy(oldpolicydb, &policydb, sizeof(policydb));
+	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
 	sidtab_set(&oldsidtab, &sidtab);
 
 	/* Install the new policydb and SID table. */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&policydb, newpolicydb, sizeof(policydb));
+	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
+
 	sidtab_set(&sidtab, &newsidtab);
 	security_load_policycaps();
 	oldmap = crm->current_mapping;
@@ -2222,7 +2240,7 @@ size_t security_policydb_len(void)
 	size_t len;
 
 	read_lock(&policy_rwlock);
-	len = policydb.len;
+	len = crm->policydb.len;
 	read_unlock(&policy_rwlock);
 
 	return len;
@@ -2241,7 +2259,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_PORT];
+	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
 		if (c->u.port.protocol == protocol &&
 		    c->u.port.low_port <= port &&
@@ -2281,7 +2299,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBPKEY];
+	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
 		if (c->u.ibpkey.low_pkey <= pkey_num &&
 		    c->u.ibpkey.high_pkey >= pkey_num &&
@@ -2321,7 +2339,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_IBENDPORT];
+	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
 		if (c->u.ibendport.port == port_num &&
 		    !strncmp(c->u.ibendport.dev_name,
@@ -2361,7 +2379,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_NETIF];
+	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
 		if (strcmp(name, c->u.name) == 0)
 			break;
@@ -2430,7 +2448,7 @@ int security_node_sid(u16 domain,
 
 		addr = *((u32 *)addrp);
 
-		c = policydb.ocontexts[OCON_NODE];
+		c = crm->policydb.ocontexts[OCON_NODE];
 		while (c) {
 			if (c->u.node.addr == (addr & c->u.node.mask))
 				break;
@@ -2443,7 +2461,7 @@ int security_node_sid(u16 domain,
 		rc = -EINVAL;
 		if (addrlen != sizeof(u64) * 2)
 			goto out;
-		c = policydb.ocontexts[OCON_NODE6];
+		c = crm->policydb.ocontexts[OCON_NODE6];
 		while (c) {
 			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
 						c->u.node6.mask))
@@ -2522,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	rc = -EINVAL;
-	user = hashtab_search(policydb.p_users.table, username);
+	user = hashtab_search(crm->policydb.p_users.table, username);
 	if (!user)
 		goto out_unlock;
 
@@ -2534,12 +2552,12 @@ int security_get_user_sids(u32 fromsid,
 		goto out_unlock;
 
 	ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
-		role = policydb.role_val_to_struct[i];
+		role = crm->policydb.role_val_to_struct[i];
 		usercon.role = i + 1;
 		ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 			usercon.type = j + 1;
 
-			if (mls_setup_user_range(&policydb, fromcon,
+			if (mls_setup_user_range(&crm->policydb, fromcon,
 						 user, &usercon))
 				continue;
 
@@ -2623,7 +2641,7 @@ static inline int __security_genfs_sid(const char *fstype,
 	sclass = unmap_class(orig_sclass);
 	*sid = SECINITSID_UNLABELED;
 
-	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+	for (genfs = crm->policydb.genfs; genfs; genfs = genfs->next) {
 		cmp = strcmp(fstype, genfs->fstype);
 		if (cmp <= 0)
 			break;
@@ -2692,7 +2710,7 @@ int security_fs_use(struct super_block *sb)
 
 	read_lock(&policy_rwlock);
 
-	c = policydb.ocontexts[OCON_FSUSE];
+	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
 		if (strcmp(fstype, c->u.name) == 0)
 			break;
@@ -2733,7 +2751,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	*values = NULL;
 
 	rc = 0;
-	*len = policydb.p_bools.nprim;
+	*len = crm->policydb.p_bools.nprim;
 	if (!*len)
 		goto out;
 
@@ -2748,10 +2766,11 @@ int security_get_bools(int *len, char ***names, int **values)
 		goto err;
 
 	for (i = 0; i < *len; i++) {
-		(*values)[i] = policydb.bool_val_to_struct[i]->state;
+		(*values)[i] = crm->policydb.bool_val_to_struct[i]->state;
 
 		rc = -ENOMEM;
-		(*names)[i] = kstrdup(sym_name(&policydb, SYM_BOOLS, i), GFP_ATOMIC);
+		(*names)[i] = kstrdup(sym_name(&crm->policydb, SYM_BOOLS, i),
+				      GFP_ATOMIC);
 		if (!(*names)[i])
 			goto err;
 	}
@@ -2778,29 +2797,30 @@ int security_set_bools(int len, int *values)
 	write_lock_irq(&policy_rwlock);
 
 	rc = -EFAULT;
-	lenp = policydb.p_bools.nprim;
+	lenp = crm->policydb.p_bools.nprim;
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
-		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+		if (!!values[i] !=
+		    crm->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&policydb, SYM_BOOLS, i),
+				sym_name(&crm->policydb, SYM_BOOLS, i),
 				!!values[i],
-				policydb.bool_val_to_struct[i]->state,
+				crm->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			policydb.bool_val_to_struct[i]->state = 1;
+			crm->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			policydb.bool_val_to_struct[i]->state = 0;
+			crm->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&policydb, cur);
+	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&crm->policydb, cur);
 		if (rc)
 			goto out;
 	}
@@ -2826,11 +2846,11 @@ int security_get_bool_value(int index)
 	read_lock(&policy_rwlock);
 
 	rc = -EFAULT;
-	len = policydb.p_bools.nprim;
+	len = crm->policydb.p_bools.nprim;
 	if (index >= len)
 		goto out;
 
-	rc = policydb.bool_val_to_struct[index]->state;
+	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -2881,7 +2901,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	int rc;
 
 	rc = 0;
-	if (!ss_initialized || !policydb.mls_enabled) {
+	if (!ss_initialized || !crm->policydb.mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -2914,7 +2934,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		goto out_unlock;
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &newcon)) {
+	if (!policydb_context_isvalid(&crm->policydb, &newcon)) {
 		rc = convert_context_handle_invalid_context(&newcon);
 		if (rc) {
 			if (!context_struct_to_string(&newcon, &s, &len)) {
@@ -2984,7 +3004,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	/* 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 (!policydb.mls_enabled)
+	if (!crm->policydb.mls_enabled)
 		return 0;
 
 	read_lock(&policy_rwlock);
@@ -3038,12 +3058,12 @@ int security_get_classes(char ***classes, int *nclasses)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOMEM;
-	*nclasses = policydb.p_classes.nprim;
+	*nclasses = crm->policydb.p_classes.nprim;
 	*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
 	if (!*classes)
 		goto out;
 
-	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+	rc = hashtab_map(crm->policydb.p_classes.table, get_classes_callback,
 			*classes);
 	if (rc) {
 		int i;
@@ -3078,7 +3098,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	match = hashtab_search(policydb.p_classes.table, class);
+	match = hashtab_search(crm->policydb.p_classes.table, class);
 	if (!match) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized class %s\n",
 			__func__, class);
@@ -3117,12 +3137,12 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 
 int security_get_reject_unknown(void)
 {
-	return policydb.reject_unknown;
+	return crm->policydb.reject_unknown;
 }
 
 int security_get_allow_unknown(void)
 {
-	return policydb.allow_unknown;
+	return crm->policydb.allow_unknown;
 }
 
 /**
@@ -3140,7 +3160,7 @@ int security_policycap_supported(unsigned int req_cap)
 	int rc;
 
 	read_lock(&policy_rwlock);
-	rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
+	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
 	read_unlock(&policy_rwlock);
 
 	return rc;
@@ -3213,7 +3233,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_USER:
 	case AUDIT_OBJ_USER:
 		rc = -EINVAL;
-		userdatum = hashtab_search(policydb.p_users.table, rulestr);
+		userdatum = hashtab_search(crm->policydb.p_users.table,
+					   rulestr);
 		if (!userdatum)
 			goto out;
 		tmprule->au_ctxt.user = userdatum->value;
@@ -3221,7 +3242,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_ROLE:
 	case AUDIT_OBJ_ROLE:
 		rc = -EINVAL;
-		roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+		roledatum = hashtab_search(crm->policydb.p_roles.table,
+					   rulestr);
 		if (!roledatum)
 			goto out;
 		tmprule->au_ctxt.role = roledatum->value;
@@ -3229,7 +3251,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_TYPE:
 	case AUDIT_OBJ_TYPE:
 		rc = -EINVAL;
-		typedatum = hashtab_search(policydb.p_types.table, rulestr);
+		typedatum = hashtab_search(crm->policydb.p_types.table,
+					   rulestr);
 		if (!typedatum)
 			goto out;
 		tmprule->au_ctxt.type = typedatum->value;
@@ -3238,8 +3261,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	case AUDIT_SUBJ_CLR:
 	case AUDIT_OBJ_LEV_LOW:
 	case AUDIT_OBJ_LEV_HIGH:
-		rc = mls_from_string(&policydb, rulestr, &tmprule->au_ctxt,
-				     GFP_ATOMIC);
+		rc = mls_from_string(&crm->policydb, rulestr,
+				     &tmprule->au_ctxt, GFP_ATOMIC);
 		if (rc)
 			goto out;
 		break;
@@ -3489,15 +3512,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		ctx_new.user = ctx->user;
 		ctx_new.role = ctx->role;
 		ctx_new.type = ctx->type;
-		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
+		mls_import_netlbl_lvl(&crm->policydb, &ctx_new, secattr);
 		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-			rc = mls_import_netlbl_cat(&policydb, &ctx_new,
+			rc = mls_import_netlbl_cat(&crm->policydb, &ctx_new,
 						   secattr);
 			if (rc)
 				goto out;
 		}
 		rc = -EIDRM;
-		if (!mls_context_isvalid(&policydb, &ctx_new))
+		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
 		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
@@ -3545,15 +3568,16 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 		goto out;
 
 	rc = -ENOMEM;
-	secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
+	secattr->domain = kstrdup(sym_name(&crm->policydb,
+					   SYM_TYPES, ctx->type - 1),
 				  GFP_ATOMIC);
 	if (secattr->domain == NULL)
 		goto out;
 
 	secattr->attr.secid = sid;
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
-	mls_export_netlbl_lvl(&policydb, ctx, secattr);
-	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
+	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
+	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -3584,7 +3608,7 @@ int security_read_policy(void **data, size_t *len)
 	fp.len = *len;
 
 	read_lock(&policy_rwlock);
-	rc = policydb_write(&policydb, &fp);
+	rc = policydb_write(&crm->policydb, &fp);
 	read_unlock(&policy_rwlock);
 
 	if (rc)
-- 
2.7.4

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

* [PATCH v2 3/5] selinux: Move sidtab to pointer structure
  2018-01-26 14:32 ` peter.enderborg at sony.com
  (?)
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  -1 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we need access the sidtab trough
a pointer. This moves the sittab to a dynamic allocated struture.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 140 ++++++++++++++++++++++-------------------
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 21400bd..2a8486c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -89,7 +89,6 @@ int selinux_policycap_nnp_nosuid_transition;
 
 static DEFINE_RWLOCK(policy_rwlock);
 
-static struct sidtab sidtab;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
+	struct sidtab sidtab;
 };
 
 static struct shared_current_mapping *crm;
@@ -804,7 +804,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
-	ocontext = sidtab_search(&sidtab, oldsid);
+	ocontext = sidtab_search(&crm->sidtab, oldsid);
 	if (!ocontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, oldsid);
@@ -812,7 +812,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	ncontext = sidtab_search(&sidtab, newsid);
+	ncontext = sidtab_search(&crm->sidtab, newsid);
 	if (!ncontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, newsid);
@@ -820,7 +820,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tasksid);
+	tcontext = sidtab_search(&crm->sidtab, tasksid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, tasksid);
@@ -882,7 +882,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	old_context = sidtab_search(&sidtab, old_sid);
+	old_context = sidtab_search(&crm->sidtab, old_sid);
 	if (!old_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, old_sid);
@@ -890,7 +890,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	}
 
 	rc = -EINVAL;
-	new_context = sidtab_search(&sidtab, new_sid);
+	new_context = sidtab_search(&crm->sidtab, new_sid);
 	if (!new_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, new_sid);
@@ -1033,14 +1033,14 @@ void security_compute_xperms_decision(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1116,7 +1116,7 @@ void security_compute_av(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1127,7 +1127,7 @@ void security_compute_av(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1162,7 +1162,7 @@ void security_compute_av_user(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1173,7 +1173,7 @@ void security_compute_av_user(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1295,9 +1295,9 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	read_lock(&policy_rwlock);
 	if (force)
-		context = sidtab_search_force(&sidtab, sid);
+		context = sidtab_search_force(&crm->sidtab, sid);
 	else
-		context = sidtab_search(&sidtab, sid);
+		context = sidtab_search(&crm->sidtab, sid);
 	if (!context) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -1459,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1467,7 +1467,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 		str = NULL;
 	} else if (rc)
 		goto out_unlock;
-	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
 	read_unlock(&policy_rwlock);
@@ -1630,14 +1630,14 @@ static int security_compute_sid(u32 ssid,
 		sock = security_is_socket_class(map_class(tclass));
 	}
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		rc = -EINVAL;
 		goto out_unlock;
 	}
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1757,7 +1757,7 @@ static int security_compute_sid(u32 ssid,
 			goto out_unlock;
 	}
 	/* Obtain the sid for the context. */
-	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcontext);
@@ -2017,36 +2017,33 @@ static int convert_context(u32 key,
 	goto out;
 }
 
-static void security_load_policycaps(void)
+static void security_load_policycaps(struct policydb *pdb)
 {
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-			  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_netpeer = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass = ebitmap_get_bit(&pdb->policycaps,
+					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
 	selinux_policycap_alwaysnetwork =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&crm->policydb.policycaps, i));
+			ebitmap_get_bit(&pdb->policycaps, i));
 
-	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2072,6 +2069,8 @@ int security_load_policy(void *data, size_t len)
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
 	struct shared_current_mapping *new_mapping;
+	struct shared_current_mapping *next_rcu;
+
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2089,6 +2088,11 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 	newpolicydb = oldpolicydb + 1;
+	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	if (!ss_initialized) {
 		crm = kzalloc(sizeof(struct shared_current_mapping),
@@ -2097,7 +2101,6 @@ int security_load_policy(void *data, size_t len)
 			rc = -ENOMEM;
 			goto out;
 		}
-
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2121,7 +2124,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
 		if (rc) {
 			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
@@ -2130,7 +2133,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		security_load_policycaps();
+		security_load_policycaps(&crm->policydb);
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2143,7 +2146,7 @@ int security_load_policy(void *data, size_t len)
 	}
 
 #if 0
-	sidtab_hash_eval(&sidtab, "sids");
+	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
 
 	rc = policydb_read(newpolicydb, fp);
@@ -2175,9 +2178,9 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Clone the SID table. */
-	sidtab_shutdown(&sidtab);
+	sidtab_shutdown(&crm->sidtab);
 
-	rc = sidtab_map(&sidtab, clone_sid, &newsidtab);
+	rc = sidtab_map(&crm->sidtab, clone_sid, &newsidtab);
 	if (rc)
 		goto err;
 
@@ -2197,19 +2200,21 @@ int security_load_policy(void *data, size_t len)
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
-	sidtab_set(&oldsidtab, &sidtab);
+	sidtab_set(&oldsidtab, &crm->sidtab);
 
 	/* Install the new policydb and SID table. */
+	/* next */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
-
-	sidtab_set(&sidtab, &newsidtab);
-	security_load_policycaps();
+	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
+	sidtab_set(&next_rcu->sidtab, &newsidtab);
+	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
-	crm->current_mapping = map;
-	crm->current_mapping_size = map_size;
+	next_rcu->current_mapping = map;
+	next_rcu->current_mapping_size = map_size;
+
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
+	crm = next_rcu;
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2270,7 +2275,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2311,7 +2316,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2352,7 +2357,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2388,12 +2393,12 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	if (c) {
 		if (!c->sid[0] || !c->sid[1]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						  &c->context[0],
 						  &c->sid[0]);
 			if (rc)
 				goto out;
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[1],
 						   &c->sid[1]);
 			if (rc)
@@ -2478,7 +2483,7 @@ int security_node_sid(u16 domain,
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2535,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	context_init(&usercon);
 
 	rc = -EINVAL;
-	fromcon = sidtab_search(&sidtab, fromsid);
+	fromcon = sidtab_search(&crm->sidtab, fromsid);
 	if (!fromcon)
 		goto out_unlock;
 
@@ -2561,7 +2566,8 @@ int security_get_user_sids(u32 fromsid,
 						 user, &usercon))
 				continue;
 
-			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+			rc = sidtab_context_to_sid(&crm->sidtab, &usercon,
+						   &sid);
 			if (rc)
 				goto out_unlock;
 			if (mynel < maxnel) {
@@ -2663,7 +2669,8 @@ static inline int __security_genfs_sid(const char *fstype,
 		goto out;
 
 	if (!c->sid[0]) {
-		rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+		rc = sidtab_context_to_sid(&crm->sidtab, &c->context[0],
+					   &c->sid[0]);
 		if (rc)
 			goto out;
 	}
@@ -2720,7 +2727,8 @@ int security_fs_use(struct super_block *sb)
 	if (c) {
 		sbsec->behavior = c->v.behavior;
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			rc = sidtab_context_to_sid(&crm->sidtab,
+						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -2911,7 +2919,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	context1 = sidtab_search(&sidtab, sid);
+	context1 = sidtab_search(&crm->sidtab, sid);
 	if (!context1) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -2919,7 +2927,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	}
 
 	rc = -EINVAL;
-	context2 = sidtab_search(&sidtab, mls_sid);
+	context2 = sidtab_search(&crm->sidtab, mls_sid);
 	if (!context2) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, mls_sid);
@@ -2948,7 +2956,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		}
 	}
 
-	rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcon);
@@ -3010,14 +3018,14 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
 	if (!nlbl_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, nlbl_sid);
 		goto out;
 	}
 	rc = -EINVAL;
-	xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+	xfrm_ctx = sidtab_search(&crm->sidtab, xfrm_sid);
 	if (!xfrm_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, xfrm_sid);
@@ -3326,7 +3334,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		goto out;
 	}
 
-	ctxt = sidtab_search(&sidtab, sid);
+	ctxt = sidtab_search(&crm->sidtab, sid);
 	if (unlikely(!ctxt)) {
 		WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
 			  sid);
@@ -3504,7 +3512,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		*sid = secattr->attr.secid;
 	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
 		rc = -EIDRM;
-		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
+		ctx = sidtab_search(&crm->sidtab, SECINITSID_NETMSG);
 		if (ctx == NULL)
 			goto out;
 
@@ -3523,7 +3531,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
-		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
+		rc = sidtab_context_to_sid(&crm->sidtab, &ctx_new, sid);
 		if (rc)
 			goto out_free;
 
@@ -3563,7 +3571,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOENT;
-	ctx = sidtab_search(&sidtab, sid);
+	ctx = sidtab_search(&crm->sidtab, sid);
 	if (ctx == NULL)
 		goto out;
 
-- 
2.7.4

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

* [PATCH v2 3/5] selinux: Move sidtab to pointer structure
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we need access the sidtab trough
a pointer. This moves the sittab to a dynamic allocated struture.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 140 ++++++++++++++++++++++-------------------
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 21400bd..2a8486c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -89,7 +89,6 @@ int selinux_policycap_nnp_nosuid_transition;
 
 static DEFINE_RWLOCK(policy_rwlock);
 
-static struct sidtab sidtab;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
+	struct sidtab sidtab;
 };
 
 static struct shared_current_mapping *crm;
@@ -804,7 +804,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
-	ocontext = sidtab_search(&sidtab, oldsid);
+	ocontext = sidtab_search(&crm->sidtab, oldsid);
 	if (!ocontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, oldsid);
@@ -812,7 +812,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	ncontext = sidtab_search(&sidtab, newsid);
+	ncontext = sidtab_search(&crm->sidtab, newsid);
 	if (!ncontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, newsid);
@@ -820,7 +820,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tasksid);
+	tcontext = sidtab_search(&crm->sidtab, tasksid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, tasksid);
@@ -882,7 +882,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	old_context = sidtab_search(&sidtab, old_sid);
+	old_context = sidtab_search(&crm->sidtab, old_sid);
 	if (!old_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, old_sid);
@@ -890,7 +890,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	}
 
 	rc = -EINVAL;
-	new_context = sidtab_search(&sidtab, new_sid);
+	new_context = sidtab_search(&crm->sidtab, new_sid);
 	if (!new_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, new_sid);
@@ -1033,14 +1033,14 @@ void security_compute_xperms_decision(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1116,7 +1116,7 @@ void security_compute_av(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1127,7 +1127,7 @@ void security_compute_av(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1162,7 +1162,7 @@ void security_compute_av_user(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1173,7 +1173,7 @@ void security_compute_av_user(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1295,9 +1295,9 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	read_lock(&policy_rwlock);
 	if (force)
-		context = sidtab_search_force(&sidtab, sid);
+		context = sidtab_search_force(&crm->sidtab, sid);
 	else
-		context = sidtab_search(&sidtab, sid);
+		context = sidtab_search(&crm->sidtab, sid);
 	if (!context) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -1459,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1467,7 +1467,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 		str = NULL;
 	} else if (rc)
 		goto out_unlock;
-	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
 	read_unlock(&policy_rwlock);
@@ -1630,14 +1630,14 @@ static int security_compute_sid(u32 ssid,
 		sock = security_is_socket_class(map_class(tclass));
 	}
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		rc = -EINVAL;
 		goto out_unlock;
 	}
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1757,7 +1757,7 @@ static int security_compute_sid(u32 ssid,
 			goto out_unlock;
 	}
 	/* Obtain the sid for the context. */
-	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcontext);
@@ -2017,36 +2017,33 @@ static int convert_context(u32 key,
 	goto out;
 }
 
-static void security_load_policycaps(void)
+static void security_load_policycaps(struct policydb *pdb)
 {
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-			  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_netpeer = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass = ebitmap_get_bit(&pdb->policycaps,
+					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
 	selinux_policycap_alwaysnetwork =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&crm->policydb.policycaps, i));
+			ebitmap_get_bit(&pdb->policycaps, i));
 
-	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2072,6 +2069,8 @@ int security_load_policy(void *data, size_t len)
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
 	struct shared_current_mapping *new_mapping;
+	struct shared_current_mapping *next_rcu;
+
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2089,6 +2088,11 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 	newpolicydb = oldpolicydb + 1;
+	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	if (!ss_initialized) {
 		crm = kzalloc(sizeof(struct shared_current_mapping),
@@ -2097,7 +2101,6 @@ int security_load_policy(void *data, size_t len)
 			rc = -ENOMEM;
 			goto out;
 		}
-
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2121,7 +2124,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
 		if (rc) {
 			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
@@ -2130,7 +2133,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		security_load_policycaps();
+		security_load_policycaps(&crm->policydb);
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2143,7 +2146,7 @@ int security_load_policy(void *data, size_t len)
 	}
 
 #if 0
-	sidtab_hash_eval(&sidtab, "sids");
+	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
 
 	rc = policydb_read(newpolicydb, fp);
@@ -2175,9 +2178,9 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Clone the SID table. */
-	sidtab_shutdown(&sidtab);
+	sidtab_shutdown(&crm->sidtab);
 
-	rc = sidtab_map(&sidtab, clone_sid, &newsidtab);
+	rc = sidtab_map(&crm->sidtab, clone_sid, &newsidtab);
 	if (rc)
 		goto err;
 
@@ -2197,19 +2200,21 @@ int security_load_policy(void *data, size_t len)
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
-	sidtab_set(&oldsidtab, &sidtab);
+	sidtab_set(&oldsidtab, &crm->sidtab);
 
 	/* Install the new policydb and SID table. */
+	/* next */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
-
-	sidtab_set(&sidtab, &newsidtab);
-	security_load_policycaps();
+	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
+	sidtab_set(&next_rcu->sidtab, &newsidtab);
+	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
-	crm->current_mapping = map;
-	crm->current_mapping_size = map_size;
+	next_rcu->current_mapping = map;
+	next_rcu->current_mapping_size = map_size;
+
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
+	crm = next_rcu;
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2270,7 +2275,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2311,7 +2316,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2352,7 +2357,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2388,12 +2393,12 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	if (c) {
 		if (!c->sid[0] || !c->sid[1]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						  &c->context[0],
 						  &c->sid[0]);
 			if (rc)
 				goto out;
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[1],
 						   &c->sid[1]);
 			if (rc)
@@ -2478,7 +2483,7 @@ int security_node_sid(u16 domain,
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2535,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	context_init(&usercon);
 
 	rc = -EINVAL;
-	fromcon = sidtab_search(&sidtab, fromsid);
+	fromcon = sidtab_search(&crm->sidtab, fromsid);
 	if (!fromcon)
 		goto out_unlock;
 
@@ -2561,7 +2566,8 @@ int security_get_user_sids(u32 fromsid,
 						 user, &usercon))
 				continue;
 
-			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+			rc = sidtab_context_to_sid(&crm->sidtab, &usercon,
+						   &sid);
 			if (rc)
 				goto out_unlock;
 			if (mynel < maxnel) {
@@ -2663,7 +2669,8 @@ static inline int __security_genfs_sid(const char *fstype,
 		goto out;
 
 	if (!c->sid[0]) {
-		rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+		rc = sidtab_context_to_sid(&crm->sidtab, &c->context[0],
+					   &c->sid[0]);
 		if (rc)
 			goto out;
 	}
@@ -2720,7 +2727,8 @@ int security_fs_use(struct super_block *sb)
 	if (c) {
 		sbsec->behavior = c->v.behavior;
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			rc = sidtab_context_to_sid(&crm->sidtab,
+						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -2911,7 +2919,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	context1 = sidtab_search(&sidtab, sid);
+	context1 = sidtab_search(&crm->sidtab, sid);
 	if (!context1) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -2919,7 +2927,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	}
 
 	rc = -EINVAL;
-	context2 = sidtab_search(&sidtab, mls_sid);
+	context2 = sidtab_search(&crm->sidtab, mls_sid);
 	if (!context2) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, mls_sid);
@@ -2948,7 +2956,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		}
 	}
 
-	rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcon);
@@ -3010,14 +3018,14 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
 	if (!nlbl_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, nlbl_sid);
 		goto out;
 	}
 	rc = -EINVAL;
-	xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+	xfrm_ctx = sidtab_search(&crm->sidtab, xfrm_sid);
 	if (!xfrm_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, xfrm_sid);
@@ -3326,7 +3334,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		goto out;
 	}
 
-	ctxt = sidtab_search(&sidtab, sid);
+	ctxt = sidtab_search(&crm->sidtab, sid);
 	if (unlikely(!ctxt)) {
 		WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
 			  sid);
@@ -3504,7 +3512,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		*sid = secattr->attr.secid;
 	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
 		rc = -EIDRM;
-		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
+		ctx = sidtab_search(&crm->sidtab, SECINITSID_NETMSG);
 		if (ctx == NULL)
 			goto out;
 
@@ -3523,7 +3531,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
-		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
+		rc = sidtab_context_to_sid(&crm->sidtab, &ctx_new, sid);
 		if (rc)
 			goto out_free;
 
@@ -3563,7 +3571,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOENT;
-	ctx = sidtab_search(&sidtab, sid);
+	ctx = sidtab_search(&crm->sidtab, sid);
 	if (ctx == NULL)
 		goto out;
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 3/5] selinux: Move sidtab to pointer structure
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

To be able to use rcu locks we need access the sidtab trough
a pointer. This moves the sittab to a dynamic allocated struture.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 140 ++++++++++++++++++++++-------------------
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 21400bd..2a8486c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -89,7 +89,6 @@ int selinux_policycap_nnp_nosuid_transition;
 
 static DEFINE_RWLOCK(policy_rwlock);
 
-static struct sidtab sidtab;
 int ss_initialized;
 
 /*
@@ -120,6 +119,7 @@ struct shared_current_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
+	struct sidtab sidtab;
 };
 
 static struct shared_current_mapping *crm;
@@ -804,7 +804,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 	tclass_datum = crm->policydb.class_val_to_struct[tclass - 1];
 
-	ocontext = sidtab_search(&sidtab, oldsid);
+	ocontext = sidtab_search(&crm->sidtab, oldsid);
 	if (!ocontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, oldsid);
@@ -812,7 +812,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	ncontext = sidtab_search(&sidtab, newsid);
+	ncontext = sidtab_search(&crm->sidtab, newsid);
 	if (!ncontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, newsid);
@@ -820,7 +820,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tasksid);
+	tcontext = sidtab_search(&crm->sidtab, tasksid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, tasksid);
@@ -882,7 +882,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	old_context = sidtab_search(&sidtab, old_sid);
+	old_context = sidtab_search(&crm->sidtab, old_sid);
 	if (!old_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, old_sid);
@@ -890,7 +890,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	}
 
 	rc = -EINVAL;
-	new_context = sidtab_search(&sidtab, new_sid);
+	new_context = sidtab_search(&crm->sidtab, new_sid);
 	if (!new_context) {
 		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
 		       __func__, new_sid);
@@ -1033,14 +1033,14 @@ void security_compute_xperms_decision(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		goto out;
 	}
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1116,7 +1116,7 @@ void security_compute_av(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1127,7 +1127,7 @@ void security_compute_av(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1162,7 +1162,7 @@ void security_compute_av_user(u32 ssid,
 	if (!ss_initialized)
 		goto allow;
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
@@ -1173,7 +1173,7 @@ void security_compute_av_user(u32 ssid,
 	if (ebitmap_get_bit(&crm->policydb.permissive_map, scontext->type))
 		avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1295,9 +1295,9 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	read_lock(&policy_rwlock);
 	if (force)
-		context = sidtab_search_force(&sidtab, sid);
+		context = sidtab_search_force(&crm->sidtab, sid);
 	else
-		context = sidtab_search(&sidtab, sid);
+		context = sidtab_search(&crm->sidtab, sid);
 	if (!context) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -1459,7 +1459,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	}
 
 	read_lock(&policy_rwlock);
-	rc = string_to_context_struct(&crm->policydb, &sidtab, scontext2,
+	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
 		context.str = str;
@@ -1467,7 +1467,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 		str = NULL;
 	} else if (rc)
 		goto out_unlock;
-	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
 	read_unlock(&policy_rwlock);
@@ -1630,14 +1630,14 @@ static int security_compute_sid(u32 ssid,
 		sock = security_is_socket_class(map_class(tclass));
 	}
 
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(&crm->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, ssid);
 		rc = -EINVAL;
 		goto out_unlock;
 	}
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(&crm->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, tsid);
@@ -1757,7 +1757,7 @@ static int security_compute_sid(u32 ssid,
 			goto out_unlock;
 	}
 	/* Obtain the sid for the context. */
-	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcontext);
@@ -2017,36 +2017,33 @@ static int convert_context(u32 key,
 	goto out;
 }
 
-static void security_load_policycaps(void)
+static void security_load_policycaps(struct policydb *pdb)
 {
 	unsigned int i;
 	struct ebitmap_node *node;
 
-	selinux_policycap_netpeer =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-			  POLICYDB_CAPABILITY_NETPEER);
-	selinux_policycap_openperm =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_OPENPERM);
-	selinux_policycap_extsockclass =
-		ebitmap_get_bit(&crm->policydb.policycaps,
-				POLICYDB_CAPABILITY_EXTSOCKCLASS);
+	selinux_policycap_netpeer = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_NETPEER);
+	selinux_policycap_openperm = ebitmap_get_bit(&pdb->policycaps,
+						  POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_extsockclass = ebitmap_get_bit(&pdb->policycaps,
+					  POLICYDB_CAPABILITY_EXTSOCKCLASS);
 	selinux_policycap_alwaysnetwork =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_ALWAYSNETWORK);
 	selinux_policycap_cgroupseclabel =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_CGROUPSECLABEL);
 	selinux_policycap_nnp_nosuid_transition =
-		ebitmap_get_bit(&crm->policydb.policycaps,
+		ebitmap_get_bit(&pdb->policycaps,
 				POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 
 	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
 		pr_info("SELinux:  policy capability %s=%d\n",
 			selinux_policycap_names[i],
-			ebitmap_get_bit(&crm->policydb.policycaps, i));
+			ebitmap_get_bit(&pdb->policycaps, i));
 
-	ebitmap_for_each_positive_bit(&crm->policydb.policycaps, node, i) {
+	ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
 		if (i >= ARRAY_SIZE(selinux_policycap_names))
 			pr_info("SELinux:  unknown policy capability %u\n",
 				i);
@@ -2072,6 +2069,8 @@ int security_load_policy(void *data, size_t len)
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
 	struct shared_current_mapping *new_mapping;
+	struct shared_current_mapping *next_rcu;
+
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
@@ -2089,6 +2088,11 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 	newpolicydb = oldpolicydb + 1;
+	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	if (!ss_initialized) {
 		crm = kzalloc(sizeof(struct shared_current_mapping),
@@ -2097,7 +2101,6 @@ int security_load_policy(void *data, size_t len)
 			rc = -ENOMEM;
 			goto out;
 		}
-
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
@@ -2121,7 +2124,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &sidtab);
+		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
 		if (rc) {
 			policydb_destroy(&crm->policydb);
 			avtab_cache_destroy();
@@ -2130,7 +2133,7 @@ int security_load_policy(void *data, size_t len)
 			goto out;
 		}
 
-		security_load_policycaps();
+		security_load_policycaps(&crm->policydb);
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2143,7 +2146,7 @@ int security_load_policy(void *data, size_t len)
 	}
 
 #if 0
-	sidtab_hash_eval(&sidtab, "sids");
+	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
 
 	rc = policydb_read(newpolicydb, fp);
@@ -2175,9 +2178,9 @@ int security_load_policy(void *data, size_t len)
 	}
 
 	/* Clone the SID table. */
-	sidtab_shutdown(&sidtab);
+	sidtab_shutdown(&crm->sidtab);
 
-	rc = sidtab_map(&sidtab, clone_sid, &newsidtab);
+	rc = sidtab_map(&crm->sidtab, clone_sid, &newsidtab);
 	if (rc)
 		goto err;
 
@@ -2197,19 +2200,21 @@ int security_load_policy(void *data, size_t len)
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(oldpolicydb, &crm->policydb, sizeof(struct policydb));
-	sidtab_set(&oldsidtab, &sidtab);
+	sidtab_set(&oldsidtab, &crm->sidtab);
 
 	/* Install the new policydb and SID table. */
+	/* next */
 	write_lock_irq(&policy_rwlock);
-	memcpy(&crm->policydb, newpolicydb, sizeof(struct policydb));
-
-	sidtab_set(&sidtab, &newsidtab);
-	security_load_policycaps();
+	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
+	sidtab_set(&next_rcu->sidtab, &newsidtab);
+	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
-	crm->current_mapping = map;
-	crm->current_mapping_size = map_size;
+	next_rcu->current_mapping = map;
+	next_rcu->current_mapping_size = map_size;
+
 	seqno = ++latest_granting;
 	write_unlock_irq(&policy_rwlock);
+	crm = next_rcu;
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2270,7 +2275,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2311,7 +2316,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2352,7 +2357,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2388,12 +2393,12 @@ int security_netif_sid(char *name, u32 *if_sid)
 
 	if (c) {
 		if (!c->sid[0] || !c->sid[1]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						  &c->context[0],
 						  &c->sid[0]);
 			if (rc)
 				goto out;
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[1],
 						   &c->sid[1]);
 			if (rc)
@@ -2478,7 +2483,7 @@ int security_node_sid(u16 domain,
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(&crm->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
@@ -2535,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	context_init(&usercon);
 
 	rc = -EINVAL;
-	fromcon = sidtab_search(&sidtab, fromsid);
+	fromcon = sidtab_search(&crm->sidtab, fromsid);
 	if (!fromcon)
 		goto out_unlock;
 
@@ -2561,7 +2566,8 @@ int security_get_user_sids(u32 fromsid,
 						 user, &usercon))
 				continue;
 
-			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+			rc = sidtab_context_to_sid(&crm->sidtab, &usercon,
+						   &sid);
 			if (rc)
 				goto out_unlock;
 			if (mynel < maxnel) {
@@ -2663,7 +2669,8 @@ static inline int __security_genfs_sid(const char *fstype,
 		goto out;
 
 	if (!c->sid[0]) {
-		rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+		rc = sidtab_context_to_sid(&crm->sidtab, &c->context[0],
+					   &c->sid[0]);
 		if (rc)
 			goto out;
 	}
@@ -2720,7 +2727,8 @@ int security_fs_use(struct super_block *sb)
 	if (c) {
 		sbsec->behavior = c->v.behavior;
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+			rc = sidtab_context_to_sid(&crm->sidtab,
+						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -2911,7 +2919,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	context1 = sidtab_search(&sidtab, sid);
+	context1 = sidtab_search(&crm->sidtab, sid);
 	if (!context1) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, sid);
@@ -2919,7 +2927,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 	}
 
 	rc = -EINVAL;
-	context2 = sidtab_search(&sidtab, mls_sid);
+	context2 = sidtab_search(&crm->sidtab, mls_sid);
 	if (!context2) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 			__func__, mls_sid);
@@ -2948,7 +2956,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 		}
 	}
 
-	rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
+	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
 	read_unlock(&policy_rwlock);
 	context_destroy(&newcon);
@@ -3010,14 +3018,14 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	read_lock(&policy_rwlock);
 
 	rc = -EINVAL;
-	nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
 	if (!nlbl_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, nlbl_sid);
 		goto out;
 	}
 	rc = -EINVAL;
-	xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+	xfrm_ctx = sidtab_search(&crm->sidtab, xfrm_sid);
 	if (!xfrm_ctx) {
 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
 		       __func__, xfrm_sid);
@@ -3326,7 +3334,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		goto out;
 	}
 
-	ctxt = sidtab_search(&sidtab, sid);
+	ctxt = sidtab_search(&crm->sidtab, sid);
 	if (unlikely(!ctxt)) {
 		WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
 			  sid);
@@ -3504,7 +3512,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		*sid = secattr->attr.secid;
 	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
 		rc = -EIDRM;
-		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
+		ctx = sidtab_search(&crm->sidtab, SECINITSID_NETMSG);
 		if (ctx == NULL)
 			goto out;
 
@@ -3523,7 +3531,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		if (!mls_context_isvalid(&crm->policydb, &ctx_new))
 			goto out_free;
 
-		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
+		rc = sidtab_context_to_sid(&crm->sidtab, &ctx_new, sid);
 		if (rc)
 			goto out_free;
 
@@ -3563,7 +3571,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	read_lock(&policy_rwlock);
 
 	rc = -ENOENT;
-	ctx = sidtab_search(&sidtab, sid);
+	ctx = sidtab_search(&crm->sidtab, sid);
 	if (ctx == NULL)
 		goto out;
 
-- 
2.7.4

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  2018-01-26 14:32 ` peter.enderborg at sony.com
  (?)
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  -1 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

This i preparation for switching to RCU locks. To be able to use
RCU we need atomic switched pointer. This adds the dynamic
memory copying to be a single pointer. It copy all the
data structures in to new ones. This is an overhead
for writing rules but the benifit is RCU.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 139 +++++++++++++++++++++++------------------
 1 file changed, 78 insertions(+), 61 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 2a8486c..81c5717 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2064,76 +2064,67 @@ static int security_preserve_bools(struct policydb *p);
  */
 int security_load_policy(void *data, size_t len)
 {
-	struct policydb *oldpolicydb, *newpolicydb;
+	struct policydb *oldpolicydb;
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *new_mapping;
 	struct shared_current_mapping *next_rcu;
-
+	struct shared_current_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
-	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
-	if (!oldpolicydb) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-	if (!new_mapping) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	newpolicydb = oldpolicydb + 1;
-	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	if (!next_rcu) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
 	if (!ss_initialized) {
-		crm = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-		if (!crm) {
+		struct shared_current_mapping *first_mapping;
+
+		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+					GFP_KERNEL);
+		if (!first_mapping) {
 			rc = -ENOMEM;
 			goto out;
 		}
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&crm->policydb, fp);
+		rc = policydb_read(&first_mapping->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		crm->policydb.len = len;
-		rc = selinux_set_mapping(&crm->policydb, secclass_map,
-					 &crm->current_mapping,
-					 &crm->current_mapping_size);
+		first_mapping->policydb.len = len;
+		rc = selinux_set_mapping(&first_mapping->policydb, secclass_map,
+					 &first_mapping->current_mapping,
+					 &first_mapping->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
+		rc = policydb_load_isids(&first_mapping->policydb,
+					 &first_mapping->sidtab);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		security_load_policycaps(&crm->policydb);
+		security_load_policycaps(&first_mapping->policydb);
+		crm = first_mapping;
+
+		smp_mb(); /* make sure that crm exist before we */
+			  /* switch ss_initialized */
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2148,30 +2139,44 @@ int security_load_policy(void *data, size_t len)
 #if 0
 	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
+	oldpolicydb = kzalloc(sizeof(*oldpolicydb), GFP_KERNEL);
+	if (!oldpolicydb) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		kfree(oldpolicydb);
+		rc = -ENOMEM;
+		goto out;
+	}
 
-	rc = policydb_read(newpolicydb, fp);
+	rc = policydb_read(&next_rcu->policydb, fp);
 	if (rc)
 		goto out;
 
-	newpolicydb->len = len;
+	next_rcu->policydb.len = len;
+	read_lock(&policy_rwlock);
 	/* If switching between different policy types, log MLS status */
-	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
-	rc = policydb_load_isids(newpolicydb, &newsidtab);
+	rc = policydb_load_isids(&next_rcu->policydb, &newsidtab);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
-		policydb_destroy(newpolicydb);
+		policydb_destroy(&next_rcu->policydb);
 		goto out;
 	}
 
-	rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
+	rc = selinux_set_mapping(&next_rcu->policydb, secclass_map,
+				 &map, &map_size);
 	if (rc)
 		goto err;
 
-	rc = security_preserve_bools(newpolicydb);
+	rc = security_preserve_bools(&next_rcu->policydb);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
 		goto err;
@@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t len)
 	 * in the new SID table.
 	 */
 	args.oldp = &crm->policydb;
-	args.newp = newpolicydb;
+	args.newp = &next_rcu->policydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to convert the internal"
@@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t len)
 
 	/* Install the new policydb and SID table. */
 	/* next */
+	security_load_policycaps(&next_rcu->policydb);
+	read_unlock(&policy_rwlock);
 	write_lock_irq(&policy_rwlock);
-	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
@@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t len)
 	next_rcu->current_mapping_size = map_size;
 
 	seqno = ++latest_granting;
-	write_unlock_irq(&policy_rwlock);
+	old_rcu = crm;
 	crm = next_rcu;
+	write_unlock_irq(&policy_rwlock);
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t len)
 	selinux_status_update_policyload(seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
+	kfree(oldpolicydb);
+	kfree(old_rcu);
 
 	rc = 0;
 	goto out;
-
 err:
 	kfree(map);
 	sidtab_destroy(&newsidtab);
-	policydb_destroy(newpolicydb);
-
+	policydb_destroy(&next_rcu->policydb);
 out:
-	kfree(oldpolicydb);
 	return rc;
 }
 
@@ -2795,54 +2801,65 @@ int security_get_bools(int *len, char ***names, int **values)
 	goto out;
 }
 
-
 int security_set_bools(int len, int *values)
 {
+	struct shared_current_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	write_lock_irq(&policy_rwlock);
-
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	read_lock(&policy_rwlock);
+	old_rcu = crm;
+	memcpy(&next_rcu->policydb, &old_rcu->policydb,
+	       sizeof(struct policydb));
 	rc = -EFAULT;
-	lenp = crm->policydb.p_bools.nprim;
+	lenp = next_rcu->policydb.p_bools.nprim;
+
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
 		if (!!values[i] !=
-		    crm->policydb.bool_val_to_struct[i]->state) {
+		    next_rcu->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&crm->policydb, SYM_BOOLS, i),
+				sym_name(&next_rcu->policydb, SYM_BOOLS, i),
 				!!values[i],
-				crm->policydb.bool_val_to_struct[i]->state,
+				next_rcu->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			crm->policydb.bool_val_to_struct[i]->state = 1;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			crm->policydb.bool_val_to_struct[i]->state = 0;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&crm->policydb, cur);
+	for (cur = next_rcu->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&next_rcu->policydb, cur);
 		if (rc)
 			goto out;
 	}
+	read_unlock(&policy_rwlock);
+	rc = 0;
 
+	write_lock_irq(&policy_rwlock);
 	seqno = ++latest_granting;
-	rc = 0;
-out:
+	crm = next_rcu;
 	write_unlock_irq(&policy_rwlock);
+out:
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
 		selinux_status_update_policyload(seqno);
 		selinux_xfrm_notify_policyload();
+	} else {
+		kfree(next_rcu);
 	}
+	kfree(old_rcu);
+
 	return rc;
 }
 
-- 
2.7.4

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

From: Peter Enderborg <peter.enderborg@sony.com>

This i preparation for switching to RCU locks. To be able to use
RCU we need atomic switched pointer. This adds the dynamic
memory copying to be a single pointer. It copy all the
data structures in to new ones. This is an overhead
for writing rules but the benifit is RCU.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 139 +++++++++++++++++++++++------------------
 1 file changed, 78 insertions(+), 61 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 2a8486c..81c5717 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2064,76 +2064,67 @@ static int security_preserve_bools(struct policydb *p);
  */
 int security_load_policy(void *data, size_t len)
 {
-	struct policydb *oldpolicydb, *newpolicydb;
+	struct policydb *oldpolicydb;
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *new_mapping;
 	struct shared_current_mapping *next_rcu;
-
+	struct shared_current_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
-	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
-	if (!oldpolicydb) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-	if (!new_mapping) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	newpolicydb = oldpolicydb + 1;
-	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	if (!next_rcu) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
 	if (!ss_initialized) {
-		crm = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-		if (!crm) {
+		struct shared_current_mapping *first_mapping;
+
+		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+					GFP_KERNEL);
+		if (!first_mapping) {
 			rc = -ENOMEM;
 			goto out;
 		}
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&crm->policydb, fp);
+		rc = policydb_read(&first_mapping->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		crm->policydb.len = len;
-		rc = selinux_set_mapping(&crm->policydb, secclass_map,
-					 &crm->current_mapping,
-					 &crm->current_mapping_size);
+		first_mapping->policydb.len = len;
+		rc = selinux_set_mapping(&first_mapping->policydb, secclass_map,
+					 &first_mapping->current_mapping,
+					 &first_mapping->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
+		rc = policydb_load_isids(&first_mapping->policydb,
+					 &first_mapping->sidtab);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		security_load_policycaps(&crm->policydb);
+		security_load_policycaps(&first_mapping->policydb);
+		crm = first_mapping;
+
+		smp_mb(); /* make sure that crm exist before we */
+			  /* switch ss_initialized */
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2148,30 +2139,44 @@ int security_load_policy(void *data, size_t len)
 #if 0
 	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
+	oldpolicydb = kzalloc(sizeof(*oldpolicydb), GFP_KERNEL);
+	if (!oldpolicydb) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		kfree(oldpolicydb);
+		rc = -ENOMEM;
+		goto out;
+	}
 
-	rc = policydb_read(newpolicydb, fp);
+	rc = policydb_read(&next_rcu->policydb, fp);
 	if (rc)
 		goto out;
 
-	newpolicydb->len = len;
+	next_rcu->policydb.len = len;
+	read_lock(&policy_rwlock);
 	/* If switching between different policy types, log MLS status */
-	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
-	rc = policydb_load_isids(newpolicydb, &newsidtab);
+	rc = policydb_load_isids(&next_rcu->policydb, &newsidtab);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
-		policydb_destroy(newpolicydb);
+		policydb_destroy(&next_rcu->policydb);
 		goto out;
 	}
 
-	rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
+	rc = selinux_set_mapping(&next_rcu->policydb, secclass_map,
+				 &map, &map_size);
 	if (rc)
 		goto err;
 
-	rc = security_preserve_bools(newpolicydb);
+	rc = security_preserve_bools(&next_rcu->policydb);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
 		goto err;
@@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t len)
 	 * in the new SID table.
 	 */
 	args.oldp = &crm->policydb;
-	args.newp = newpolicydb;
+	args.newp = &next_rcu->policydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to convert the internal"
@@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t len)
 
 	/* Install the new policydb and SID table. */
 	/* next */
+	security_load_policycaps(&next_rcu->policydb);
+	read_unlock(&policy_rwlock);
 	write_lock_irq(&policy_rwlock);
-	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
@@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t len)
 	next_rcu->current_mapping_size = map_size;
 
 	seqno = ++latest_granting;
-	write_unlock_irq(&policy_rwlock);
+	old_rcu = crm;
 	crm = next_rcu;
+	write_unlock_irq(&policy_rwlock);
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t len)
 	selinux_status_update_policyload(seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
+	kfree(oldpolicydb);
+	kfree(old_rcu);
 
 	rc = 0;
 	goto out;
-
 err:
 	kfree(map);
 	sidtab_destroy(&newsidtab);
-	policydb_destroy(newpolicydb);
-
+	policydb_destroy(&next_rcu->policydb);
 out:
-	kfree(oldpolicydb);
 	return rc;
 }
 
@@ -2795,54 +2801,65 @@ int security_get_bools(int *len, char ***names, int **values)
 	goto out;
 }
 
-
 int security_set_bools(int len, int *values)
 {
+	struct shared_current_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	write_lock_irq(&policy_rwlock);
-
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	read_lock(&policy_rwlock);
+	old_rcu = crm;
+	memcpy(&next_rcu->policydb, &old_rcu->policydb,
+	       sizeof(struct policydb));
 	rc = -EFAULT;
-	lenp = crm->policydb.p_bools.nprim;
+	lenp = next_rcu->policydb.p_bools.nprim;
+
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
 		if (!!values[i] !=
-		    crm->policydb.bool_val_to_struct[i]->state) {
+		    next_rcu->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&crm->policydb, SYM_BOOLS, i),
+				sym_name(&next_rcu->policydb, SYM_BOOLS, i),
 				!!values[i],
-				crm->policydb.bool_val_to_struct[i]->state,
+				next_rcu->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			crm->policydb.bool_val_to_struct[i]->state = 1;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			crm->policydb.bool_val_to_struct[i]->state = 0;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&crm->policydb, cur);
+	for (cur = next_rcu->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&next_rcu->policydb, cur);
 		if (rc)
 			goto out;
 	}
+	read_unlock(&policy_rwlock);
+	rc = 0;
 
+	write_lock_irq(&policy_rwlock);
 	seqno = ++latest_granting;
-	rc = 0;
-out:
+	crm = next_rcu;
 	write_unlock_irq(&policy_rwlock);
+out:
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
 		selinux_status_update_policyload(seqno);
 		selinux_xfrm_notify_policyload();
+	} else {
+		kfree(next_rcu);
 	}
+	kfree(old_rcu);
+
 	return rc;
 }
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

This i preparation for switching to RCU locks. To be able to use
RCU we need atomic switched pointer. This adds the dynamic
memory copying to be a single pointer. It copy all the
data structures in to new ones. This is an overhead
for writing rules but the benifit is RCU.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 security/selinux/ss/services.c | 139 +++++++++++++++++++++++------------------
 1 file changed, 78 insertions(+), 61 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 2a8486c..81c5717 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2064,76 +2064,67 @@ static int security_preserve_bools(struct policydb *p);
  */
 int security_load_policy(void *data, size_t len)
 {
-	struct policydb *oldpolicydb, *newpolicydb;
+	struct policydb *oldpolicydb;
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *new_mapping;
 	struct shared_current_mapping *next_rcu;
-
+	struct shared_current_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
-	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
-	if (!oldpolicydb) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-	if (!new_mapping) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	newpolicydb = oldpolicydb + 1;
-	next_rcu = kmalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	if (!next_rcu) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
 	if (!ss_initialized) {
-		crm = kzalloc(sizeof(struct shared_current_mapping),
-			      GFP_KERNEL);
-		if (!crm) {
+		struct shared_current_mapping *first_mapping;
+
+		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+					GFP_KERNEL);
+		if (!first_mapping) {
 			rc = -ENOMEM;
 			goto out;
 		}
 		avtab_cache_init();
 		ebitmap_cache_init();
 		hashtab_cache_init();
-		rc = policydb_read(&crm->policydb, fp);
+		rc = policydb_read(&first_mapping->policydb, fp);
 		if (rc) {
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		crm->policydb.len = len;
-		rc = selinux_set_mapping(&crm->policydb, secclass_map,
-					 &crm->current_mapping,
-					 &crm->current_mapping_size);
+		first_mapping->policydb.len = len;
+		rc = selinux_set_mapping(&first_mapping->policydb, secclass_map,
+					 &first_mapping->current_mapping,
+					 &first_mapping->current_mapping_size);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		rc = policydb_load_isids(&crm->policydb, &crm->sidtab);
+		rc = policydb_load_isids(&first_mapping->policydb,
+					 &first_mapping->sidtab);
 		if (rc) {
-			policydb_destroy(&crm->policydb);
+			policydb_destroy(&first_mapping->policydb);
 			avtab_cache_destroy();
 			ebitmap_cache_destroy();
 			hashtab_cache_destroy();
+			kfree(first_mapping);
 			goto out;
 		}
 
-		security_load_policycaps(&crm->policydb);
+		security_load_policycaps(&first_mapping->policydb);
+		crm = first_mapping;
+
+		smp_mb(); /* make sure that crm exist before we */
+			  /* switch ss_initialized */
 		ss_initialized = 1;
 		seqno = ++latest_granting;
 		selinux_complete_init();
@@ -2148,30 +2139,44 @@ int security_load_policy(void *data, size_t len)
 #if 0
 	sidtab_hash_eval(&crm->sidtab, "sids");
 #endif
+	oldpolicydb = kzalloc(sizeof(*oldpolicydb), GFP_KERNEL);
+	if (!oldpolicydb) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	if (!next_rcu) {
+		kfree(oldpolicydb);
+		rc = -ENOMEM;
+		goto out;
+	}
 
-	rc = policydb_read(newpolicydb, fp);
+	rc = policydb_read(&next_rcu->policydb, fp);
 	if (rc)
 		goto out;
 
-	newpolicydb->len = len;
+	next_rcu->policydb.len = len;
+	read_lock(&policy_rwlock);
 	/* If switching between different policy types, log MLS status */
-	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
+	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-	else if (!crm->policydb.mls_enabled && newpolicydb->mls_enabled)
+	else if (!crm->policydb.mls_enabled && next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
-	rc = policydb_load_isids(newpolicydb, &newsidtab);
+	rc = policydb_load_isids(&next_rcu->policydb, &newsidtab);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
-		policydb_destroy(newpolicydb);
+		policydb_destroy(&next_rcu->policydb);
 		goto out;
 	}
 
-	rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
+	rc = selinux_set_mapping(&next_rcu->policydb, secclass_map,
+				 &map, &map_size);
 	if (rc)
 		goto err;
 
-	rc = security_preserve_bools(newpolicydb);
+	rc = security_preserve_bools(&next_rcu->policydb);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
 		goto err;
@@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t len)
 	 * in the new SID table.
 	 */
 	args.oldp = &crm->policydb;
-	args.newp = newpolicydb;
+	args.newp = &next_rcu->policydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to convert the internal"
@@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t len)
 
 	/* Install the new policydb and SID table. */
 	/* next */
+	security_load_policycaps(&next_rcu->policydb);
+	read_unlock(&policy_rwlock);
 	write_lock_irq(&policy_rwlock);
-	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct policydb));
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
@@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t len)
 	next_rcu->current_mapping_size = map_size;
 
 	seqno = ++latest_granting;
-	write_unlock_irq(&policy_rwlock);
+	old_rcu = crm;
 	crm = next_rcu;
+	write_unlock_irq(&policy_rwlock);
 
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
@@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t len)
 	selinux_status_update_policyload(seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
+	kfree(oldpolicydb);
+	kfree(old_rcu);
 
 	rc = 0;
 	goto out;
-
 err:
 	kfree(map);
 	sidtab_destroy(&newsidtab);
-	policydb_destroy(newpolicydb);
-
+	policydb_destroy(&next_rcu->policydb);
 out:
-	kfree(oldpolicydb);
 	return rc;
 }
 
@@ -2795,54 +2801,65 @@ int security_get_bools(int *len, char ***names, int **values)
 	goto out;
 }
 
-
 int security_set_bools(int len, int *values)
 {
+	struct shared_current_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	write_lock_irq(&policy_rwlock);
-
+	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	read_lock(&policy_rwlock);
+	old_rcu = crm;
+	memcpy(&next_rcu->policydb, &old_rcu->policydb,
+	       sizeof(struct policydb));
 	rc = -EFAULT;
-	lenp = crm->policydb.p_bools.nprim;
+	lenp = next_rcu->policydb.p_bools.nprim;
+
 	if (len != lenp)
 		goto out;
 
 	for (i = 0; i < len; i++) {
 		if (!!values[i] !=
-		    crm->policydb.bool_val_to_struct[i]->state) {
+		    next_rcu->policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
 				"bool=%s val=%d old_val=%d auid=%u ses=%u",
-				sym_name(&crm->policydb, SYM_BOOLS, i),
+				sym_name(&next_rcu->policydb, SYM_BOOLS, i),
 				!!values[i],
-				crm->policydb.bool_val_to_struct[i]->state,
+				next_rcu->policydb.bool_val_to_struct[i]->state,
 				from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				audit_get_sessionid(current));
 		}
 		if (values[i])
-			crm->policydb.bool_val_to_struct[i]->state = 1;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 1;
 		else
-			crm->policydb.bool_val_to_struct[i]->state = 0;
+			next_rcu->policydb.bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(&crm->policydb, cur);
+	for (cur = next_rcu->policydb.cond_list; cur; cur = cur->next) {
+		rc = evaluate_cond_node(&next_rcu->policydb, cur);
 		if (rc)
 			goto out;
 	}
+	read_unlock(&policy_rwlock);
+	rc = 0;
 
+	write_lock_irq(&policy_rwlock);
 	seqno = ++latest_granting;
-	rc = 0;
-out:
+	crm = next_rcu;
 	write_unlock_irq(&policy_rwlock);
+out:
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
 		selinux_status_update_policyload(seqno);
 		selinux_xfrm_notify_policyload();
+	} else {
+		kfree(next_rcu);
 	}
+	kfree(old_rcu);
+
 	return rc;
 }
 
-- 
2.7.4

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

* [PATCH v2 5/5] selinux: Switch locking to RCU.
  2018-01-26 14:32 ` peter.enderborg at sony.com
  (?)
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  -1 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

This patch switch to using RCU locks instead of rwlocks. This has
the big advantage that it does not has preempt disable.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
Reported-by: Björn Davidsson <bjorn.davidsson@sony.com>
---
 security/selinux/ss/services.c | 162 +++++++++++++++++++++--------------------
 1 file changed, 82 insertions(+), 80 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 81c5717..f142ef8 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -87,7 +87,7 @@ int selinux_policycap_alwaysnetwork;
 int selinux_policycap_cgroupseclabel;
 int selinux_policycap_nnp_nosuid_transition;
 
-static DEFINE_RWLOCK(policy_rwlock);
+static DEFINE_SPINLOCK(policy_w_lock);
 
 int ss_initialized;
 
@@ -115,14 +115,14 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-struct shared_current_mapping {
+struct shared_rcu_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
 	struct sidtab sidtab;
 };
 
-static struct shared_current_mapping *crm;
+static struct shared_rcu_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -791,7 +791,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (!user)
 		tclass = unmap_class(orig_tclass);
@@ -845,7 +845,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -879,7 +879,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	int index;
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	old_context = sidtab_search(&crm->sidtab, old_sid);
@@ -941,7 +941,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 		kfree(old_name);
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -1029,7 +1029,7 @@ void security_compute_xperms_decision(u32 ssid,
 	memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
 	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (!ss_initialized)
 		goto allow;
 
@@ -1083,7 +1083,7 @@ void security_compute_xperms_decision(u32 ssid,
 		}
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
@@ -1110,7 +1110,7 @@ void security_compute_av(u32 ssid,
 	u16 tclass;
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	xperms->len = 0;
 	if (!ss_initialized)
@@ -1143,7 +1143,7 @@ void security_compute_av(u32 ssid,
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
 	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1157,7 +1157,7 @@ void security_compute_av_user(u32 ssid,
 {
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	if (!ss_initialized)
 		goto allow;
@@ -1188,7 +1188,7 @@ void security_compute_av_user(u32 ssid,
 
 	context_struct_compute_av(scontext, tcontext, tclass, avd, NULL);
  out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1293,7 +1293,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 		rc = -EINVAL;
 		goto out;
 	}
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (force)
 		context = sidtab_search_force(&crm->sidtab, sid);
 	else
@@ -1306,7 +1306,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	rc = context_struct_to_string(context, scontext, scontext_len);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	return rc;
 
@@ -1458,7 +1458,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 			goto out;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
@@ -1470,7 +1470,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	kfree(scontext2);
 	kfree(str);
@@ -1620,7 +1620,7 @@ static int security_compute_sid(u32 ssid,
 
 	context_init(&newcontext);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (kern) {
 		tclass = unmap_class(orig_tclass);
@@ -1759,7 +1759,7 @@ static int security_compute_sid(u32 ssid,
 	/* Obtain the sid for the context. */
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcontext);
 out:
 	return rc;
@@ -2051,7 +2051,6 @@ static void security_load_policycaps(struct policydb *pdb)
 }
 
 static int security_preserve_bools(struct policydb *p);
-
 /**
  * security_load_policy - Load a security policy configuration.
  * @data: binary policy data
@@ -2068,17 +2067,17 @@ int security_load_policy(void *data, size_t len)
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *next_rcu;
-	struct shared_current_mapping *old_rcu;
+	struct shared_rcu_mapping *next_rcu;
+	struct shared_rcu_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
 	if (!ss_initialized) {
-		struct shared_current_mapping *first_mapping;
+		struct shared_rcu_mapping *first_mapping;
 
-		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+		first_mapping = kzalloc(sizeof(struct shared_rcu_mapping),
 					GFP_KERNEL);
 		if (!first_mapping) {
 			rc = -ENOMEM;
@@ -2145,7 +2144,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
 	if (!next_rcu) {
 		kfree(oldpolicydb);
 		rc = -ENOMEM;
@@ -2157,7 +2156,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 
 	next_rcu->policydb.len = len;
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	/* If switching between different policy types, log MLS status */
 	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
@@ -2210,19 +2209,19 @@ int security_load_policy(void *data, size_t len)
 	/* Install the new policydb and SID table. */
 	/* next */
 	security_load_policycaps(&next_rcu->policydb);
-	read_unlock(&policy_rwlock);
-	write_lock_irq(&policy_rwlock);
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
+	rcu_read_unlock();
 	next_rcu->current_mapping = map;
 	next_rcu->current_mapping_size = map_size;
 
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	old_rcu = crm;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
-
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
 	sidtab_destroy(&oldsidtab);
@@ -2250,9 +2249,9 @@ size_t security_policydb_len(void)
 {
 	size_t len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	len = crm->policydb.len;
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return len;
 }
@@ -2268,7 +2267,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
@@ -2293,7 +2292,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2308,7 +2307,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
@@ -2333,7 +2332,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2348,7 +2347,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
@@ -2374,7 +2373,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2388,7 +2387,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 	int rc = 0;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
@@ -2415,7 +2414,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 		*if_sid = SECINITSID_NETIF;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2447,7 +2446,7 @@ int security_node_sid(u16 domain,
 	int rc;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	switch (domain) {
 	case AF_INET: {
@@ -2502,7 +2501,7 @@ int security_node_sid(u16 domain,
 
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2541,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	if (!ss_initialized)
 		goto out;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	context_init(&usercon);
 
@@ -2593,7 +2592,7 @@ int security_get_user_sids(u32 fromsid,
 	}
 	rc = 0;
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	if (rc || !mynel) {
 		kfree(mysids);
 		goto out;
@@ -2704,9 +2703,9 @@ int security_genfs_sid(const char *fstype,
 {
 	int retval;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -2721,7 +2720,7 @@ int security_fs_use(struct super_block *sb)
 	struct superblock_security_struct *sbsec = sb->s_security;
 	const char *fstype = sb->s_type->name;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
@@ -2752,7 +2751,7 @@ int security_fs_use(struct super_block *sb)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2760,7 +2759,7 @@ int security_get_bools(int *len, char ***names, int **values)
 {
 	int i, rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	*names = NULL;
 	*values = NULL;
 
@@ -2790,7 +2789,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 err:
 	if (*names) {
@@ -2803,13 +2802,14 @@ int security_get_bools(int *len, char ***names, int **values)
 
 int security_set_bools(int len, int *values)
 {
-	struct shared_current_mapping *next_rcu, *old_rcu;
+
+	struct shared_rcu_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	read_lock(&policy_rwlock);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
+	rcu_read_lock();
 	old_rcu = crm;
 	memcpy(&next_rcu->policydb, &old_rcu->policydb,
 	       sizeof(struct policydb));
@@ -2842,13 +2842,15 @@ int security_set_bools(int len, int *values)
 		if (rc)
 			goto out;
 	}
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
+
 	rc = 0;
 
-	write_lock_irq(&policy_rwlock);
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 out:
 	if (!rc) {
 		avc_ss_reset(seqno);
@@ -2868,7 +2870,7 @@ int security_get_bool_value(int index)
 	int rc;
 	int len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EFAULT;
 	len = crm->policydb.p_bools.nprim;
@@ -2877,7 +2879,7 @@ int security_get_bool_value(int index)
 
 	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2933,7 +2935,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	context_init(&newcon);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	context1 = sidtab_search(&crm->sidtab, sid);
@@ -2975,7 +2977,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcon);
 out:
 	return rc;
@@ -3032,7 +3034,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	if (!crm->policydb.mls_enabled)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
@@ -3059,7 +3061,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	 * expressive */
 	*peer_sid = xfrm_sid;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3080,7 +3082,7 @@ int security_get_classes(char ***classes, int *nclasses)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOMEM;
 	*nclasses = crm->policydb.p_classes.nprim;
@@ -3098,7 +3100,7 @@ int security_get_classes(char ***classes, int *nclasses)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3120,7 +3122,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	int rc, i;
 	struct class_datum *match;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	match = hashtab_search(crm->policydb.p_classes.table, class);
@@ -3149,11 +3151,11 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 		goto err;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 
 err:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	for (i = 0; i < *nperms; i++)
 		kfree((*perms)[i]);
 	kfree(*perms);
@@ -3184,9 +3186,9 @@ int security_policycap_supported(unsigned int req_cap)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -3250,7 +3252,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
 	context_init(&tmprule->au_ctxt);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	tmprule->au_seqno = latest_granting;
 
@@ -3294,7 +3296,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc) {
 		selinux_audit_rule_free(tmprule);
@@ -3344,7 +3346,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		return -ENOENT;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (rule->au_seqno < latest_granting) {
 		match = -ESTALE;
@@ -3435,7 +3437,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return match;
 }
 
@@ -3521,7 +3523,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		return 0;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (secattr->flags & NETLBL_SECATTR_CACHE)
 		*sid = *(u32 *)secattr->cache->data;
@@ -3558,12 +3560,12 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 	} else
 		*sid = SECSID_NULL;
 
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return 0;
 out_free:
 	ebitmap_destroy(&ctx_new.range.level[0].cat);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3585,7 +3587,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOENT;
 	ctx = sidtab_search(&crm->sidtab, sid);
@@ -3604,7 +3606,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
 	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 #endif /* CONFIG_NETLABEL */
@@ -3632,9 +3634,9 @@ int security_read_policy(void **data, size_t *len)
 	fp.data = *data;
 	fp.len = *len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = policydb_write(&crm->policydb, &fp);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc)
 		return rc;
-- 
2.7.4

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

* [PATCH v2 5/5] selinux: Switch locking to RCU.
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg at sony.com @ 2018-01-26 14:32 UTC (permalink / raw)
  To: linux-security-module

From: Peter Enderborg <peter.enderborg@sony.com>

This patch switch to using RCU locks instead of rwlocks. This has
the big advantage that it does not has preempt disable.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
Reported-by: Bj?rn Davidsson <bjorn.davidsson@sony.com>
---
 security/selinux/ss/services.c | 162 +++++++++++++++++++++--------------------
 1 file changed, 82 insertions(+), 80 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 81c5717..f142ef8 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -87,7 +87,7 @@ int selinux_policycap_alwaysnetwork;
 int selinux_policycap_cgroupseclabel;
 int selinux_policycap_nnp_nosuid_transition;
 
-static DEFINE_RWLOCK(policy_rwlock);
+static DEFINE_SPINLOCK(policy_w_lock);
 
 int ss_initialized;
 
@@ -115,14 +115,14 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-struct shared_current_mapping {
+struct shared_rcu_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
 	struct sidtab sidtab;
 };
 
-static struct shared_current_mapping *crm;
+static struct shared_rcu_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -791,7 +791,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (!user)
 		tclass = unmap_class(orig_tclass);
@@ -845,7 +845,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -879,7 +879,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	int index;
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	old_context = sidtab_search(&crm->sidtab, old_sid);
@@ -941,7 +941,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 		kfree(old_name);
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -1029,7 +1029,7 @@ void security_compute_xperms_decision(u32 ssid,
 	memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
 	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (!ss_initialized)
 		goto allow;
 
@@ -1083,7 +1083,7 @@ void security_compute_xperms_decision(u32 ssid,
 		}
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
@@ -1110,7 +1110,7 @@ void security_compute_av(u32 ssid,
 	u16 tclass;
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	xperms->len = 0;
 	if (!ss_initialized)
@@ -1143,7 +1143,7 @@ void security_compute_av(u32 ssid,
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
 	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1157,7 +1157,7 @@ void security_compute_av_user(u32 ssid,
 {
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	if (!ss_initialized)
 		goto allow;
@@ -1188,7 +1188,7 @@ void security_compute_av_user(u32 ssid,
 
 	context_struct_compute_av(scontext, tcontext, tclass, avd, NULL);
  out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1293,7 +1293,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 		rc = -EINVAL;
 		goto out;
 	}
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (force)
 		context = sidtab_search_force(&crm->sidtab, sid);
 	else
@@ -1306,7 +1306,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	rc = context_struct_to_string(context, scontext, scontext_len);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	return rc;
 
@@ -1458,7 +1458,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 			goto out;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
@@ -1470,7 +1470,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	kfree(scontext2);
 	kfree(str);
@@ -1620,7 +1620,7 @@ static int security_compute_sid(u32 ssid,
 
 	context_init(&newcontext);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (kern) {
 		tclass = unmap_class(orig_tclass);
@@ -1759,7 +1759,7 @@ static int security_compute_sid(u32 ssid,
 	/* Obtain the sid for the context. */
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcontext);
 out:
 	return rc;
@@ -2051,7 +2051,6 @@ static void security_load_policycaps(struct policydb *pdb)
 }
 
 static int security_preserve_bools(struct policydb *p);
-
 /**
  * security_load_policy - Load a security policy configuration.
  * @data: binary policy data
@@ -2068,17 +2067,17 @@ int security_load_policy(void *data, size_t len)
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *next_rcu;
-	struct shared_current_mapping *old_rcu;
+	struct shared_rcu_mapping *next_rcu;
+	struct shared_rcu_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
 	if (!ss_initialized) {
-		struct shared_current_mapping *first_mapping;
+		struct shared_rcu_mapping *first_mapping;
 
-		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+		first_mapping = kzalloc(sizeof(struct shared_rcu_mapping),
 					GFP_KERNEL);
 		if (!first_mapping) {
 			rc = -ENOMEM;
@@ -2145,7 +2144,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
 	if (!next_rcu) {
 		kfree(oldpolicydb);
 		rc = -ENOMEM;
@@ -2157,7 +2156,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 
 	next_rcu->policydb.len = len;
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	/* If switching between different policy types, log MLS status */
 	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
@@ -2210,19 +2209,19 @@ int security_load_policy(void *data, size_t len)
 	/* Install the new policydb and SID table. */
 	/* next */
 	security_load_policycaps(&next_rcu->policydb);
-	read_unlock(&policy_rwlock);
-	write_lock_irq(&policy_rwlock);
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
+	rcu_read_unlock();
 	next_rcu->current_mapping = map;
 	next_rcu->current_mapping_size = map_size;
 
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	old_rcu = crm;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
-
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
 	sidtab_destroy(&oldsidtab);
@@ -2250,9 +2249,9 @@ size_t security_policydb_len(void)
 {
 	size_t len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	len = crm->policydb.len;
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return len;
 }
@@ -2268,7 +2267,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
@@ -2293,7 +2292,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2308,7 +2307,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
@@ -2333,7 +2332,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2348,7 +2347,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
@@ -2374,7 +2373,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2388,7 +2387,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 	int rc = 0;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
@@ -2415,7 +2414,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 		*if_sid = SECINITSID_NETIF;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2447,7 +2446,7 @@ int security_node_sid(u16 domain,
 	int rc;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	switch (domain) {
 	case AF_INET: {
@@ -2502,7 +2501,7 @@ int security_node_sid(u16 domain,
 
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2541,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	if (!ss_initialized)
 		goto out;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	context_init(&usercon);
 
@@ -2593,7 +2592,7 @@ int security_get_user_sids(u32 fromsid,
 	}
 	rc = 0;
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	if (rc || !mynel) {
 		kfree(mysids);
 		goto out;
@@ -2704,9 +2703,9 @@ int security_genfs_sid(const char *fstype,
 {
 	int retval;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -2721,7 +2720,7 @@ int security_fs_use(struct super_block *sb)
 	struct superblock_security_struct *sbsec = sb->s_security;
 	const char *fstype = sb->s_type->name;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
@@ -2752,7 +2751,7 @@ int security_fs_use(struct super_block *sb)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2760,7 +2759,7 @@ int security_get_bools(int *len, char ***names, int **values)
 {
 	int i, rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	*names = NULL;
 	*values = NULL;
 
@@ -2790,7 +2789,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 err:
 	if (*names) {
@@ -2803,13 +2802,14 @@ int security_get_bools(int *len, char ***names, int **values)
 
 int security_set_bools(int len, int *values)
 {
-	struct shared_current_mapping *next_rcu, *old_rcu;
+
+	struct shared_rcu_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	read_lock(&policy_rwlock);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
+	rcu_read_lock();
 	old_rcu = crm;
 	memcpy(&next_rcu->policydb, &old_rcu->policydb,
 	       sizeof(struct policydb));
@@ -2842,13 +2842,15 @@ int security_set_bools(int len, int *values)
 		if (rc)
 			goto out;
 	}
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
+
 	rc = 0;
 
-	write_lock_irq(&policy_rwlock);
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 out:
 	if (!rc) {
 		avc_ss_reset(seqno);
@@ -2868,7 +2870,7 @@ int security_get_bool_value(int index)
 	int rc;
 	int len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EFAULT;
 	len = crm->policydb.p_bools.nprim;
@@ -2877,7 +2879,7 @@ int security_get_bool_value(int index)
 
 	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2933,7 +2935,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	context_init(&newcon);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	context1 = sidtab_search(&crm->sidtab, sid);
@@ -2975,7 +2977,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcon);
 out:
 	return rc;
@@ -3032,7 +3034,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	if (!crm->policydb.mls_enabled)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
@@ -3059,7 +3061,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	 * expressive */
 	*peer_sid = xfrm_sid;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3080,7 +3082,7 @@ int security_get_classes(char ***classes, int *nclasses)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOMEM;
 	*nclasses = crm->policydb.p_classes.nprim;
@@ -3098,7 +3100,7 @@ int security_get_classes(char ***classes, int *nclasses)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3120,7 +3122,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	int rc, i;
 	struct class_datum *match;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	match = hashtab_search(crm->policydb.p_classes.table, class);
@@ -3149,11 +3151,11 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 		goto err;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 
 err:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	for (i = 0; i < *nperms; i++)
 		kfree((*perms)[i]);
 	kfree(*perms);
@@ -3184,9 +3186,9 @@ int security_policycap_supported(unsigned int req_cap)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -3250,7 +3252,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
 	context_init(&tmprule->au_ctxt);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	tmprule->au_seqno = latest_granting;
 
@@ -3294,7 +3296,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc) {
 		selinux_audit_rule_free(tmprule);
@@ -3344,7 +3346,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		return -ENOENT;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (rule->au_seqno < latest_granting) {
 		match = -ESTALE;
@@ -3435,7 +3437,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return match;
 }
 
@@ -3521,7 +3523,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		return 0;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (secattr->flags & NETLBL_SECATTR_CACHE)
 		*sid = *(u32 *)secattr->cache->data;
@@ -3558,12 +3560,12 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 	} else
 		*sid = SECSID_NULL;
 
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return 0;
 out_free:
 	ebitmap_destroy(&ctx_new.range.level[0].cat);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3585,7 +3587,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOENT;
 	ctx = sidtab_search(&crm->sidtab, sid);
@@ -3604,7 +3606,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
 	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 #endif /* CONFIG_NETLABEL */
@@ -3632,9 +3634,9 @@ int security_read_policy(void **data, size_t *len)
 	fp.data = *data;
 	fp.len = *len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = policydb_write(&crm->policydb, &fp);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc)
 		return rc;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 5/5] selinux: Switch locking to RCU.
@ 2018-01-26 14:32   ` peter.enderborg at sony.com
  0 siblings, 0 replies; 38+ messages in thread
From: peter.enderborg @ 2018-01-26 14:32 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn
  Cc: Peter Enderborg

From: Peter Enderborg <peter.enderborg@sony.com>

This patch switch to using RCU locks instead of rwlocks. This has
the big advantage that it does not has preempt disable.

Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
Reported-by: Björn Davidsson <bjorn.davidsson@sony.com>
---
 security/selinux/ss/services.c | 162 +++++++++++++++++++++--------------------
 1 file changed, 82 insertions(+), 80 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 81c5717..f142ef8 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -87,7 +87,7 @@ int selinux_policycap_alwaysnetwork;
 int selinux_policycap_cgroupseclabel;
 int selinux_policycap_nnp_nosuid_transition;
 
-static DEFINE_RWLOCK(policy_rwlock);
+static DEFINE_SPINLOCK(policy_w_lock);
 
 int ss_initialized;
 
@@ -115,14 +115,14 @@ struct selinux_mapping {
 	u32 perms[sizeof(u32) * 8];
 };
 
-struct shared_current_mapping {
+struct shared_rcu_mapping {
 	struct selinux_mapping *current_mapping;
 	u16 current_mapping_size;
 	struct policydb policydb;
 	struct sidtab sidtab;
 };
 
-static struct shared_current_mapping *crm;
+static struct shared_rcu_mapping *crm;
 
 static int selinux_set_mapping(struct policydb *pol,
 			       struct security_class_mapping *map,
@@ -791,7 +791,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (!user)
 		tclass = unmap_class(orig_tclass);
@@ -845,7 +845,7 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -879,7 +879,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 	int index;
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	old_context = sidtab_search(&crm->sidtab, old_sid);
@@ -941,7 +941,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 		kfree(old_name);
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -1029,7 +1029,7 @@ void security_compute_xperms_decision(u32 ssid,
 	memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
 	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (!ss_initialized)
 		goto allow;
 
@@ -1083,7 +1083,7 @@ void security_compute_xperms_decision(u32 ssid,
 		}
 	}
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
@@ -1110,7 +1110,7 @@ void security_compute_av(u32 ssid,
 	u16 tclass;
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	xperms->len = 0;
 	if (!ss_initialized)
@@ -1143,7 +1143,7 @@ void security_compute_av(u32 ssid,
 	context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
 	map_decision(orig_tclass, avd, crm->policydb.allow_unknown);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1157,7 +1157,7 @@ void security_compute_av_user(u32 ssid,
 {
 	struct context *scontext = NULL, *tcontext = NULL;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	avd_init(avd);
 	if (!ss_initialized)
 		goto allow;
@@ -1188,7 +1188,7 @@ void security_compute_av_user(u32 ssid,
 
 	context_struct_compute_av(scontext, tcontext, tclass, avd, NULL);
  out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return;
 allow:
 	avd->allowed = 0xffffffff;
@@ -1293,7 +1293,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 		rc = -EINVAL;
 		goto out;
 	}
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	if (force)
 		context = sidtab_search_force(&crm->sidtab, sid);
 	else
@@ -1306,7 +1306,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext,
 	}
 	rc = context_struct_to_string(context, scontext, scontext_len);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	return rc;
 
@@ -1458,7 +1458,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 			goto out;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = string_to_context_struct(&crm->policydb, &crm->sidtab, scontext2,
 				      scontext_len, &context, def_sid);
 	if (rc == -EINVAL && force) {
@@ -1470,7 +1470,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	rc = sidtab_context_to_sid(&crm->sidtab, &context, sid);
 	context_destroy(&context);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 out:
 	kfree(scontext2);
 	kfree(str);
@@ -1620,7 +1620,7 @@ static int security_compute_sid(u32 ssid,
 
 	context_init(&newcontext);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (kern) {
 		tclass = unmap_class(orig_tclass);
@@ -1759,7 +1759,7 @@ static int security_compute_sid(u32 ssid,
 	/* Obtain the sid for the context. */
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcontext, out_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcontext);
 out:
 	return rc;
@@ -2051,7 +2051,6 @@ static void security_load_policycaps(struct policydb *pdb)
 }
 
 static int security_preserve_bools(struct policydb *p);
-
 /**
  * security_load_policy - Load a security policy configuration.
  * @data: binary policy data
@@ -2068,17 +2067,17 @@ int security_load_policy(void *data, size_t len)
 	struct sidtab oldsidtab, newsidtab;
 	struct selinux_mapping *oldmap = NULL, *map = NULL;
 	struct convert_context_args args;
-	struct shared_current_mapping *next_rcu;
-	struct shared_current_mapping *old_rcu;
+	struct shared_rcu_mapping *next_rcu;
+	struct shared_rcu_mapping *old_rcu;
 	u32 seqno;
 	u16 map_size;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
 	if (!ss_initialized) {
-		struct shared_current_mapping *first_mapping;
+		struct shared_rcu_mapping *first_mapping;
 
-		first_mapping = kzalloc(sizeof(struct shared_current_mapping),
+		first_mapping = kzalloc(sizeof(struct shared_rcu_mapping),
 					GFP_KERNEL);
 		if (!first_mapping) {
 			rc = -ENOMEM;
@@ -2145,7 +2144,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 	}
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
 	if (!next_rcu) {
 		kfree(oldpolicydb);
 		rc = -ENOMEM;
@@ -2157,7 +2156,7 @@ int security_load_policy(void *data, size_t len)
 		goto out;
 
 	next_rcu->policydb.len = len;
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	/* If switching between different policy types, log MLS status */
 	if (crm->policydb.mls_enabled && !next_rcu->policydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
@@ -2210,19 +2209,19 @@ int security_load_policy(void *data, size_t len)
 	/* Install the new policydb and SID table. */
 	/* next */
 	security_load_policycaps(&next_rcu->policydb);
-	read_unlock(&policy_rwlock);
-	write_lock_irq(&policy_rwlock);
 	sidtab_set(&next_rcu->sidtab, &newsidtab);
 	security_load_policycaps(&next_rcu->policydb);
 	oldmap = crm->current_mapping;
+	rcu_read_unlock();
 	next_rcu->current_mapping = map;
 	next_rcu->current_mapping_size = map_size;
 
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	old_rcu = crm;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
-
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 	/* Free the old policydb and SID table. */
 	policydb_destroy(oldpolicydb);
 	sidtab_destroy(&oldsidtab);
@@ -2250,9 +2249,9 @@ size_t security_policydb_len(void)
 {
 	size_t len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	len = crm->policydb.len;
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return len;
 }
@@ -2268,7 +2267,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_PORT];
 	while (c) {
@@ -2293,7 +2292,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2308,7 +2307,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBPKEY];
 	while (c) {
@@ -2333,7 +2332,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2348,7 +2347,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 	struct ocontext *c;
 	int rc = 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_IBENDPORT];
 	while (c) {
@@ -2374,7 +2373,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 		*out_sid = SECINITSID_UNLABELED;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2388,7 +2387,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 	int rc = 0;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_NETIF];
 	while (c) {
@@ -2415,7 +2414,7 @@ int security_netif_sid(char *name, u32 *if_sid)
 		*if_sid = SECINITSID_NETIF;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2447,7 +2446,7 @@ int security_node_sid(u16 domain,
 	int rc;
 	struct ocontext *c;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	switch (domain) {
 	case AF_INET: {
@@ -2502,7 +2501,7 @@ int security_node_sid(u16 domain,
 
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2541,7 +2540,7 @@ int security_get_user_sids(u32 fromsid,
 	if (!ss_initialized)
 		goto out;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	context_init(&usercon);
 
@@ -2593,7 +2592,7 @@ int security_get_user_sids(u32 fromsid,
 	}
 	rc = 0;
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	if (rc || !mynel) {
 		kfree(mysids);
 		goto out;
@@ -2704,9 +2703,9 @@ int security_genfs_sid(const char *fstype,
 {
 	int retval;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -2721,7 +2720,7 @@ int security_fs_use(struct super_block *sb)
 	struct superblock_security_struct *sbsec = sb->s_security;
 	const char *fstype = sb->s_type->name;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	c = crm->policydb.ocontexts[OCON_FSUSE];
 	while (c) {
@@ -2752,7 +2751,7 @@ int security_fs_use(struct super_block *sb)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2760,7 +2759,7 @@ int security_get_bools(int *len, char ***names, int **values)
 {
 	int i, rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	*names = NULL;
 	*values = NULL;
 
@@ -2790,7 +2789,7 @@ int security_get_bools(int *len, char ***names, int **values)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 err:
 	if (*names) {
@@ -2803,13 +2802,14 @@ int security_get_bools(int *len, char ***names, int **values)
 
 int security_set_bools(int len, int *values)
 {
-	struct shared_current_mapping *next_rcu, *old_rcu;
+
+	struct shared_rcu_mapping *next_rcu, *old_rcu;
 	int i, rc;
 	int lenp, seqno = 0;
 	struct cond_node *cur;
 
-	next_rcu = kzalloc(sizeof(struct shared_current_mapping), GFP_KERNEL);
-	read_lock(&policy_rwlock);
+	next_rcu = kzalloc(sizeof(struct shared_rcu_mapping), GFP_KERNEL);
+	rcu_read_lock();
 	old_rcu = crm;
 	memcpy(&next_rcu->policydb, &old_rcu->policydb,
 	       sizeof(struct policydb));
@@ -2842,13 +2842,15 @@ int security_set_bools(int len, int *values)
 		if (rc)
 			goto out;
 	}
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
+
 	rc = 0;
 
-	write_lock_irq(&policy_rwlock);
+	spin_lock(&policy_w_lock);
 	seqno = ++latest_granting;
 	crm = next_rcu;
-	write_unlock_irq(&policy_rwlock);
+	spin_unlock(&policy_w_lock);
+	synchronize_rcu();
 out:
 	if (!rc) {
 		avc_ss_reset(seqno);
@@ -2868,7 +2870,7 @@ int security_get_bool_value(int index)
 	int rc;
 	int len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EFAULT;
 	len = crm->policydb.p_bools.nprim;
@@ -2877,7 +2879,7 @@ int security_get_bool_value(int index)
 
 	rc = crm->policydb.bool_val_to_struct[index]->state;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -2933,7 +2935,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	context_init(&newcon);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	context1 = sidtab_search(&crm->sidtab, sid);
@@ -2975,7 +2977,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
 	rc = sidtab_context_to_sid(&crm->sidtab, &newcon, new_sid);
 out_unlock:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	context_destroy(&newcon);
 out:
 	return rc;
@@ -3032,7 +3034,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	if (!crm->policydb.mls_enabled)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	nlbl_ctx = sidtab_search(&crm->sidtab, nlbl_sid);
@@ -3059,7 +3061,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
 	 * expressive */
 	*peer_sid = xfrm_sid;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3080,7 +3082,7 @@ int security_get_classes(char ***classes, int *nclasses)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOMEM;
 	*nclasses = crm->policydb.p_classes.nprim;
@@ -3098,7 +3100,7 @@ int security_get_classes(char ***classes, int *nclasses)
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3120,7 +3122,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 	int rc, i;
 	struct class_datum *match;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -EINVAL;
 	match = hashtab_search(crm->policydb.p_classes.table, class);
@@ -3149,11 +3151,11 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
 		goto err;
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 
 err:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	for (i = 0; i < *nperms; i++)
 		kfree((*perms)[i]);
 	kfree(*perms);
@@ -3184,9 +3186,9 @@ int security_policycap_supported(unsigned int req_cap)
 {
 	int rc;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = ebitmap_get_bit(&crm->policydb.policycaps, req_cap);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	return rc;
 }
@@ -3250,7 +3252,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
 	context_init(&tmprule->au_ctxt);
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	tmprule->au_seqno = latest_granting;
 
@@ -3294,7 +3296,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 	}
 	rc = 0;
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc) {
 		selinux_audit_rule_free(tmprule);
@@ -3344,7 +3346,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 		return -ENOENT;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (rule->au_seqno < latest_granting) {
 		match = -ESTALE;
@@ -3435,7 +3437,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
 	}
 
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return match;
 }
 
@@ -3521,7 +3523,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 		return 0;
 	}
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	if (secattr->flags & NETLBL_SECATTR_CACHE)
 		*sid = *(u32 *)secattr->cache->data;
@@ -3558,12 +3560,12 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 	} else
 		*sid = SECSID_NULL;
 
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return 0;
 out_free:
 	ebitmap_destroy(&ctx_new.range.level[0].cat);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 
@@ -3585,7 +3587,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	if (!ss_initialized)
 		return 0;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 
 	rc = -ENOENT;
 	ctx = sidtab_search(&crm->sidtab, sid);
@@ -3604,7 +3606,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	mls_export_netlbl_lvl(&crm->policydb, ctx, secattr);
 	rc = mls_export_netlbl_cat(&crm->policydb, ctx, secattr);
 out:
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 	return rc;
 }
 #endif /* CONFIG_NETLABEL */
@@ -3632,9 +3634,9 @@ int security_read_policy(void **data, size_t *len)
 	fp.data = *data;
 	fp.len = *len;
 
-	read_lock(&policy_rwlock);
+	rcu_read_lock();
 	rc = policydb_write(&crm->policydb, &fp);
-	read_unlock(&policy_rwlock);
+	rcu_read_unlock();
 
 	if (rc)
 		return rc;
-- 
2.7.4

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

* Re: [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds
  2018-01-26 14:32 ` peter.enderborg at sony.com
@ 2018-01-30 13:37   ` Stephen Smalley
  -1 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 13:37 UTC (permalink / raw)
  To: peter.enderborg, Paul Moore, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> Holding the preempt_disable is very bad for low latency tasks
> as audio and therefore we need to break out the rule-set dependent
> part from this disable. By using a RCU instead of rwlock we
> have an efficient locking and less preemption interference.

NB: rcu_read_lock() may disable preemption as well if
CONFIG_PREEMPT_COUNT=y.  I assume you aren't concerned with that
configuration?

> 
> Selinux uses a lot of read_locks. This patch replaces the rwlock
> with RCY that does not hold preempt_disable.
> 
> Intel Xeon W3520 2.67 Ghz running FC27 with 4.15.0-rc9git
> (+measurement)
> I get preempt_disable in worst case for 1.2ms in
> security_compute_av().
> With the patch I get 960us as the longest security_compute_av()
> without preempt disabeld. It very much noise in the measurement
> but it is not likely a degrade.
> 
> And the preempt_disable times is also very dependent on the selinux
> rule-set.
> 
> In security_get_user_sids() we have two nested for-loops and the
> inner part calls sittab_context_to_sid() that calls
> sidtab_search_context() that has a for loop() over a while() where
> the loops is dependent on the rules.
> 
> On the test system the average lookup time is 60us and does
> not change with the RCU usage.
> 
> To use RCU the structure of policydb has to be accesses through a
> pointer.
> We need 4 patches to get there.
> 
>   [PATCH v2 1/5] selinux:Remove direct references to policydb.
>   We remove direct references and pass it through function arguments.
> 
>   [PATCH v2 2/5] selinux: Move policydb to pointer structure
>   Move the policydb to dynamic allocated structure.
> 
>   [PATCH v2 3/5] selinux: Move sidtab to pointer structure
>   Same as for policydb but for sidtab. They are closly related
>   and should be switched at the same time.
>   
>   [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
>   Now we can switch rules by switching pointers.
> 
>   [PATCH v2 5/5] selinux: Switch locking to RCU.
>   We are now ready to use RCU.
>   
> History: V1 rwsem
> 

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

* [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds
@ 2018-01-30 13:37   ` Stephen Smalley
  0 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 13:37 UTC (permalink / raw)
  To: linux-security-module

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> Holding the preempt_disable is very bad for low latency tasks
> as audio and therefore we need to break out the rule-set dependent
> part from this disable. By using a RCU instead of rwlock we
> have an efficient locking and less preemption interference.

NB: rcu_read_lock() may disable preemption as well if
CONFIG_PREEMPT_COUNT=y.  I assume you aren't concerned with that
configuration?

> 
> Selinux uses a lot of read_locks. This patch replaces the rwlock
> with RCY that does not hold preempt_disable.
> 
> Intel Xeon W3520 2.67 Ghz running FC27 with 4.15.0-rc9git
> (+measurement)
> I get preempt_disable in worst case for 1.2ms in
> security_compute_av().
> With the patch I get 960us as the longest security_compute_av()
> without preempt disabeld. It very much noise in the measurement
> but it is not likely a degrade.
> 
> And the preempt_disable times is also very dependent on the selinux
> rule-set.
> 
> In security_get_user_sids() we have two nested for-loops and the
> inner part calls sittab_context_to_sid() that calls
> sidtab_search_context() that has a for loop() over a while() where
> the loops is dependent on the rules.
> 
> On the test system the average lookup time is 60us and does
> not change with the RCU usage.
> 
> To use RCU the structure of policydb has to be accesses through a
> pointer.
> We need 4 patches to get there.
> 
>   [PATCH v2 1/5] selinux:Remove direct references to policydb.
>   We remove direct references and pass it through function arguments.
> 
>   [PATCH v2 2/5] selinux: Move policydb to pointer structure
>   Move the policydb to dynamic allocated structure.
> 
>   [PATCH v2 3/5] selinux: Move sidtab to pointer structure
>   Same as for policydb but for sidtab. They are closly related
>   and should be switched at the same time.
>   
>   [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
>   Now we can switch rules by switching pointers.
> 
>   [PATCH v2 5/5] selinux: Switch locking to RCU.
>   We are now ready to use RCU.
>   
> History: V1 rwsem
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-01-26 14:32   ` peter.enderborg at sony.com
@ 2018-01-30 13:46     ` Stephen Smalley
  -1 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 13:46 UTC (permalink / raw)
  To: peter.enderborg, Paul Moore, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> From: Peter Enderborg <peter.enderborg@sony.com>
> 
> To be able to use rcu locks we seed to address the policydb
> though a pointer. This preparation removes the export of the
> policydb and send pointers to it through parameter agruments.

Just for reference, I have a patch series that does this not only for
the policydb, sidtab, and class/perm mapping, but for all of the
SELinux global state, see:
https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
and in particular
https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd

Those first three patches should have no effect on SELinux behavior.
They need to be re-based to latest selinux next branch (some minor
conflict resolution required) but I was waiting for that to advance to
something 4.15-rcX based.  I could however re-base it now if desired.

> 
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---
>  security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
>  security/selinux/ss/mls.h      | 37 +++++++++--------
>  security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++-----
> ----------
>  security/selinux/ss/services.h |  3 --
>  4 files changed, 114 insertions(+), 85 deletions(-)
> 
> diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
> index ad982ce..b1f35d3 100644
> --- a/security/selinux/ss/mls.c
> +++ b/security/selinux/ss/mls.c
> @@ -33,20 +33,20 @@
>   * Return the length in bytes for the MLS fields of the
>   * security context string representation of `context'.
>   */
> -int mls_compute_context_len(struct context *context)
> +int mls_compute_context_len(struct policydb *p, struct context
> *context)
>  {
>  	int i, l, len, head, prev;
>  	char *nm;
>  	struct ebitmap *e;
>  	struct ebitmap_node *node;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	len = 1; /* for the beginning ":" */
>  	for (l = 0; l < 2; l++) {
>  		int index_sens = context->range.level[l].sens;
> -		len += strlen(sym_name(&policydb, SYM_LEVELS,
> index_sens - 1));
> +		len += strlen(sym_name(p, SYM_LEVELS, index_sens -
> 1));
>  
>  		/* categories */
>  		head = -2;
> @@ -56,17 +56,17 @@ int mls_compute_context_len(struct context
> *context)
>  			if (i - prev > 1) {
>  				/* one or more negative bits are
> skipped */
>  				if (head != prev) {
> -					nm = sym_name(&policydb,
> SYM_CATS, prev);
> +					nm = sym_name(p, SYM_CATS,
> prev);
>  					len += strlen(nm) + 1;
>  				}
> -				nm = sym_name(&policydb, SYM_CATS,
> i);
> +				nm = sym_name(p, SYM_CATS, i);
>  				len += strlen(nm) + 1;
>  				head = i;
>  			}
>  			prev = i;
>  		}
>  		if (prev != head) {
> -			nm = sym_name(&policydb, SYM_CATS, prev);
> +			nm = sym_name(p, SYM_CATS, prev);
>  			len += strlen(nm) + 1;
>  		}
>  		if (l == 0) {
> @@ -86,7 +86,7 @@ int mls_compute_context_len(struct context
> *context)
>   * the MLS fields of `context' into the string `*scontext'.
>   * Update `*scontext' to point to the end of the MLS fields.
>   */
> -void mls_sid_to_context(struct context *context,
> +void mls_sid_to_context(struct policydb *p, struct context *context,
>  			char **scontext)
>  {
>  	char *scontextp, *nm;
> @@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
>  	struct ebitmap *e;
>  	struct ebitmap_node *node;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	scontextp = *scontext;
> @@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
>  	scontextp++;
>  
>  	for (l = 0; l < 2; l++) {
> -		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
> +		strcpy(scontextp, sym_name(p, SYM_LEVELS,
>  					   context-
> >range.level[l].sens - 1));
>  		scontextp += strlen(scontextp);
>  
> @@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
>  						*scontextp++ = '.';
>  					else
>  						*scontextp++ = ',';
> -					nm = sym_name(&policydb,
> SYM_CATS, prev);
> +					nm = sym_name(p, SYM_CATS,
> prev);
>  					strcpy(scontextp, nm);
>  					scontextp += strlen(nm);
>  				}
> @@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
>  					*scontextp++ = ':';
>  				else
>  					*scontextp++ = ',';
> -				nm = sym_name(&policydb, SYM_CATS,
> i);
> +				nm = sym_name(p, SYM_CATS, i);
>  				strcpy(scontextp, nm);
>  				scontextp += strlen(nm);
>  				head = i;
> @@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
>  				*scontextp++ = '.';
>  			else
>  				*scontextp++ = ',';
> -			nm = sym_name(&policydb, SYM_CATS, prev);
> +			nm = sym_name(p, SYM_CATS, prev);
>  			strcpy(scontextp, nm);
>  			scontextp += strlen(nm);
>  		}
> @@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
>   * the string `str'.  This function will allocate temporary memory
> with the
>   * given constraints of gfp_mask.
>   */
> -int mls_from_string(char *str, struct context *context, gfp_t
> gfp_mask)
> +int mls_from_string(struct policydb *p, char *str, struct context
> *context,
> +		    gfp_t gfp_mask)
>  {
>  	char *tmpstr, *freestr;
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return -EINVAL;
>  
>  	/* we need freestr because mls_context_to_sid will change
> @@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context
> *context, gfp_t gfp_mask)
>  	if (!tmpstr) {
>  		rc = -ENOMEM;
>  	} else {
> -		rc = mls_context_to_sid(&policydb, ':', &tmpstr,
> context,
> +		rc = mls_context_to_sid(p, ':', &tmpstr, context,
>  					NULL, SECSID_NULL);
>  		kfree(freestr);
>  	}
> @@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
>  	return rc;
>  }
>  
> -int mls_setup_user_range(struct context *fromcon, struct user_datum
> *user,
> -			 struct context *usercon)
> +int mls_setup_user_range(struct policydb *p, struct context
> *fromcon,
> +			 struct user_datum *user, struct context
> *usercon)
>  {
> -	if (policydb.mls_enabled) {
> +	if (p->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]);
> @@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon,
> struct user_datum *user,
>   * structure `c' from the values specified in the
>   * policy `oldp' to the values specified in the policy `newp'.
>   */
> -int mls_convert_context(struct policydb *oldp,
> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>  			struct policydb *newp,
>  			struct context *c)
>  {
> @@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
>  	struct ebitmap_node *node;
>  	int l, i;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	for (l = 0; l < 2; l++) {
> @@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
>  	return 0;
>  }
>  
> -int mls_compute_sid(struct context *scontext,
> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>  		    struct context *tcontext,
>  		    u16 tclass,
>  		    u32 specified,
> @@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
>  	struct class_datum *cladatum;
>  	int default_range = 0;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	switch (specified) {
> @@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
>  		rtr.source_type = scontext->type;
>  		rtr.target_type = tcontext->type;
>  		rtr.target_class = tclass;
> -		r = hashtab_search(policydb.range_tr, &rtr);
> +		r = hashtab_search(p->range_tr, &rtr);
>  		if (r)
>  			return mls_range_set(newcontext, r);
>  
> -		if (tclass && tclass <= policydb.p_classes.nprim) {
> -			cladatum =
> policydb.class_val_to_struct[tclass - 1];
> +		if (tclass && tclass <= p->p_classes.nprim) {
> +			cladatum = p->class_val_to_struct[tclass -
> 1];
>  			if (cladatum)
>  				default_range = cladatum-
> >default_range;
>  		}
> @@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
>  
>  		/* Fallthrough */
>  	case AVTAB_CHANGE:
> -		if ((tclass == policydb.process_class) || (sock ==
> true))
> +		if ((tclass == p->process_class) || (sock == true))
>  			/* Use the process MLS attributes. */
>  			return mls_context_cpy(newcontext,
> scontext);
>  		else
> @@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
>   * NetLabel MLS sensitivity level field.
>   *
>   */
> -void mls_export_netlbl_lvl(struct context *context,
> +void mls_export_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr)
>  {
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
> @@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context
> *context,
>   * NetLabel MLS sensitivity level into the context.
>   *
>   */
> -void mls_import_netlbl_lvl(struct context *context,
> +void mls_import_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr)
>  {
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
> @@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context
> *context,
>   * MLS category field.  Returns zero on success, negative values on
> failure.
>   *
>   */
> -int mls_export_netlbl_cat(struct context *context,
> +int mls_export_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr)
>  {
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
> @@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context
> *context,
>   * negative values on failure.
>   *
>   */
> -int mls_import_netlbl_cat(struct context *context,
> +int mls_import_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr)
>  {
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
> diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
> index 131d762..cb039c0 100644
> --- a/security/selinux/ss/mls.h
> +++ b/security/selinux/ss/mls.h
> @@ -25,8 +25,9 @@
>  #include "context.h"
>  #include "policydb.h"
>  
> -int mls_compute_context_len(struct context *context);
> -void mls_sid_to_context(struct context *context, char **scontext);
> +int mls_compute_context_len(struct policydb *p, struct context
> *context);
> +void mls_sid_to_context(struct policydb *p, struct context *context,
> +			char **scontext);
>  int mls_context_isvalid(struct policydb *p, struct context *c);
>  int mls_range_isvalid(struct policydb *p, struct mls_range *r);
>  int mls_level_isvalid(struct policydb *p, struct mls_level *l);
> @@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
>  		       struct sidtab *s,
>  		       u32 def_sid);
>  
> -int mls_from_string(char *str, struct context *context, gfp_t
> gfp_mask);
> +int mls_from_string(struct policydb *p, char *str, struct context
> *context,
> +		    gfp_t gfp_mask);
>  
>  int mls_range_set(struct context *context, struct mls_range *range);
>  
> -int mls_convert_context(struct policydb *oldp,
> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>  			struct policydb *newp,
>  			struct context *context);
>  
> -int mls_compute_sid(struct context *scontext,
> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>  		    struct context *tcontext,
>  		    u16 tclass,
>  		    u32 specified,
>  		    struct context *newcontext,
>  		    bool sock);
>  
> -int mls_setup_user_range(struct context *fromcon, struct user_datum
> *user,
> -			 struct context *usercon);
> +int mls_setup_user_range(struct policydb *p, struct context
> *fromcon,
> +			 struct user_datum *user, struct context
> *usercon);
>  
>  #ifdef CONFIG_NETLABEL
> -void mls_export_netlbl_lvl(struct context *context,
> +void mls_export_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr);
> -void mls_import_netlbl_lvl(struct context *context,
> +void mls_import_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr);
> -int mls_export_netlbl_cat(struct context *context,
> +int mls_export_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr);
> -int mls_import_netlbl_cat(struct context *context,
> +int mls_import_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr);
>  #else
> -static inline void mls_export_netlbl_lvl(struct context *context,
> +static inline void mls_export_netlbl_lvl(struct policydb *p,
> +					 struct context *context,
>  					 struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return;
>  }
> -static inline void mls_import_netlbl_lvl(struct context *context,
> +static inline void mls_import_netlbl_lvl(struct policydb *p,
> +					 struct context *context,
>  					 struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return;
>  }
> -static inline int mls_export_netlbl_cat(struct context *context,
> +static inline int mls_export_netlbl_cat(struct policydb *p,
> +					struct context *context,
>  					struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return -ENOMEM;
>  }
> -static inline int mls_import_netlbl_cat(struct context *context,
> +static inline int mls_import_netlbl_cat(struct policydb *p,
> +					struct context *context,
>  					struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return -ENOMEM;
> @@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct
> context *context,
>  #endif
>  
>  #endif	/* _SS_MLS_H */
> -
> diff --git a/security/selinux/ss/services.c
> b/security/selinux/ss/services.c
> index 33cfe5d..47d8030 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
>  static DEFINE_RWLOCK(policy_rwlock);
>  
>  static struct sidtab sidtab;
> -struct policydb policydb;
> +static struct policydb policydb;
>  int ss_initialized;
>  
>  /*
> @@ -117,8 +117,12 @@ struct selinux_mapping {
>  	u32 perms[sizeof(u32) * 8];
>  };
>  
> -static struct selinux_mapping *current_mapping;
> -static u16 current_mapping_size;
> +struct shared_current_mapping {
> +	struct selinux_mapping *current_mapping;
> +	u16 current_mapping_size;
> +};
> +
> +static struct shared_current_mapping *crm;
>  
>  static int selinux_set_mapping(struct policydb *pol,
>  			       struct security_class_mapping *map,
> @@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb
> *pol,
>  
>  static u16 unmap_class(u16 tclass)
>  {
> -	if (tclass < current_mapping_size)
> -		return current_mapping[tclass].value;
> +	if (tclass < crm->current_mapping_size)
> +		return crm->current_mapping[tclass].value;
>  
>  	return tclass;
>  }
> @@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
>  {
>  	u16 i;
>  
> -	for (i = 1; i < current_mapping_size; i++) {
> -		if (current_mapping[i].value == pol_value)
> +	for (i = 1; i < crm->current_mapping_size; i++) {
> +		if (crm->current_mapping[i].value == pol_value)
>  			return i;
>  	}
>  
> @@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
>  static void map_decision(u16 tclass, struct av_decision *avd,
>  			 int allow_unknown)
>  {
> -	if (tclass < current_mapping_size) {
> -		unsigned i, n = current_mapping[tclass].num_perms;
> +	if (tclass < crm->current_mapping_size) {
> +		unsigned int i, n = crm-
> >current_mapping[tclass].num_perms;
>  		u32 result;
>  
>  		for (i = 0, result = 0; i < n; i++) {
> -			if (avd->allowed &
> current_mapping[tclass].perms[i])
> +			if (avd->allowed &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
> -			if (allow_unknown &&
> !current_mapping[tclass].perms[i])
> +			if (allow_unknown &&
> +			    !crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		}
>  		avd->allowed = result;
>  
>  		for (i = 0, result = 0; i < n; i++)
> -			if (avd->auditallow &
> current_mapping[tclass].perms[i])
> +			if (avd->auditallow &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		avd->auditallow = result;
>  
>  		for (i = 0, result = 0; i < n; i++) {
> -			if (avd->auditdeny &
> current_mapping[tclass].perms[i])
> +			if (avd->auditdeny &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
> -			if (!allow_unknown &&
> !current_mapping[tclass].perms[i])
> +			if (!allow_unknown &&
> +			    !crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		}
>  		/*
> @@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct
> context *context, char **scontext, u3
>  	*scontext_len += strlen(sym_name(&policydb, SYM_USERS,
> context->user - 1)) + 1;
>  	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES,
> context->role - 1)) + 1;
>  	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES,
> context->type - 1)) + 1;
> -	*scontext_len += mls_compute_context_len(context);
> +	*scontext_len += mls_compute_context_len(&policydb,
> context);
>  
>  	if (!scontext)
>  		return 0;
> @@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct
> context *context, char **scontext, u3
>  		sym_name(&policydb, SYM_ROLES, context->role - 1),
>  		sym_name(&policydb, SYM_TYPES, context->type - 1));
>  
> -	mls_sid_to_context(context, &scontextp);
> +	mls_sid_to_context(&policydb, context, &scontextp);
>  
>  	*scontextp = 0;
>  
> @@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
>  
>  	/* Set the MLS attributes.
>  	   This is done last because it may allocate memory. */
> -	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
> +	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass,
> specified,
>  			     &newcontext, sock);
>  	if (rc)
>  		goto out_unlock;
> @@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
>  
>  	/* Convert the MLS fields if dealing with MLS policies */
>  	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
> -		rc = mls_convert_context(args->oldp, args->newp, c);
> +		rc = mls_convert_context(&policydb, args->oldp,
> args->newp, c);
>  		if (rc)
>  			goto bad;
>  	} else if (args->oldp->mls_enabled && !args->newp-
> >mls_enabled) {
> @@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t
> len)
>  {
>  	struct policydb *oldpolicydb, *newpolicydb;
>  	struct sidtab oldsidtab, newsidtab;
> -	struct selinux_mapping *oldmap, *map = NULL;
> +	struct selinux_mapping *oldmap = NULL, *map = NULL;
>  	struct convert_context_args args;
> +	struct shared_current_mapping *new_mapping;
>  	u32 seqno;
>  	u16 map_size;
>  	int rc = 0;
> @@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t
> len)
>  		rc = -ENOMEM;
>  		goto out;
>  	}
> +	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
> +			      GFP_KERNEL);
> +	if (!new_mapping) {
> +		rc = -ENOMEM;
> +		goto out;
> +	}
>  	newpolicydb = oldpolicydb + 1;
>  
>  	if (!ss_initialized) {
> +		crm = kzalloc(sizeof(struct shared_current_mapping),
> +			      GFP_KERNEL);
> +		if (!crm) {
> +			rc = -ENOMEM;
> +			goto out;
> +		}
> +
>  		avtab_cache_init();
>  		ebitmap_cache_init();
>  		hashtab_cache_init();
> @@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t
> len)
>  
>  		policydb.len = len;
>  		rc = selinux_set_mapping(&policydb, secclass_map,
> -					 &current_mapping,
> -					 &current_mapping_size);
> +					 &crm->current_mapping,
> +					 &crm-
> >current_mapping_size);
>  		if (rc) {
>  			policydb_destroy(&policydb);
>  			avtab_cache_destroy();
> @@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t
> len)
>  	memcpy(&policydb, newpolicydb, sizeof(policydb));
>  	sidtab_set(&sidtab, &newsidtab);
>  	security_load_policycaps();
> -	oldmap = current_mapping;
> -	current_mapping = map;
> -	current_mapping_size = map_size;
> +	oldmap = crm->current_mapping;
> +	crm->current_mapping = map;
> +	crm->current_mapping_size = map_size;
>  	seqno = ++latest_granting;
>  	write_unlock_irq(&policy_rwlock);
>  
> @@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
>  		ebitmap_for_each_positive_bit(&role->types, tnode,
> j) {
>  			usercon.type = j + 1;
>  
> -			if (mls_setup_user_range(fromcon, user,
> &usercon))
> +			if (mls_setup_user_range(&policydb, fromcon,
> +						 user, &usercon))
>  				continue;
>  
>  			rc = sidtab_context_to_sid(&sidtab,
> &usercon, &sid);
> @@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
>   * cannot support xattr or use a fixed labeling behavior like
>   * transition SIDs or task SIDs.
>   *
> - * The caller must acquire the policy_rwlock before calling this
> function.
> + * The caller must hold rcu before calling this function.
>   */
>  static inline int __security_genfs_sid(const char *fstype,
>  				       char *path,
> @@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const
> char *fstype,
>   * @sclass: file security class
>   * @sid: SID for path
>   *
> - * Acquire policy_rwlock before calling __security_genfs_sid() and
> release
> + * Hold rcu before calling __security_genfs_sid() and release
>   * it afterward.
>   */
>  int security_genfs_sid(const char *fstype,
> @@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op,
> char *rulestr, void **vrule)
>  	case AUDIT_SUBJ_CLR:
>  	case AUDIT_OBJ_LEV_LOW:
>  	case AUDIT_OBJ_LEV_HIGH:
> -		rc = mls_from_string(rulestr, &tmprule->au_ctxt,
> GFP_ATOMIC);
> +		rc = mls_from_string(&policydb, rulestr, &tmprule-
> >au_ctxt,
> +				     GFP_ATOMIC);
>  		if (rc)
>  			goto out;
>  		break;
> @@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct
> netlbl_lsm_secattr *secattr,
>  		ctx_new.user = ctx->user;
>  		ctx_new.role = ctx->role;
>  		ctx_new.type = ctx->type;
> -		mls_import_netlbl_lvl(&ctx_new, secattr);
> +		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
>  		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
> -			rc = mls_import_netlbl_cat(&ctx_new,
> secattr);
> +			rc = mls_import_netlbl_cat(&policydb,
> &ctx_new,
> +						   secattr);
>  			if (rc)
>  				goto out;
>  		}
> @@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid,
> struct netlbl_lsm_secattr *secattr)
>  
>  	secattr->attr.secid = sid;
>  	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY |
> NETLBL_SECATTR_SECID;
> -	mls_export_netlbl_lvl(ctx, secattr);
> -	rc = mls_export_netlbl_cat(ctx, secattr);
> +	mls_export_netlbl_lvl(&policydb, ctx, secattr);
> +	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
>  out:
>  	read_unlock(&policy_rwlock);
>  	return rc;
> diff --git a/security/selinux/ss/services.h
> b/security/selinux/ss/services.h
> index 356bdd3..50c7ceb 100644
> --- a/security/selinux/ss/services.h
> +++ b/security/selinux/ss/services.h
> @@ -10,8 +10,6 @@
>  #include "policydb.h"
>  #include "sidtab.h"
>  
> -extern struct policydb policydb;
> -
>  void services_compute_xperms_drivers(struct extended_perms *xperms,
>  				struct avtab_node *node);
>  
> @@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct
> extended_perms_decision *xpermd,
>  					struct avtab_node *node);
>  
>  #endif	/* _SS_SERVICES_H_ */
> -

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-01-30 13:46     ` Stephen Smalley
  0 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 13:46 UTC (permalink / raw)
  To: linux-security-module

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> From: Peter Enderborg <peter.enderborg@sony.com>
> 
> To be able to use rcu locks we seed to address the policydb
> though a pointer. This preparation removes the export of the
> policydb and send pointers to it through parameter agruments.

Just for reference, I have a patch series that does this not only for
the policydb, sidtab, and class/perm mapping, but for all of the
SELinux global state, see:
https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
and in particular
https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd

Those first three patches should have no effect on SELinux behavior.
They need to be re-based to latest selinux next branch (some minor
conflict resolution required) but I was waiting for that to advance to
something 4.15-rcX based.  I could however re-base it now if desired.

> 
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---
>  security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
>  security/selinux/ss/mls.h      | 37 +++++++++--------
>  security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++-----
> ----------
>  security/selinux/ss/services.h |  3 --
>  4 files changed, 114 insertions(+), 85 deletions(-)
> 
> diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
> index ad982ce..b1f35d3 100644
> --- a/security/selinux/ss/mls.c
> +++ b/security/selinux/ss/mls.c
> @@ -33,20 +33,20 @@
>   * Return the length in bytes for the MLS fields of the
>   * security context string representation of `context'.
>   */
> -int mls_compute_context_len(struct context *context)
> +int mls_compute_context_len(struct policydb *p, struct context
> *context)
>  {
>  	int i, l, len, head, prev;
>  	char *nm;
>  	struct ebitmap *e;
>  	struct ebitmap_node *node;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	len = 1; /* for the beginning ":" */
>  	for (l = 0; l < 2; l++) {
>  		int index_sens = context->range.level[l].sens;
> -		len += strlen(sym_name(&policydb, SYM_LEVELS,
> index_sens - 1));
> +		len += strlen(sym_name(p, SYM_LEVELS, index_sens -
> 1));
>  
>  		/* categories */
>  		head = -2;
> @@ -56,17 +56,17 @@ int mls_compute_context_len(struct context
> *context)
>  			if (i - prev > 1) {
>  				/* one or more negative bits are
> skipped */
>  				if (head != prev) {
> -					nm = sym_name(&policydb,
> SYM_CATS, prev);
> +					nm = sym_name(p, SYM_CATS,
> prev);
>  					len += strlen(nm) + 1;
>  				}
> -				nm = sym_name(&policydb, SYM_CATS,
> i);
> +				nm = sym_name(p, SYM_CATS, i);
>  				len += strlen(nm) + 1;
>  				head = i;
>  			}
>  			prev = i;
>  		}
>  		if (prev != head) {
> -			nm = sym_name(&policydb, SYM_CATS, prev);
> +			nm = sym_name(p, SYM_CATS, prev);
>  			len += strlen(nm) + 1;
>  		}
>  		if (l == 0) {
> @@ -86,7 +86,7 @@ int mls_compute_context_len(struct context
> *context)
>   * the MLS fields of `context' into the string `*scontext'.
>   * Update `*scontext' to point to the end of the MLS fields.
>   */
> -void mls_sid_to_context(struct context *context,
> +void mls_sid_to_context(struct policydb *p, struct context *context,
>  			char **scontext)
>  {
>  	char *scontextp, *nm;
> @@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
>  	struct ebitmap *e;
>  	struct ebitmap_node *node;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	scontextp = *scontext;
> @@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
>  	scontextp++;
>  
>  	for (l = 0; l < 2; l++) {
> -		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
> +		strcpy(scontextp, sym_name(p, SYM_LEVELS,
>  					   context-
> >range.level[l].sens - 1));
>  		scontextp += strlen(scontextp);
>  
> @@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
>  						*scontextp++ = '.';
>  					else
>  						*scontextp++ = ',';
> -					nm = sym_name(&policydb,
> SYM_CATS, prev);
> +					nm = sym_name(p, SYM_CATS,
> prev);
>  					strcpy(scontextp, nm);
>  					scontextp += strlen(nm);
>  				}
> @@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
>  					*scontextp++ = ':';
>  				else
>  					*scontextp++ = ',';
> -				nm = sym_name(&policydb, SYM_CATS,
> i);
> +				nm = sym_name(p, SYM_CATS, i);
>  				strcpy(scontextp, nm);
>  				scontextp += strlen(nm);
>  				head = i;
> @@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
>  				*scontextp++ = '.';
>  			else
>  				*scontextp++ = ',';
> -			nm = sym_name(&policydb, SYM_CATS, prev);
> +			nm = sym_name(p, SYM_CATS, prev);
>  			strcpy(scontextp, nm);
>  			scontextp += strlen(nm);
>  		}
> @@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
>   * the string `str'.  This function will allocate temporary memory
> with the
>   * given constraints of gfp_mask.
>   */
> -int mls_from_string(char *str, struct context *context, gfp_t
> gfp_mask)
> +int mls_from_string(struct policydb *p, char *str, struct context
> *context,
> +		    gfp_t gfp_mask)
>  {
>  	char *tmpstr, *freestr;
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return -EINVAL;
>  
>  	/* we need freestr because mls_context_to_sid will change
> @@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context
> *context, gfp_t gfp_mask)
>  	if (!tmpstr) {
>  		rc = -ENOMEM;
>  	} else {
> -		rc = mls_context_to_sid(&policydb, ':', &tmpstr,
> context,
> +		rc = mls_context_to_sid(p, ':', &tmpstr, context,
>  					NULL, SECSID_NULL);
>  		kfree(freestr);
>  	}
> @@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
>  	return rc;
>  }
>  
> -int mls_setup_user_range(struct context *fromcon, struct user_datum
> *user,
> -			 struct context *usercon)
> +int mls_setup_user_range(struct policydb *p, struct context
> *fromcon,
> +			 struct user_datum *user, struct context
> *usercon)
>  {
> -	if (policydb.mls_enabled) {
> +	if (p->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]);
> @@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon,
> struct user_datum *user,
>   * structure `c' from the values specified in the
>   * policy `oldp' to the values specified in the policy `newp'.
>   */
> -int mls_convert_context(struct policydb *oldp,
> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>  			struct policydb *newp,
>  			struct context *c)
>  {
> @@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
>  	struct ebitmap_node *node;
>  	int l, i;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	for (l = 0; l < 2; l++) {
> @@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
>  	return 0;
>  }
>  
> -int mls_compute_sid(struct context *scontext,
> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>  		    struct context *tcontext,
>  		    u16 tclass,
>  		    u32 specified,
> @@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
>  	struct class_datum *cladatum;
>  	int default_range = 0;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	switch (specified) {
> @@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
>  		rtr.source_type = scontext->type;
>  		rtr.target_type = tcontext->type;
>  		rtr.target_class = tclass;
> -		r = hashtab_search(policydb.range_tr, &rtr);
> +		r = hashtab_search(p->range_tr, &rtr);
>  		if (r)
>  			return mls_range_set(newcontext, r);
>  
> -		if (tclass && tclass <= policydb.p_classes.nprim) {
> -			cladatum =
> policydb.class_val_to_struct[tclass - 1];
> +		if (tclass && tclass <= p->p_classes.nprim) {
> +			cladatum = p->class_val_to_struct[tclass -
> 1];
>  			if (cladatum)
>  				default_range = cladatum-
> >default_range;
>  		}
> @@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
>  
>  		/* Fallthrough */
>  	case AVTAB_CHANGE:
> -		if ((tclass == policydb.process_class) || (sock ==
> true))
> +		if ((tclass == p->process_class) || (sock == true))
>  			/* Use the process MLS attributes. */
>  			return mls_context_cpy(newcontext,
> scontext);
>  		else
> @@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
>   * NetLabel MLS sensitivity level field.
>   *
>   */
> -void mls_export_netlbl_lvl(struct context *context,
> +void mls_export_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr)
>  {
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
> @@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context
> *context,
>   * NetLabel MLS sensitivity level into the context.
>   *
>   */
> -void mls_import_netlbl_lvl(struct context *context,
> +void mls_import_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr)
>  {
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return;
>  
>  	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
> @@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context
> *context,
>   * MLS category field.  Returns zero on success, negative values on
> failure.
>   *
>   */
> -int mls_export_netlbl_cat(struct context *context,
> +int mls_export_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr)
>  {
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
> @@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context
> *context,
>   * negative values on failure.
>   *
>   */
> -int mls_import_netlbl_cat(struct context *context,
> +int mls_import_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr)
>  {
>  	int rc;
>  
> -	if (!policydb.mls_enabled)
> +	if (!p->mls_enabled)
>  		return 0;
>  
>  	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
> diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
> index 131d762..cb039c0 100644
> --- a/security/selinux/ss/mls.h
> +++ b/security/selinux/ss/mls.h
> @@ -25,8 +25,9 @@
>  #include "context.h"
>  #include "policydb.h"
>  
> -int mls_compute_context_len(struct context *context);
> -void mls_sid_to_context(struct context *context, char **scontext);
> +int mls_compute_context_len(struct policydb *p, struct context
> *context);
> +void mls_sid_to_context(struct policydb *p, struct context *context,
> +			char **scontext);
>  int mls_context_isvalid(struct policydb *p, struct context *c);
>  int mls_range_isvalid(struct policydb *p, struct mls_range *r);
>  int mls_level_isvalid(struct policydb *p, struct mls_level *l);
> @@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
>  		       struct sidtab *s,
>  		       u32 def_sid);
>  
> -int mls_from_string(char *str, struct context *context, gfp_t
> gfp_mask);
> +int mls_from_string(struct policydb *p, char *str, struct context
> *context,
> +		    gfp_t gfp_mask);
>  
>  int mls_range_set(struct context *context, struct mls_range *range);
>  
> -int mls_convert_context(struct policydb *oldp,
> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>  			struct policydb *newp,
>  			struct context *context);
>  
> -int mls_compute_sid(struct context *scontext,
> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>  		    struct context *tcontext,
>  		    u16 tclass,
>  		    u32 specified,
>  		    struct context *newcontext,
>  		    bool sock);
>  
> -int mls_setup_user_range(struct context *fromcon, struct user_datum
> *user,
> -			 struct context *usercon);
> +int mls_setup_user_range(struct policydb *p, struct context
> *fromcon,
> +			 struct user_datum *user, struct context
> *usercon);
>  
>  #ifdef CONFIG_NETLABEL
> -void mls_export_netlbl_lvl(struct context *context,
> +void mls_export_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr);
> -void mls_import_netlbl_lvl(struct context *context,
> +void mls_import_netlbl_lvl(struct policydb *p, struct context
> *context,
>  			   struct netlbl_lsm_secattr *secattr);
> -int mls_export_netlbl_cat(struct context *context,
> +int mls_export_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr);
> -int mls_import_netlbl_cat(struct context *context,
> +int mls_import_netlbl_cat(struct policydb *p, struct context
> *context,
>  			  struct netlbl_lsm_secattr *secattr);
>  #else
> -static inline void mls_export_netlbl_lvl(struct context *context,
> +static inline void mls_export_netlbl_lvl(struct policydb *p,
> +					 struct context *context,
>  					 struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return;
>  }
> -static inline void mls_import_netlbl_lvl(struct context *context,
> +static inline void mls_import_netlbl_lvl(struct policydb *p,
> +					 struct context *context,
>  					 struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return;
>  }
> -static inline int mls_export_netlbl_cat(struct context *context,
> +static inline int mls_export_netlbl_cat(struct policydb *p,
> +					struct context *context,
>  					struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return -ENOMEM;
>  }
> -static inline int mls_import_netlbl_cat(struct context *context,
> +static inline int mls_import_netlbl_cat(struct policydb *p,
> +					struct context *context,
>  					struct netlbl_lsm_secattr
> *secattr)
>  {
>  	return -ENOMEM;
> @@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct
> context *context,
>  #endif
>  
>  #endif	/* _SS_MLS_H */
> -
> diff --git a/security/selinux/ss/services.c
> b/security/selinux/ss/services.c
> index 33cfe5d..47d8030 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
>  static DEFINE_RWLOCK(policy_rwlock);
>  
>  static struct sidtab sidtab;
> -struct policydb policydb;
> +static struct policydb policydb;
>  int ss_initialized;
>  
>  /*
> @@ -117,8 +117,12 @@ struct selinux_mapping {
>  	u32 perms[sizeof(u32) * 8];
>  };
>  
> -static struct selinux_mapping *current_mapping;
> -static u16 current_mapping_size;
> +struct shared_current_mapping {
> +	struct selinux_mapping *current_mapping;
> +	u16 current_mapping_size;
> +};
> +
> +static struct shared_current_mapping *crm;
>  
>  static int selinux_set_mapping(struct policydb *pol,
>  			       struct security_class_mapping *map,
> @@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb
> *pol,
>  
>  static u16 unmap_class(u16 tclass)
>  {
> -	if (tclass < current_mapping_size)
> -		return current_mapping[tclass].value;
> +	if (tclass < crm->current_mapping_size)
> +		return crm->current_mapping[tclass].value;
>  
>  	return tclass;
>  }
> @@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
>  {
>  	u16 i;
>  
> -	for (i = 1; i < current_mapping_size; i++) {
> -		if (current_mapping[i].value == pol_value)
> +	for (i = 1; i < crm->current_mapping_size; i++) {
> +		if (crm->current_mapping[i].value == pol_value)
>  			return i;
>  	}
>  
> @@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
>  static void map_decision(u16 tclass, struct av_decision *avd,
>  			 int allow_unknown)
>  {
> -	if (tclass < current_mapping_size) {
> -		unsigned i, n = current_mapping[tclass].num_perms;
> +	if (tclass < crm->current_mapping_size) {
> +		unsigned int i, n = crm-
> >current_mapping[tclass].num_perms;
>  		u32 result;
>  
>  		for (i = 0, result = 0; i < n; i++) {
> -			if (avd->allowed &
> current_mapping[tclass].perms[i])
> +			if (avd->allowed &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
> -			if (allow_unknown &&
> !current_mapping[tclass].perms[i])
> +			if (allow_unknown &&
> +			    !crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		}
>  		avd->allowed = result;
>  
>  		for (i = 0, result = 0; i < n; i++)
> -			if (avd->auditallow &
> current_mapping[tclass].perms[i])
> +			if (avd->auditallow &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		avd->auditallow = result;
>  
>  		for (i = 0, result = 0; i < n; i++) {
> -			if (avd->auditdeny &
> current_mapping[tclass].perms[i])
> +			if (avd->auditdeny &
> +			    crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
> -			if (!allow_unknown &&
> !current_mapping[tclass].perms[i])
> +			if (!allow_unknown &&
> +			    !crm->current_mapping[tclass].perms[i])
>  				result |= 1<<i;
>  		}
>  		/*
> @@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct
> context *context, char **scontext, u3
>  	*scontext_len += strlen(sym_name(&policydb, SYM_USERS,
> context->user - 1)) + 1;
>  	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES,
> context->role - 1)) + 1;
>  	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES,
> context->type - 1)) + 1;
> -	*scontext_len += mls_compute_context_len(context);
> +	*scontext_len += mls_compute_context_len(&policydb,
> context);
>  
>  	if (!scontext)
>  		return 0;
> @@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct
> context *context, char **scontext, u3
>  		sym_name(&policydb, SYM_ROLES, context->role - 1),
>  		sym_name(&policydb, SYM_TYPES, context->type - 1));
>  
> -	mls_sid_to_context(context, &scontextp);
> +	mls_sid_to_context(&policydb, context, &scontextp);
>  
>  	*scontextp = 0;
>  
> @@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
>  
>  	/* Set the MLS attributes.
>  	   This is done last because it may allocate memory. */
> -	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
> +	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass,
> specified,
>  			     &newcontext, sock);
>  	if (rc)
>  		goto out_unlock;
> @@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
>  
>  	/* Convert the MLS fields if dealing with MLS policies */
>  	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
> -		rc = mls_convert_context(args->oldp, args->newp, c);
> +		rc = mls_convert_context(&policydb, args->oldp,
> args->newp, c);
>  		if (rc)
>  			goto bad;
>  	} else if (args->oldp->mls_enabled && !args->newp-
> >mls_enabled) {
> @@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t
> len)
>  {
>  	struct policydb *oldpolicydb, *newpolicydb;
>  	struct sidtab oldsidtab, newsidtab;
> -	struct selinux_mapping *oldmap, *map = NULL;
> +	struct selinux_mapping *oldmap = NULL, *map = NULL;
>  	struct convert_context_args args;
> +	struct shared_current_mapping *new_mapping;
>  	u32 seqno;
>  	u16 map_size;
>  	int rc = 0;
> @@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t
> len)
>  		rc = -ENOMEM;
>  		goto out;
>  	}
> +	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
> +			      GFP_KERNEL);
> +	if (!new_mapping) {
> +		rc = -ENOMEM;
> +		goto out;
> +	}
>  	newpolicydb = oldpolicydb + 1;
>  
>  	if (!ss_initialized) {
> +		crm = kzalloc(sizeof(struct shared_current_mapping),
> +			      GFP_KERNEL);
> +		if (!crm) {
> +			rc = -ENOMEM;
> +			goto out;
> +		}
> +
>  		avtab_cache_init();
>  		ebitmap_cache_init();
>  		hashtab_cache_init();
> @@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t
> len)
>  
>  		policydb.len = len;
>  		rc = selinux_set_mapping(&policydb, secclass_map,
> -					 &current_mapping,
> -					 &current_mapping_size);
> +					 &crm->current_mapping,
> +					 &crm-
> >current_mapping_size);
>  		if (rc) {
>  			policydb_destroy(&policydb);
>  			avtab_cache_destroy();
> @@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t
> len)
>  	memcpy(&policydb, newpolicydb, sizeof(policydb));
>  	sidtab_set(&sidtab, &newsidtab);
>  	security_load_policycaps();
> -	oldmap = current_mapping;
> -	current_mapping = map;
> -	current_mapping_size = map_size;
> +	oldmap = crm->current_mapping;
> +	crm->current_mapping = map;
> +	crm->current_mapping_size = map_size;
>  	seqno = ++latest_granting;
>  	write_unlock_irq(&policy_rwlock);
>  
> @@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
>  		ebitmap_for_each_positive_bit(&role->types, tnode,
> j) {
>  			usercon.type = j + 1;
>  
> -			if (mls_setup_user_range(fromcon, user,
> &usercon))
> +			if (mls_setup_user_range(&policydb, fromcon,
> +						 user, &usercon))
>  				continue;
>  
>  			rc = sidtab_context_to_sid(&sidtab,
> &usercon, &sid);
> @@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
>   * cannot support xattr or use a fixed labeling behavior like
>   * transition SIDs or task SIDs.
>   *
> - * The caller must acquire the policy_rwlock before calling this
> function.
> + * The caller must hold rcu before calling this function.
>   */
>  static inline int __security_genfs_sid(const char *fstype,
>  				       char *path,
> @@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const
> char *fstype,
>   * @sclass: file security class
>   * @sid: SID for path
>   *
> - * Acquire policy_rwlock before calling __security_genfs_sid() and
> release
> + * Hold rcu before calling __security_genfs_sid() and release
>   * it afterward.
>   */
>  int security_genfs_sid(const char *fstype,
> @@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op,
> char *rulestr, void **vrule)
>  	case AUDIT_SUBJ_CLR:
>  	case AUDIT_OBJ_LEV_LOW:
>  	case AUDIT_OBJ_LEV_HIGH:
> -		rc = mls_from_string(rulestr, &tmprule->au_ctxt,
> GFP_ATOMIC);
> +		rc = mls_from_string(&policydb, rulestr, &tmprule-
> >au_ctxt,
> +				     GFP_ATOMIC);
>  		if (rc)
>  			goto out;
>  		break;
> @@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct
> netlbl_lsm_secattr *secattr,
>  		ctx_new.user = ctx->user;
>  		ctx_new.role = ctx->role;
>  		ctx_new.type = ctx->type;
> -		mls_import_netlbl_lvl(&ctx_new, secattr);
> +		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
>  		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
> -			rc = mls_import_netlbl_cat(&ctx_new,
> secattr);
> +			rc = mls_import_netlbl_cat(&policydb,
> &ctx_new,
> +						   secattr);
>  			if (rc)
>  				goto out;
>  		}
> @@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid,
> struct netlbl_lsm_secattr *secattr)
>  
>  	secattr->attr.secid = sid;
>  	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY |
> NETLBL_SECATTR_SECID;
> -	mls_export_netlbl_lvl(ctx, secattr);
> -	rc = mls_export_netlbl_cat(ctx, secattr);
> +	mls_export_netlbl_lvl(&policydb, ctx, secattr);
> +	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
>  out:
>  	read_unlock(&policy_rwlock);
>  	return rc;
> diff --git a/security/selinux/ss/services.h
> b/security/selinux/ss/services.h
> index 356bdd3..50c7ceb 100644
> --- a/security/selinux/ss/services.h
> +++ b/security/selinux/ss/services.h
> @@ -10,8 +10,6 @@
>  #include "policydb.h"
>  #include "sidtab.h"
>  
> -extern struct policydb policydb;
> -
>  void services_compute_xperms_drivers(struct extended_perms *xperms,
>  				struct avtab_node *node);
>  
> @@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct
> extended_perms_decision *xpermd,
>  					struct avtab_node *node);
>  
>  #endif	/* _SS_SERVICES_H_ */
> -
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  2018-01-26 14:32   ` peter.enderborg at sony.com
@ 2018-01-30 14:37     ` Stephen Smalley
  -1 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 14:37 UTC (permalink / raw)
  To: peter.enderborg, Paul Moore, Eric Paris, James Morris,
	Daniel Jurgens, Doug Ledford, selinux, linux-security-module,
	linux-kernel, Ingo Molnar, alsa-devel, Serge E . Hallyn

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

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> From: Peter Enderborg <peter.enderborg@sony.com>
> 
> This i preparation for switching to RCU locks. To be able to use
> RCU we need atomic switched pointer. This adds the dynamic
> memory copying to be a single pointer. It copy all the
> data structures in to new ones. This is an overhead
> for writing rules but the benifit is RCU.
> 
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---
>  security/selinux/ss/services.c | 139 +++++++++++++++++++++++------
> ------------
>  1 file changed, 78 insertions(+), 61 deletions(-)
> 
> diff --git a/security/selinux/ss/services.c
> b/security/selinux/ss/services.c
> index 2a8486c..81c5717 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -2064,76 +2064,67 @@ static int security_preserve_bools(struct
> policydb *p);
>   */
>  int security_load_policy(void *data, size_t len)
>  {
> -	struct policydb *oldpolicydb, *newpolicydb;
> +	struct policydb *oldpolicydb;
>  	struct sidtab oldsidtab, newsidtab;
>  	struct selinux_mapping *oldmap = NULL, *map = NULL;
>  	struct convert_context_args args;
> -	struct shared_current_mapping *new_mapping;
>  	struct shared_current_mapping *next_rcu;
> -
> +	struct shared_current_mapping *old_rcu;
>  	u32 seqno;
>  	u16 map_size;
>  	int rc = 0;
>  	struct policy_file file = { data, len }, *fp = &file;
>  
> -	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
> -	if (!oldpolicydb) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
> -			      GFP_KERNEL);
> -	if (!new_mapping) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -	newpolicydb = oldpolicydb + 1;
> -	next_rcu = kmalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> -	if (!next_rcu) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -
>  	if (!ss_initialized) {
> -		crm = kzalloc(sizeof(struct shared_current_mapping),
> -			      GFP_KERNEL);
> -		if (!crm) {
> +		struct shared_current_mapping *first_mapping;
> +
> +		first_mapping = kzalloc(sizeof(struct
> shared_current_mapping),
> +					GFP_KERNEL);
> +		if (!first_mapping) {
>  			rc = -ENOMEM;
>  			goto out;
>  		}
>  		avtab_cache_init();
>  		ebitmap_cache_init();
>  		hashtab_cache_init();
> -		rc = policydb_read(&crm->policydb, fp);
> +		rc = policydb_read(&first_mapping->policydb, fp);
>  		if (rc) {
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		crm->policydb.len = len;
> -		rc = selinux_set_mapping(&crm->policydb,
> secclass_map,
> -					 &crm->current_mapping,
> -					 &crm-
> >current_mapping_size);
> +		first_mapping->policydb.len = len;
> +		rc = selinux_set_mapping(&first_mapping->policydb,
> secclass_map,
> +					 &first_mapping-
> >current_mapping,
> +					 &first_mapping-
> >current_mapping_size);
>  		if (rc) {
> -			policydb_destroy(&crm->policydb);
> +			policydb_destroy(&first_mapping->policydb);
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		rc = policydb_load_isids(&crm->policydb, &crm-
> >sidtab);
> +		rc = policydb_load_isids(&first_mapping->policydb,
> +					 &first_mapping->sidtab);
>  		if (rc) {
> -			policydb_destroy(&crm->policydb);
> +			policydb_destroy(&first_mapping->policydb);
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		security_load_policycaps(&crm->policydb);
> +		security_load_policycaps(&first_mapping->policydb);
> +		crm = first_mapping;
> +
> +		smp_mb(); /* make sure that crm exist before we */
> +			  /* switch ss_initialized */
>  		ss_initialized = 1;
>  		seqno = ++latest_granting;
>  		selinux_complete_init();
> @@ -2148,30 +2139,44 @@ int security_load_policy(void *data, size_t
> len)
>  #if 0
>  	sidtab_hash_eval(&crm->sidtab, "sids");
>  #endif
> +	oldpolicydb = kzalloc(sizeof(*oldpolicydb), GFP_KERNEL);
> +	if (!oldpolicydb) {
> +		rc = -ENOMEM;
> +		goto out;
> +	}
> +
> +	next_rcu = kzalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> +	if (!next_rcu) {
> +		kfree(oldpolicydb);
> +		rc = -ENOMEM;
> +		goto out;
> +	}
>  
> -	rc = policydb_read(newpolicydb, fp);
> +	rc = policydb_read(&next_rcu->policydb, fp);
>  	if (rc)
>  		goto out;
>  
> -	newpolicydb->len = len;
> +	next_rcu->policydb.len = len;
> +	read_lock(&policy_rwlock);
>  	/* If switching between different policy types, log MLS
> status */
> -	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
> +	if (crm->policydb.mls_enabled && !next_rcu-
> >policydb.mls_enabled)
>  		printk(KERN_INFO "SELinux: Disabling MLS
> support...\n");
> -	else if (!crm->policydb.mls_enabled && newpolicydb-
> >mls_enabled)
> +	else if (!crm->policydb.mls_enabled && next_rcu-
> >policydb.mls_enabled)
>  		printk(KERN_INFO "SELinux: Enabling MLS
> support...\n");
>  
> -	rc = policydb_load_isids(newpolicydb, &newsidtab);
> +	rc = policydb_load_isids(&next_rcu->policydb, &newsidtab);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to load the
> initial SIDs\n");
> -		policydb_destroy(newpolicydb);
> +		policydb_destroy(&next_rcu->policydb);
>  		goto out;
>  	}
>  
> -	rc = selinux_set_mapping(newpolicydb, secclass_map, &map,
> &map_size);
> +	rc = selinux_set_mapping(&next_rcu->policydb, secclass_map,
> +				 &map, &map_size);
>  	if (rc)
>  		goto err;
>  
> -	rc = security_preserve_bools(newpolicydb);
> +	rc = security_preserve_bools(&next_rcu->policydb);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to preserve
> booleans\n");
>  		goto err;

Most of this shouldn't need to be under the read lock.

> @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
> len)
>  	 * in the new SID table.
>  	 */
>  	args.oldp = &crm->policydb;
> -	args.newp = newpolicydb;
> +	args.newp = &next_rcu->policydb;
>  	rc = sidtab_map(&newsidtab, convert_context, &args);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to convert the
> internal"
> @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
> len)
>  
>  	/* Install the new policydb and SID table. */
>  	/* next */
> +	security_load_policycaps(&next_rcu->policydb);

This cannot be done outside of the write lock; it has to be atomic with
the policy switch.

> +	read_unlock(&policy_rwlock);
>  	write_lock_irq(&policy_rwlock);
> -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
> policydb));
>  	sidtab_set(&next_rcu->sidtab, &newsidtab);
>  	security_load_policycaps(&next_rcu->policydb);
>  	oldmap = crm->current_mapping;
> @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
> len)
>  	next_rcu->current_mapping_size = map_size;
>  
>  	seqno = ++latest_granting;
> -	write_unlock_irq(&policy_rwlock);
> +	old_rcu = crm;
>  	crm = next_rcu;
> +	write_unlock_irq(&policy_rwlock);
>  
>  	/* Free the old policydb and SID table. */
>  	policydb_destroy(oldpolicydb);
> @@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t
> len)
>  	selinux_status_update_policyload(seqno);
>  	selinux_netlbl_cache_invalidate();
>  	selinux_xfrm_notify_policyload();
> +	kfree(oldpolicydb);
> +	kfree(old_rcu);
>  
>  	rc = 0;
>  	goto out;
> -
>  err:
>  	kfree(map);
>  	sidtab_destroy(&newsidtab);
> -	policydb_destroy(newpolicydb);
> -
> +	policydb_destroy(&next_rcu->policydb);
>  out:
> -	kfree(oldpolicydb);
>  	return rc;
>  }
>  
> @@ -2795,54 +2801,65 @@ int security_get_bools(int *len, char
> ***names, int **values)
>  	goto out;
>  }
>  
> -
>  int security_set_bools(int len, int *values)
>  {
> +	struct shared_current_mapping *next_rcu, *old_rcu;
>  	int i, rc;
>  	int lenp, seqno = 0;
>  	struct cond_node *cur;
>  
> -	write_lock_irq(&policy_rwlock);
> -
> +	next_rcu = kzalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> +	read_lock(&policy_rwlock);
> +	old_rcu = crm;
> +	memcpy(&next_rcu->policydb, &old_rcu->policydb,
> +	       sizeof(struct policydb));

You are only doing a "shallow" copy of the policydb here, which
contains pointers to other structures.  So then below when you modify
state, you are modifying the original, not just the copy.  And you'll
end up double freeing if you free them both.

For reference, attached is a very old attempt to convert the policy
rwlock to RCU from KaiGai Kohei.  It may provide some insight into what
is needed here.
 
>  	rc = -EFAULT;
> -	lenp = crm->policydb.p_bools.nprim;
> +	lenp = next_rcu->policydb.p_bools.nprim;
> +
>  	if (len != lenp)
>  		goto out;
>  
>  	for (i = 0; i < len; i++) {
>  		if (!!values[i] !=
> -		    crm->policydb.bool_val_to_struct[i]->state) {
> +		    next_rcu->policydb.bool_val_to_struct[i]->state) 
> {
>  			audit_log(current->audit_context,
> GFP_ATOMIC,
>  				AUDIT_MAC_CONFIG_CHANGE,
>  				"bool=%s val=%d old_val=%d auid=%u
> ses=%u",
> -				sym_name(&crm->policydb, SYM_BOOLS,
> i),
> +				sym_name(&next_rcu->policydb,
> SYM_BOOLS, i),
>  				!!values[i],
> -				crm->policydb.bool_val_to_struct[i]-
> >state,
> +				next_rcu-
> >policydb.bool_val_to_struct[i]->state,
>  				from_kuid(&init_user_ns,
> audit_get_loginuid(current)),
>  				audit_get_sessionid(current));
>  		}
>  		if (values[i])
> -			crm->policydb.bool_val_to_struct[i]->state =
> 1;
> +			next_rcu->policydb.bool_val_to_struct[i]-
> >state = 1;
>  		else
> -			crm->policydb.bool_val_to_struct[i]->state =
> 0;
> +			next_rcu->policydb.bool_val_to_struct[i]-
> >state = 0;
>  	}
>  
> -	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
> -		rc = evaluate_cond_node(&crm->policydb, cur);
> +	for (cur = next_rcu->policydb.cond_list; cur; cur = cur-
> >next) {
> +		rc = evaluate_cond_node(&next_rcu->policydb, cur);
>  		if (rc)
>  			goto out;
>  	}
> +	read_unlock(&policy_rwlock);
> +	rc = 0;
>  
> +	write_lock_irq(&policy_rwlock);
>  	seqno = ++latest_granting;
> -	rc = 0;
> -out:
> +	crm = next_rcu;
>  	write_unlock_irq(&policy_rwlock);
> +out:
>  	if (!rc) {
>  		avc_ss_reset(seqno);
>  		selnl_notify_policyload(seqno);
>  		selinux_status_update_policyload(seqno);
>  		selinux_xfrm_notify_policyload();
> +	} else {
> +		kfree(next_rcu);
>  	}
> +	kfree(old_rcu);
> +
>  	return rc;
>  }
>  

[-- Attachment #2: selinux-nolock-policydb-041110.patch --]
[-- Type: text/x-patch, Size: 43716 bytes --]

diff -rNU4 linux-2.6.9.selinux/security/selinux/hooks.c linux-2.6.9.selinux-policydb/security/selinux/hooks.c
--- linux-2.6.9.selinux/security/selinux/hooks.c	2004-11-09 19:27:09.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/hooks.c	2004-11-09 19:27:07.000000000 +0900
@@ -290,9 +290,9 @@
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 /* The security server must be initialized before
    any labeling or access decisions can be provided. */
-extern int ss_initialized;
+extern struct policydb *policydb;
 
 /* The file system's label must be initialized prior to use. */
 
 static char *labeling_behaviors[6] = {
@@ -506,16 +506,18 @@
 	down(&sbsec->sem);
 	if (sbsec->initialized)
 		goto out;
 
-	if (!ss_initialized) {
+	rcu_read_lock();
+	if (!policydb) {
 		/* Defer initialization until selinux_complete_init,
 		   after the initial policy is loaded and the security
 		   server is ready to handle calls. */
 		spin_lock(&sb_security_lock);
 		if (list_empty(&sbsec->list))
 			list_add(&sbsec->list, &superblock_security_head);
 		spin_unlock(&sb_security_lock);
+		rcu_read_unlock();
 		goto out;
 	}
 
 	/* Determine the labeling behavior to use for this filesystem type. */
@@ -4416,12 +4418,15 @@
 {
 	extern void exit_sel_fs(void);
 	static int selinux_disabled = 0;
 
-	if (ss_initialized) {
+	rcu_read_lock();
+	if (policydb) {
 		/* Not permitted after initial policy load. */
+		rcu_read_unlock();
 		return -EINVAL;
 	}
+	rcu_read_unlock();
 
 	if (selinux_disabled) {
 		/* Only do this once. */
 		return -EINVAL;
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/avtab.c linux-2.6.9.selinux-policydb/security/selinux/ss/avtab.c
--- linux-2.6.9.selinux/security/selinux/ss/avtab.c	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/avtab.c	2004-11-10 11:43:39.000000000 +0900
@@ -231,9 +231,9 @@
 			kmem_cache_free(avtab_node_cachep, temp);
 		}
 		h->htable[i] = NULL;
 	}
-	vfree(h->htable);
+	kfree(h->htable);
 	h->htable = NULL;
 }
 
 
@@ -264,9 +264,9 @@
 int avtab_init(struct avtab *h)
 {
 	int i;
 
-	h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE);
+	h->htable = kmalloc(sizeof(*(h->htable)) * AVTAB_SIZE, GFP_KERNEL);
 	if (!h->htable)
 		return -ENOMEM;
 	for (i = 0; i < AVTAB_SIZE; i++)
 		h->htable[i] = NULL;
@@ -406,4 +406,38 @@
 	avtab_node_cachep = kmem_cache_create("avtab_node",
 					      sizeof(struct avtab_node),
 					      0, SLAB_PANIC, NULL, NULL);
 }
+
+int avtab_duplicate(struct avtab *new, struct avtab *orig)
+{
+	int i,rc;
+	struct avtab_node *node, *tmp, *tail;
+
+	if (!new || !orig)
+		return -EFAULT;
+
+	rc = avtab_init(new);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < AVTAB_SIZE; i++) {
+		tail = NULL;
+		for (node = orig->htable[i]; node; node = node->next) {
+			tmp = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
+			if (!tmp)
+				goto error;
+			memcpy(tmp, node, sizeof(struct avtab_node));
+			if (!tail) {
+				new->htable[i] = tmp;
+			} else {
+				tail->next = tmp;
+			}
+			tail = tmp;
+			new->nel++;
+		}
+	}
+	return 0;
+ error:
+	avtab_destroy(new);
+	return -ENOMEM;
+}
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/avtab.h linux-2.6.9.selinux-policydb/security/selinux/ss/avtab.h
--- linux-2.6.9.selinux/security/selinux/ss/avtab.h	2004-11-09 19:27:07.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/avtab.h	2004-11-10 11:44:09.000000000 +0900
@@ -79,9 +79,12 @@
 struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
 
 void avtab_cache_init(void);
 
-#define AVTAB_HASH_BITS 15
+int avtab_duplicate(struct avtab *new, struct avtab *orig);
+
+//#define AVTAB_HASH_BITS 15
+#define AVTAB_HASH_BITS 13
 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
 #define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
 
 #define AVTAB_SIZE AVTAB_HASH_BUCKETS
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/conditional.c linux-2.6.9.selinux-policydb/security/selinux/ss/conditional.c
--- linux-2.6.9.selinux/security/selinux/ss/conditional.c	2004-11-09 19:27:07.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/conditional.c	2004-11-10 21:29:08.000000000 +0900
@@ -12,9 +12,9 @@
 #include <linux/string.h>
 #include <linux/spinlock.h>
 #include <asm/semaphore.h>
 #include <linux/slab.h>
-
+#include <linux/rcupdate.h>
 #include "security.h"
 #include "conditional.h"
 
 /*
@@ -484,4 +484,213 @@
 			avd->auditallow |= avtab_auditallow(&node->datum);
 	}
 	return;
 }
+/* ------------------------------------------------------------ */
+static struct cond_av_list *cond_dup_av_list(struct cond_av_list *orig, struct avtab *te_cond)
+{
+	struct avtab_datum *avdatum;
+	struct cond_av_list *cur, *tmp, *tail = NULL, *head = NULL;
+
+	for (cur = orig; cur; cur = cur->next) {
+		avdatum = avtab_search(te_cond, &cur->node->key, cur->node->datum.specified);
+		if (!avdatum)
+			goto error;
+
+		tmp = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+		if (!tmp)
+			goto error;
+
+		tmp->node = container_of(avdatum, struct avtab_node, datum);
+		tmp->next = NULL;
+		if (!head) {
+			head = tail = tmp;
+		} else {
+			tail->next = tmp;
+			tail = tmp;
+		}
+	}
+	return head;
+ error:
+	for (cur=head; cur; cur = tmp) {
+		tmp = cur->next;
+		kfree(tmp);
+	}
+	return NULL;
+}
+
+static struct cond_expr *cond_dup_expr(struct cond_expr *orig)
+{
+	struct cond_expr *cur, *tmp, *tail, *head;
+
+	tail = head = NULL;
+	for (cur = orig; cur; cur = cur->next) {
+		tmp = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
+		if (!tmp)
+			goto error;
+		tmp->expr_type = cur->expr_type;
+		tmp->bool = cur->bool;
+		tmp->next = NULL;
+		if (!head) {
+			head = tail = tmp;
+		} else {
+			tail->next = tmp;
+			tail = tmp;
+		}
+	}
+	return head; /* success */
+
+ error:
+        for (cur = head; cur; cur = tmp) {
+                tmp = cur->next;
+                kfree(cur);
+        }
+        return NULL;
+}
+
+/* ------------------------------------------------------------ */
+int duplicate_policydb_cond_list(struct policydb *new, struct policydb *orig)
+{
+	int rc;
+	struct cond_node *cur, *tmp, *tail = NULL;
+
+	rc = avtab_duplicate(&new->te_cond_avtab, &orig->te_cond_avtab);
+	if (rc)
+		return rc;
+
+	new->cond_list = NULL;
+	for (cur = orig->cond_list; cur; cur = cur->next) {
+		tmp = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
+		if (!tmp)
+			goto error;
+		memset(tmp, 0, sizeof(struct cond_node));
+		tmp->cur_state = cur->cur_state;
+
+		if (!tail) {
+			new->cond_list = tmp;
+		} else {
+			tail->next = tmp;
+		}
+		tail = tmp;
+
+		tmp->expr = cond_dup_expr(cur->expr);
+		if (cur->expr && !tmp->expr)
+			goto error;
+
+		tmp->true_list = cond_dup_av_list(cur->true_list, &new->te_cond_avtab);
+		if (cur->true_list && !tmp->true_list)
+			goto error;
+
+		tmp->false_list = cond_dup_av_list(cur->false_list, &new->te_cond_avtab);
+		if (cur->false_list && !tmp->false_list)
+			goto error;
+	}
+	return 0; /* success*/
+
+ error:
+	cond_list_destroy(new->cond_list);
+	return -ENOMEM;
+}
+
+static int cond_bools_destroy(void *key, void *datum, void *args)
+{
+	kfree(datum);
+	return 0;
+}
+
+static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, void *args)
+{
+	struct cond_bool_datum *datum;
+
+	datum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
+	if (!datum)
+		return -ENOMEM;
+
+	memcpy(datum, orig->datum, sizeof(struct cond_bool_datum));
+
+	new->key = orig->key; /* Not need to duplicate */
+	new->datum = datum;
+	return 0;
+}
+
+static int cond_bools_index(void *key, void *datum, void *args)
+{
+	struct cond_bool_datum *booldatum, **cond_bool_array;
+
+	booldatum = datum;
+	cond_bool_array = args;
+	cond_bool_array[booldatum->value -1] = booldatum;
+
+	return 0;
+}
+
+static int duplicate_policydb_bools(struct policydb *newdb, struct policydb *orig)
+{
+	int len;
+	struct hashtab *newht;
+	struct cond_bool_datum **cond_bool_array;
+
+	if (!newdb || !orig)
+		return -EFAULT;
+
+	len = sizeof(struct cond_bool_datum *) * orig->p_bools.nprim;
+	cond_bool_array = kmalloc(len, GFP_KERNEL);
+	if (!cond_bool_array)
+		return -ENOMEM;
+	memset(cond_bool_array, 0, len);
+
+	newht = hashtab_duplicate(orig->p_bools.table, cond_bools_copy,
+					cond_bools_destroy, NULL);
+	if (!newht) {
+		kfree(cond_bool_array);
+		return -ENOMEM;
+	}
+	hashtab_map(newht, cond_bools_index, cond_bool_array);
+	newdb->bool_val_to_struct = cond_bool_array;
+	newdb->p_bools.table = newht;
+	newdb->p_bools.nprim = newht->nel;
+
+	return 0;
+}
+
+void cond_policydb_free_rcu(struct rcu_head *p)
+{
+	struct policydb *old_policy;
+
+	old_policy = container_of(p, struct policydb, rhead);
+
+	hashtab_map(old_policy->p_bools.table, cond_bools_destroy, NULL);
+	hashtab_destroy(old_policy->p_bools.table);
+	kfree(old_policy->bool_val_to_struct);
+	
+	avtab_destroy(&old_policy->te_cond_avtab);
+	cond_list_destroy(old_policy->cond_list);
+
+	printk("olddb was kfree()'d at cond_policydb_free_rcu()\n");
+	
+	kfree(old_policy);
+}
+
+struct policydb *cond_policydb_dup(struct policydb *orig)
+{
+	struct policydb *newdb;
+
+	newdb = kmalloc(sizeof(struct policydb), GFP_KERNEL);
+	if (!newdb)
+		return NULL;
+
+	memcpy(newdb, orig, sizeof(struct policydb));
+
+	if (duplicate_policydb_bools(newdb, orig)) {
+		kfree(newdb);
+		return NULL;
+	}
+
+	if (duplicate_policydb_cond_list(newdb, orig)) {
+		cond_policydb_destroy(newdb);
+		kfree(newdb);
+		return NULL;
+	}
+
+	return newdb; /* success */
+}
+/* ------------------------------------------------------------ */
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/conditional.h linux-2.6.9.selinux-policydb/security/selinux/ss/conditional.h
--- linux-2.6.9.selinux/security/selinux/ss/conditional.h	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/conditional.h	2004-11-09 19:27:05.000000000 +0900
@@ -73,5 +73,8 @@
 void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
 
 int evaluate_cond_node(struct policydb *p, struct cond_node *node);
 
+void cond_policydb_free_rcu(struct rcu_head *p);
+struct policydb *cond_policydb_dup(struct policydb *orig);
+
 #endif /* _CONDITIONAL_H_ */
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/hashtab.c linux-2.6.9.selinux-policydb/security/selinux/ss/hashtab.c
--- linux-2.6.9.selinux/security/selinux/ss/hashtab.c	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/hashtab.c	2004-11-10 21:32:56.000000000 +0900
@@ -277,4 +277,56 @@
 
 	info->slots_used = slots_used;
 	info->max_chain_len = max_chain_len;
 }
+
+struct hashtab *hashtab_duplicate(struct hashtab *orig,
+		int (*copy)(struct hashtab_node *new, struct hashtab_node *orig, void *args),
+		int (*destroy)(void *k, void *d, void *args),
+		void *args)
+{
+	int i,rc;
+	struct hashtab *new;
+	struct hashtab_node *cur, *tmp, *tail;
+
+	if (!orig || !copy || !destroy)
+		return NULL;
+
+	new = hashtab_create(orig->hash_value, orig->keycmp, orig->size);
+	if (!new)
+		return NULL;
+
+	for (i = 0; i < orig->size; i++) {
+		tail = NULL;
+		for (cur = orig->htable[i]; cur; cur = cur->next) {
+			tmp = kmalloc(sizeof(struct hashtab_node), GFP_KERNEL);
+			if (!tmp)
+				goto error;
+			rc = copy(tmp, cur, args);
+			if (rc) {
+				kfree(tmp);
+				goto error;
+			}
+			tmp->next = NULL;
+			if (!tail) {
+				new->htable[i] = tmp;
+			} else {
+				tail->next = tmp;
+			}
+			tail = tmp;
+			new->nel++;
+		}
+	}
+	return new;
+ error:
+	for (i = 0; i < new->size; i++) {
+		for (cur = new->htable[i]; cur; cur = tmp) {
+			tmp = cur->next;
+			destroy(cur->key, cur->datum, args);
+			kfree(cur);
+		}
+	}
+	kfree(new);
+	return NULL;	
+}
+
+
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/hashtab.h linux-2.6.9.selinux-policydb/security/selinux/ss/hashtab.h
--- linux-2.6.9.selinux/security/selinux/ss/hashtab.h	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/hashtab.h	2004-11-09 19:27:05.000000000 +0900
@@ -121,5 +121,12 @@
 
 /* Fill info with some hash table statistics */
 void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
 
+
+struct hashtab *hashtab_duplicate(struct hashtab *orig,
+		int (*copy)(struct hashtab_node *new, struct hashtab_node *orig, void *args),
+		int (*destroy)(void *k, void *d, void *args),
+		void *args);
+
+
 #endif	/* _SS_HASHTAB_H */
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/policydb.c linux-2.6.9.selinux-policydb/security/selinux/ss/policydb.c
--- linux-2.6.9.selinux/security/selinux/ss/policydb.c	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/policydb.c	2004-11-11 10:27:54.889230773 +0900
@@ -141,8 +141,13 @@
 	int i, rc;
 
 	memset(p, 0, sizeof(*p));
 
+	p->sidtab = kmalloc(sizeof(struct sidtab), GFP_KERNEL);
+	if (!p->sidtab)
+		return -ENOMEM;
+	sidtab_init(p->sidtab);
+
 	for (i = 0; i < SYM_NUM; i++) {
 		rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
 		if (rc)
 			goto out_free_symtab;
@@ -168,8 +173,9 @@
 
 out_free_symtab:
 	for (i = 0; i < SYM_NUM; i++)
 		hashtab_destroy(p->symtab[i].table);
+	kfree(p->sidtab);
 	goto out;
 }
 
 /*
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/policydb.h linux-2.6.9.selinux-policydb/security/selinux/ss/policydb.h
--- linux-2.6.9.selinux/security/selinux/ss/policydb.h	2004-11-09 19:27:08.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/policydb.h	2004-11-09 19:27:04.000000000 +0900
@@ -17,8 +17,9 @@
 
 #ifndef _SS_POLICYDB_H_
 #define _SS_POLICYDB_H_
 
+#include <linux/rcupdate.h>
 #include "symtab.h"
 #include "avtab.h"
 #include "sidtab.h"
 #include "context.h"
@@ -245,8 +246,10 @@
 	struct ebitmap trustedreaders;
 	struct ebitmap trustedwriters;
 	struct ebitmap trustedobjects;
 #endif
+	struct rcu_head rhead;
+	struct sidtab *sidtab;
 };
 
 extern int policydb_init(struct policydb *p);
 extern int policydb_index_classes(struct policydb *p);
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/services.c linux-2.6.9.selinux-policydb/security/selinux/ss/services.c
--- linux-2.6.9.selinux/security/selinux/ss/services.c	2004-11-09 20:14:15.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/services.c	2004-11-10 21:29:15.000000000 +0900
@@ -41,21 +41,16 @@
 
 extern void selnl_notify_policyload(u32 seqno);
 extern int policydb_loaded_version;
 
-static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED;
-#define POLICY_RDLOCK read_lock(&policy_rwlock)
-#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
-#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
-#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
+#define POLICY_RDLOCK	rcu_read_lock();
+#define POLICY_RDUNLOCK	rcu_read_unlock();
 
 static DECLARE_MUTEX(load_sem);
-#define LOAD_LOCK down(&load_sem)
-#define LOAD_UNLOCK up(&load_sem)
+#define LOAD_LOCK do{ down(&load_sem); rcu_read_lock(); } while(0)
+#define LOAD_UNLOCK do{ rcu_read_unlock(); up(&load_sem); } while(0)
 
-struct sidtab sidtab;
-struct policydb policydb;
-int ss_initialized = 0;
+struct policydb *policydb = NULL;
 
 /*
  * The largest sequence number that has been used when
  * providing an access decision to the access vector cache.
@@ -68,9 +63,10 @@
  * Return the boolean value of a constraint expression
  * when it is applied to the specified source and target
  * security contexts.
  */
-static int constraint_expr_eval(struct context *scontext,
+static int constraint_expr_eval(struct policydb *p,
+				struct context *scontext,
 				struct context *tcontext,
 				struct constraint_expr *cexpr)
 {
 	u32 val1, val2;
@@ -110,10 +106,10 @@
 				break;
 			case CEXPR_ROLE:
 				val1 = scontext->role;
 				val2 = tcontext->role;
-				r1 = policydb.role_val_to_struct[val1 - 1];
-				r2 = policydb.role_val_to_struct[val2 - 1];
+				r1 = p->role_val_to_struct[val1 - 1];
+				r2 = p->role_val_to_struct[val2 - 1];
 				switch (e->op) {
 				case CEXPR_DOM:
 					s[++sp] = ebitmap_get_bit(&r1->dominates,
 								  val2 - 1);
@@ -191,9 +187,10 @@
 /*
  * Compute access vectors based on a context structure pair for
  * the permissions in a particular class.
  */
-static int context_struct_compute_av(struct context *scontext,
+static int context_struct_compute_av(struct policydb *p,
+				     struct context *scontext,
 				     struct context *tcontext,
 				     u16 tclass,
 				     u32 requested,
 				     struct av_decision *avd)
@@ -214,14 +211,14 @@
 		if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
 		    tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
 			tclass = SECCLASS_NETLINK_SOCKET;
 
-	if (!tclass || tclass > policydb.p_classes.nprim) {
+	if (!tclass || tclass > p->p_classes.nprim) {
 		printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
 		       tclass);
 		return -EINVAL;
 	}
-	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+	tclass_datum = p->class_val_to_struct[tclass - 1];
 
 	/*
 	 * Initialize the access vectors to the default values.
 	 */
@@ -237,9 +234,9 @@
 	 */
 	avkey.source_type = scontext->type;
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
-	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
+	avdatum = avtab_search(&p->te_avtab, &avkey, AVTAB_AV);
 	if (avdatum) {
 		if (avdatum->specified & AVTAB_ALLOWED)
 			avd->allowed = avtab_allowed(avdatum);
 		if (avdatum->specified & AVTAB_AUDITDENY)
@@ -248,9 +245,9 @@
 			avd->auditallow = avtab_auditallow(avdatum);
 	}
 
 	/* Check conditional av table for additional permissions */
-	cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
+	cond_compute_av(&p->te_cond_avtab, &avkey, avd);
 
 	/*
 	 * Remove any permissions prohibited by the MLS policy.
 	 */
@@ -261,9 +258,9 @@
 	 */
 	constraint = tclass_datum->constraints;
 	while (constraint) {
 		if ((constraint->permissions & (avd->allowed)) &&
-		    !constraint_expr_eval(scontext, tcontext,
+		    !constraint_expr_eval(p, scontext, tcontext,
 					  constraint->expr)) {
 			avd->allowed = (avd->allowed) & ~(constraint->permissions);
 		}
 		constraint = constraint->next;
@@ -276,9 +273,9 @@
 	 */
 	if (tclass == SECCLASS_PROCESS &&
 	    (avd->allowed & PROCESS__TRANSITION) &&
 	    scontext->role != tcontext->role) {
-		for (ra = policydb.role_allow; ra; ra = ra->next) {
+		for (ra = p->role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
 			    tcontext->role == ra->new_role)
 				break;
 		}
@@ -307,38 +304,40 @@
 			u16 tclass,
 			u32 requested,
 			struct av_decision *avd)
 {
+	struct policydb *p;
 	struct context *scontext = NULL, *tcontext = NULL;
 	int rc = 0;
 
-	if (!ss_initialized) {
+	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
 		avd->allowed = requested;
 		avd->decided = requested;
 		avd->auditallow = 0;
 		avd->auditdeny = 0xffffffff;
 		avd->seqno = latest_granting;
-		return 0;
+		goto out;
 	}
 
-	POLICY_RDLOCK;
-
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(p->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "security_compute_av:  unrecognized SID %d\n",
 		       ssid);
 		rc = -EINVAL;
 		goto out;
 	}
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(p->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "security_compute_av:  unrecognized SID %d\n",
 		       tsid);
 		rc = -EINVAL;
 		goto out;
 	}
 
-	rc = context_struct_compute_av(scontext, tcontext, tclass,
+	rc = context_struct_compute_av(p, scontext, tcontext, tclass,
 				       requested, avd);
 out:
 	POLICY_RDUNLOCK;
 	return rc;
@@ -350,19 +349,20 @@
  * allocated string of the correct size.  Set `*scontext'
  * to point to this string and set `*scontext_len' to
  * the length of the string.
  */
-int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
+int context_struct_to_string(struct policydb *p, struct context *context,
+                             char **scontext, u32 *scontext_len)
 {
 	char *scontextp;
 
 	*scontext = NULL;
 	*scontext_len = 0;
 
 	/* Compute the size of the context. */
-	*scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
-	*scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
-	*scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+	*scontext_len += strlen(p->p_user_val_to_name[context->user - 1]) + 1;
+	*scontext_len += strlen(p->p_role_val_to_name[context->role - 1]) + 1;
+	*scontext_len += strlen(p->p_type_val_to_name[context->type - 1]) + 1;
 	*scontext_len += mls_compute_context_len(context);
 
 	/* Allocate space for the context; caller must free this space. */
 	scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC);
@@ -374,14 +374,14 @@
 	/*
 	 * Copy the user name, role name and type name into the context.
 	 */
 	sprintf(scontextp, "%s:%s:%s:",
-		policydb.p_user_val_to_name[context->user - 1],
-		policydb.p_role_val_to_name[context->role - 1],
-		policydb.p_type_val_to_name[context->type - 1]);
-	scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
-	             1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
-	             1 + strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+		p->p_user_val_to_name[context->user - 1],
+		p->p_role_val_to_name[context->role - 1],
+		p->p_type_val_to_name[context->type - 1]);
+	scontextp += strlen(p->p_user_val_to_name[context->user - 1]) +
+	             1 + strlen(p->p_role_val_to_name[context->role - 1]) +
+	             1 + strlen(p->p_type_val_to_name[context->type - 1]) + 1;
 
 	mls_sid_to_context(context, &scontextp);
 
 	scontextp--;
@@ -403,12 +403,16 @@
  * to point to this string and set @scontext_len to the length of the string.
  */
 int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
 {
+	struct policydb *p;
 	struct context *context;
 	int rc = 0;
 
-	if (!ss_initialized) {
+	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
 		if (sid <= SECINITSID_NUM) {
 			char *scontextp;
 
 			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
@@ -421,20 +425,19 @@
 		       "load_policy on unknown SID %d\n", sid);
 		rc = -EINVAL;
 		goto out;
 	}
-	POLICY_RDLOCK;
-	context = sidtab_search(&sidtab, sid);
+
+	context = sidtab_search(p->sidtab, sid);
 	if (!context) {
 		printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
 		       "%d\n", sid);
 		rc = -EINVAL;
-		goto out_unlock;
+		goto out;
 	}
-	rc = context_struct_to_string(context, scontext, scontext_len);
-out_unlock:
-	POLICY_RDUNLOCK;
+	rc = context_struct_to_string(p, context, scontext, scontext_len);
 out:
+	POLICY_RDUNLOCK;
 	return rc;
 
 }
 
@@ -451,47 +454,46 @@
  */
 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 {
 	char *scontext2;
+	struct policydb *pol;
 	struct context context;
 	struct role_datum *role;
 	struct type_datum *typdatum;
 	struct user_datum *usrdatum;
 	char *scontextp, *p, oldc;
 	int rc = 0;
 
-	if (!ss_initialized) {
+	/* Copy the string so that we can modify the copy as we parse it.
+	   The string should already by null terminated, but we append a
+	   null suffix to the copy to avoid problems with the existing
+	   attr package, which doesn't view the null terminator as part
+	   of the attribute value. */
+	scontext2 = kmalloc(scontext_len+1,GFP_KERNEL);
+	if (!scontext2)
+		return -ENOMEM;
+	memcpy(scontext2, scontext, scontext_len);
+	scontext2[scontext_len] = 0;
+
+	POLICY_RDLOCK;
+	pol = policydb;
+
+	if (!pol) {
 		int i;
 
 		for (i = 1; i < SECINITSID_NUM; i++) {
-			if (!strcmp(initial_sid_to_string[i], scontext)) {
+			if (!strcmp(initial_sid_to_string[i], scontext2)) {
 				*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);
-	if (!scontext2) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	memcpy(scontext2, scontext, scontext_len);
-	scontext2[scontext_len] = 0;
 
 	context_init(&context);
 	*sid = SECSID_NULL;
 
-	POLICY_RDLOCK;
-
 	/* Parse the security context. */
 
 	rc = -EINVAL;
 	scontextp = (char *) scontext2;
@@ -505,9 +507,9 @@
 		goto out_unlock;
 
 	*p++ = 0;
 
-	usrdatum = hashtab_search(policydb.p_users.table, scontextp);
+	usrdatum = hashtab_search(pol->p_users.table, scontextp);
 	if (!usrdatum)
 		goto out_unlock;
 
 	context.user = usrdatum->value;
@@ -521,9 +523,9 @@
 		goto out_unlock;
 
 	*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;
 
@@ -533,9 +535,9 @@
 		p++;
 	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;
 
 	context.type = typdatum->value;
@@ -549,43 +551,44 @@
 		goto out_unlock;
 	}
 
 	/* Check the validity of the new context. */
-	if (!policydb_context_isvalid(&policydb, &context)) {
+	if (!policydb_context_isvalid(pol, &context)) {
 		rc = -EINVAL;
 		goto out_unlock;
 	}
 	/* Obtain the new sid. */
-	rc = sidtab_context_to_sid(&sidtab, &context, sid);
+	rc = sidtab_context_to_sid(pol->sidtab, &context, sid);
 out_unlock:
 	POLICY_RDUNLOCK;
 	context_destroy(&context);
-	kfree(scontext2);
 out:
+	kfree(scontext2);
 	return rc;
 }
 
 static int compute_sid_handle_invalid_context(
+	struct policydb *p,
 	struct context *scontext,
 	struct context *tcontext,
 	u16 tclass,
 	struct context *newcontext)
 {
 	char *s = NULL, *t = NULL, *n = NULL;
 	u32 slen, tlen, nlen;
 
-	if (context_struct_to_string(scontext, &s, &slen) < 0)
+	if (context_struct_to_string(p, scontext, &s, &slen) < 0)
 		goto out;
-	if (context_struct_to_string(tcontext, &t, &tlen) < 0)
+	if (context_struct_to_string(p, tcontext, &t, &tlen) < 0)
 		goto out;
-	if (context_struct_to_string(newcontext, &n, &nlen) < 0)
+	if (context_struct_to_string(p, newcontext, &n, &nlen) < 0)
 		goto out;
 	audit_log(current->audit_context,
 		  "security_compute_sid:  invalid context %s"
 		  " for scontext=%s"
 		  " tcontext=%s"
 		  " tclass=%s",
-		  n, s, t, policydb.p_class_val_to_name[tclass-1]);
+		  n, s, t, p->p_class_val_to_name[tclass-1]);
 out:
 	kfree(s);
 	kfree(t);
 	kfree(n);
@@ -599,17 +602,21 @@
 				u16 tclass,
 				u32 specified,
 				u32 *out_sid)
 {
+	struct policydb *p;
 	struct context *scontext = NULL, *tcontext = NULL, newcontext;
 	struct role_trans *roletr = NULL;
 	struct avtab_key avkey;
 	struct avtab_datum *avdatum;
 	struct avtab_node *node;
 	unsigned int type_change = 0;
 	int rc = 0;
 
-	if (!ss_initialized) {
+	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
 		switch (tclass) {
 		case SECCLASS_PROCESS:
 			*out_sid = ssid;
 			break;
@@ -619,18 +626,16 @@
 		}
 		goto out;
 	}
 
-	POLICY_RDLOCK;
-
-	scontext = sidtab_search(&sidtab, ssid);
+	scontext = sidtab_search(p->sidtab, ssid);
 	if (!scontext) {
 		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
 		       ssid);
 		rc = -EINVAL;
 		goto out_unlock;
 	}
-	tcontext = sidtab_search(&sidtab, tsid);
+	tcontext = sidtab_search(p->sidtab, tsid);
 	if (!tcontext) {
 		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
 		       tsid);
 		rc = -EINVAL;
@@ -669,13 +674,13 @@
 	/* Look for a type transition/member/change rule. */
 	avkey.source_type = scontext->type;
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
-	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
+	avdatum = avtab_search(&p->te_avtab, &avkey, AVTAB_TYPE);
 
 	/* If no permanent rule, also check for enabled conditional rules */
 	if(!avdatum) {
-		node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified);
+		node = avtab_search_node(&p->te_cond_avtab, &avkey, specified);
 		for (; node != NULL; node = avtab_search_node_next(node, specified)) {
 			if (node->datum.specified & AVTAB_ENABLED) {
 				avdatum = &node->datum;
 				break;
@@ -703,9 +708,9 @@
 	switch (tclass) {
 	case SECCLASS_PROCESS:
 		if (specified & AVTAB_TRANSITION) {
 			/* Look for a role transition rule. */
-			for (roletr = policydb.role_tr; roletr;
+			for (roletr = p->role_tr; roletr;
 			     roletr = roletr->next) {
 				if (roletr->role == scontext->role &&
 				    roletr->type == tcontext->type) {
 					/* Use the role transition rule. */
@@ -740,18 +745,16 @@
 	if (rc)
 		goto out_unlock;
 
 	/* Check the validity of the context. */
-	if (!policydb_context_isvalid(&policydb, &newcontext)) {
-		rc = compute_sid_handle_invalid_context(scontext,
-							tcontext,
-							tclass,
-							&newcontext);
+	if (!policydb_context_isvalid(p, &newcontext)) {
+		rc = compute_sid_handle_invalid_context(p, scontext, tcontext,
+							tclass, &newcontext);
 		if (rc)
 			goto out_unlock;
 	}
 	/* Obtain the sid for the context. */
-	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+	rc = sidtab_context_to_sid(p->sidtab, &newcontext, out_sid);
 out_unlock:
 	POLICY_RDUNLOCK;
 	context_destroy(&newcontext);
 out:
@@ -913,9 +916,9 @@
 
 	return sidtab_insert(s, sid, context);
 }
 
-static inline int convert_context_handle_invalid_context(struct context *context)
+static inline int convert_context_handle_invalid_context(struct policydb *p, struct context *context)
 {
 	int rc = 0;
 
 	if (selinux_enforcing) {
@@ -923,9 +926,9 @@
 	} else {
 		char *s;
 		u32 len;
 
-		context_struct_to_string(context, &s, &len);
+		context_struct_to_string(p, context, &s, &len);
 		printk(KERN_ERR "security:  context %s is invalid\n", s);
 		kfree(s);
 	}
 	return rc;
@@ -993,26 +996,37 @@
 		goto bad;
 
 	/* Check the validity of the new context. */
 	if (!policydb_context_isvalid(args->newp, c)) {
-		rc = convert_context_handle_invalid_context(&oldc);
+		rc = convert_context_handle_invalid_context(args->oldp, &oldc);
 		if (rc)
 			goto bad;
 	}
 
 	context_destroy(&oldc);
 out:
 	return rc;
 bad:
-	context_struct_to_string(&oldc, &s, &len);
+	context_struct_to_string(args->oldp, &oldc, &s, &len);
 	context_destroy(&oldc);
 	printk(KERN_ERR "security:  invalidating context %s\n", s);
 	kfree(s);
 	goto out;
 }
 
 extern void selinux_complete_init(void);
 
+void policydb_destroy_rcu(struct rcu_head *p)
+{
+	struct policydb *olddb;
+	olddb = container_of(p, struct policydb, rhead);
+
+	sidtab_destroy(olddb->sidtab);	
+	policydb_destroy(olddb);
+	kfree(olddb);
+	printk("kfree(olddb) in policydb_destroy_rcu() preempt()=0x%x\n",preempt_count());
+}
+
 /**
  * security_load_policy - Load a security policy configuration.
  * @data: binary policy data
  * @len: length of data in bytes
@@ -1023,29 +1037,34 @@
  * loading the new policy.
  */
 int security_load_policy(void *data, size_t len)
 {
-	struct policydb oldpolicydb, newpolicydb;
-	struct sidtab oldsidtab, newsidtab;
+	struct policydb *newdb, *olddb;
 	struct convert_context_args args;
 	u32 seqno;
 	int rc = 0;
 	struct policy_file file = { data, len }, *fp = &file;
 
+	newdb = kmalloc(sizeof(struct policydb), GFP_KERNEL);
+	if (!newdb)
+		return -ENOMEM;
+
 	LOAD_LOCK;
+	olddb = policydb;
 
-	if (!ss_initialized) {
+	if (!olddb) {
 		avtab_cache_init();
-		if (policydb_read(&policydb, fp)) {
+		if (policydb_read(newdb, fp)) {
 			LOAD_UNLOCK;
 			return -EINVAL;
 		}
-		if (policydb_load_isids(&policydb, &sidtab)) {
+		if (policydb_load_isids(newdb, newdb->sidtab)) {
 			LOAD_UNLOCK;
-			policydb_destroy(&policydb);
+			policydb_destroy(newdb);
 			return -EINVAL;
 		}
-		ss_initialized = 1;
+		smp_wmb();
+		policydb = newdb;
 
 		LOAD_UNLOCK;
 		selinux_complete_init();
 		return 0;
@@ -1054,62 +1073,52 @@
 #if 0
 	sidtab_hash_eval(&sidtab, "sids");
 #endif
 
-	if (policydb_read(&newpolicydb, fp)) {
+	if (policydb_read(newdb, fp)) {
 		LOAD_UNLOCK;
 		return -EINVAL;
 	}
 
-	sidtab_init(&newsidtab);
-
 	/* Verify that the existing classes did not change. */
-	if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
+	if (hashtab_map(olddb->p_classes.table, validate_class, newdb)) {
 		printk(KERN_ERR "security:  the definition of an existing "
 		       "class changed\n");
 		rc = -EINVAL;
 		goto err;
 	}
-
+	
 	/* Clone the SID table. */
-	sidtab_shutdown(&sidtab);
-	if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
+	sidtab_shutdown(olddb->sidtab);
+	if (sidtab_map(olddb->sidtab, clone_sid, newdb->sidtab)) {
 		rc = -ENOMEM;
 		goto err;
 	}
 
 	/* Convert the internal representations of contexts
 	   in the new SID table and remove invalid SIDs. */
-	args.oldp = &policydb;
-	args.newp = &newpolicydb;
-	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
-
-	/* Save the old policydb and SID table to free later. */
-	memcpy(&oldpolicydb, &policydb, sizeof policydb);
-	sidtab_set(&oldsidtab, &sidtab);
-
-	/* Install the new policydb and SID table. */
-	POLICY_WRLOCK;
-	memcpy(&policydb, &newpolicydb, sizeof policydb);
-	sidtab_set(&sidtab, &newsidtab);
+	args.oldp = olddb;
+	args.newp = newdb;
+	sidtab_map_remove_on_error(newdb->sidtab, convert_context, &args);
+
+	/* update policydb atomically */
+	smp_wmb();
+	policydb = newdb;
 	seqno = ++latest_granting;
-
-	POLICY_WRUNLOCK;
+	
 	LOAD_UNLOCK;
 
-	/* Free the old policydb and SID table. */
-	policydb_destroy(&oldpolicydb);
-	sidtab_destroy(&oldsidtab);
+	call_rcu(&olddb->rhead, policydb_destroy_rcu);
 
 	avc_ss_reset(seqno);
 	selnl_notify_policyload(seqno);
 
 	return 0;
 
 err:
 	LOAD_UNLOCK;
-	sidtab_destroy(&newsidtab);
-	policydb_destroy(&newpolicydb);
+	sidtab_destroy(newdb->sidtab);
+	policydb_destroy(newdb);
 	return rc;
 
 }
 
@@ -1126,14 +1135,21 @@
 		      u8 protocol,
 		      u16 port,
 		      u32 *out_sid)
 {
+	struct policydb *p;
 	struct ocontext *c;
 	int rc = 0;
 
 	POLICY_RDLOCK;
+	p = policydb;
 
-	c = policydb.ocontexts[OCON_PORT];
+	if (!p) {
+		*out_sid = SECINITSID_PORT;
+		goto out;
+	}
+
+	c = p->ocontexts[OCON_PORT];
 	while (c) {
 		if (c->u.port.protocol == protocol &&
 		    c->u.port.low_port <= port &&
 		    c->u.port.high_port >= port)
@@ -1142,9 +1158,9 @@
 	}
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(p->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -1169,27 +1185,35 @@
 		       u32 *if_sid,
 		       u32 *msg_sid)
 {
 	int rc = 0;
+	struct policydb *p;
 	struct ocontext *c;
 
 	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
+		*if_sid = SECINITSID_NETIF;
+		*msg_sid = SECINITSID_NETMSG;
+		goto out;
+	}
 
-	c = policydb.ocontexts[OCON_NETIF];
+	c = p->ocontexts[OCON_NETIF];
 	while (c) {
 		if (strcmp(name, c->u.name) == 0)
 			break;
 		c = c->next;
 	}
 
 	if (c) {
 		if (!c->sid[0] || !c->sid[1]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(p->sidtab,
 						  &c->context[0],
 						  &c->sid[0]);
 			if (rc)
 				goto out;
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(p->sidtab,
 						   &c->context[1],
 						   &c->sid[1]);
 			if (rc)
 				goto out;
@@ -1231,11 +1255,18 @@
 		      u32 addrlen,
 		      u32 *out_sid)
 {
 	int rc = 0;
+	struct policydb *p;
 	struct ocontext *c;
 
 	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
+		*out_sid = SECINITSID_NODE;
+		goto out;
+	}
 
 	switch (domain) {
 	case AF_INET: {
 		u32 addr;
@@ -1246,9 +1277,9 @@
 		}
 
 		addr = *((u32 *)addrp);
 
-		c = policydb.ocontexts[OCON_NODE];
+		c = p->ocontexts[OCON_NODE];
 		while (c) {
 			if (c->u.node.addr == (addr & c->u.node.mask))
 				break;
 			c = c->next;
@@ -1260,9 +1291,9 @@
 		if (addrlen != sizeof(u64) * 2) {
 			rc = -EINVAL;
 			goto out;
 		}
-		c = policydb.ocontexts[OCON_NODE6];
+		c = p->ocontexts[OCON_NODE6];
 		while (c) {
 			if (match_ipv6_addrmask(addrp, c->u.node6.addr,
 						c->u.node6.mask))
 				break;
@@ -1276,9 +1307,9 @@
 	}
 
 	if (c) {
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(p->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -1313,64 +1344,66 @@
 	                   char *username,
 			   u32 **sids,
 			   u32 *nel)
 {
+	struct policydb *p;
 	struct context *fromcon, usercon;
 	u32 *mysids, *mysids2, sid;
 	u32 mynel = 0, maxnel = SIDS_NEL;
 	struct user_datum *user;
 	struct role_datum *role;
 	struct av_decision avd;
 	int rc = 0, i, j;
 
-	if (!ss_initialized) {
+	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
 		*sids = NULL;
 		*nel = 0;
 		goto out;
 	}
 
-	POLICY_RDLOCK;
-
-	fromcon = sidtab_search(&sidtab, fromsid);
+	fromcon = sidtab_search(p->sidtab, fromsid);
 	if (!fromcon) {
 		rc = -EINVAL;
-		goto out_unlock;
+		goto out;
 	}
 
-	user = hashtab_search(policydb.p_users.table, username);
+	user = hashtab_search(p->p_users.table, username);
 	if (!user) {
 		rc = -EINVAL;
-		goto out_unlock;
+		goto out;
 	}
 	usercon.user = user->value;
 
 	mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC);
 	if (!mysids) {
 		rc = -ENOMEM;
-		goto out_unlock;
+		goto out;
 	}
 	memset(mysids, 0, maxnel*sizeof(*mysids));
 
 	for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) {
 		if (!ebitmap_get_bit(&user->roles, i))
 			continue;
-		role = policydb.role_val_to_struct[i];
+		role = p->role_val_to_struct[i];
 		usercon.role = i+1;
 		for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) {
 			if (!ebitmap_get_bit(&role->types, j))
 				continue;
 			usercon.type = j+1;
 			mls_for_user_ranges(user,usercon) {
-				rc = context_struct_compute_av(fromcon, &usercon,
+				rc = context_struct_compute_av(p, fromcon, &usercon,
 							       SECCLASS_PROCESS,
 							       PROCESS__TRANSITION,
 							       &avd);
 				if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
 					continue;
-				rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+				rc = sidtab_context_to_sid(p->sidtab, &usercon, &sid);
 				if (rc) {
 					kfree(mysids);
-					goto out_unlock;
+					goto out;
 				}
 				if (mynel < maxnel) {
 					mysids[mynel++] = sid;
 				} else {
@@ -1378,9 +1411,9 @@
 					mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
 					if (!mysids2) {
 						rc = -ENOMEM;
 						kfree(mysids);
-						goto out_unlock;
+						goto out;
 					}
 					memset(mysids2, 0, maxnel*sizeof(*mysids2));
 					memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
 					kfree(mysids);
@@ -1393,12 +1426,10 @@
 	}
 
 	*sids = mysids;
 	*nel = mynel;
-
-out_unlock:
-	POLICY_RDUNLOCK;
 out:
+	POLICY_RDUNLOCK;
 	return rc;
 }
 
 /**
@@ -1417,15 +1448,23 @@
 		       u16 sclass,
 		       u32 *sid)
 {
 	int len;
+	struct policydb *p;
 	struct genfs *genfs;
 	struct ocontext *c;
 	int rc = 0, cmp = 0;
 
 	POLICY_RDLOCK;
+	p = policydb;
 
-	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+	if (!p) {
+		*sid = SECINITSID_UNLABELED;
+		rc = -ENOENT;
+		goto out;
+	}
+
+	for (genfs = p->genfs; genfs; genfs = genfs->next) {
 		cmp = strcmp(fstype, genfs->fstype);
 		if (cmp <= 0)
 			break;
 	}
@@ -1449,9 +1488,9 @@
 		goto out;
 	}
 
 	if (!c->sid[0]) {
-		rc = sidtab_context_to_sid(&sidtab,
+		rc = sidtab_context_to_sid(p->sidtab,
 					   &c->context[0],
 					   &c->sid[0]);
 		if (rc)
 			goto out;
@@ -1474,13 +1513,21 @@
 	unsigned int *behavior,
 	u32 *sid)
 {
 	int rc = 0;
+	struct policydb *p;
 	struct ocontext *c;
 
 	POLICY_RDLOCK;
+	p = policydb;
+
+	if (!p) {
+		*sid = SECINITSID_UNLABELED;
+		*behavior = SECURITY_FS_USE_NONE;
+		goto out;
+	}
 
-	c = policydb.ocontexts[OCON_FSUSE];
+	c = p->ocontexts[OCON_FSUSE];
 	while (c) {
 		if (strcmp(fstype, c->u.name) == 0)
 			break;
 		c = c->next;
@@ -1488,9 +1535,9 @@
 
 	if (c) {
 		*behavior = c->v.behavior;
 		if (!c->sid[0]) {
-			rc = sidtab_context_to_sid(&sidtab,
+			rc = sidtab_context_to_sid(p->sidtab,
 						   &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
@@ -1513,14 +1560,25 @@
 
 int security_get_bools(int *len, char ***names, int **values)
 {
 	int i, rc = -ENOMEM;
+	struct policydb *p;
 
 	POLICY_RDLOCK;
+	p = policydb;
+	if (!p) {
+		*len = 0;
+		*names = NULL;
+		*values = NULL;
+		rc = 0;
+		goto out;
+	}
+
+
 	*names = NULL;
 	*values = NULL;
 
-	*len = policydb.p_bools.nprim;
+	*len = p->p_bools.nprim;
 	if (!*len) {
 		rc = 0;
 		goto out;
 	}
@@ -1535,14 +1593,14 @@
 		goto err;
 
 	for (i = 0; i < *len; i++) {
 		size_t name_len;
-		(*values)[i] = policydb.bool_val_to_struct[i]->state;
-		name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+		(*values)[i] = p->bool_val_to_struct[i]->state;
+		name_len = strlen(p->p_bool_val_to_name[i]) + 1;
 		(*names)[i] = (char*)kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
 		if (!(*names)[i])
 			goto err;
-		strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+		strncpy((*names)[i], p->p_bool_val_to_name[i], name_len);
 		(*names)[i][name_len - 1] = 0;
 	}
 	rc = 0;
 out:
@@ -1563,42 +1621,53 @@
 int security_set_bools(int len, int *values)
 {
 	int i, rc = 0;
 	int lenp, seqno = 0;
+	struct policydb *newdb, *olddb;
 	struct cond_node *cur;
 
-	POLICY_WRLOCK;
+	LOAD_LOCK;
+	olddb = policydb;
 
-	lenp = policydb.p_bools.nprim;
+	lenp = olddb->p_bools.nprim;
 	if (len != lenp) {
 		rc = -EFAULT;
 		goto out;
 	}
+	newdb = cond_policydb_dup(olddb);
+	if (!newdb) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	printk(KERN_INFO "security: committed booleans { ");
 	for (i = 0; i < len; i++) {
 		if (values[i]) {
-			policydb.bool_val_to_struct[i]->state = 1;
+			newdb->bool_val_to_struct[i]->state = 1;
 		} else {
-			policydb.bool_val_to_struct[i]->state = 0;
+			newdb->bool_val_to_struct[i]->state = 0;
 		}
 		if (i != 0)
 			printk(", ");
-		printk("%s:%d", policydb.p_bool_val_to_name[i],
-		       policydb.bool_val_to_struct[i]->state);
+		printk("%s:%d", newdb->p_bool_val_to_name[i],
+		       newdb->bool_val_to_struct[i]->state);
 	}
 	printk(" }\n");
 
-	for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
-		rc = evaluate_cond_node(&policydb, cur);
-		if (rc)
+	for (cur = newdb->cond_list; cur != NULL; cur = cur->next) {
+		rc = evaluate_cond_node(newdb, cur);
+		if (rc) {
+			call_rcu(&newdb->rhead, cond_policydb_free_rcu);
 			goto out;
+		}
 	}
-
+	smp_wmb();
+	policydb = newdb;
 	seqno = ++latest_granting;
 
+	call_rcu(&olddb->rhead, cond_policydb_free_rcu);
 out:
-	POLICY_WRUNLOCK;
+	LOAD_UNLOCK;
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
 	}
@@ -1608,18 +1677,25 @@
 int security_get_bool_value(int bool)
 {
 	int rc = 0;
 	int len;
+	struct policydb *p;
 
 	POLICY_RDLOCK;
+	p = policydb;
+	if (!p) {
+		rc = -EFAULT;
+		goto out;
+	}
+
 
-	len = policydb.p_bools.nprim;
+	len = p->p_bools.nprim;
 	if (bool >= len) {
 		rc = -EFAULT;
 		goto out;
 	}
 
-	rc = policydb.bool_val_to_struct[bool]->state;
+	rc = p->bool_val_to_struct[bool]->state;
 out:
 	POLICY_RDUNLOCK;
 	return rc;
 }
diff -rNU4 linux-2.6.9.selinux/security/selinux/ss/services.h linux-2.6.9.selinux-policydb/security/selinux/ss/services.h
--- linux-2.6.9.selinux/security/selinux/ss/services.h	2004-11-09 19:27:07.000000000 +0900
+++ linux-2.6.9.selinux-policydb/security/selinux/ss/services.h	2004-11-09 19:27:05.000000000 +0900
@@ -13,9 +13,9 @@
  * The security server uses two global data structures
  * when providing its services:  the SID table (sidtab)
  * and the policy database (policydb).
  */
-extern struct sidtab sidtab;
-extern struct policydb policydb;
+//extern struct sidtab sidtab;
+extern struct policydb *policydb;
 
 #endif	/* _SS_SERVICES_H_ */
 

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
@ 2018-01-30 14:37     ` Stephen Smalley
  0 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-01-30 14:37 UTC (permalink / raw)
  To: linux-security-module

On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> From: Peter Enderborg <peter.enderborg@sony.com>
> 
> This i preparation for switching to RCU locks. To be able to use
> RCU we need atomic switched pointer. This adds the dynamic
> memory copying to be a single pointer. It copy all the
> data structures in to new ones. This is an overhead
> for writing rules but the benifit is RCU.
> 
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---
>  security/selinux/ss/services.c | 139 +++++++++++++++++++++++------
> ------------
>  1 file changed, 78 insertions(+), 61 deletions(-)
> 
> diff --git a/security/selinux/ss/services.c
> b/security/selinux/ss/services.c
> index 2a8486c..81c5717 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -2064,76 +2064,67 @@ static int security_preserve_bools(struct
> policydb *p);
>   */
>  int security_load_policy(void *data, size_t len)
>  {
> -	struct policydb *oldpolicydb, *newpolicydb;
> +	struct policydb *oldpolicydb;
>  	struct sidtab oldsidtab, newsidtab;
>  	struct selinux_mapping *oldmap = NULL, *map = NULL;
>  	struct convert_context_args args;
> -	struct shared_current_mapping *new_mapping;
>  	struct shared_current_mapping *next_rcu;
> -
> +	struct shared_current_mapping *old_rcu;
>  	u32 seqno;
>  	u16 map_size;
>  	int rc = 0;
>  	struct policy_file file = { data, len }, *fp = &file;
>  
> -	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
> -	if (!oldpolicydb) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
> -			      GFP_KERNEL);
> -	if (!new_mapping) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -	newpolicydb = oldpolicydb + 1;
> -	next_rcu = kmalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> -	if (!next_rcu) {
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -
>  	if (!ss_initialized) {
> -		crm = kzalloc(sizeof(struct shared_current_mapping),
> -			      GFP_KERNEL);
> -		if (!crm) {
> +		struct shared_current_mapping *first_mapping;
> +
> +		first_mapping = kzalloc(sizeof(struct
> shared_current_mapping),
> +					GFP_KERNEL);
> +		if (!first_mapping) {
>  			rc = -ENOMEM;
>  			goto out;
>  		}
>  		avtab_cache_init();
>  		ebitmap_cache_init();
>  		hashtab_cache_init();
> -		rc = policydb_read(&crm->policydb, fp);
> +		rc = policydb_read(&first_mapping->policydb, fp);
>  		if (rc) {
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		crm->policydb.len = len;
> -		rc = selinux_set_mapping(&crm->policydb,
> secclass_map,
> -					 &crm->current_mapping,
> -					 &crm-
> >current_mapping_size);
> +		first_mapping->policydb.len = len;
> +		rc = selinux_set_mapping(&first_mapping->policydb,
> secclass_map,
> +					 &first_mapping-
> >current_mapping,
> +					 &first_mapping-
> >current_mapping_size);
>  		if (rc) {
> -			policydb_destroy(&crm->policydb);
> +			policydb_destroy(&first_mapping->policydb);
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		rc = policydb_load_isids(&crm->policydb, &crm-
> >sidtab);
> +		rc = policydb_load_isids(&first_mapping->policydb,
> +					 &first_mapping->sidtab);
>  		if (rc) {
> -			policydb_destroy(&crm->policydb);
> +			policydb_destroy(&first_mapping->policydb);
>  			avtab_cache_destroy();
>  			ebitmap_cache_destroy();
>  			hashtab_cache_destroy();
> +			kfree(first_mapping);
>  			goto out;
>  		}
>  
> -		security_load_policycaps(&crm->policydb);
> +		security_load_policycaps(&first_mapping->policydb);
> +		crm = first_mapping;
> +
> +		smp_mb(); /* make sure that crm exist before we */
> +			  /* switch ss_initialized */
>  		ss_initialized = 1;
>  		seqno = ++latest_granting;
>  		selinux_complete_init();
> @@ -2148,30 +2139,44 @@ int security_load_policy(void *data, size_t
> len)
>  #if 0
>  	sidtab_hash_eval(&crm->sidtab, "sids");
>  #endif
> +	oldpolicydb = kzalloc(sizeof(*oldpolicydb), GFP_KERNEL);
> +	if (!oldpolicydb) {
> +		rc = -ENOMEM;
> +		goto out;
> +	}
> +
> +	next_rcu = kzalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> +	if (!next_rcu) {
> +		kfree(oldpolicydb);
> +		rc = -ENOMEM;
> +		goto out;
> +	}
>  
> -	rc = policydb_read(newpolicydb, fp);
> +	rc = policydb_read(&next_rcu->policydb, fp);
>  	if (rc)
>  		goto out;
>  
> -	newpolicydb->len = len;
> +	next_rcu->policydb.len = len;
> +	read_lock(&policy_rwlock);
>  	/* If switching between different policy types, log MLS
> status */
> -	if (crm->policydb.mls_enabled && !newpolicydb->mls_enabled)
> +	if (crm->policydb.mls_enabled && !next_rcu-
> >policydb.mls_enabled)
>  		printk(KERN_INFO "SELinux: Disabling MLS
> support...\n");
> -	else if (!crm->policydb.mls_enabled && newpolicydb-
> >mls_enabled)
> +	else if (!crm->policydb.mls_enabled && next_rcu-
> >policydb.mls_enabled)
>  		printk(KERN_INFO "SELinux: Enabling MLS
> support...\n");
>  
> -	rc = policydb_load_isids(newpolicydb, &newsidtab);
> +	rc = policydb_load_isids(&next_rcu->policydb, &newsidtab);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to load the
> initial SIDs\n");
> -		policydb_destroy(newpolicydb);
> +		policydb_destroy(&next_rcu->policydb);
>  		goto out;
>  	}
>  
> -	rc = selinux_set_mapping(newpolicydb, secclass_map, &map,
> &map_size);
> +	rc = selinux_set_mapping(&next_rcu->policydb, secclass_map,
> +				 &map, &map_size);
>  	if (rc)
>  		goto err;
>  
> -	rc = security_preserve_bools(newpolicydb);
> +	rc = security_preserve_bools(&next_rcu->policydb);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to preserve
> booleans\n");
>  		goto err;

Most of this shouldn't need to be under the read lock.

> @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
> len)
>  	 * in the new SID table.
>  	 */
>  	args.oldp = &crm->policydb;
> -	args.newp = newpolicydb;
> +	args.newp = &next_rcu->policydb;
>  	rc = sidtab_map(&newsidtab, convert_context, &args);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to convert the
> internal"
> @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
> len)
>  
>  	/* Install the new policydb and SID table. */
>  	/* next */
> +	security_load_policycaps(&next_rcu->policydb);

This cannot be done outside of the write lock; it has to be atomic with
the policy switch.

> +	read_unlock(&policy_rwlock);
>  	write_lock_irq(&policy_rwlock);
> -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
> policydb));
>  	sidtab_set(&next_rcu->sidtab, &newsidtab);
>  	security_load_policycaps(&next_rcu->policydb);
>  	oldmap = crm->current_mapping;
> @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
> len)
>  	next_rcu->current_mapping_size = map_size;
>  
>  	seqno = ++latest_granting;
> -	write_unlock_irq(&policy_rwlock);
> +	old_rcu = crm;
>  	crm = next_rcu;
> +	write_unlock_irq(&policy_rwlock);
>  
>  	/* Free the old policydb and SID table. */
>  	policydb_destroy(oldpolicydb);
> @@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t
> len)
>  	selinux_status_update_policyload(seqno);
>  	selinux_netlbl_cache_invalidate();
>  	selinux_xfrm_notify_policyload();
> +	kfree(oldpolicydb);
> +	kfree(old_rcu);
>  
>  	rc = 0;
>  	goto out;
> -
>  err:
>  	kfree(map);
>  	sidtab_destroy(&newsidtab);
> -	policydb_destroy(newpolicydb);
> -
> +	policydb_destroy(&next_rcu->policydb);
>  out:
> -	kfree(oldpolicydb);
>  	return rc;
>  }
>  
> @@ -2795,54 +2801,65 @@ int security_get_bools(int *len, char
> ***names, int **values)
>  	goto out;
>  }
>  
> -
>  int security_set_bools(int len, int *values)
>  {
> +	struct shared_current_mapping *next_rcu, *old_rcu;
>  	int i, rc;
>  	int lenp, seqno = 0;
>  	struct cond_node *cur;
>  
> -	write_lock_irq(&policy_rwlock);
> -
> +	next_rcu = kzalloc(sizeof(struct shared_current_mapping),
> GFP_KERNEL);
> +	read_lock(&policy_rwlock);
> +	old_rcu = crm;
> +	memcpy(&next_rcu->policydb, &old_rcu->policydb,
> +	       sizeof(struct policydb));

You are only doing a "shallow" copy of the policydb here, which
contains pointers to other structures.  So then below when you modify
state, you are modifying the original, not just the copy.  And you'll
end up double freeing if you free them both.

For reference, attached is a very old attempt to convert the policy
rwlock to RCU from KaiGai Kohei.  It may provide some insight into what
is needed here.
 
>  	rc = -EFAULT;
> -	lenp = crm->policydb.p_bools.nprim;
> +	lenp = next_rcu->policydb.p_bools.nprim;
> +
>  	if (len != lenp)
>  		goto out;
>  
>  	for (i = 0; i < len; i++) {
>  		if (!!values[i] !=
> -		    crm->policydb.bool_val_to_struct[i]->state) {
> +		    next_rcu->policydb.bool_val_to_struct[i]->state) 
> {
>  			audit_log(current->audit_context,
> GFP_ATOMIC,
>  				AUDIT_MAC_CONFIG_CHANGE,
>  				"bool=%s val=%d old_val=%d auid=%u
> ses=%u",
> -				sym_name(&crm->policydb, SYM_BOOLS,
> i),
> +				sym_name(&next_rcu->policydb,
> SYM_BOOLS, i),
>  				!!values[i],
> -				crm->policydb.bool_val_to_struct[i]-
> >state,
> +				next_rcu-
> >policydb.bool_val_to_struct[i]->state,
>  				from_kuid(&init_user_ns,
> audit_get_loginuid(current)),
>  				audit_get_sessionid(current));
>  		}
>  		if (values[i])
> -			crm->policydb.bool_val_to_struct[i]->state =
> 1;
> +			next_rcu->policydb.bool_val_to_struct[i]-
> >state = 1;
>  		else
> -			crm->policydb.bool_val_to_struct[i]->state =
> 0;
> +			next_rcu->policydb.bool_val_to_struct[i]-
> >state = 0;
>  	}
>  
> -	for (cur = crm->policydb.cond_list; cur; cur = cur->next) {
> -		rc = evaluate_cond_node(&crm->policydb, cur);
> +	for (cur = next_rcu->policydb.cond_list; cur; cur = cur-
> >next) {
> +		rc = evaluate_cond_node(&next_rcu->policydb, cur);
>  		if (rc)
>  			goto out;
>  	}
> +	read_unlock(&policy_rwlock);
> +	rc = 0;
>  
> +	write_lock_irq(&policy_rwlock);
>  	seqno = ++latest_granting;
> -	rc = 0;
> -out:
> +	crm = next_rcu;
>  	write_unlock_irq(&policy_rwlock);
> +out:
>  	if (!rc) {
>  		avc_ss_reset(seqno);
>  		selnl_notify_policyload(seqno);
>  		selinux_status_update_policyload(seqno);
>  		selinux_xfrm_notify_policyload();
> +	} else {
> +		kfree(next_rcu);
>  	}
> +	kfree(old_rcu);
> +
>  	return rc;
>  }
>  

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-01-30 13:46     ` Stephen Smalley
@ 2018-02-01 15:17       ` peter enderborg
  -1 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-02-01 15:17 UTC (permalink / raw)
  To: Stephen Smalley, selinux, linux-security-module

On 01/30/2018 02:46 PM, Stephen Smalley wrote:
> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
>> From: Peter Enderborg <peter.enderborg@sony.com>
>>
>> To be able to use rcu locks we seed to address the policydb
>> though a pointer. This preparation removes the export of the
>> policydb and send pointers to it through parameter agruments.
> Just for reference, I have a patch series that does this not only for
> the policydb, sidtab, and class/perm mapping, but for all of the
> SELinux global state, see:
> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
> and in particular
> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>
> Those first three patches should have no effect on SELinux behavior.
> They need to be re-based to latest selinux next branch (some minor
> conflict resolution required) but I was waiting for that to advance to
> something 4.15-rcX based.  I could however re-base it now if desired.
I read that as that you want me to rebase the patches on that tree? Seems to
be partly prepared but lot of changes.  Is it a moving target?

>> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
>> ---
>>  security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
>>  security/selinux/ss/mls.h      | 37 +++++++++--------
>>  security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++-----
>> ----------
>>  security/selinux/ss/services.h |  3 --
>>  4 files changed, 114 insertions(+), 85 deletions(-)
>>
>> diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
>> index ad982ce..b1f35d3 100644
>> --- a/security/selinux/ss/mls.c
>> +++ b/security/selinux/ss/mls.c
>> @@ -33,20 +33,20 @@
>>   * Return the length in bytes for the MLS fields of the
>>   * security context string representation of `context'.
>>   */
>> -int mls_compute_context_len(struct context *context)
>> +int mls_compute_context_len(struct policydb *p, struct context
>> *context)
>>  {
>>  	int i, l, len, head, prev;
>>  	char *nm;
>>  	struct ebitmap *e;
>>  	struct ebitmap_node *node;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	len = 1; /* for the beginning ":" */
>>  	for (l = 0; l < 2; l++) {
>>  		int index_sens = context->range.level[l].sens;
>> -		len += strlen(sym_name(&policydb, SYM_LEVELS,
>> index_sens - 1));
>> +		len += strlen(sym_name(p, SYM_LEVELS, index_sens -
>> 1));
>>  
>>  		/* categories */
>>  		head = -2;
>> @@ -56,17 +56,17 @@ int mls_compute_context_len(struct context
>> *context)
>>  			if (i - prev > 1) {
>>  				/* one or more negative bits are
>> skipped */
>>  				if (head != prev) {
>> -					nm = sym_name(&policydb,
>> SYM_CATS, prev);
>> +					nm = sym_name(p, SYM_CATS,
>> prev);
>>  					len += strlen(nm) + 1;
>>  				}
>> -				nm = sym_name(&policydb, SYM_CATS,
>> i);
>> +				nm = sym_name(p, SYM_CATS, i);
>>  				len += strlen(nm) + 1;
>>  				head = i;
>>  			}
>>  			prev = i;
>>  		}
>>  		if (prev != head) {
>> -			nm = sym_name(&policydb, SYM_CATS, prev);
>> +			nm = sym_name(p, SYM_CATS, prev);
>>  			len += strlen(nm) + 1;
>>  		}
>>  		if (l == 0) {
>> @@ -86,7 +86,7 @@ int mls_compute_context_len(struct context
>> *context)
>>   * the MLS fields of `context' into the string `*scontext'.
>>   * Update `*scontext' to point to the end of the MLS fields.
>>   */
>> -void mls_sid_to_context(struct context *context,
>> +void mls_sid_to_context(struct policydb *p, struct context *context,
>>  			char **scontext)
>>  {
>>  	char *scontextp, *nm;
>> @@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
>>  	struct ebitmap *e;
>>  	struct ebitmap_node *node;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	scontextp = *scontext;
>> @@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
>>  	scontextp++;
>>  
>>  	for (l = 0; l < 2; l++) {
>> -		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
>> +		strcpy(scontextp, sym_name(p, SYM_LEVELS,
>>  					   context-
>>> range.level[l].sens - 1));
>>  		scontextp += strlen(scontextp);
>>  
>> @@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
>>  						*scontextp++ = '.';
>>  					else
>>  						*scontextp++ = ',';
>> -					nm = sym_name(&policydb,
>> SYM_CATS, prev);
>> +					nm = sym_name(p, SYM_CATS,
>> prev);
>>  					strcpy(scontextp, nm);
>>  					scontextp += strlen(nm);
>>  				}
>> @@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
>>  					*scontextp++ = ':';
>>  				else
>>  					*scontextp++ = ',';
>> -				nm = sym_name(&policydb, SYM_CATS,
>> i);
>> +				nm = sym_name(p, SYM_CATS, i);
>>  				strcpy(scontextp, nm);
>>  				scontextp += strlen(nm);
>>  				head = i;
>> @@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
>>  				*scontextp++ = '.';
>>  			else
>>  				*scontextp++ = ',';
>> -			nm = sym_name(&policydb, SYM_CATS, prev);
>> +			nm = sym_name(p, SYM_CATS, prev);
>>  			strcpy(scontextp, nm);
>>  			scontextp += strlen(nm);
>>  		}
>> @@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
>>   * the string `str'.  This function will allocate temporary memory
>> with the
>>   * given constraints of gfp_mask.
>>   */
>> -int mls_from_string(char *str, struct context *context, gfp_t
>> gfp_mask)
>> +int mls_from_string(struct policydb *p, char *str, struct context
>> *context,
>> +		    gfp_t gfp_mask)
>>  {
>>  	char *tmpstr, *freestr;
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return -EINVAL;
>>  
>>  	/* we need freestr because mls_context_to_sid will change
>> @@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context
>> *context, gfp_t gfp_mask)
>>  	if (!tmpstr) {
>>  		rc = -ENOMEM;
>>  	} else {
>> -		rc = mls_context_to_sid(&policydb, ':', &tmpstr,
>> context,
>> +		rc = mls_context_to_sid(p, ':', &tmpstr, context,
>>  					NULL, SECSID_NULL);
>>  		kfree(freestr);
>>  	}
>> @@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
>>  	return rc;
>>  }
>>  
>> -int mls_setup_user_range(struct context *fromcon, struct user_datum
>> *user,
>> -			 struct context *usercon)
>> +int mls_setup_user_range(struct policydb *p, struct context
>> *fromcon,
>> +			 struct user_datum *user, struct context
>> *usercon)
>>  {
>> -	if (policydb.mls_enabled) {
>> +	if (p->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]);
>> @@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon,
>> struct user_datum *user,
>>   * structure `c' from the values specified in the
>>   * policy `oldp' to the values specified in the policy `newp'.
>>   */
>> -int mls_convert_context(struct policydb *oldp,
>> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>>  			struct policydb *newp,
>>  			struct context *c)
>>  {
>> @@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
>>  	struct ebitmap_node *node;
>>  	int l, i;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	for (l = 0; l < 2; l++) {
>> @@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
>>  	return 0;
>>  }
>>  
>> -int mls_compute_sid(struct context *scontext,
>> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>>  		    struct context *tcontext,
>>  		    u16 tclass,
>>  		    u32 specified,
>> @@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
>>  	struct class_datum *cladatum;
>>  	int default_range = 0;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	switch (specified) {
>> @@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
>>  		rtr.source_type = scontext->type;
>>  		rtr.target_type = tcontext->type;
>>  		rtr.target_class = tclass;
>> -		r = hashtab_search(policydb.range_tr, &rtr);
>> +		r = hashtab_search(p->range_tr, &rtr);
>>  		if (r)
>>  			return mls_range_set(newcontext, r);
>>  
>> -		if (tclass && tclass <= policydb.p_classes.nprim) {
>> -			cladatum =
>> policydb.class_val_to_struct[tclass - 1];
>> +		if (tclass && tclass <= p->p_classes.nprim) {
>> +			cladatum = p->class_val_to_struct[tclass -
>> 1];
>>  			if (cladatum)
>>  				default_range = cladatum-
>>> default_range;
>>  		}
>> @@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
>>  
>>  		/* Fallthrough */
>>  	case AVTAB_CHANGE:
>> -		if ((tclass == policydb.process_class) || (sock ==
>> true))
>> +		if ((tclass == p->process_class) || (sock == true))
>>  			/* Use the process MLS attributes. */
>>  			return mls_context_cpy(newcontext,
>> scontext);
>>  		else
>> @@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
>>   * NetLabel MLS sensitivity level field.
>>   *
>>   */
>> -void mls_export_netlbl_lvl(struct context *context,
>> +void mls_export_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr)
>>  {
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
>> @@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context
>> *context,
>>   * NetLabel MLS sensitivity level into the context.
>>   *
>>   */
>> -void mls_import_netlbl_lvl(struct context *context,
>> +void mls_import_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr)
>>  {
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
>> @@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context
>> *context,
>>   * MLS category field.  Returns zero on success, negative values on
>> failure.
>>   *
>>   */
>> -int mls_export_netlbl_cat(struct context *context,
>> +int mls_export_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr)
>>  {
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
>> @@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context
>> *context,
>>   * negative values on failure.
>>   *
>>   */
>> -int mls_import_netlbl_cat(struct context *context,
>> +int mls_import_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr)
>>  {
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
>> diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
>> index 131d762..cb039c0 100644
>> --- a/security/selinux/ss/mls.h
>> +++ b/security/selinux/ss/mls.h
>> @@ -25,8 +25,9 @@
>>  #include "context.h"
>>  #include "policydb.h"
>>  
>> -int mls_compute_context_len(struct context *context);
>> -void mls_sid_to_context(struct context *context, char **scontext);
>> +int mls_compute_context_len(struct policydb *p, struct context
>> *context);
>> +void mls_sid_to_context(struct policydb *p, struct context *context,
>> +			char **scontext);
>>  int mls_context_isvalid(struct policydb *p, struct context *c);
>>  int mls_range_isvalid(struct policydb *p, struct mls_range *r);
>>  int mls_level_isvalid(struct policydb *p, struct mls_level *l);
>> @@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
>>  		       struct sidtab *s,
>>  		       u32 def_sid);
>>  
>> -int mls_from_string(char *str, struct context *context, gfp_t
>> gfp_mask);
>> +int mls_from_string(struct policydb *p, char *str, struct context
>> *context,
>> +		    gfp_t gfp_mask);
>>  
>>  int mls_range_set(struct context *context, struct mls_range *range);
>>  
>> -int mls_convert_context(struct policydb *oldp,
>> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>>  			struct policydb *newp,
>>  			struct context *context);
>>  
>> -int mls_compute_sid(struct context *scontext,
>> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>>  		    struct context *tcontext,
>>  		    u16 tclass,
>>  		    u32 specified,
>>  		    struct context *newcontext,
>>  		    bool sock);
>>  
>> -int mls_setup_user_range(struct context *fromcon, struct user_datum
>> *user,
>> -			 struct context *usercon);
>> +int mls_setup_user_range(struct policydb *p, struct context
>> *fromcon,
>> +			 struct user_datum *user, struct context
>> *usercon);
>>  
>>  #ifdef CONFIG_NETLABEL
>> -void mls_export_netlbl_lvl(struct context *context,
>> +void mls_export_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr);
>> -void mls_import_netlbl_lvl(struct context *context,
>> +void mls_import_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr);
>> -int mls_export_netlbl_cat(struct context *context,
>> +int mls_export_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr);
>> -int mls_import_netlbl_cat(struct context *context,
>> +int mls_import_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr);
>>  #else
>> -static inline void mls_export_netlbl_lvl(struct context *context,
>> +static inline void mls_export_netlbl_lvl(struct policydb *p,
>> +					 struct context *context,
>>  					 struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return;
>>  }
>> -static inline void mls_import_netlbl_lvl(struct context *context,
>> +static inline void mls_import_netlbl_lvl(struct policydb *p,
>> +					 struct context *context,
>>  					 struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return;
>>  }
>> -static inline int mls_export_netlbl_cat(struct context *context,
>> +static inline int mls_export_netlbl_cat(struct policydb *p,
>> +					struct context *context,
>>  					struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return -ENOMEM;
>>  }
>> -static inline int mls_import_netlbl_cat(struct context *context,
>> +static inline int mls_import_netlbl_cat(struct policydb *p,
>> +					struct context *context,
>>  					struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return -ENOMEM;
>> @@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct
>> context *context,
>>  #endif
>>  
>>  #endif	/* _SS_MLS_H */
>> -
>> diff --git a/security/selinux/ss/services.c
>> b/security/selinux/ss/services.c
>> index 33cfe5d..47d8030 100644
>> --- a/security/selinux/ss/services.c
>> +++ b/security/selinux/ss/services.c
>> @@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
>>  static DEFINE_RWLOCK(policy_rwlock);
>>  
>>  static struct sidtab sidtab;
>> -struct policydb policydb;
>> +static struct policydb policydb;
>>  int ss_initialized;
>>  
>>  /*
>> @@ -117,8 +117,12 @@ struct selinux_mapping {
>>  	u32 perms[sizeof(u32) * 8];
>>  };
>>  
>> -static struct selinux_mapping *current_mapping;
>> -static u16 current_mapping_size;
>> +struct shared_current_mapping {
>> +	struct selinux_mapping *current_mapping;
>> +	u16 current_mapping_size;
>> +};
>> +
>> +static struct shared_current_mapping *crm;
>>  
>>  static int selinux_set_mapping(struct policydb *pol,
>>  			       struct security_class_mapping *map,
>> @@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb
>> *pol,
>>  
>>  static u16 unmap_class(u16 tclass)
>>  {
>> -	if (tclass < current_mapping_size)
>> -		return current_mapping[tclass].value;
>> +	if (tclass < crm->current_mapping_size)
>> +		return crm->current_mapping[tclass].value;
>>  
>>  	return tclass;
>>  }
>> @@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
>>  {
>>  	u16 i;
>>  
>> -	for (i = 1; i < current_mapping_size; i++) {
>> -		if (current_mapping[i].value == pol_value)
>> +	for (i = 1; i < crm->current_mapping_size; i++) {
>> +		if (crm->current_mapping[i].value == pol_value)
>>  			return i;
>>  	}
>>  
>> @@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
>>  static void map_decision(u16 tclass, struct av_decision *avd,
>>  			 int allow_unknown)
>>  {
>> -	if (tclass < current_mapping_size) {
>> -		unsigned i, n = current_mapping[tclass].num_perms;
>> +	if (tclass < crm->current_mapping_size) {
>> +		unsigned int i, n = crm-
>>> current_mapping[tclass].num_perms;
>>  		u32 result;
>>  
>>  		for (i = 0, result = 0; i < n; i++) {
>> -			if (avd->allowed &
>> current_mapping[tclass].perms[i])
>> +			if (avd->allowed &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>> -			if (allow_unknown &&
>> !current_mapping[tclass].perms[i])
>> +			if (allow_unknown &&
>> +			    !crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		}
>>  		avd->allowed = result;
>>  
>>  		for (i = 0, result = 0; i < n; i++)
>> -			if (avd->auditallow &
>> current_mapping[tclass].perms[i])
>> +			if (avd->auditallow &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		avd->auditallow = result;
>>  
>>  		for (i = 0, result = 0; i < n; i++) {
>> -			if (avd->auditdeny &
>> current_mapping[tclass].perms[i])
>> +			if (avd->auditdeny &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>> -			if (!allow_unknown &&
>> !current_mapping[tclass].perms[i])
>> +			if (!allow_unknown &&
>> +			    !crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		}
>>  		/*
>> @@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct
>> context *context, char **scontext, u3
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_USERS,
>> context->user - 1)) + 1;
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES,
>> context->role - 1)) + 1;
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES,
>> context->type - 1)) + 1;
>> -	*scontext_len += mls_compute_context_len(context);
>> +	*scontext_len += mls_compute_context_len(&policydb,
>> context);
>>  
>>  	if (!scontext)
>>  		return 0;
>> @@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct
>> context *context, char **scontext, u3
>>  		sym_name(&policydb, SYM_ROLES, context->role - 1),
>>  		sym_name(&policydb, SYM_TYPES, context->type - 1));
>>  
>> -	mls_sid_to_context(context, &scontextp);
>> +	mls_sid_to_context(&policydb, context, &scontextp);
>>  
>>  	*scontextp = 0;
>>  
>> @@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
>>  
>>  	/* Set the MLS attributes.
>>  	   This is done last because it may allocate memory. */
>> -	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
>> +	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass,
>> specified,
>>  			     &newcontext, sock);
>>  	if (rc)
>>  		goto out_unlock;
>> @@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
>>  
>>  	/* Convert the MLS fields if dealing with MLS policies */
>>  	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
>> -		rc = mls_convert_context(args->oldp, args->newp, c);
>> +		rc = mls_convert_context(&policydb, args->oldp,
>> args->newp, c);
>>  		if (rc)
>>  			goto bad;
>>  	} else if (args->oldp->mls_enabled && !args->newp-
>>> mls_enabled) {
>> @@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  {
>>  	struct policydb *oldpolicydb, *newpolicydb;
>>  	struct sidtab oldsidtab, newsidtab;
>> -	struct selinux_mapping *oldmap, *map = NULL;
>> +	struct selinux_mapping *oldmap = NULL, *map = NULL;
>>  	struct convert_context_args args;
>> +	struct shared_current_mapping *new_mapping;
>>  	u32 seqno;
>>  	u16 map_size;
>>  	int rc = 0;
>> @@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t
>> len)
>>  		rc = -ENOMEM;
>>  		goto out;
>>  	}
>> +	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
>> +			      GFP_KERNEL);
>> +	if (!new_mapping) {
>> +		rc = -ENOMEM;
>> +		goto out;
>> +	}
>>  	newpolicydb = oldpolicydb + 1;
>>  
>>  	if (!ss_initialized) {
>> +		crm = kzalloc(sizeof(struct shared_current_mapping),
>> +			      GFP_KERNEL);
>> +		if (!crm) {
>> +			rc = -ENOMEM;
>> +			goto out;
>> +		}
>> +
>>  		avtab_cache_init();
>>  		ebitmap_cache_init();
>>  		hashtab_cache_init();
>> @@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t
>> len)
>>  
>>  		policydb.len = len;
>>  		rc = selinux_set_mapping(&policydb, secclass_map,
>> -					 &current_mapping,
>> -					 &current_mapping_size);
>> +					 &crm->current_mapping,
>> +					 &crm-
>>> current_mapping_size);
>>  		if (rc) {
>>  			policydb_destroy(&policydb);
>>  			avtab_cache_destroy();
>> @@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  	memcpy(&policydb, newpolicydb, sizeof(policydb));
>>  	sidtab_set(&sidtab, &newsidtab);
>>  	security_load_policycaps();
>> -	oldmap = current_mapping;
>> -	current_mapping = map;
>> -	current_mapping_size = map_size;
>> +	oldmap = crm->current_mapping;
>> +	crm->current_mapping = map;
>> +	crm->current_mapping_size = map_size;
>>  	seqno = ++latest_granting;
>>  	write_unlock_irq(&policy_rwlock);
>>  
>> @@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
>>  		ebitmap_for_each_positive_bit(&role->types, tnode,
>> j) {
>>  			usercon.type = j + 1;
>>  
>> -			if (mls_setup_user_range(fromcon, user,
>> &usercon))
>> +			if (mls_setup_user_range(&policydb, fromcon,
>> +						 user, &usercon))
>>  				continue;
>>  
>>  			rc = sidtab_context_to_sid(&sidtab,
>> &usercon, &sid);
>> @@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
>>   * cannot support xattr or use a fixed labeling behavior like
>>   * transition SIDs or task SIDs.
>>   *
>> - * The caller must acquire the policy_rwlock before calling this
>> function.
>> + * The caller must hold rcu before calling this function.
>>   */
>>  static inline int __security_genfs_sid(const char *fstype,
>>  				       char *path,
>> @@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const
>> char *fstype,
>>   * @sclass: file security class
>>   * @sid: SID for path
>>   *
>> - * Acquire policy_rwlock before calling __security_genfs_sid() and
>> release
>> + * Hold rcu before calling __security_genfs_sid() and release
>>   * it afterward.
>>   */
>>  int security_genfs_sid(const char *fstype,
>> @@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op,
>> char *rulestr, void **vrule)
>>  	case AUDIT_SUBJ_CLR:
>>  	case AUDIT_OBJ_LEV_LOW:
>>  	case AUDIT_OBJ_LEV_HIGH:
>> -		rc = mls_from_string(rulestr, &tmprule->au_ctxt,
>> GFP_ATOMIC);
>> +		rc = mls_from_string(&policydb, rulestr, &tmprule-
>>> au_ctxt,
>> +				     GFP_ATOMIC);
>>  		if (rc)
>>  			goto out;
>>  		break;
>> @@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct
>> netlbl_lsm_secattr *secattr,
>>  		ctx_new.user = ctx->user;
>>  		ctx_new.role = ctx->role;
>>  		ctx_new.type = ctx->type;
>> -		mls_import_netlbl_lvl(&ctx_new, secattr);
>> +		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
>>  		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
>> -			rc = mls_import_netlbl_cat(&ctx_new,
>> secattr);
>> +			rc = mls_import_netlbl_cat(&policydb,
>> &ctx_new,
>> +						   secattr);
>>  			if (rc)
>>  				goto out;
>>  		}
>> @@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid,
>> struct netlbl_lsm_secattr *secattr)
>>  
>>  	secattr->attr.secid = sid;
>>  	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY |
>> NETLBL_SECATTR_SECID;
>> -	mls_export_netlbl_lvl(ctx, secattr);
>> -	rc = mls_export_netlbl_cat(ctx, secattr);
>> +	mls_export_netlbl_lvl(&policydb, ctx, secattr);
>> +	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
>>  out:
>>  	read_unlock(&policy_rwlock);
>>  	return rc;
>> diff --git a/security/selinux/ss/services.h
>> b/security/selinux/ss/services.h
>> index 356bdd3..50c7ceb 100644
>> --- a/security/selinux/ss/services.h
>> +++ b/security/selinux/ss/services.h
>> @@ -10,8 +10,6 @@
>>  #include "policydb.h"
>>  #include "sidtab.h"
>>  
>> -extern struct policydb policydb;
>> -
>>  void services_compute_xperms_drivers(struct extended_perms *xperms,
>>  				struct avtab_node *node);
>>  
>> @@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct
>> extended_perms_decision *xpermd,
>>  					struct avtab_node *node);
>>  
>>  #endif	/* _SS_SERVICES_H_ */
>> -

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-02-01 15:17       ` peter enderborg
  0 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-02-01 15:17 UTC (permalink / raw)
  To: linux-security-module

On 01/30/2018 02:46 PM, Stephen Smalley wrote:
> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
>> From: Peter Enderborg <peter.enderborg@sony.com>
>>
>> To be able to use rcu locks we seed to address the policydb
>> though a pointer. This preparation removes the export of the
>> policydb and send pointers to it through parameter agruments.
> Just for reference, I have a patch series that does this not only for
> the policydb, sidtab, and class/perm mapping, but for all of the
> SELinux global state, see:
> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
> and in particular
> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>
> Those first three patches should have no effect on SELinux behavior.
> They need to be re-based to latest selinux next branch (some minor
> conflict resolution required) but I was waiting for that to advance to
> something 4.15-rcX based.  I could however re-base it now if desired.
I read that as that you want me to rebase the patches on that tree? Seems to
be partly prepared but lot of changes.? Is it a moving target?

>> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
>> ---
>>  security/selinux/ss/mls.c      | 69 ++++++++++++++++----------------
>>  security/selinux/ss/mls.h      | 37 +++++++++--------
>>  security/selinux/ss/services.c | 90 +++++++++++++++++++++++++++-----
>> ----------
>>  security/selinux/ss/services.h |  3 --
>>  4 files changed, 114 insertions(+), 85 deletions(-)
>>
>> diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
>> index ad982ce..b1f35d3 100644
>> --- a/security/selinux/ss/mls.c
>> +++ b/security/selinux/ss/mls.c
>> @@ -33,20 +33,20 @@
>>   * Return the length in bytes for the MLS fields of the
>>   * security context string representation of `context'.
>>   */
>> -int mls_compute_context_len(struct context *context)
>> +int mls_compute_context_len(struct policydb *p, struct context
>> *context)
>>  {
>>  	int i, l, len, head, prev;
>>  	char *nm;
>>  	struct ebitmap *e;
>>  	struct ebitmap_node *node;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	len = 1; /* for the beginning ":" */
>>  	for (l = 0; l < 2; l++) {
>>  		int index_sens = context->range.level[l].sens;
>> -		len += strlen(sym_name(&policydb, SYM_LEVELS,
>> index_sens - 1));
>> +		len += strlen(sym_name(p, SYM_LEVELS, index_sens -
>> 1));
>>  
>>  		/* categories */
>>  		head = -2;
>> @@ -56,17 +56,17 @@ int mls_compute_context_len(struct context
>> *context)
>>  			if (i - prev > 1) {
>>  				/* one or more negative bits are
>> skipped */
>>  				if (head != prev) {
>> -					nm = sym_name(&policydb,
>> SYM_CATS, prev);
>> +					nm = sym_name(p, SYM_CATS,
>> prev);
>>  					len += strlen(nm) + 1;
>>  				}
>> -				nm = sym_name(&policydb, SYM_CATS,
>> i);
>> +				nm = sym_name(p, SYM_CATS, i);
>>  				len += strlen(nm) + 1;
>>  				head = i;
>>  			}
>>  			prev = i;
>>  		}
>>  		if (prev != head) {
>> -			nm = sym_name(&policydb, SYM_CATS, prev);
>> +			nm = sym_name(p, SYM_CATS, prev);
>>  			len += strlen(nm) + 1;
>>  		}
>>  		if (l == 0) {
>> @@ -86,7 +86,7 @@ int mls_compute_context_len(struct context
>> *context)
>>   * the MLS fields of `context' into the string `*scontext'.
>>   * Update `*scontext' to point to the end of the MLS fields.
>>   */
>> -void mls_sid_to_context(struct context *context,
>> +void mls_sid_to_context(struct policydb *p, struct context *context,
>>  			char **scontext)
>>  {
>>  	char *scontextp, *nm;
>> @@ -94,7 +94,7 @@ void mls_sid_to_context(struct context *context,
>>  	struct ebitmap *e;
>>  	struct ebitmap_node *node;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	scontextp = *scontext;
>> @@ -103,7 +103,7 @@ void mls_sid_to_context(struct context *context,
>>  	scontextp++;
>>  
>>  	for (l = 0; l < 2; l++) {
>> -		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
>> +		strcpy(scontextp, sym_name(p, SYM_LEVELS,
>>  					   context-
>>> range.level[l].sens - 1));
>>  		scontextp += strlen(scontextp);
>>  
>> @@ -119,7 +119,7 @@ void mls_sid_to_context(struct context *context,
>>  						*scontextp++ = '.';
>>  					else
>>  						*scontextp++ = ',';
>> -					nm = sym_name(&policydb,
>> SYM_CATS, prev);
>> +					nm = sym_name(p, SYM_CATS,
>> prev);
>>  					strcpy(scontextp, nm);
>>  					scontextp += strlen(nm);
>>  				}
>> @@ -127,7 +127,7 @@ void mls_sid_to_context(struct context *context,
>>  					*scontextp++ = ':';
>>  				else
>>  					*scontextp++ = ',';
>> -				nm = sym_name(&policydb, SYM_CATS,
>> i);
>> +				nm = sym_name(p, SYM_CATS, i);
>>  				strcpy(scontextp, nm);
>>  				scontextp += strlen(nm);
>>  				head = i;
>> @@ -140,7 +140,7 @@ void mls_sid_to_context(struct context *context,
>>  				*scontextp++ = '.';
>>  			else
>>  				*scontextp++ = ',';
>> -			nm = sym_name(&policydb, SYM_CATS, prev);
>> +			nm = sym_name(p, SYM_CATS, prev);
>>  			strcpy(scontextp, nm);
>>  			scontextp += strlen(nm);
>>  		}
>> @@ -375,12 +375,13 @@ int mls_context_to_sid(struct policydb *pol,
>>   * the string `str'.  This function will allocate temporary memory
>> with the
>>   * given constraints of gfp_mask.
>>   */
>> -int mls_from_string(char *str, struct context *context, gfp_t
>> gfp_mask)
>> +int mls_from_string(struct policydb *p, char *str, struct context
>> *context,
>> +		    gfp_t gfp_mask)
>>  {
>>  	char *tmpstr, *freestr;
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return -EINVAL;
>>  
>>  	/* we need freestr because mls_context_to_sid will change
>> @@ -389,7 +390,7 @@ int mls_from_string(char *str, struct context
>> *context, gfp_t gfp_mask)
>>  	if (!tmpstr) {
>>  		rc = -ENOMEM;
>>  	} else {
>> -		rc = mls_context_to_sid(&policydb, ':', &tmpstr,
>> context,
>> +		rc = mls_context_to_sid(p, ':', &tmpstr, context,
>>  					NULL, SECSID_NULL);
>>  		kfree(freestr);
>>  	}
>> @@ -417,10 +418,10 @@ int mls_range_set(struct context *context,
>>  	return rc;
>>  }
>>  
>> -int mls_setup_user_range(struct context *fromcon, struct user_datum
>> *user,
>> -			 struct context *usercon)
>> +int mls_setup_user_range(struct policydb *p, struct context
>> *fromcon,
>> +			 struct user_datum *user, struct context
>> *usercon)
>>  {
>> -	if (policydb.mls_enabled) {
>> +	if (p->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]);
>> @@ -460,7 +461,7 @@ int mls_setup_user_range(struct context *fromcon,
>> struct user_datum *user,
>>   * structure `c' from the values specified in the
>>   * policy `oldp' to the values specified in the policy `newp'.
>>   */
>> -int mls_convert_context(struct policydb *oldp,
>> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>>  			struct policydb *newp,
>>  			struct context *c)
>>  {
>> @@ -470,7 +471,7 @@ int mls_convert_context(struct policydb *oldp,
>>  	struct ebitmap_node *node;
>>  	int l, i;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	for (l = 0; l < 2; l++) {
>> @@ -503,7 +504,7 @@ int mls_convert_context(struct policydb *oldp,
>>  	return 0;
>>  }
>>  
>> -int mls_compute_sid(struct context *scontext,
>> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>>  		    struct context *tcontext,
>>  		    u16 tclass,
>>  		    u32 specified,
>> @@ -515,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
>>  	struct class_datum *cladatum;
>>  	int default_range = 0;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	switch (specified) {
>> @@ -524,12 +525,12 @@ int mls_compute_sid(struct context *scontext,
>>  		rtr.source_type = scontext->type;
>>  		rtr.target_type = tcontext->type;
>>  		rtr.target_class = tclass;
>> -		r = hashtab_search(policydb.range_tr, &rtr);
>> +		r = hashtab_search(p->range_tr, &rtr);
>>  		if (r)
>>  			return mls_range_set(newcontext, r);
>>  
>> -		if (tclass && tclass <= policydb.p_classes.nprim) {
>> -			cladatum =
>> policydb.class_val_to_struct[tclass - 1];
>> +		if (tclass && tclass <= p->p_classes.nprim) {
>> +			cladatum = p->class_val_to_struct[tclass -
>> 1];
>>  			if (cladatum)
>>  				default_range = cladatum-
>>> default_range;
>>  		}
>> @@ -551,7 +552,7 @@ int mls_compute_sid(struct context *scontext,
>>  
>>  		/* Fallthrough */
>>  	case AVTAB_CHANGE:
>> -		if ((tclass == policydb.process_class) || (sock ==
>> true))
>> +		if ((tclass == p->process_class) || (sock == true))
>>  			/* Use the process MLS attributes. */
>>  			return mls_context_cpy(newcontext,
>> scontext);
>>  		else
>> @@ -577,10 +578,10 @@ int mls_compute_sid(struct context *scontext,
>>   * NetLabel MLS sensitivity level field.
>>   *
>>   */
>> -void mls_export_netlbl_lvl(struct context *context,
>> +void mls_export_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr)
>>  {
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
>> @@ -597,10 +598,10 @@ void mls_export_netlbl_lvl(struct context
>> *context,
>>   * NetLabel MLS sensitivity level into the context.
>>   *
>>   */
>> -void mls_import_netlbl_lvl(struct context *context,
>> +void mls_import_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr)
>>  {
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return;
>>  
>>  	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
>> @@ -617,12 +618,12 @@ void mls_import_netlbl_lvl(struct context
>> *context,
>>   * MLS category field.  Returns zero on success, negative values on
>> failure.
>>   *
>>   */
>> -int mls_export_netlbl_cat(struct context *context,
>> +int mls_export_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr)
>>  {
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
>> @@ -645,12 +646,12 @@ int mls_export_netlbl_cat(struct context
>> *context,
>>   * negative values on failure.
>>   *
>>   */
>> -int mls_import_netlbl_cat(struct context *context,
>> +int mls_import_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr)
>>  {
>>  	int rc;
>>  
>> -	if (!policydb.mls_enabled)
>> +	if (!p->mls_enabled)
>>  		return 0;
>>  
>>  	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
>> diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
>> index 131d762..cb039c0 100644
>> --- a/security/selinux/ss/mls.h
>> +++ b/security/selinux/ss/mls.h
>> @@ -25,8 +25,9 @@
>>  #include "context.h"
>>  #include "policydb.h"
>>  
>> -int mls_compute_context_len(struct context *context);
>> -void mls_sid_to_context(struct context *context, char **scontext);
>> +int mls_compute_context_len(struct policydb *p, struct context
>> *context);
>> +void mls_sid_to_context(struct policydb *p, struct context *context,
>> +			char **scontext);
>>  int mls_context_isvalid(struct policydb *p, struct context *c);
>>  int mls_range_isvalid(struct policydb *p, struct mls_range *r);
>>  int mls_level_isvalid(struct policydb *p, struct mls_level *l);
>> @@ -38,50 +39,55 @@ int mls_context_to_sid(struct policydb *p,
>>  		       struct sidtab *s,
>>  		       u32 def_sid);
>>  
>> -int mls_from_string(char *str, struct context *context, gfp_t
>> gfp_mask);
>> +int mls_from_string(struct policydb *p, char *str, struct context
>> *context,
>> +		    gfp_t gfp_mask);
>>  
>>  int mls_range_set(struct context *context, struct mls_range *range);
>>  
>> -int mls_convert_context(struct policydb *oldp,
>> +int mls_convert_context(struct policydb *p, struct policydb *oldp,
>>  			struct policydb *newp,
>>  			struct context *context);
>>  
>> -int mls_compute_sid(struct context *scontext,
>> +int mls_compute_sid(struct policydb *p, struct context *scontext,
>>  		    struct context *tcontext,
>>  		    u16 tclass,
>>  		    u32 specified,
>>  		    struct context *newcontext,
>>  		    bool sock);
>>  
>> -int mls_setup_user_range(struct context *fromcon, struct user_datum
>> *user,
>> -			 struct context *usercon);
>> +int mls_setup_user_range(struct policydb *p, struct context
>> *fromcon,
>> +			 struct user_datum *user, struct context
>> *usercon);
>>  
>>  #ifdef CONFIG_NETLABEL
>> -void mls_export_netlbl_lvl(struct context *context,
>> +void mls_export_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr);
>> -void mls_import_netlbl_lvl(struct context *context,
>> +void mls_import_netlbl_lvl(struct policydb *p, struct context
>> *context,
>>  			   struct netlbl_lsm_secattr *secattr);
>> -int mls_export_netlbl_cat(struct context *context,
>> +int mls_export_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr);
>> -int mls_import_netlbl_cat(struct context *context,
>> +int mls_import_netlbl_cat(struct policydb *p, struct context
>> *context,
>>  			  struct netlbl_lsm_secattr *secattr);
>>  #else
>> -static inline void mls_export_netlbl_lvl(struct context *context,
>> +static inline void mls_export_netlbl_lvl(struct policydb *p,
>> +					 struct context *context,
>>  					 struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return;
>>  }
>> -static inline void mls_import_netlbl_lvl(struct context *context,
>> +static inline void mls_import_netlbl_lvl(struct policydb *p,
>> +					 struct context *context,
>>  					 struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return;
>>  }
>> -static inline int mls_export_netlbl_cat(struct context *context,
>> +static inline int mls_export_netlbl_cat(struct policydb *p,
>> +					struct context *context,
>>  					struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return -ENOMEM;
>>  }
>> -static inline int mls_import_netlbl_cat(struct context *context,
>> +static inline int mls_import_netlbl_cat(struct policydb *p,
>> +					struct context *context,
>>  					struct netlbl_lsm_secattr
>> *secattr)
>>  {
>>  	return -ENOMEM;
>> @@ -89,4 +95,3 @@ static inline int mls_import_netlbl_cat(struct
>> context *context,
>>  #endif
>>  
>>  #endif	/* _SS_MLS_H */
>> -
>> diff --git a/security/selinux/ss/services.c
>> b/security/selinux/ss/services.c
>> index 33cfe5d..47d8030 100644
>> --- a/security/selinux/ss/services.c
>> +++ b/security/selinux/ss/services.c
>> @@ -90,7 +90,7 @@ int selinux_policycap_nnp_nosuid_transition;
>>  static DEFINE_RWLOCK(policy_rwlock);
>>  
>>  static struct sidtab sidtab;
>> -struct policydb policydb;
>> +static struct policydb policydb;
>>  int ss_initialized;
>>  
>>  /*
>> @@ -117,8 +117,12 @@ struct selinux_mapping {
>>  	u32 perms[sizeof(u32) * 8];
>>  };
>>  
>> -static struct selinux_mapping *current_mapping;
>> -static u16 current_mapping_size;
>> +struct shared_current_mapping {
>> +	struct selinux_mapping *current_mapping;
>> +	u16 current_mapping_size;
>> +};
>> +
>> +static struct shared_current_mapping *crm;
>>  
>>  static int selinux_set_mapping(struct policydb *pol,
>>  			       struct security_class_mapping *map,
>> @@ -208,8 +212,8 @@ static int selinux_set_mapping(struct policydb
>> *pol,
>>  
>>  static u16 unmap_class(u16 tclass)
>>  {
>> -	if (tclass < current_mapping_size)
>> -		return current_mapping[tclass].value;
>> +	if (tclass < crm->current_mapping_size)
>> +		return crm->current_mapping[tclass].value;
>>  
>>  	return tclass;
>>  }
>> @@ -221,8 +225,8 @@ static u16 map_class(u16 pol_value)
>>  {
>>  	u16 i;
>>  
>> -	for (i = 1; i < current_mapping_size; i++) {
>> -		if (current_mapping[i].value == pol_value)
>> +	for (i = 1; i < crm->current_mapping_size; i++) {
>> +		if (crm->current_mapping[i].value == pol_value)
>>  			return i;
>>  	}
>>  
>> @@ -232,27 +236,32 @@ static u16 map_class(u16 pol_value)
>>  static void map_decision(u16 tclass, struct av_decision *avd,
>>  			 int allow_unknown)
>>  {
>> -	if (tclass < current_mapping_size) {
>> -		unsigned i, n = current_mapping[tclass].num_perms;
>> +	if (tclass < crm->current_mapping_size) {
>> +		unsigned int i, n = crm-
>>> current_mapping[tclass].num_perms;
>>  		u32 result;
>>  
>>  		for (i = 0, result = 0; i < n; i++) {
>> -			if (avd->allowed &
>> current_mapping[tclass].perms[i])
>> +			if (avd->allowed &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>> -			if (allow_unknown &&
>> !current_mapping[tclass].perms[i])
>> +			if (allow_unknown &&
>> +			    !crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		}
>>  		avd->allowed = result;
>>  
>>  		for (i = 0, result = 0; i < n; i++)
>> -			if (avd->auditallow &
>> current_mapping[tclass].perms[i])
>> +			if (avd->auditallow &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		avd->auditallow = result;
>>  
>>  		for (i = 0, result = 0; i < n; i++) {
>> -			if (avd->auditdeny &
>> current_mapping[tclass].perms[i])
>> +			if (avd->auditdeny &
>> +			    crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>> -			if (!allow_unknown &&
>> !current_mapping[tclass].perms[i])
>> +			if (!allow_unknown &&
>> +			    !crm->current_mapping[tclass].perms[i])
>>  				result |= 1<<i;
>>  		}
>>  		/*
>> @@ -1211,7 +1220,7 @@ static int context_struct_to_string(struct
>> context *context, char **scontext, u3
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_USERS,
>> context->user - 1)) + 1;
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES,
>> context->role - 1)) + 1;
>>  	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES,
>> context->type - 1)) + 1;
>> -	*scontext_len += mls_compute_context_len(context);
>> +	*scontext_len += mls_compute_context_len(&policydb,
>> context);
>>  
>>  	if (!scontext)
>>  		return 0;
>> @@ -1230,7 +1239,7 @@ static int context_struct_to_string(struct
>> context *context, char **scontext, u3
>>  		sym_name(&policydb, SYM_ROLES, context->role - 1),
>>  		sym_name(&policydb, SYM_TYPES, context->type - 1));
>>  
>> -	mls_sid_to_context(context, &scontextp);
>> +	mls_sid_to_context(&policydb, context, &scontextp);
>>  
>>  	*scontextp = 0;
>>  
>> @@ -1721,7 +1730,7 @@ static int security_compute_sid(u32 ssid,
>>  
>>  	/* Set the MLS attributes.
>>  	   This is done last because it may allocate memory. */
>> -	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
>> +	rc = mls_compute_sid(&policydb, scontext, tcontext, tclass,
>> specified,
>>  			     &newcontext, sock);
>>  	if (rc)
>>  		goto out_unlock;
>> @@ -1935,7 +1944,7 @@ static int convert_context(u32 key,
>>  
>>  	/* Convert the MLS fields if dealing with MLS policies */
>>  	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
>> -		rc = mls_convert_context(args->oldp, args->newp, c);
>> +		rc = mls_convert_context(&policydb, args->oldp,
>> args->newp, c);
>>  		if (rc)
>>  			goto bad;
>>  	} else if (args->oldp->mls_enabled && !args->newp-
>>> mls_enabled) {
>> @@ -2043,8 +2052,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  {
>>  	struct policydb *oldpolicydb, *newpolicydb;
>>  	struct sidtab oldsidtab, newsidtab;
>> -	struct selinux_mapping *oldmap, *map = NULL;
>> +	struct selinux_mapping *oldmap = NULL, *map = NULL;
>>  	struct convert_context_args args;
>> +	struct shared_current_mapping *new_mapping;
>>  	u32 seqno;
>>  	u16 map_size;
>>  	int rc = 0;
>> @@ -2055,9 +2065,22 @@ int security_load_policy(void *data, size_t
>> len)
>>  		rc = -ENOMEM;
>>  		goto out;
>>  	}
>> +	new_mapping = kzalloc(sizeof(struct shared_current_mapping),
>> +			      GFP_KERNEL);
>> +	if (!new_mapping) {
>> +		rc = -ENOMEM;
>> +		goto out;
>> +	}
>>  	newpolicydb = oldpolicydb + 1;
>>  
>>  	if (!ss_initialized) {
>> +		crm = kzalloc(sizeof(struct shared_current_mapping),
>> +			      GFP_KERNEL);
>> +		if (!crm) {
>> +			rc = -ENOMEM;
>> +			goto out;
>> +		}
>> +
>>  		avtab_cache_init();
>>  		ebitmap_cache_init();
>>  		hashtab_cache_init();
>> @@ -2071,8 +2094,8 @@ int security_load_policy(void *data, size_t
>> len)
>>  
>>  		policydb.len = len;
>>  		rc = selinux_set_mapping(&policydb, secclass_map,
>> -					 &current_mapping,
>> -					 &current_mapping_size);
>> +					 &crm->current_mapping,
>> +					 &crm-
>>> current_mapping_size);
>>  		if (rc) {
>>  			policydb_destroy(&policydb);
>>  			avtab_cache_destroy();
>> @@ -2164,9 +2187,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  	memcpy(&policydb, newpolicydb, sizeof(policydb));
>>  	sidtab_set(&sidtab, &newsidtab);
>>  	security_load_policycaps();
>> -	oldmap = current_mapping;
>> -	current_mapping = map;
>> -	current_mapping_size = map_size;
>> +	oldmap = crm->current_mapping;
>> +	crm->current_mapping = map;
>> +	crm->current_mapping_size = map_size;
>>  	seqno = ++latest_granting;
>>  	write_unlock_irq(&policy_rwlock);
>>  
>> @@ -2516,7 +2539,8 @@ int security_get_user_sids(u32 fromsid,
>>  		ebitmap_for_each_positive_bit(&role->types, tnode,
>> j) {
>>  			usercon.type = j + 1;
>>  
>> -			if (mls_setup_user_range(fromcon, user,
>> &usercon))
>> +			if (mls_setup_user_range(&policydb, fromcon,
>> +						 user, &usercon))
>>  				continue;
>>  
>>  			rc = sidtab_context_to_sid(&sidtab,
>> &usercon, &sid);
>> @@ -2580,7 +2604,7 @@ int security_get_user_sids(u32 fromsid,
>>   * cannot support xattr or use a fixed labeling behavior like
>>   * transition SIDs or task SIDs.
>>   *
>> - * The caller must acquire the policy_rwlock before calling this
>> function.
>> + * The caller must hold rcu before calling this function.
>>   */
>>  static inline int __security_genfs_sid(const char *fstype,
>>  				       char *path,
>> @@ -2639,7 +2663,7 @@ static inline int __security_genfs_sid(const
>> char *fstype,
>>   * @sclass: file security class
>>   * @sid: SID for path
>>   *
>> - * Acquire policy_rwlock before calling __security_genfs_sid() and
>> release
>> + * Hold rcu before calling __security_genfs_sid() and release
>>   * it afterward.
>>   */
>>  int security_genfs_sid(const char *fstype,
>> @@ -3214,7 +3238,8 @@ int selinux_audit_rule_init(u32 field, u32 op,
>> char *rulestr, void **vrule)
>>  	case AUDIT_SUBJ_CLR:
>>  	case AUDIT_OBJ_LEV_LOW:
>>  	case AUDIT_OBJ_LEV_HIGH:
>> -		rc = mls_from_string(rulestr, &tmprule->au_ctxt,
>> GFP_ATOMIC);
>> +		rc = mls_from_string(&policydb, rulestr, &tmprule-
>>> au_ctxt,
>> +				     GFP_ATOMIC);
>>  		if (rc)
>>  			goto out;
>>  		break;
>> @@ -3464,9 +3489,10 @@ int security_netlbl_secattr_to_sid(struct
>> netlbl_lsm_secattr *secattr,
>>  		ctx_new.user = ctx->user;
>>  		ctx_new.role = ctx->role;
>>  		ctx_new.type = ctx->type;
>> -		mls_import_netlbl_lvl(&ctx_new, secattr);
>> +		mls_import_netlbl_lvl(&policydb, &ctx_new, secattr);
>>  		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
>> -			rc = mls_import_netlbl_cat(&ctx_new,
>> secattr);
>> +			rc = mls_import_netlbl_cat(&policydb,
>> &ctx_new,
>> +						   secattr);
>>  			if (rc)
>>  				goto out;
>>  		}
>> @@ -3526,8 +3552,8 @@ int security_netlbl_sid_to_secattr(u32 sid,
>> struct netlbl_lsm_secattr *secattr)
>>  
>>  	secattr->attr.secid = sid;
>>  	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY |
>> NETLBL_SECATTR_SECID;
>> -	mls_export_netlbl_lvl(ctx, secattr);
>> -	rc = mls_export_netlbl_cat(ctx, secattr);
>> +	mls_export_netlbl_lvl(&policydb, ctx, secattr);
>> +	rc = mls_export_netlbl_cat(&policydb, ctx, secattr);
>>  out:
>>  	read_unlock(&policy_rwlock);
>>  	return rc;
>> diff --git a/security/selinux/ss/services.h
>> b/security/selinux/ss/services.h
>> index 356bdd3..50c7ceb 100644
>> --- a/security/selinux/ss/services.h
>> +++ b/security/selinux/ss/services.h
>> @@ -10,8 +10,6 @@
>>  #include "policydb.h"
>>  #include "sidtab.h"
>>  
>> -extern struct policydb policydb;
>> -
>>  void services_compute_xperms_drivers(struct extended_perms *xperms,
>>  				struct avtab_node *node);
>>  
>> @@ -19,4 +17,3 @@ void services_compute_xperms_decision(struct
>> extended_perms_decision *xpermd,
>>  					struct avtab_node *node);
>>  
>>  #endif	/* _SS_SERVICES_H_ */
>> -


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-02-01 15:17       ` peter enderborg
@ 2018-02-01 15:28         ` Stephen Smalley
  -1 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-02-01 15:28 UTC (permalink / raw)
  To: peter enderborg, selinux, linux-security-module

On Thu, 2018-02-01 at 16:17 +0100, peter enderborg wrote:
> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
> > On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> > > From: Peter Enderborg <peter.enderborg@sony.com>
> > > 
> > > To be able to use rcu locks we seed to address the policydb
> > > though a pointer. This preparation removes the export of the
> > > policydb and send pointers to it through parameter agruments.
> > 
> > Just for reference, I have a patch series that does this not only
> > for
> > the policydb, sidtab, and class/perm mapping, but for all of the
> > SELinux global state, see:
> > https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
> > and in particular
> > https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd
> > 720c8f8aab51007e805bf7c4f10d2
> > https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173
> > d56a331423b6d1564b801f0915afc
> > https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e
> > 4458bc4562c47d8f7bc4f56fbfefd
> > 
> > Those first three patches should have no effect on SELinux
> > behavior.
> > They need to be re-based to latest selinux next branch (some minor
> > conflict resolution required) but I was waiting for that to advance
> > to
> > something 4.15-rcX based.  I could however re-base it now if
> > desired.
> 
> I read that as that you want me to rebase the patches on that tree?
> Seems to
> be partly prepared but lot of changes.  Is it a moving target?

No, I wouldn't re-base on that tree.  If/when Paul updates the selinux
next branch (which should be what your patches are relative to), then I
will re-base my patches on his branch and re-submit the first few
patches to see if we can get those merged now since they don't change
SELinux behavior or interfaces.  That will take care of removing direct
references to the policydb, sidtab, and class/perm mapping among other
things.

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-02-01 15:28         ` Stephen Smalley
  0 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-02-01 15:28 UTC (permalink / raw)
  To: linux-security-module

On Thu, 2018-02-01 at 16:17 +0100, peter enderborg wrote:
> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
> > On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> > > From: Peter Enderborg <peter.enderborg@sony.com>
> > > 
> > > To be able to use rcu locks we seed to address the policydb
> > > though a pointer. This preparation removes the export of the
> > > policydb and send pointers to it through parameter agruments.
> > 
> > Just for reference, I have a patch series that does this not only
> > for
> > the policydb, sidtab, and class/perm mapping, but for all of the
> > SELinux global state, see:
> > https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
> > and in particular
> > https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd
> > 720c8f8aab51007e805bf7c4f10d2
> > https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173
> > d56a331423b6d1564b801f0915afc
> > https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e
> > 4458bc4562c47d8f7bc4f56fbfefd
> > 
> > Those first three patches should have no effect on SELinux
> > behavior.
> > They need to be re-based to latest selinux next branch (some minor
> > conflict resolution required) but I was waiting for that to advance
> > to
> > something 4.15-rcX based.  I could however re-base it now if
> > desired.
> 
> I read that as that you want me to rebase the patches on that tree?
> Seems to
> be partly prepared but lot of changes.  Is it a moving target?

No, I wouldn't re-base on that tree.  If/when Paul updates the selinux
next branch (which should be what your patches are relative to), then I
will re-base my patches on his branch and re-submit the first few
patches to see if we can get those merged now since they don't change
SELinux behavior or interfaces.  That will take care of removing direct
references to the policydb, sidtab, and class/perm mapping among other
things.


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-02-01 15:17       ` peter enderborg
@ 2018-02-01 15:55         ` Paul Moore
  -1 siblings, 0 replies; 38+ messages in thread
From: Paul Moore @ 2018-02-01 15:55 UTC (permalink / raw)
  To: peter enderborg, Stephen Smalley; +Cc: selinux, linux-security-module

On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
<peter.enderborg@sony.com> wrote:
> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>
>>> To be able to use rcu locks we seed to address the policydb
>>> though a pointer. This preparation removes the export of the
>>> policydb and send pointers to it through parameter agruments.
>> Just for reference, I have a patch series that does this not only for
>> the policydb, sidtab, and class/perm mapping, but for all of the
>> SELinux global state, see:
>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>> and in particular
>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>
>> Those first three patches should have no effect on SELinux behavior.
>> They need to be re-based to latest selinux next branch (some minor
>> conflict resolution required) but I was waiting for that to advance to
>> something 4.15-rcX based.  I could however re-base it now if desired.
>
> I read that as that you want me to rebase the patches on that tree? Seems to
> be partly prepared but lot of changes.  Is it a moving target?

Stephen is being nice and not throwing me under the bus, but I'm most
likely the problem here.

Last summer/fall Stephen and I had a discussion about SELinux
namespacing and we talked about some of the preparatory work that
needed to be done before the namespacing work could be started.  The
namespacing work is obviously off topic for the work you are doing,
but a big part of the necessary cleanup work was the consolidation and
encapsulation of the various SELinux global state variables.  At the
time I encouraged Stephen to post this work as I felt it would be
useful independent of the namespacing work, and I think we are seeing
one reason why with the work you are doing.

I owe Stephen some review/feedback on his namespace patchset, at the
very least the global state work that he referenced with you.  I'm
just getting back from some traveling over the past week or so, let me
review the first few patches in Stephen's patchset with the idea of
getting those merged and then you can use those as a base for your
work.  From what I can see, I imagine that having Stephen's work as a
base would be helpful for you.  I'll make a promise to get Stephen
feedback by the end of next week at the latest; I'll aim for sooner.

Does that help?

-- 
paul moore
www.paul-moore.com

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-02-01 15:55         ` Paul Moore
  0 siblings, 0 replies; 38+ messages in thread
From: Paul Moore @ 2018-02-01 15:55 UTC (permalink / raw)
  To: linux-security-module

On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
<peter.enderborg@sony.com> wrote:
> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>
>>> To be able to use rcu locks we seed to address the policydb
>>> though a pointer. This preparation removes the export of the
>>> policydb and send pointers to it through parameter agruments.
>> Just for reference, I have a patch series that does this not only for
>> the policydb, sidtab, and class/perm mapping, but for all of the
>> SELinux global state, see:
>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>> and in particular
>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>
>> Those first three patches should have no effect on SELinux behavior.
>> They need to be re-based to latest selinux next branch (some minor
>> conflict resolution required) but I was waiting for that to advance to
>> something 4.15-rcX based.  I could however re-base it now if desired.
>
> I read that as that you want me to rebase the patches on that tree? Seems to
> be partly prepared but lot of changes.  Is it a moving target?

Stephen is being nice and not throwing me under the bus, but I'm most
likely the problem here.

Last summer/fall Stephen and I had a discussion about SELinux
namespacing and we talked about some of the preparatory work that
needed to be done before the namespacing work could be started.  The
namespacing work is obviously off topic for the work you are doing,
but a big part of the necessary cleanup work was the consolidation and
encapsulation of the various SELinux global state variables.  At the
time I encouraged Stephen to post this work as I felt it would be
useful independent of the namespacing work, and I think we are seeing
one reason why with the work you are doing.

I owe Stephen some review/feedback on his namespace patchset, at the
very least the global state work that he referenced with you.  I'm
just getting back from some traveling over the past week or so, let me
review the first few patches in Stephen's patchset with the idea of
getting those merged and then you can use those as a base for your
work.  From what I can see, I imagine that having Stephen's work as a
base would be helpful for you.  I'll make a promise to get Stephen
feedback by the end of next week at the latest; I'll aim for sooner.

Does that help?

-- 
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  2018-01-30 14:37     ` Stephen Smalley
@ 2018-02-08  7:16       ` peter enderborg
  -1 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-02-08  7:16 UTC (permalink / raw)
  To: Stephen Smalley, selinux, linux-security-module

On 01/30/2018 03:37 PM, Stephen Smalley wrote:
> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> goto err;
>  
> -	rc = security_preserve_bools(newpolicydb);
> +	rc = security_preserve_bools(&next_rcu->policydb);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to preserve
> booleans\n");
>  		goto err;
> Most of this shouldn't need to be under the read lock.
>
>> @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
>> len)
>>  	 * in the new SID table.
>>  	 */
>>  	args.oldp = &crm->policydb;
>> -	args.newp = newpolicydb;
>> +	args.newp = &next_rcu->policydb;
>>  	rc = sidtab_map(&newsidtab, convert_context, &args);
>>  	if (rc) {
>>  		printk(KERN_ERR "SELinux:  unable to convert the
>> internal"
>> @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  
>>  	/* Install the new policydb and SID table. */
>>  	/* next */
>> +	security_load_policycaps(&next_rcu->policydb);
> This cannot be done outside of the write lock; it has to be atomic with
> the policy switch.
Can you please elaborate, does some else write the policydb without a lock?
Is there any other data that is shared? I see this as a private until we switch the pointer.
>> +	read_unlock(&policy_rwlock);
>>  	write_lock_irq(&policy_rwlock);
>> -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
>> policydb));
>>  	sidtab_set(&next_rcu->sidtab, &newsidtab);
>>  	security_load_policycaps(&next_rcu->policydb);
>>  	oldmap = crm->current_mapping;
>> @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  	next_rcu->current_mapping_size = map_size;
>>  
>>  	seqno = ++latest_granting;
>> -	write_unlock_irq(&policy_rwlock);
>> +	old_rcu = crm;
>>  	crm = next_rcu;
>> +	write_unlock_irq(&policy_rwlock);
>>  
>>  	/* Free the old policydb and SID table. */
>>  	policydb_destroy(oldpolicydb);
>> @@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t
>> len)
>>  	selinux_status_update_policyload(seqno);
>>  	selinux_netlbl_cache_invalidate();
>>  	selinux_xfrm_notify_policyload();
>> +	kfree(oldpolicydb);
>> +	kfree(old_rcu);
>>  
>>  	rc = 0;
>>  	goto out;
>> -
>>  err:
>>  	kfree(map);
>>  	sidtab_destroy(&newsidtab);
>> -	policydb_destroy(newpolicydb);
>> -
>> +	

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
@ 2018-02-08  7:16       ` peter enderborg
  0 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-02-08  7:16 UTC (permalink / raw)
  To: linux-security-module

On 01/30/2018 03:37 PM, Stephen Smalley wrote:
> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> goto err;
>  
> -	rc = security_preserve_bools(newpolicydb);
> +	rc = security_preserve_bools(&next_rcu->policydb);
>  	if (rc) {
>  		printk(KERN_ERR "SELinux:  unable to preserve
> booleans\n");
>  		goto err;
> Most of this shouldn't need to be under the read lock.
>
>> @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
>> len)
>>  	 * in the new SID table.
>>  	 */
>>  	args.oldp = &crm->policydb;
>> -	args.newp = newpolicydb;
>> +	args.newp = &next_rcu->policydb;
>>  	rc = sidtab_map(&newsidtab, convert_context, &args);
>>  	if (rc) {
>>  		printk(KERN_ERR "SELinux:  unable to convert the
>> internal"
>> @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  
>>  	/* Install the new policydb and SID table. */
>>  	/* next */
>> +	security_load_policycaps(&next_rcu->policydb);
> This cannot be done outside of the write lock; it has to be atomic with
> the policy switch.
Can you please elaborate, does some else write the policydb without a lock?
Is there any other data that is shared? I see this as a private until we switch the pointer.
>> +	read_unlock(&policy_rwlock);
>>  	write_lock_irq(&policy_rwlock);
>> -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
>> policydb));
>>  	sidtab_set(&next_rcu->sidtab, &newsidtab);
>>  	security_load_policycaps(&next_rcu->policydb);
>>  	oldmap = crm->current_mapping;
>> @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
>> len)
>>  	next_rcu->current_mapping_size = map_size;
>>  
>>  	seqno = ++latest_granting;
>> -	write_unlock_irq(&policy_rwlock);
>> +	old_rcu = crm;
>>  	crm = next_rcu;
>> +	write_unlock_irq(&policy_rwlock);
>>  
>>  	/* Free the old policydb and SID table. */
>>  	policydb_destroy(oldpolicydb);
>> @@ -2226,17 +2233,16 @@ int security_load_policy(void *data, size_t
>> len)
>>  	selinux_status_update_policyload(seqno);
>>  	selinux_netlbl_cache_invalidate();
>>  	selinux_xfrm_notify_policyload();
>> +	kfree(oldpolicydb);
>> +	kfree(old_rcu);
>>  
>>  	rc = 0;
>>  	goto out;
>> -
>>  err:
>>  	kfree(map);
>>  	sidtab_destroy(&newsidtab);
>> -	policydb_destroy(newpolicydb);
>> -
>> +	

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
  2018-02-08  7:16       ` peter enderborg
@ 2018-02-08 15:10         ` Stephen Smalley
  -1 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-02-08 15:10 UTC (permalink / raw)
  To: peter enderborg, selinux, linux-security-module

On Thu, 2018-02-08 at 08:16 +0100, peter enderborg wrote:
> On 01/30/2018 03:37 PM, Stephen Smalley wrote:
> > On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
> > goto err;
> >  
> > -	rc = security_preserve_bools(newpolicydb);
> > +	rc = security_preserve_bools(&next_rcu->policydb);
> >  	if (rc) {
> >  		printk(KERN_ERR "SELinux:  unable to preserve
> > booleans\n");
> >  		goto err;
> > Most of this shouldn't need to be under the read lock.
> > 
> > > @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  	 * in the new SID table.
> > >  	 */
> > >  	args.oldp = &crm->policydb;
> > > -	args.newp = newpolicydb;
> > > +	args.newp = &next_rcu->policydb;
> > >  	rc = sidtab_map(&newsidtab, convert_context, &args);
> > >  	if (rc) {
> > >  		printk(KERN_ERR "SELinux:  unable to convert the
> > > internal"
> > > @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  
> > >  	/* Install the new policydb and SID table. */
> > >  	/* next */
> > > +	security_load_policycaps(&next_rcu->policydb);
> > 
> > This cannot be done outside of the write lock; it has to be atomic
> > with
> > the policy switch.
> 
> Can you please elaborate, does some else write the policydb without a
> lock?
> Is there any other data that is shared? I see this as a private until
> we switch the pointer.

security_load_policycaps() updates the selinux_policycap_* variables
from the policydb.  Those variables are used by the hooks to
enable/disable policy-specific functionality, like whether to check
open permission or assign finer-grained security classes to sockets. 
We need to atomically update those variables with the active policy;
otherwise, a hook may perform a permission check that wasn't supposed
to be enabled under the old policy against the old policy (yielding an
unexpected denial).  Everything done under the write lock currently is
there for a reason.

> > > +	read_unlock(&policy_rwlock);
> > >  	write_lock_irq(&policy_rwlock);
> > > -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
> > > policydb));
> > >  	sidtab_set(&next_rcu->sidtab, &newsidtab);
> > >  	security_load_policycaps(&next_rcu->policydb);
> > >  	oldmap = crm->current_mapping;
> > > @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  	next_rcu->current_mapping_size = map_size;
> > >  
> > >  	seqno = ++latest_granting;
> > > -	write_unlock_irq(&policy_rwlock);
> > > +	old_rcu = crm;
> > >  	crm = next_rcu;
> > > +	write_unlock_irq(&policy_rwlock);
> > >  
> > >  	/* Free the old policydb and SID table. */
> > >  	policydb_destroy(oldpolicydb);
> > > @@ -2226,17 +2233,16 @@ int security_load_policy(void *data,
> > > size_t
> > > len)
> > >  	selinux_status_update_policyload(seqno);
> > >  	selinux_netlbl_cache_invalidate();
> > >  	selinux_xfrm_notify_policyload();
> > > +	kfree(oldpolicydb);
> > > +	kfree(old_rcu);
> > >  
> > >  	rc = 0;
> > >  	goto out;
> > > -
> > >  err:
> > >  	kfree(map);
> > >  	sidtab_destroy(&newsidtab);
> > > -	policydb_destroy(newpolicydb);
> > > -
> > > +	
> 
> 

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

* [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab
@ 2018-02-08 15:10         ` Stephen Smalley
  0 siblings, 0 replies; 38+ messages in thread
From: Stephen Smalley @ 2018-02-08 15:10 UTC (permalink / raw)
  To: linux-security-module

On Thu, 2018-02-08 at 08:16 +0100, peter enderborg wrote:
> On 01/30/2018 03:37 PM, Stephen Smalley wrote:
> > On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
> > goto err;
> >  
> > -	rc = security_preserve_bools(newpolicydb);
> > +	rc = security_preserve_bools(&next_rcu->policydb);
> >  	if (rc) {
> >  		printk(KERN_ERR "SELinux:  unable to preserve
> > booleans\n");
> >  		goto err;
> > Most of this shouldn't need to be under the read lock.
> > 
> > > @@ -2189,7 +2194,7 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  	 * in the new SID table.
> > >  	 */
> > >  	args.oldp = &crm->policydb;
> > > -	args.newp = newpolicydb;
> > > +	args.newp = &next_rcu->policydb;
> > >  	rc = sidtab_map(&newsidtab, convert_context, &args);
> > >  	if (rc) {
> > >  		printk(KERN_ERR "SELinux:  unable to convert the
> > > internal"
> > > @@ -2204,8 +2209,9 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  
> > >  	/* Install the new policydb and SID table. */
> > >  	/* next */
> > > +	security_load_policycaps(&next_rcu->policydb);
> > 
> > This cannot be done outside of the write lock; it has to be atomic
> > with
> > the policy switch.
> 
> Can you please elaborate, does some else write the policydb without a
> lock?
> Is there any other data that is shared? I see this as a private until
> we switch the pointer.

security_load_policycaps() updates the selinux_policycap_* variables
from the policydb.  Those variables are used by the hooks to
enable/disable policy-specific functionality, like whether to check
open permission or assign finer-grained security classes to sockets. 
We need to atomically update those variables with the active policy;
otherwise, a hook may perform a permission check that wasn't supposed
to be enabled under the old policy against the old policy (yielding an
unexpected denial).  Everything done under the write lock currently is
there for a reason.

> > > +	read_unlock(&policy_rwlock);
> > >  	write_lock_irq(&policy_rwlock);
> > > -	memcpy(&next_rcu->policydb, newpolicydb, sizeof(struct
> > > policydb));
> > >  	sidtab_set(&next_rcu->sidtab, &newsidtab);
> > >  	security_load_policycaps(&next_rcu->policydb);
> > >  	oldmap = crm->current_mapping;
> > > @@ -2213,8 +2219,9 @@ int security_load_policy(void *data, size_t
> > > len)
> > >  	next_rcu->current_mapping_size = map_size;
> > >  
> > >  	seqno = ++latest_granting;
> > > -	write_unlock_irq(&policy_rwlock);
> > > +	old_rcu = crm;
> > >  	crm = next_rcu;
> > > +	write_unlock_irq(&policy_rwlock);
> > >  
> > >  	/* Free the old policydb and SID table. */
> > >  	policydb_destroy(oldpolicydb);
> > > @@ -2226,17 +2233,16 @@ int security_load_policy(void *data,
> > > size_t
> > > len)
> > >  	selinux_status_update_policyload(seqno);
> > >  	selinux_netlbl_cache_invalidate();
> > >  	selinux_xfrm_notify_policyload();
> > > +	kfree(oldpolicydb);
> > > +	kfree(old_rcu);
> > >  
> > >  	rc = 0;
> > >  	goto out;
> > > -
> > >  err:
> > >  	kfree(map);
> > >  	sidtab_destroy(&newsidtab);
> > > -	policydb_destroy(newpolicydb);
> > > -
> > > +	
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-02-01 15:55         ` Paul Moore
@ 2018-04-03 11:41           ` peter enderborg
  -1 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-04-03 11:41 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley; +Cc: selinux, linux-security-module

On 02/01/2018 04:55 PM, Paul Moore wrote:
> On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
> <peter.enderborg@sony.com> wrote:
>> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
>>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>>
>>>> To be able to use rcu locks we seed to address the policydb
>>>> though a pointer. This preparation removes the export of the
>>>> policydb and send pointers to it through parameter agruments.
>>> Just for reference, I have a patch series that does this not only for
>>> the policydb, sidtab, and class/perm mapping, but for all of the
>>> SELinux global state, see:
>>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>>> and in particular
>>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>>
>>> Those first three patches should have no effect on SELinux behavior.
>>> They need to be re-based to latest selinux next branch (some minor
>>> conflict resolution required) but I was waiting for that to advance to
>>> something 4.15-rcX based.  I could however re-base it now if desired.
>> I read that as that you want me to rebase the patches on that tree? Seems to
>> be partly prepared but lot of changes.  Is it a moving target?
> Stephen is being nice and not throwing me under the bus, but I'm most
> likely the problem here.
>
> Last summer/fall Stephen and I had a discussion about SELinux
> namespacing and we talked about some of the preparatory work that
> needed to be done before the namespacing work could be started.  The
> namespacing work is obviously off topic for the work you are doing,
> but a big part of the necessary cleanup work was the consolidation and
> encapsulation of the various SELinux global state variables.  At the
> time I encouraged Stephen to post this work as I felt it would be
> useful independent of the namespacing work, and I think we are seeing
> one reason why with the work you are doing.
>
> I owe Stephen some review/feedback on his namespace patchset, at the
> very least the global state work that he referenced with you.  I'm
> just getting back from some traveling over the past week or so, let me
> review the first few patches in Stephen's patchset with the idea of
> getting those merged and then you can use those as a base for your
> work.  From what I can see, I imagine that having Stephen's work as a
> base would be helpful for you.  I'll make a promise to get Stephen
> feedback by the end of next week at the latest; I'll aim for sooner.
>
> Does that help?
>
Hi. Need follow up on this. I dont see any progress on this lately.  Is there any
conclusions about namespace thing in kernel code yet?

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-04-03 11:41           ` peter enderborg
  0 siblings, 0 replies; 38+ messages in thread
From: peter enderborg @ 2018-04-03 11:41 UTC (permalink / raw)
  To: linux-security-module

On 02/01/2018 04:55 PM, Paul Moore wrote:
> On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
> <peter.enderborg@sony.com> wrote:
>> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
>>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>>
>>>> To be able to use rcu locks we seed to address the policydb
>>>> though a pointer. This preparation removes the export of the
>>>> policydb and send pointers to it through parameter agruments.
>>> Just for reference, I have a patch series that does this not only for
>>> the policydb, sidtab, and class/perm mapping, but for all of the
>>> SELinux global state, see:
>>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>>> and in particular
>>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>>
>>> Those first three patches should have no effect on SELinux behavior.
>>> They need to be re-based to latest selinux next branch (some minor
>>> conflict resolution required) but I was waiting for that to advance to
>>> something 4.15-rcX based.  I could however re-base it now if desired.
>> I read that as that you want me to rebase the patches on that tree? Seems to
>> be partly prepared but lot of changes.  Is it a moving target?
> Stephen is being nice and not throwing me under the bus, but I'm most
> likely the problem here.
>
> Last summer/fall Stephen and I had a discussion about SELinux
> namespacing and we talked about some of the preparatory work that
> needed to be done before the namespacing work could be started.  The
> namespacing work is obviously off topic for the work you are doing,
> but a big part of the necessary cleanup work was the consolidation and
> encapsulation of the various SELinux global state variables.  At the
> time I encouraged Stephen to post this work as I felt it would be
> useful independent of the namespacing work, and I think we are seeing
> one reason why with the work you are doing.
>
> I owe Stephen some review/feedback on his namespace patchset, at the
> very least the global state work that he referenced with you.  I'm
> just getting back from some traveling over the past week or so, let me
> review the first few patches in Stephen's patchset with the idea of
> getting those merged and then you can use those as a base for your
> work.  From what I can see, I imagine that having Stephen's work as a
> base would be helpful for you.  I'll make a promise to get Stephen
> feedback by the end of next week at the latest; I'll aim for sooner.
>
> Does that help?
>
Hi. Need follow up on this. I dont see any progress on this lately.? Is there any
conclusions about namespace thing in kernel code yet?


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/5] selinux:Remove direct references to policydb.
  2018-04-03 11:41           ` peter enderborg
@ 2018-04-03 11:56             ` Paul Moore
  -1 siblings, 0 replies; 38+ messages in thread
From: Paul Moore @ 2018-04-03 11:56 UTC (permalink / raw)
  To: peter enderborg; +Cc: Stephen Smalley, selinux, linux-security-module

On Tue, Apr 3, 2018 at 7:41 AM, peter enderborg
<peter.enderborg@sony.com> wrote:
> On 02/01/2018 04:55 PM, Paul Moore wrote:
>> On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
>> <peter.enderborg@sony.com> wrote:
>>> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>>>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg@sony.com wrote:
>>>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>>>
>>>>> To be able to use rcu locks we seed to address the policydb
>>>>> though a pointer. This preparation removes the export of the
>>>>> policydb and send pointers to it through parameter agruments.
>>>> Just for reference, I have a patch series that does this not only for
>>>> the policydb, sidtab, and class/perm mapping, but for all of the
>>>> SELinux global state, see:
>>>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>>>> and in particular
>>>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>>>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>>>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>>>
>>>> Those first three patches should have no effect on SELinux behavior.
>>>> They need to be re-based to latest selinux next branch (some minor
>>>> conflict resolution required) but I was waiting for that to advance to
>>>> something 4.15-rcX based.  I could however re-base it now if desired.
>>> I read that as that you want me to rebase the patches on that tree? Seems to
>>> be partly prepared but lot of changes.  Is it a moving target?
>> Stephen is being nice and not throwing me under the bus, but I'm most
>> likely the problem here.
>>
>> Last summer/fall Stephen and I had a discussion about SELinux
>> namespacing and we talked about some of the preparatory work that
>> needed to be done before the namespacing work could be started.  The
>> namespacing work is obviously off topic for the work you are doing,
>> but a big part of the necessary cleanup work was the consolidation and
>> encapsulation of the various SELinux global state variables.  At the
>> time I encouraged Stephen to post this work as I felt it would be
>> useful independent of the namespacing work, and I think we are seeing
>> one reason why with the work you are doing.
>>
>> I owe Stephen some review/feedback on his namespace patchset, at the
>> very least the global state work that he referenced with you.  I'm
>> just getting back from some traveling over the past week or so, let me
>> review the first few patches in Stephen's patchset with the idea of
>> getting those merged and then you can use those as a base for your
>> work.  From what I can see, I imagine that having Stephen's work as a
>> base would be helpful for you.  I'll make a promise to get Stephen
>> feedback by the end of next week at the latest; I'll aim for sooner.
>>
>> Does that help?
>>
> Hi. Need follow up on this. I dont see any progress on this lately.  Is there any
> conclusions about namespace thing in kernel code yet?

The namespace work is still a work in progress, and to some degree an
open question as a result, but the work I believe you are interested
in, the consolidation/encapsulation patches, have been merged into the
selinux/next branch (you should have seen mail about that on-list) and
will be going up to Linus during this merge window.  I expect that to
happen within the next few days.

>From my perspective I'm expecting that you would be rebasing your work
on top of these patches, is that what you are planning?

-- 
paul moore
www.paul-moore.com

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

* [PATCH v2 1/5] selinux:Remove direct references to policydb.
@ 2018-04-03 11:56             ` Paul Moore
  0 siblings, 0 replies; 38+ messages in thread
From: Paul Moore @ 2018-04-03 11:56 UTC (permalink / raw)
  To: linux-security-module

On Tue, Apr 3, 2018 at 7:41 AM, peter enderborg
<peter.enderborg@sony.com> wrote:
> On 02/01/2018 04:55 PM, Paul Moore wrote:
>> On Thu, Feb 1, 2018 at 10:17 AM, peter enderborg
>> <peter.enderborg@sony.com> wrote:
>>> On 01/30/2018 02:46 PM, Stephen Smalley wrote:
>>>> On Fri, 2018-01-26 at 15:32 +0100, peter.enderborg at sony.com wrote:
>>>>> From: Peter Enderborg <peter.enderborg@sony.com>
>>>>>
>>>>> To be able to use rcu locks we seed to address the policydb
>>>>> though a pointer. This preparation removes the export of the
>>>>> policydb and send pointers to it through parameter agruments.
>>>> Just for reference, I have a patch series that does this not only for
>>>> the policydb, sidtab, and class/perm mapping, but for all of the
>>>> SELinux global state, see:
>>>> https://github.com/stephensmalley/selinux-kernel/tree/selinuxns
>>>> and in particular
>>>> https://github.com/stephensmalley/selinux-kernel/commit/c10d90b43cd720c8f8aab51007e805bf7c4f10d2
>>>> https://github.com/stephensmalley/selinux-kernel/commit/ec038a64173d56a331423b6d1564b801f0915afc
>>>> https://github.com/stephensmalley/selinux-kernel/commit/97aa5d7a05e4458bc4562c47d8f7bc4f56fbfefd
>>>>
>>>> Those first three patches should have no effect on SELinux behavior.
>>>> They need to be re-based to latest selinux next branch (some minor
>>>> conflict resolution required) but I was waiting for that to advance to
>>>> something 4.15-rcX based.  I could however re-base it now if desired.
>>> I read that as that you want me to rebase the patches on that tree? Seems to
>>> be partly prepared but lot of changes.  Is it a moving target?
>> Stephen is being nice and not throwing me under the bus, but I'm most
>> likely the problem here.
>>
>> Last summer/fall Stephen and I had a discussion about SELinux
>> namespacing and we talked about some of the preparatory work that
>> needed to be done before the namespacing work could be started.  The
>> namespacing work is obviously off topic for the work you are doing,
>> but a big part of the necessary cleanup work was the consolidation and
>> encapsulation of the various SELinux global state variables.  At the
>> time I encouraged Stephen to post this work as I felt it would be
>> useful independent of the namespacing work, and I think we are seeing
>> one reason why with the work you are doing.
>>
>> I owe Stephen some review/feedback on his namespace patchset, at the
>> very least the global state work that he referenced with you.  I'm
>> just getting back from some traveling over the past week or so, let me
>> review the first few patches in Stephen's patchset with the idea of
>> getting those merged and then you can use those as a base for your
>> work.  From what I can see, I imagine that having Stephen's work as a
>> base would be helpful for you.  I'll make a promise to get Stephen
>> feedback by the end of next week at the latest; I'll aim for sooner.
>>
>> Does that help?
>>
> Hi. Need follow up on this. I dont see any progress on this lately.  Is there any
> conclusions about namespace thing in kernel code yet?

The namespace work is still a work in progress, and to some degree an
open question as a result, but the work I believe you are interested
in, the consolidation/encapsulation patches, have been merged into the
selinux/next branch (you should have seen mail about that on-list) and
will be going up to Linus during this merge window.  I expect that to
happen within the next few days.

>From my perspective I'm expecting that you would be rebasing your work
on top of these patches, is that what you are planning?

-- 
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2018-04-03 11:58 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-26 14:32 [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds peter.enderborg
2018-01-26 14:32 ` peter.enderborg
2018-01-26 14:32 ` peter.enderborg at sony.com
2018-01-26 14:32 ` [PATCH v2 1/5] selinux:Remove direct references to policydb peter.enderborg
2018-01-26 14:32   ` peter.enderborg
2018-01-26 14:32   ` peter.enderborg at sony.com
2018-01-30 13:46   ` Stephen Smalley
2018-01-30 13:46     ` Stephen Smalley
2018-02-01 15:17     ` peter enderborg
2018-02-01 15:17       ` peter enderborg
2018-02-01 15:28       ` Stephen Smalley
2018-02-01 15:28         ` Stephen Smalley
2018-02-01 15:55       ` Paul Moore
2018-02-01 15:55         ` Paul Moore
2018-04-03 11:41         ` peter enderborg
2018-04-03 11:41           ` peter enderborg
2018-04-03 11:56           ` Paul Moore
2018-04-03 11:56             ` Paul Moore
2018-01-26 14:32 ` [PATCH v2 2/5] selinux: Move policydb to pointer structure peter.enderborg
2018-01-26 14:32   ` peter.enderborg
2018-01-26 14:32   ` peter.enderborg at sony.com
2018-01-26 14:32 ` [PATCH v2 3/5] selinux: Move sidtab " peter.enderborg
2018-01-26 14:32   ` peter.enderborg
2018-01-26 14:32   ` peter.enderborg at sony.com
2018-01-26 14:32 ` [PATCH v2 4/5] selinux: Use pointer to switch policydb and sidtab peter.enderborg
2018-01-26 14:32   ` peter.enderborg
2018-01-26 14:32   ` peter.enderborg at sony.com
2018-01-30 14:37   ` Stephen Smalley
2018-01-30 14:37     ` Stephen Smalley
2018-02-08  7:16     ` peter enderborg
2018-02-08  7:16       ` peter enderborg
2018-02-08 15:10       ` Stephen Smalley
2018-02-08 15:10         ` Stephen Smalley
2018-01-26 14:32 ` [PATCH v2 5/5] selinux: Switch locking to RCU peter.enderborg
2018-01-26 14:32   ` peter.enderborg
2018-01-26 14:32   ` peter.enderborg at sony.com
2018-01-30 13:37 ` [PATCH v2 0/5] selinux:Significant reduce of preempt_disable holds Stephen Smalley
2018-01-30 13:37   ` 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.