diff mbox series

[2/6] selinux: simplify security_preserve_bools()

Message ID 20200116120439.303034-3-omosnace@redhat.com (mailing list archive)
State Superseded
Headers show
Series selinux: Assorted simplifications and cleanups | expand

Commit Message

Ondrej Mosnacek Jan. 16, 2020, 12:04 p.m. UTC
First, evaluate_cond_node() never returns an error. Make it just return
void.

Second, drop the use of security_get_bools() from
security_preserve_bools() and read from the old policydb directly. This
saves some useless allocations and together with the first change makes
security_preserve_bools() no longer possibly return an error. Again the
return type is changed to void.

Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
 security/selinux/ss/conditional.c |  3 +-
 security/selinux/ss/conditional.h |  2 +-
 security/selinux/ss/services.c    | 52 ++++++++++---------------------
 3 files changed, 18 insertions(+), 39 deletions(-)

Comments

Stephen Smalley Jan. 16, 2020, 4:42 p.m. UTC | #1
On 1/16/20 7:04 AM, Ondrej Mosnacek wrote:
> First, evaluate_cond_node() never returns an error. Make it just return
> void.
> 
> Second, drop the use of security_get_bools() from
> security_preserve_bools() and read from the old policydb directly. This
> saves some useless allocations and together with the first change makes
> security_preserve_bools() no longer possibly return an error. Again the
> return type is changed to void.
> 
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

Dropping use of security_get_bools() means we are no longer reading the 
boolean values with the policy read-lock held so they could in theory 
change underneath us.  However, this is presently prevented via the 
fsi->mutex taken by selinuxfs so I believe this is safe.

Reviewed-by: Stephen Smalley <sds@tycho.nsa.gov>

