diff mbox series

[v2,2/3] selinux: eliminate the redundant policycap array

Message ID 20200826135906.1912186-3-omosnace@redhat.com (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series selinux: RCU conversion follow-ups | expand

Commit Message

Ondrej Mosnacek Aug. 26, 2020, 1:59 p.m. UTC
The policycap array in struct selinux_state is redundant and can be
substituted by calling security_policycap_supported().

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

Comments

Stephen Smalley Aug. 26, 2020, 2:11 p.m. UTC | #1
On Wed, Aug 26, 2020 at 9:59 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
>
> The policycap array in struct selinux_state is redundant and can be
> substituted by calling security_policycap_supported().
>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> ---

> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index 7cc2f7486c18f..e82a2cfe171f3 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -2113,30 +2113,6 @@ bad:
>         return 0;
>  }
>
> -static void security_load_policycaps(struct selinux_state *state,
> -                               struct selinux_policy *policy)
> -{
> -       struct policydb *p;
> -       unsigned int i;
> -       struct ebitmap_node *node;
> -
> -       p = &policy->policydb;
> -
> -       for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
> -               state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
> -
> -       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(&p->policycaps, i));
> -
> -       ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
> -               if (i >= ARRAY_SIZE(selinux_policycap_names))
> -                       pr_info("SELinux:  unknown policy capability %u\n",
> -                               i);
> -       }
> -}
> -

Two requests:
1. Can you do a little benchmarking to confirm that calling
security_policycap_supported() each time doesn't cause any significant
overheads?  Networking benchmark might be of interest.

2. Can you retain the logging of the policy capability values?  Just
drop the first part of the function and rename it e.g.
security_log_policycaps().
Ondrej Mosnacek Aug. 27, 2020, 7:40 a.m. UTC | #2
On Wed, Aug 26, 2020 at 4:12 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Wed, Aug 26, 2020 at 9:59 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> >
> > The policycap array in struct selinux_state is redundant and can be
> > substituted by calling security_policycap_supported().
> >
> > Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> > ---
>
> > diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> > index 7cc2f7486c18f..e82a2cfe171f3 100644
> > --- a/security/selinux/ss/services.c
> > +++ b/security/selinux/ss/services.c
> > @@ -2113,30 +2113,6 @@ bad:
> >         return 0;
> >  }
> >
> > -static void security_load_policycaps(struct selinux_state *state,
> > -                               struct selinux_policy *policy)
> > -{
> > -       struct policydb *p;
> > -       unsigned int i;
> > -       struct ebitmap_node *node;
> > -
> > -       p = &policy->policydb;
> > -
> > -       for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
> > -               state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
> > -
> > -       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(&p->policycaps, i));
> > -
> > -       ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
> > -               if (i >= ARRAY_SIZE(selinux_policycap_names))
> > -                       pr_info("SELinux:  unknown policy capability %u\n",
> > -                               i);
> > -       }
> > -}
> > -
>
> Two requests:
> 1. Can you do a little benchmarking to confirm that calling
> security_policycap_supported() each time doesn't cause any significant
> overheads?  Networking benchmark might be of interest.

I tried to sample a simple `ping -f -i 0 -c 5000000 127.0.0.1` with
perf and indeed security_policycap_supported() now makes up about half
the time spent in some hooks (selinux_socket_sock_rcv_skb(),
selinux_ip_postroute()), mainly because of ebitmap_get_bit() it seems.
I'll try moving the array to policydb and using it in
security_policycap_supported() instead of the bitmap.

>
> 2. Can you retain the logging of the policy capability values?  Just
> drop the first part of the function and rename it e.g.
> security_log_policycaps().

Sure, somehow I failed to notice those prints...
diff mbox series

Patch

diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 839774929a10d..9ab8f8da47812 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -96,7 +96,6 @@  struct selinux_state {
 #endif
 	bool checkreqprot;
 	bool initialized;
-	bool policycap[__POLICYDB_CAPABILITY_MAX];
 
 	struct page *status_page;
 	struct mutex status_lock;
@@ -159,53 +158,49 @@  static inline bool selinux_disabled(struct selinux_state *state)
 }
 #endif
 
+int security_policycap_supported(struct selinux_state *state,
+				 unsigned int req_cap);
+
 static inline bool selinux_policycap_netpeer(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_NETPEER];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_NETPEER);
 }
 
 static inline bool selinux_policycap_openperm(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_OPENPERM];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_OPENPERM);
 }
 
 static inline bool selinux_policycap_extsockclass(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_EXTSOCKCLASS];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_EXTSOCKCLASS);
 }
 
 static inline bool selinux_policycap_alwaysnetwork(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_ALWAYSNETWORK];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_ALWAYSNETWORK);
 }
 
 static inline bool selinux_policycap_cgroupseclabel(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_CGROUPSECLABEL];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_CGROUPSECLABEL);
 }
 
 static inline bool selinux_policycap_nnp_nosuid_transition(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
 }
 
 static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
 {
-	struct selinux_state *state = &selinux_state;
-
-	return state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS];
+	return security_policycap_supported(&selinux_state,
+					    POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS);
 }
 
 int security_mls_enabled(struct selinux_state *state);
@@ -219,9 +214,6 @@  void selinux_policy_cancel(struct selinux_state *state,
 int security_read_policy(struct selinux_state *state,
 			 void **data, size_t *len);
 
-int security_policycap_supported(struct selinux_state *state,
-				 unsigned int req_cap);
-
 #define SEL_VEC_MAX 32
 struct av_decision {
 	u32 allowed;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 7cc2f7486c18f..e82a2cfe171f3 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2113,30 +2113,6 @@  bad:
 	return 0;
 }
 
-static void security_load_policycaps(struct selinux_state *state,
-				struct selinux_policy *policy)
-{
-	struct policydb *p;
-	unsigned int i;
-	struct ebitmap_node *node;
-
-	p = &policy->policydb;
-
-	for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
-		state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
-
-	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(&p->policycaps, i));
-
-	ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
-		if (i >= ARRAY_SIZE(selinux_policycap_names))
-			pr_info("SELinux:  unknown policy capability %u\n",
-				i);
-	}
-}
-
 static int security_preserve_bools(struct selinux_policy *oldpolicy,
 				struct selinux_policy *newpolicy);
 
@@ -2218,9 +2194,6 @@  void selinux_policy_commit(struct selinux_state *state,
 	/* Install the new policy. */
 	rcu_assign_pointer(state->policy, newpolicy);
 
-	/* Load the policycaps from the new policy */
-	security_load_policycaps(state, newpolicy);
-
 	if (!selinux_initialized(state)) {
 		/*
 		 * After first policy load, the security server is