]> Git Repo - J-linux.git/commitdiff
Merge tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Wed, 3 Jun 2020 00:16:47 +0000 (17:16 -0700)
committerLinus Torvalds <[email protected]>
Wed, 3 Jun 2020 00:16:47 +0000 (17:16 -0700)
Pull SELinux updates from Paul Moore:
 "The highlights:

   - A number of improvements to various SELinux internal data
     structures to help improve performance. We move the role
     transitions into a hash table. In the content structure we shift
     from hashing the content string (aka SELinux label) to the
     structure itself, when it is valid. This last change not only
     offers a speedup, but it helps us simplify the code some as well.

   - Add a new SELinux policy version which allows for a more space
     efficient way of storing the filename transitions in the binary
     policy. Given the default Fedora SELinux policy with the unconfined
     module enabled, this change drops the policy size from ~7.6MB to
     ~3.3MB. The kernel policy load time dropped as well.

   - Some fixes to the error handling code in the policy parser to
     properly return error codes when things go wrong"

* tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: netlabel: Remove unused inline function
  selinux: do not allocate hashtabs dynamically
  selinux: fix return value on error in policydb_read()
  selinux: simplify range_write()
  selinux: fix error return code in policydb_read()
  selinux: don't produce incorrect filename_trans_count
  selinux: implement new format of filename transitions
  selinux: move context hashing under sidtab
  selinux: hash context structure directly
  selinux: store role transitions in a hash table
  selinux: drop unnecessary smp_load_acquire() call
  selinux: fix warning Comparison to bool

1  2 
security/selinux/ss/policydb.c

index c21b922e5ebec1c851c74c22d43e17c39ff0c4e8,a30cad18931b8ef94ba1b492a614d4bf6f8598ce..98f343005d6b5ae3d2a71c2b713570c5d769fdff
@@@ -154,6 -154,11 +154,11 @@@ static struct policydb_compat_info poli
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
        },
+       {
+               .version        = POLICYDB_VERSION_COMP_FTRANS,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
+       },
  };
  
  static struct policydb_compat_info *policydb_lookup_compat(int version)
