Re: [RFC PATCH] selinux: Use call_rcu for policydb and booleans

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

 



This will might even compile! :-)

>From f2d5b2a33c97fef896758becfe62e79aed96352d Mon Sep 17 00:00:00 2001
From: Peter Enderborg <peter.enderborg@xxxxxxxx>
Date: Wed, 19 Aug 2020 10:20:28 +0200
Subject: [PATCH] selinux: Use call_rcu for policydb and booleans

This patch adds call_rcu that moves sycronize out

out call path. In the callback we can no call
cond_resched so they have to be remvoed.

Signed-off-by: Peter Enderborg <peter.enderborg@xxxxxxxx>
---
 security/selinux/ss/policydb.c |  6 -----
 security/selinux/ss/services.c | 43 ++++++++++++++++++++++++++++++----
 2 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 9fccf417006b..bcf49da4d7b2 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -341,7 +341,6 @@ static int filenametr_destroy(void *key, void *datum, void *p)
                kfree(d);
                d = next;
        } while (unlikely(d));
-       cond_resched();
        return 0;
 }
 
@@ -353,7 +352,6 @@ static int range_tr_destroy(void *key, void *datum, void *p)
        ebitmap_destroy(&rt->level[0].cat);
        ebitmap_destroy(&rt->level[1].cat);
        kfree(datum);
-       cond_resched();
        return 0;
 }
 
@@ -791,7 +789,6 @@ void policydb_destroy(struct policydb *p)
        struct role_allow *ra, *lra = NULL;
 
        for (i = 0; i < SYM_NUM; i++) {
-               cond_resched();
                hashtab_map(&p->symtab[i].table, destroy_f[i], NULL);
                hashtab_destroy(&p->symtab[i].table);
        }
@@ -807,7 +804,6 @@ void policydb_destroy(struct policydb *p)
        avtab_destroy(&p->te_avtab);
 
        for (i = 0; i < OCON_NUM; i++) {
-               cond_resched();
                c = p->ocontexts[i];
                while (c) {
                        ctmp = c;
@@ -819,7 +815,6 @@ void policydb_destroy(struct policydb *p)
 
        g = p->genfs;
        while (g) {
-               cond_resched();
                kfree(g->fstype);
                c = g->head;
                while (c) {
@@ -839,7 +834,6 @@ void policydb_destroy(struct policydb *p)
        hashtab_destroy(&p->role_tr);
 
        for (ra = p->role_allow; ra; ra = ra->next) {
-               cond_resched();
                kfree(lra);
                lra = ra;
        }
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index ba9347517e5b..61e8296908df 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2184,11 +2184,29 @@ static void selinux_notify_policy_change(struct selinux_state *state,
        selinux_xfrm_notify_policyload();
 }
 
+struct deprecated_policy {
+       struct selinux_policy *policy;
+       int partial;
+       struct rcu_head rcu;
+};
+
+void policy_reclaim(struct rcu_head *rp)
+{
+       struct deprecated_policy *dep = container_of(rp, struct deprecated_policy, rcu);
+
+       if (dep->partial)
+               selinux_policy_cond_free(dep->policy);
+       else
+               selinux_policy_free(dep->policy);
+       kfree(dep);
+}
+
 void selinux_policy_commit(struct selinux_state *state,
                        struct selinux_policy *newpolicy)
 {
        struct selinux_policy *oldpolicy;
        u32 seqno;
+       struct deprecated_policy *dep;
 
        /*
         * NOTE: We do not need to take the rcu read lock
@@ -2231,8 +2249,16 @@ void selinux_policy_commit(struct selinux_state *state,
        }
 
        /* Free the old policy */
-       synchronize_rcu();
-       selinux_policy_free(oldpolicy);
+       /* if cant alloc we need to it the slow way */
+       dep  = kzalloc(sizeof(struct deprecated_policy), GFP_KERNEL);
+       if (dep) {
+               dep->policy = oldpolicy;
+               dep->partial = 0;
+               call_rcu(&dep->rcu, policy_reclaim);
+       } else {
+               synchronize_rcu();
+               selinux_policy_free(oldpolicy);
+       }
 
        /* Notify others of the policy change */
        selinux_notify_policy_change(state, seqno);
@@ -2956,6 +2982,7 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
        struct selinux_policy *newpolicy, *oldpolicy;
        int rc;
        u32 i, seqno = 0;
+       struct deprecated_policy *dep;
 
        if (!selinux_initialized(state))
                return -EINVAL;
@@ -3020,8 +3047,16 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
         * that were copied for the new policy, and the oldpolicy
         * structure itself but not what it references.
         */
-       synchronize_rcu();
-       selinux_policy_cond_free(oldpolicy);
+       /* if we can not alloc do it the slow way */
+       dep  = kzalloc(sizeof(struct deprecated_policy), GFP_KERNEL);
+       if (dep) {
+               dep->policy = oldpolicy;
+               dep->partial = 1;
+               call_rcu(&dep->rcu, policy_reclaim);
+       } else {
+               synchronize_rcu();
+               selinux_policy_cond_free(oldpolicy);
+       }
 
        /* Notify others of the policy change */
        selinux_notify_policy_change(state, seqno);
-- 
2.17.1





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

  Powered by Linux