]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - security/selinux/ss/policydb.c
SELinux: tune avtab to reduce memory usage
[linux-2.6.git] / security / selinux / ss / policydb.c
index 2f5f539875f2d0e60b780b407deef7fb64aeecdb..5ecbad7d8b9fcd295029035843d27e7de3545bb8 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -96,6 +97,11 @@ static struct policydb_compat_info policydb_compat[] = {
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
        },
+       {
+               .version        = POLICYDB_VERSION_RANGETRANS,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
+       },
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -103,7 +109,7 @@ static struct policydb_compat_info *policydb_lookup_compat(int version)
        int i;
        struct policydb_compat_info *info = NULL;
 
-       for (i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++) {
+       for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
                if (policydb_compat[i].version == version) {
                        info = &policydb_compat[i];
                        break;
@@ -171,18 +177,15 @@ static int policydb_init(struct policydb *p)
 
        rc = roles_init(p);
        if (rc)
-               goto out_free_avtab;
+               goto out_free_symtab;
 
        rc = cond_policydb_init(p);
        if (rc)
-               goto out_free_avtab;
+               goto out_free_symtab;
 
 out:
        return rc;
 
-out_free_avtab:
-       avtab_destroy(&p->te_avtab);
-
 out_free_symtab:
        for (i = 0; i < SYM_NUM; i++)
                hashtab_destroy(p->symtab[i].table);
@@ -369,7 +372,7 @@ static void symtab_hash_eval(struct symtab *s)
                struct hashtab_info info;
 
                hashtab_stat(h, &info);
-               printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, "
+               printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, "
                       "longest chain length %d\n", symtab_name[i], h->nel,
                       info.slots_used, h->size, info.max_chain_len);
        }
@@ -386,14 +389,14 @@ static int policydb_index_others(struct policydb *p)
 {
        int i, rc = 0;
 
-       printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
+       printk(KERN_DEBUG "security:  %d users, %d roles, %d types, %d bools",
               p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
        if (selinux_mls_enabled)
                printk(", %d sens, %d cats", p->p_levels.nprim,
                       p->p_cats.nprim);
        printk("\n");
 
-       printk(KERN_INFO "security:  %d classes, %d rules\n",
+       printk(KERN_DEBUG "security:  %d classes, %d rules\n",
               p->p_classes.nprim, p->te_avtab.nel);
 
 #ifdef DEBUG_HASHES
@@ -463,7 +466,7 @@ static int common_destroy(void *key, void *datum, void *p)
        return 0;
 }
 
-static int class_destroy(void *key, void *datum, void *p)
+static int cls_destroy(void *key, void *datum, void *p)
 {
        struct class_datum *cladatum;
        struct constraint_node *constraint, *ctemp;
@@ -561,7 +564,7 @@ static int cat_destroy(void *key, void *datum, void *p)
 static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
 {
        common_destroy,
-       class_destroy,
+       cls_destroy,
        role_destroy,
        type_destroy,
        user_destroy,
@@ -593,6 +596,7 @@ void policydb_destroy(struct policydb *p)
        struct range_trans *rt, *lrt = 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);
        }
@@ -607,16 +611,19 @@ 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;
                        c = c->next;
                        ocontext_destroy(ctmp,i);
                }
+               p->ocontexts[i] = NULL;
        }
 
        g = p->genfs;
        while (g) {
+               cond_resched();
                kfree(g->fstype);
                c = g->head;
                while (c) {
@@ -628,26 +635,38 @@ void policydb_destroy(struct policydb *p)
                g = g->next;
                kfree(gtmp);
        }
+       p->genfs = NULL;
 
        cond_policydb_destroy(p);
 
        for (tr = p->role_tr; tr; tr = tr->next) {
-               if (ltr) kfree(ltr);
+               cond_resched();
+               kfree(ltr);
                ltr = tr;
        }
-       if (ltr) kfree(ltr);
+       kfree(ltr);
 
        for (ra = p->role_allow; ra; ra = ra -> next) {
-               if (lra) kfree(lra);
+               cond_resched();
+               kfree(lra);
                lra = ra;
        }
-       if (lra) kfree(lra);
+       kfree(lra);
 
        for (rt = p->range_tr; rt; rt = rt -> next) {
-               if (lrt) kfree(lrt);
+               cond_resched();
+               if (lrt) {
+                       ebitmap_destroy(&lrt->target_range.level[0].cat);
+                       ebitmap_destroy(&lrt->target_range.level[1].cat);
+                       kfree(lrt);
+               }
                lrt = rt;
        }
-       if (lrt) kfree(lrt);
+       if (lrt) {
+               ebitmap_destroy(&lrt->target_range.level[0].cat);
+               ebitmap_destroy(&lrt->target_range.level[1].cat);
+               kfree(lrt);
+       }
 
        if (p->type_attr_map) {
                for (i = 0; i < p->p_types.nprim; i++)
@@ -1109,7 +1128,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 out:
        return rc;
 bad:
-       class_destroy(key, cladatum, NULL);
+       cls_destroy(key, cladatum, NULL);
        goto out;
 }
 
@@ -1821,6 +1840,7 @@ int policydb_read(struct policydb *p, void *fp)
        }
 
        if (p->policyvers >= POLICYDB_VERSION_MLS) {
+               int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS;
                rc = next_entry(buf, fp, sizeof(u32));
                if (rc < 0)
                        goto bad;
@@ -1839,9 +1859,16 @@ int policydb_read(struct policydb *p, void *fp)
                        rc = next_entry(buf, fp, (sizeof(u32) * 2));
                        if (rc < 0)
                                goto bad;
-                       rt->dom = le32_to_cpu(buf[0]);
-                       rt->type = le32_to_cpu(buf[1]);
-                       rc = mls_read_range_helper(&rt->range, fp);
+                       rt->source_type = le32_to_cpu(buf[0]);
+                       rt->target_type = le32_to_cpu(buf[1]);
+                       if (new_rangetr) {
+                               rc = next_entry(buf, fp, sizeof(u32));
+                               if (rc < 0)
+                                       goto bad;
+                               rt->target_class = le32_to_cpu(buf[0]);
+                       } else
+                               rt->target_class = SECCLASS_PROCESS;
+                       rc = mls_read_range_helper(&rt->target_range, fp);
                        if (rc)
                                goto bad;
                        lrt = rt;