@@@ -190,8 -195,8 +195,8 @@@ static int common_destroy(void *key, vo
        kfree(key);
        if (datum) {
                comdatum = datum;
-               hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
-               hashtab_destroy(comdatum->permissions.table);
+               hashtab_map(&comdatum->permissions.table, perm_destroy, NULL);
+               hashtab_destroy(&comdatum->permissions.table);
        }
        kfree(datum);
        return 0;
@@@ -219,8 -224,8 +224,8 @@@ static int cls_destroy(void *key, void 
        kfree(key);
        if (datum) {
                cladatum = datum;
-               hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
-               hashtab_destroy(cladatum->permissions.table);
+               hashtab_map(&cladatum->permissions.table, perm_destroy, NULL);
+               hashtab_destroy(&cladatum->permissions.table);
                constraint = cladatum->constraints;
                while (constraint) {
                        e = constraint->expr;
@@@ -352,6 -357,13 +357,13 @@@ static int range_tr_destroy(void *key, 
        return 0;
  }
  
+ static int role_tr_destroy(void *key, void *datum, void *p)
+ {
+       kfree(key);
+       kfree(datum);
+       return 0;
+ }
  static void ocontext_destroy(struct ocontext *c, int i)
  {
        if (!c)
@@@ -388,7 -400,7 +400,7 @@@ static int roles_init(struct policydb *
        if (!key)
                goto out;
  
-       rc = hashtab_insert(p->p_roles.table, key, role);
+       rc = hashtab_insert(&p->p_roles.table, key, role);
        if (rc)
                goto out;
  
@@@ -458,26 -470,43 +470,43 @@@ static int rangetr_cmp(struct hashtab *
        return v;
  }
  
+ static u32 role_trans_hash(struct hashtab *h, const void *k)
+ {
+       const struct role_trans_key *key = k;
+       return (key->role + (key->type << 3) + (key->tclass << 5)) &
+               (h->size - 1);
+ }
+ static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
+ {
+       const struct role_trans_key *key1 = k1, *key2 = k2;
+       int v;
+       v = key1->role - key2->role;
+       if (v)
+               return v;
+       v = key1->type - key2->type;
+       if (v)
+               return v;
+       return key1->tclass - key2->tclass;
+ }
  /*
   * Initialize a policy database structure.
   */
- static int policydb_init(struct policydb *p)
+ static void policydb_init(struct policydb *p)
  {
        memset(p, 0, sizeof(*p));
  
        avtab_init(&p->te_avtab);
        cond_policydb_init(p);
  
-       p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp,
-                                          (1 << 11));
-       if (!p->filename_trans)
-               return -ENOMEM;
        ebitmap_init(&p->filename_trans_ttypes);
        ebitmap_init(&p->policycaps);
        ebitmap_init(&p->permissive_map);
-       return 0;
  }
  
  /*
@@@ -639,7 -668,7 +668,7 @@@ static void symtab_hash_eval(struct sym
        int i;
  
        for (i = 0; i < SYM_NUM; i++)
-               hash_eval(s[i].table, symtab_name[i]);
+               hash_eval(&s[i].table, symtab_name[i]);
  }
  
  #else
@@@ -710,7 -739,7 +739,7 @@@ static int policydb_index(struct policy
                if (!p->sym_val_to_name[i])
                        return -ENOMEM;
  
-               rc = hashtab_map(p->symtab[i].table, index_f[i], p);
+               rc = hashtab_map(&p->symtab[i].table, index_f[i], p);
                if (rc)
                        goto out;
        }
@@@ -728,12 -757,11 +757,11 @@@ void policydb_destroy(struct policydb *
        struct genfs *g, *gtmp;
        int i;
        struct role_allow *ra, *lra = NULL;
-       struct role_trans *tr, *ltr = 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);
+               hashtab_map(&p->symtab[i].table, destroy_f[i], NULL);
+               hashtab_destroy(&p->symtab[i].table);
        }
  
        for (i = 0; i < SYM_NUM; i++)
  
        cond_policydb_destroy(p);
  
-       for (tr = p->role_tr; tr; tr = tr->next) {
-               cond_resched();
-               kfree(ltr);
-               ltr = tr;
-       }
-       kfree(ltr);
+       hashtab_map(&p->role_tr, role_tr_destroy, NULL);
+       hashtab_destroy(&p->role_tr);
  
        for (ra = p->role_allow; ra; ra = ra->next) {
                cond_resched();
        }
        kfree(lra);
  
-       hashtab_map(p->filename_trans, filenametr_destroy, NULL);
-       hashtab_destroy(p->filename_trans);
+       hashtab_map(&p->filename_trans, filenametr_destroy, NULL);
+       hashtab_destroy(&p->filename_trans);
  
-       hashtab_map(p->range_tr, range_tr_destroy, NULL);
-       hashtab_destroy(p->range_tr);
+       hashtab_map(&p->range_tr, range_tr_destroy, NULL);
+       hashtab_destroy(&p->range_tr);
  
        if (p->type_attr_map_array) {
                for (i = 0; i < p->p_types.nprim; i++)
@@@ -836,11 -860,6 +860,6 @@@ int policydb_load_isids(struct policyd
                if (!name)
                        continue;
  
-               rc = context_add_hash(p, &c->context[0]);
-               if (rc) {
-                       sidtab_destroy(s);
-                       goto out;
-               }
                rc = sidtab_set_initial(s, sid, &c->context[0]);
                if (rc) {
                        pr_err("SELinux:  unable to load initial SID %s.\n",
@@@ -1035,14 -1054,14 +1054,14 @@@ static int str_read(char **strp, gfp_t 
        if (!str)
                return -ENOMEM;
  
 -      /* it's expected the caller should free the str */
 -      *strp = str;
 -
        rc = next_entry(str, fp, len);
 -      if (rc)
 +      if (rc) {
 +              kfree(str);
                return rc;
 +      }
  
        str[len] = '\0';
 +      *strp = str;
        return 0;
  }
  
@@@ -1109,7 -1128,7 +1128,7 @@@ static int common_read(struct policydb 
                goto bad;
  
        for (i = 0; i < nel; i++) {
-               rc = perm_read(p, comdatum->permissions.table, fp);
+               rc = perm_read(p, &comdatum->permissions.table, fp);
                if (rc)
                        goto bad;
        }
@@@ -1281,7 -1300,8 +1300,8 @@@ static int class_read(struct policydb *
                        goto bad;
  
                rc = -EINVAL;
-               cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey);
+               cladatum->comdatum = hashtab_search(&p->p_commons.table,
+                                                   cladatum->comkey);
                if (!cladatum->comdatum) {
                        pr_err("SELinux:  unknown common %s\n",
                               cladatum->comkey);
                }
        }
        for (i = 0; i < nel; i++) {
-               rc = perm_read(p, cladatum->permissions.table, fp);
+               rc = perm_read(p, &cladatum->permissions.table, fp);
                if (rc)
                        goto bad;
        }
@@@ -1712,18 -1732,15 +1732,15 @@@ static int policydb_bounds_sanity_check
        if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
                return 0;
  
-       rc = hashtab_map(p->p_users.table,
-                        user_bounds_sanity_check, p);
+       rc = hashtab_map(&p->p_users.table, user_bounds_sanity_check, p);
        if (rc)
                return rc;
  
-       rc = hashtab_map(p->p_roles.table,
-                        role_bounds_sanity_check, p);
+       rc = hashtab_map(&p->p_roles.table, role_bounds_sanity_check, p);
        if (rc)
                return rc;
  
-       rc = hashtab_map(p->p_types.table,
-                        type_bounds_sanity_check, p);
+       rc = hashtab_map(&p->p_types.table, type_bounds_sanity_check, p);
        if (rc)
                return rc;
  
@@@ -1734,7 -1751,7 +1751,7 @@@ u16 string_to_security_class(struct pol
  {
        struct class_datum *cladatum;
  
-       cladatum = hashtab_search(p->p_classes.table, name);
+       cladatum = hashtab_search(&p->p_classes.table, name);
        if (!cladatum)
                return 0;
  
@@@ -1753,11 -1770,9 +1770,9 @@@ u32 string_to_av_perm(struct policydb *
        cladatum = p->class_val_to_struct[tclass-1];
        comdatum = cladatum->comdatum;
        if (comdatum)
-               perdatum = hashtab_search(comdatum->permissions.table,
-                                         name);
+               perdatum = hashtab_search(&comdatum->permissions.table, name);
        if (!perdatum)
-               perdatum = hashtab_search(cladatum->permissions.table,
-                                         name);
+               perdatum = hashtab_search(&cladatum->permissions.table, name);
        if (!perdatum)
                return 0;
  
@@@ -1781,9 -1796,9 +1796,9 @@@ static int range_read(struct policydb *
  
        nel = le32_to_cpu(buf[0]);
  
-       p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, nel);
-       if (!p->range_tr)
-               return -ENOMEM;
+       rc = hashtab_init(&p->range_tr, rangetr_hash, rangetr_cmp, nel);
+       if (rc)
+               return rc;
  
        for (i = 0; i < nel; i++) {
                rc = -ENOMEM;
                        goto out;
                }
  
-               rc = hashtab_insert(p->range_tr, rt, r);
+               rc = hashtab_insert(&p->range_tr, rt, r);
                if (rc)
                        goto out;
  
                rt = NULL;
                r = NULL;
        }
-       hash_eval(p->range_tr, "rangetr");
+       hash_eval(&p->range_tr, "rangetr");
        rc = 0;
  out:
        kfree(rt);
        return rc;
  }
  
- static int filename_trans_read_one(struct policydb *p, void *fp)
+ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
  {
        struct filename_trans_key key, *ft = NULL;
        struct filename_trans_datum *last, *datum = NULL;
        otype = le32_to_cpu(buf[3]);
  
        last = NULL;
-       datum = hashtab_search(p->filename_trans, &key);
+       datum = hashtab_search(&p->filename_trans, &key);
        while (datum) {
                if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
                        /* conflicting/duplicate rules are ignored */
                        if (!ft)
                                goto out;
  
-                       rc = hashtab_insert(p->filename_trans, ft, datum);
+                       rc = hashtab_insert(&p->filename_trans, ft, datum);
                        if (rc)
                                goto out;
                        name = NULL;
        return rc;
  }
  
+ static int filename_trans_read_helper(struct policydb *p, void *fp)
+ {
+       struct filename_trans_key *ft = NULL;
+       struct filename_trans_datum **dst, *datum, *first = NULL;
+       char *name = NULL;
+       u32 len, ttype, tclass, ndatum, i;
+       __le32 buf[3];
+       int rc;
+       /* length of the path component string */
+       rc = next_entry(buf, fp, sizeof(u32));
+       if (rc)
+               return rc;
+       len = le32_to_cpu(buf[0]);
+       /* path component string */
+       rc = str_read(&name, GFP_KERNEL, fp, len);
+       if (rc)
+               return rc;
+       rc = next_entry(buf, fp, sizeof(u32) * 3);
+       if (rc)
+               goto out;
+       ttype = le32_to_cpu(buf[0]);
+       tclass = le32_to_cpu(buf[1]);
+       ndatum = le32_to_cpu(buf[2]);
+       if (ndatum == 0) {
+               pr_err("SELinux:  Filename transition key with no datum\n");
+               rc = -ENOENT;
+               goto out;
+       }
+       dst = &first;
+       for (i = 0; i < ndatum; i++) {
+               rc = -ENOMEM;
+               datum = kmalloc(sizeof(*datum), GFP_KERNEL);
+               if (!datum)
+                       goto out;
+               *dst = datum;
+               /* ebitmap_read() will at least init the bitmap */
+               rc = ebitmap_read(&datum->stypes, fp);
+               if (rc)
+                       goto out;
+               rc = next_entry(buf, fp, sizeof(u32));
+               if (rc)
+                       goto out;
+               datum->otype = le32_to_cpu(buf[0]);
+               datum->next = NULL;
+               dst = &datum->next;
+       }
+       rc = -ENOMEM;
+       ft = kmalloc(sizeof(*ft), GFP_KERNEL);
+       if (!ft)
+               goto out;
+       ft->ttype = ttype;
+       ft->tclass = tclass;
+       ft->name = name;
+       rc = hashtab_insert(&p->filename_trans, ft, first);
+       if (rc == -EEXIST)
+               pr_err("SELinux:  Duplicate filename transition key\n");
+       if (rc)
+               goto out;
+       return ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1);
+ out:
+       kfree(ft);
+       kfree(name);
+       while (first) {
+               datum = first;
+               first = first->next;
+               ebitmap_destroy(&datum->stypes);
+               kfree(datum);
+       }
+       return rc;
+ }
  static int filename_trans_read(struct policydb *p, void *fp)
  {
        u32 nel;
                return rc;
        nel = le32_to_cpu(buf[0]);
  
-       p->filename_trans_count = nel;
+       if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
+               p->compat_filename_trans_count = nel;
  
-       for (i = 0; i < nel; i++) {
-               rc = filename_trans_read_one(p, fp);
+               rc = hashtab_init(&p->filename_trans, filenametr_hash,
+                                 filenametr_cmp, (1 << 11));
                if (rc)
                        return rc;
+               for (i = 0; i < nel; i++) {
+                       rc = filename_trans_read_helper_compat(p, fp);
+                       if (rc)
+                               return rc;
+               }
+       } else {
+               rc = hashtab_init(&p->filename_trans, filenametr_hash,
+                                 filenametr_cmp, nel);
+               if (rc)
+                       return rc;
+               for (i = 0; i < nel; i++) {
+                       rc = filename_trans_read_helper(p, fp);
+                       if (rc)
+                               return rc;
+               }
        }
-       hash_eval(p->filename_trans, "filenametr");
+       hash_eval(&p->filename_trans, "filenametr");
        return 0;
  }
  
@@@ -2251,7 -2372,8 +2372,8 @@@ out
  int policydb_read(struct policydb *p, void *fp)
  {
        struct role_allow *ra, *lra;
-       struct role_trans *tr, *ltr;
+       struct role_trans_key *rtk = NULL;
+       struct role_trans_datum *rtd = NULL;
        int i, j, rc;
        __le32 buf[4];
        u32 len, nprim, nel;
        char *policydb_str;
        struct policydb_compat_info *info;
  
-       rc = policydb_init(p);
-       if (rc)
-               return rc;
+       policydb_init(p);
  
        /* Read the magic number and string length. */
        rc = next_entry(buf, fp, sizeof(u32) * 2);
                }
  
                for (j = 0; j < nel; j++) {
-                       rc = read_f[i](p, p->symtab[i].table, fp);
+                       rc = read_f[i](p, &p->symtab[i].table, fp);
                        if (rc)
                                goto bad;
                }
        if (rc)
                goto bad;
        nel = le32_to_cpu(buf[0]);
-       ltr = NULL;
+       rc = hashtab_init(&p->role_tr, role_trans_hash, role_trans_cmp, nel);
+       if (rc)
+               goto bad;
        for (i = 0; i < nel; i++) {
                rc = -ENOMEM;
-               tr = kzalloc(sizeof(*tr), GFP_KERNEL);
-               if (!tr)
+               rtk = kmalloc(sizeof(*rtk), GFP_KERNEL);
+               if (!rtk)
                        goto bad;
-               if (ltr)
-                       ltr->next = tr;
-               else
-                       p->role_tr = tr;
+               rc = -ENOMEM;
+               rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
+               if (!rtd)
+                       goto bad;
                rc = next_entry(buf, fp, sizeof(u32)*3);
                if (rc)
                        goto bad;
  
                rc = -EINVAL;
-               tr->role = le32_to_cpu(buf[0]);
-               tr->type = le32_to_cpu(buf[1]);
-               tr->new_role = le32_to_cpu(buf[2]);
+               rtk->role = le32_to_cpu(buf[0]);
+               rtk->type = le32_to_cpu(buf[1]);
+               rtd->new_role = le32_to_cpu(buf[2]);
                if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
                        rc = next_entry(buf, fp, sizeof(u32));
                        if (rc)
                                goto bad;
-                       tr->tclass = le32_to_cpu(buf[0]);
+                       rtk->tclass = le32_to_cpu(buf[0]);
                } else
-                       tr->tclass = p->process_class;
+                       rtk->tclass = p->process_class;
  
                rc = -EINVAL;
-               if (!policydb_role_isvalid(p, tr->role) ||
-                   !policydb_type_isvalid(p, tr->type) ||
-                   !policydb_class_isvalid(p, tr->tclass) ||
-                   !policydb_role_isvalid(p, tr->new_role))
+               if (!policydb_role_isvalid(p, rtk->role) ||
+                   !policydb_type_isvalid(p, rtk->type) ||
+                   !policydb_class_isvalid(p, rtk->tclass) ||
+                   !policydb_role_isvalid(p, rtd->new_role))
                        goto bad;
-               ltr = tr;
+               rc = hashtab_insert(&p->role_tr, rtk, rtd);
+               if (rc)
+                       goto bad;
+               rtk = NULL;
+               rtd = NULL;
        }
  
        rc = next_entry(buf, fp, sizeof(u32));
        if (rc)
                goto bad;
  
+       rc = -ENOMEM;
        p->type_attr_map_array = kvcalloc(p->p_types.nprim,
                                          sizeof(*p->type_attr_map_array),
                                          GFP_KERNEL);
  out:
        return rc;
  bad:
+       kfree(rtk);
+       kfree(rtd);
        policydb_destroy(p);
        goto out;
  }
@@@ -2653,39 -2787,45 +2787,45 @@@ static int cat_write(void *vkey, void *
        return 0;
  }
  
- static int role_trans_write(struct policydb *p, void *fp)
+ static int role_trans_write_one(void *key, void *datum, void *ptr)
  {
-       struct role_trans *r = p->role_tr;
-       struct role_trans *tr;
+       struct role_trans_key *rtk = key;
+       struct role_trans_datum *rtd = datum;
+       struct policy_data *pd = ptr;
+       void *fp = pd->fp;
+       struct policydb *p = pd->p;
        __le32 buf[3];
-       size_t nel;
        int rc;
  
-       nel = 0;
-       for (tr = r; tr; tr = tr->next)
-               nel++;
-       buf[0] = cpu_to_le32(nel);
-       rc = put_entry(buf, sizeof(u32), 1, fp);
+       buf[0] = cpu_to_le32(rtk->role);
+       buf[1] = cpu_to_le32(rtk->type);
+       buf[2] = cpu_to_le32(rtd->new_role);
+       rc = put_entry(buf, sizeof(u32), 3, fp);
        if (rc)
                return rc;
-       for (tr = r; tr; tr = tr->next) {
-               buf[0] = cpu_to_le32(tr->role);
-               buf[1] = cpu_to_le32(tr->type);
-               buf[2] = cpu_to_le32(tr->new_role);
-               rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
+               buf[0] = cpu_to_le32(rtk->tclass);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
                if (rc)
                        return rc;
-               if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
-                       buf[0] = cpu_to_le32(tr->tclass);
-                       rc = put_entry(buf, sizeof(u32), 1, fp);
-                       if (rc)
-                               return rc;
-               }
        }
        return 0;
  }
  
+ static int role_trans_write(struct policydb *p, void *fp)
+ {
+       struct policy_data pd = { .p = p, .fp = fp };
+       __le32 buf[1];
+       int rc;
+       buf[0] = cpu_to_le32(p->role_tr.nel);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return rc;
+       return hashtab_map(&p->role_tr, role_trans_write_one, &pd);
+ }
  static int role_allow_write(struct role_allow *r, void *fp)
  {
        struct role_allow *ra;
@@@ -2777,7 -2917,7 +2917,7 @@@ static int common_write(void *vkey, voi
        buf[0] = cpu_to_le32(len);
        buf[1] = cpu_to_le32(comdatum->value);
        buf[2] = cpu_to_le32(comdatum->permissions.nprim);
-       buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
+       buf[3] = cpu_to_le32(comdatum->permissions.table.nel);
        rc = put_entry(buf, sizeof(u32), 4, fp);
        if (rc)
                return rc;
        if (rc)
                return rc;
  
-       rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
+       rc = hashtab_map(&comdatum->permissions.table, perm_write, fp);
        if (rc)
                return rc;
  
@@@ -2885,10 -3025,7 +3025,7 @@@ static int class_write(void *vkey, voi
        buf[1] = cpu_to_le32(len2);
        buf[2] = cpu_to_le32(cladatum->value);
        buf[3] = cpu_to_le32(cladatum->permissions.nprim);
-       if (cladatum->permissions.table)
-               buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
-       else
-               buf[4] = 0;
+       buf[4] = cpu_to_le32(cladatum->permissions.table.nel);
        buf[5] = cpu_to_le32(ncons);
        rc = put_entry(buf, sizeof(u32), 6, fp);
        if (rc)
                        return rc;
        }
  
-       rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
+       rc = hashtab_map(&cladatum->permissions.table, perm_write, fp);
        if (rc)
                return rc;
  
@@@ -3262,14 -3399,6 +3399,6 @@@ static int genfs_write(struct policydb 
        return 0;
  }
  
- static int hashtab_cnt(void *key, void *data, void *ptr)
- {
-       int *cnt = ptr;
-       *cnt = *cnt + 1;
-       return 0;
- }
  static int range_write_helper(void *key, void *data, void *ptr)
  {
        __le32 buf[2];
  static int range_write(struct policydb *p, void *fp)
  {
        __le32 buf[1];
-       int rc, nel;
+       int rc;
        struct policy_data pd;
  
        pd.p = p;
        pd.fp = fp;
  
-       /* count the number of entries in the hashtab */
-       nel = 0;
-       rc = hashtab_map(p->range_tr, hashtab_cnt, &nel);
-       if (rc)
-               return rc;
-       buf[0] = cpu_to_le32(nel);
+       buf[0] = cpu_to_le32(p->range_tr.nel);
        rc = put_entry(buf, sizeof(u32), 1, fp);
        if (rc)
                return rc;
  
        /* actually write all of the entries */
-       rc = hashtab_map(p->range_tr, range_write_helper, &pd);
+       rc = hashtab_map(&p->range_tr, range_write_helper, &pd);
        if (rc)
                return rc;
  
        return 0;
  }
  
- static int filename_write_helper(void *key, void *data, void *ptr)
+ static int filename_write_helper_compat(void *key, void *data, void *ptr)
  {
        struct filename_trans_key *ft = key;
        struct filename_trans_datum *datum = data;
        return 0;
  }
  
- static int filename_trans_write(struct policydb *p, void *fp)
+ static int filename_write_helper(void *key, void *data, void *ptr)
  {
-       __le32 buf[1];
+       struct filename_trans_key *ft = key;
+       struct filename_trans_datum *datum;
+       void *fp = ptr;
+       __le32 buf[3];
        int rc;
+       u32 ndatum, len = strlen(ft->name);
  
-       if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
-               return 0;
-       buf[0] = cpu_to_le32(p->filename_trans_count);
+       buf[0] = cpu_to_le32(len);
        rc = put_entry(buf, sizeof(u32), 1, fp);
        if (rc)
                return rc;
  
-       rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
+       rc = put_entry(ft->name, sizeof(char), len, fp);
        if (rc)
                return rc;
  
+       ndatum = 0;
+       datum = data;
+       do {
+               ndatum++;
+               datum = datum->next;
+       } while (unlikely(datum));
+       buf[0] = cpu_to_le32(ft->ttype);
+       buf[1] = cpu_to_le32(ft->tclass);
+       buf[2] = cpu_to_le32(ndatum);
+       rc = put_entry(buf, sizeof(u32), 3, fp);
+       if (rc)
+               return rc;
+       datum = data;
+       do {
+               rc = ebitmap_write(&datum->stypes, fp);
+               if (rc)
+                       return rc;
+               buf[0] = cpu_to_le32(datum->otype);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               datum = datum->next;
+       } while (unlikely(datum));
        return 0;
  }
  
+ static int filename_trans_write(struct policydb *p, void *fp)
+ {
+       __le32 buf[1];
+       int rc;
+       if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
+               return 0;
+       if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
+               buf[0] = cpu_to_le32(p->compat_filename_trans_count);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               rc = hashtab_map(&p->filename_trans,
+                                filename_write_helper_compat, fp);
+       } else {
+               buf[0] = cpu_to_le32(p->filename_trans.nel);
+               rc = put_entry(buf, sizeof(u32), 1, fp);
+               if (rc)
+                       return rc;
+               rc = hashtab_map(&p->filename_trans, filename_write_helper, fp);
+       }
+       return rc;
+ }
  /*
   * Write the configuration data in a policy database
   * structure to a policy database binary representation
@@@ -3467,12 -3646,12 +3646,12 @@@ int policydb_write(struct policydb *p, 
                pd.p = p;
  
                buf[0] = cpu_to_le32(p->symtab[i].nprim);
-               buf[1] = cpu_to_le32(p->symtab[i].table->nel);
+               buf[1] = cpu_to_le32(p->symtab[i].table.nel);
  
                rc = put_entry(buf, sizeof(u32), 2, fp);
                if (rc)
                        return rc;
-               rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
+               rc = hashtab_map(&p->symtab[i].table, write_f[i], &pd);
                if (rc)
                        return rc;
        }
This page took 0.085265 seconds and 4 git commands to generate.