> ---
>   security/selinux/ss/conditional.c |  3 +-
>   security/selinux/ss/conditional.h |  2 +-
>   security/selinux/ss/services.c    | 52 ++++++++++---------------------
>   3 files changed, 18 insertions(+), 39 deletions(-)
> 
> diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
> index 70c378ee1a2f..04593062008d 100644
> --- a/security/selinux/ss/conditional.c
> +++ b/security/selinux/ss/conditional.c
> @@ -85,7 +85,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
>    * list appropriately. If the result of the expression is undefined
>    * all of the rules are disabled for safety.
>    */
> -int evaluate_cond_node(struct policydb *p, struct cond_node *node)
> +void evaluate_cond_node(struct policydb *p, struct cond_node *node)
>   {
>   	int new_state;
>   	struct cond_av_list *cur;
> @@ -111,7 +111,6 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
>   				cur->node->key.specified |= AVTAB_ENABLED;
>   		}
>   	}
> -	return 0;
>   }
>   
>   int cond_policydb_init(struct policydb *p)
> diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
> index ec846e45904c..d86ef286ca84 100644
> --- a/security/selinux/ss/conditional.h
> +++ b/security/selinux/ss/conditional.h
> @@ -75,6 +75,6 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
>   		struct av_decision *avd, struct extended_perms *xperms);
>   void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
>   		struct extended_perms_decision *xpermd);
> -int evaluate_cond_node(struct policydb *p, struct cond_node *node);
> +void evaluate_cond_node(struct policydb *p, struct cond_node *node);
>   
>   #endif /* _CONDITIONAL_H_ */
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index 42ca9f6dbbf4..b9eda7d89e22 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -2157,8 +2157,8 @@ static void security_load_policycaps(struct selinux_state *state)
>   	}
>   }
>   
> -static int security_preserve_bools(struct selinux_state *state,
> -				   struct policydb *newpolicydb);
> +static void security_preserve_bools(struct policydb *oldpolicydb,
> +				    struct policydb *newpolicydb);
>   
>   /**
>    * security_load_policy - Load a security policy configuration.
> @@ -2257,11 +2257,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
>   	if (rc)
>   		goto err;
>   
> -	rc = security_preserve_bools(state, newpolicydb);
> -	if (rc) {
> -		pr_err("SELinux:  unable to preserve booleans\n");
> -		goto err;
> -	}
> +	security_preserve_bools(policydb, newpolicydb);
>   
>   	oldsidtab = state->ss->sidtab;
>   
> @@ -2958,11 +2954,8 @@ int security_set_bools(struct selinux_state *state, int len, int *values)
>   			policydb->bool_val_to_struct[i]->state = 0;
>   	}
>   
> -	for (cur = policydb->cond_list; cur; cur = cur->next) {
> -		rc = evaluate_cond_node(policydb, cur);
> -		if (rc)
> -			goto out;
> -	}
> +	for (cur = policydb->cond_list; cur; cur = cur->next)
> +		evaluate_cond_node(policydb, cur);
>   
>   	seqno = ++state->ss->latest_granting;
>   	rc = 0;
> @@ -2999,36 +2992,23 @@ out:
>   	return rc;
>   }
>   
> -static int security_preserve_bools(struct selinux_state *state,
> -				   struct policydb *policydb)
> +static void security_preserve_bools(struct policydb *oldpolicydb,
> +				    struct policydb *newpolicydb)
>   {
> -	int rc, nbools = 0, *bvalues = NULL, i;
> -	char **bnames = NULL;
>   	struct cond_bool_datum *booldatum;
>   	struct cond_node *cur;
> +	int i;
>   
> -	rc = security_get_bools(state, &nbools, &bnames, &bvalues);
> -	if (rc)
> -		goto out;
> -	for (i = 0; i < nbools; i++) {
> -		booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
> -		if (booldatum)
> -			booldatum->state = bvalues[i];
> -	}
> -	for (cur = policydb->cond_list; cur; cur = cur->next) {
> -		rc = evaluate_cond_node(policydb, cur);
> -		if (rc)
> -			goto out;
> -	}
> +	for (i = 0; i < oldpolicydb->p_bools.nprim; i++) {
> +		const char *name = sym_name(oldpolicydb, SYM_BOOLS, i);
> +		int value = oldpolicydb->bool_val_to_struct[i]->state;
>   
> -out:
> -	if (bnames) {
> -		for (i = 0; i < nbools; i++)
> -			kfree(bnames[i]);
> +		booldatum = hashtab_search(newpolicydb->p_bools.table, name);
> +		if (booldatum)
> +			booldatum->state = value;
>   	}
> -	kfree(bnames);
> -	kfree(bvalues);
> -	return rc;
> +	for (cur = newpolicydb->cond_list; cur; cur = cur->next)
> +		evaluate_cond_node(newpolicydb, cur);
>   }
>   
>   /*
>
Paul Moore Jan. 16, 2020, 10:28 p.m. UTC | #2
On Thu, Jan 16, 2020 at 11:41 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 1/16/20 7:04 AM, Ondrej Mosnacek wrote:
> > First, evaluate_cond_node() never returns an error. Make it just return
> > void.
> >
> > Second, drop the use of security_get_bools() from
> > security_preserve_bools() and read from the old policydb directly. This
> > saves some useless allocations and together with the first change makes
> > security_preserve_bools() no longer possibly return an error. Again the
> > return type is changed to void.
> >
> > Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
>
> Dropping use of security_get_bools() means we are no longer reading the
> boolean values with the policy read-lock held so they could in theory
> change underneath us.  However, this is presently prevented via the
> fsi->mutex taken by selinuxfs so I believe this is safe.

Since this code shouldn't be run very often, I think I would prefer
the added abstraction and safety of preserving the call to
security_get_bools().

In an effort to make sure expectations are set correctly, patches 2
through 6 are something that should probably wait until after the
upcoming merge window, so no rush on a respin.
diff mbox series

Patch

diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 70c378ee1a2f..04593062008d 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -85,7 +85,7 @@  static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
  * list appropriately. If the result of the expression is undefined
  * all of the rules are disabled for safety.
  */
-int evaluate_cond_node(struct policydb *p, struct cond_node *node)
+void evaluate_cond_node(struct policydb *p, struct cond_node *node)
 {
 	int new_state;
 	struct cond_av_list *cur;
@@ -111,7 +111,6 @@  int evaluate_cond_node(struct policydb *p, struct cond_node *node)
 				cur->node->key.specified |= AVTAB_ENABLED;
 		}
 	}
-	return 0;
 }
 
 int cond_policydb_init(struct policydb *p)
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index ec846e45904c..d86ef286ca84 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -75,6 +75,6 @@  void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
 		struct av_decision *avd, struct extended_perms *xperms);
 void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
 		struct extended_perms_decision *xpermd);
-int evaluate_cond_node(struct policydb *p, struct cond_node *node);
+void evaluate_cond_node(struct policydb *p, struct cond_node *node);
 
 #endif /* _CONDITIONAL_H_ */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 42ca9f6dbbf4..b9eda7d89e22 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2157,8 +2157,8 @@  static void security_load_policycaps(struct selinux_state *state)
 	}
 }
 
-static int security_preserve_bools(struct selinux_state *state,
-				   struct policydb *newpolicydb);
+static void security_preserve_bools(struct policydb *oldpolicydb,
+				    struct policydb *newpolicydb);
 
 /**
  * security_load_policy - Load a security policy configuration.
@@ -2257,11 +2257,7 @@  int security_load_policy(struct selinux_state *state, void *data, size_t len)
 	if (rc)
 		goto err;
 
-	rc = security_preserve_bools(state, newpolicydb);
-	if (rc) {
-		pr_err("SELinux:  unable to preserve booleans\n");
-		goto err;
-	}
+	security_preserve_bools(policydb, newpolicydb);
 
 	oldsidtab = state->ss->sidtab;
 
@@ -2958,11 +2954,8 @@  int security_set_bools(struct selinux_state *state, int len, int *values)
 			policydb->bool_val_to_struct[i]->state = 0;
 	}
 
-	for (cur = policydb->cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(policydb, cur);
-		if (rc)
-			goto out;
-	}
+	for (cur = policydb->cond_list; cur; cur = cur->next)
+		evaluate_cond_node(policydb, cur);
 
 	seqno = ++state->ss->latest_granting;
 	rc = 0;
@@ -2999,36 +2992,23 @@  out:
 	return rc;
 }
 
-static int security_preserve_bools(struct selinux_state *state,
-				   struct policydb *policydb)
+static void security_preserve_bools(struct policydb *oldpolicydb,
+				    struct policydb *newpolicydb)
 {
-	int rc, nbools = 0, *bvalues = NULL, i;
-	char **bnames = NULL;
 	struct cond_bool_datum *booldatum;
 	struct cond_node *cur;
+	int i;
 
-	rc = security_get_bools(state, &nbools, &bnames, &bvalues);
-	if (rc)
-		goto out;
-	for (i = 0; i < nbools; i++) {
-		booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
-		if (booldatum)
-			booldatum->state = bvalues[i];
-	}
-	for (cur = policydb->cond_list; cur; cur = cur->next) {
-		rc = evaluate_cond_node(policydb, cur);
-		if (rc)
-			goto out;
-	}
+	for (i = 0; i < oldpolicydb->p_bools.nprim; i++) {
+		const char *name = sym_name(oldpolicydb, SYM_BOOLS, i);
+		int value = oldpolicydb->bool_val_to_struct[i]->state;
 
-out:
-	if (bnames) {
-		for (i = 0; i < nbools; i++)
-			kfree(bnames[i]);
+		booldatum = hashtab_search(newpolicydb->p_bools.table, name);
+		if (booldatum)
+			booldatum->state = value;
 	}
-	kfree(bnames);
-	kfree(bvalues);
-	return rc;
+	for (cur = newpolicydb->cond_list; cur; cur = cur->next)
+		evaluate_cond_node(newpolicydb, cur);
 }
 
 /*