Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / security / selinux / ss / policydb.c
index 14190ef..0111990 100644 (file)
@@ -91,6 +91,11 @@ static struct policydb_compat_info policydb_compat[] = {
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
        },
+       {
+               .version        = POLICYDB_VERSION_AVTAB,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
+       },
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -98,7 +103,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;
@@ -116,12 +121,11 @@ static int roles_init(struct policydb *p)
        int rc;
        struct role_datum *role;
 
-       role = kmalloc(sizeof(*role), GFP_KERNEL);
+       role = kzalloc(sizeof(*role), GFP_KERNEL);
        if (!role) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(role, 0, sizeof(*role));
        role->value = ++p->p_roles.nprim;
        if (role->value != OBJECT_R_VAL) {
                rc = -EINVAL;
@@ -584,23 +588,21 @@ void policydb_destroy(struct policydb *p)
        struct ocontext *c, *ctmp;
        struct genfs *g, *gtmp;
        int i;
+       struct role_allow *ra, *lra = NULL;
+       struct role_trans *tr, *ltr = NULL;
+       struct range_trans *rt, *lrt = NULL;
 
        for (i = 0; i < SYM_NUM; i++) {
                hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
                hashtab_destroy(p->symtab[i].table);
        }
 
-       for (i = 0; i < SYM_NUM; i++) {
-               if (p->sym_val_to_name[i])
-                       kfree(p->sym_val_to_name[i]);
-       }
+       for (i = 0; i < SYM_NUM; i++)
+               kfree(p->sym_val_to_name[i]);
 
-       if (p->class_val_to_struct)
-               kfree(p->class_val_to_struct);
-       if (p->role_val_to_struct)
-               kfree(p->role_val_to_struct);
-       if (p->user_val_to_struct)
-               kfree(p->user_val_to_struct);
+       kfree(p->class_val_to_struct);
+       kfree(p->role_val_to_struct);
+       kfree(p->user_val_to_struct);
 
        avtab_destroy(&p->te_avtab);
 
@@ -629,6 +631,30 @@ void policydb_destroy(struct policydb *p)
 
        cond_policydb_destroy(p);
 
+       for (tr = p->role_tr; tr; tr = tr->next) {
+               kfree(ltr);
+               ltr = tr;
+       }
+       kfree(ltr);
+
+       for (ra = p->role_allow; ra; ra = ra -> next) {
+               kfree(lra);
+               lra = ra;
+       }
+       kfree(lra);
+
+       for (rt = p->range_tr; rt; rt = rt -> next) {
+               kfree(lrt);
+               lrt = rt;
+       }
+       kfree(lrt);
+
+       if (p->type_attr_map) {
+               for (i = 0; i < p->p_types.nprim; i++)
+                       ebitmap_destroy(&p->type_attr_map[i]);
+       }
+       kfree(p->type_attr_map);
+
        return;
 }
 
@@ -719,7 +745,8 @@ int policydb_context_isvalid(struct policydb *p, struct context *c)
  */
 static int mls_read_range_helper(struct mls_range *r, void *fp)
 {
-       u32 buf[2], items;
+       __le32 buf[2];
+       u32 items;
        int rc;
 
        rc = next_entry(buf, fp, sizeof(u32));
@@ -780,7 +807,7 @@ static int context_read_and_validate(struct context *c,
                                     struct policydb *p,
                                     void *fp)
 {
-       u32 buf[3];
+       __le32 buf[3];
        int rc;
 
        rc = next_entry(buf, fp, sizeof buf);
@@ -820,14 +847,14 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct perm_datum *perdatum;
        int rc;
-       u32 buf[2], len;
+       __le32 buf[2];
+       u32 len;
 
-       perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
+       perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
        if (!perdatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(perdatum, 0, sizeof(*perdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -860,15 +887,15 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
 {
        char *key = NULL;
        struct common_datum *comdatum;
-       u32 buf[4], len, nel;
+       __le32 buf[4];
+       u32 len, nel;
        int i, rc;
 
-       comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
+       comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
        if (!comdatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(comdatum, 0, sizeof(*comdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -914,15 +941,15 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
 {
        struct constraint_node *c, *lc;
        struct constraint_expr *e, *le;
-       u32 buf[3], nexpr;
+       __le32 buf[3];
+       u32 nexpr;
        int rc, i, j, depth;
 
        lc = NULL;
        for (i = 0; i < ncons; i++) {
-               c = kmalloc(sizeof(*c), GFP_KERNEL);
+               c = kzalloc(sizeof(*c), GFP_KERNEL);
                if (!c)
                        return -ENOMEM;
-               memset(c, 0, sizeof(*c));
 
                if (lc) {
                        lc->next = c;
@@ -938,10 +965,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
                le = NULL;
                depth = -1;
                for (j = 0; j < nexpr; j++) {
-                       e = kmalloc(sizeof(*e), GFP_KERNEL);
+                       e = kzalloc(sizeof(*e), GFP_KERNEL);
                        if (!e)
                                return -ENOMEM;
-                       memset(e, 0, sizeof(*e));
 
                        if (le) {
                                le->next = e;
@@ -998,15 +1024,15 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 {
        char *key = NULL;
        struct class_datum *cladatum;
-       u32 buf[6], len, len2, ncons, nel;
+       __le32 buf[6];
+       u32 len, len2, ncons, nel;
        int i, rc;
 
-       cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
+       cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
        if (!cladatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(cladatum, 0, sizeof(*cladatum));
 
        rc = next_entry(buf, fp, sizeof(u32)*6);
        if (rc < 0)
@@ -1092,14 +1118,14 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct role_datum *role;
        int rc;
-       u32 buf[2], len;
+       __le32 buf[2];
+       u32 len;
 
-       role = kmalloc(sizeof(*role), GFP_KERNEL);
+       role = kzalloc(sizeof(*role), GFP_KERNEL);
        if (!role) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(role, 0, sizeof(*role));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -1152,14 +1178,14 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct type_datum *typdatum;
        int rc;
-       u32 buf[3], len;
+       __le32 buf[3];
+       u32 len;
 
-       typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
+       typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
        if (!typdatum) {
                rc = -ENOMEM;
                return rc;
        }
-       memset(typdatum, 0, sizeof(*typdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -1196,7 +1222,7 @@ bad:
  */
 static int mls_read_level(struct mls_level *lp, void *fp)
 {
-       u32 buf[1];
+       __le32 buf[1];
        int rc;
 
        memset(lp, 0, sizeof(*lp));
@@ -1224,14 +1250,14 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct user_datum *usrdatum;
        int rc;
-       u32 buf[2], len;
+       __le32 buf[2];
+       u32 len;
 
-       usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
+       usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
        if (!usrdatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(usrdatum, 0, sizeof(*usrdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -1278,14 +1304,14 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct level_datum *levdatum;
        int rc;
-       u32 buf[2], len;
+       __le32 buf[2];
+       u32 len;
 
-       levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+       levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
        if (!levdatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(levdatum, 0, sizeof(*levdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -1329,14 +1355,14 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
        char *key = NULL;
        struct cat_datum *catdatum;
        int rc;
-       u32 buf[3], len;
+       __le32 buf[3];
+       u32 len;
 
-       catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+       catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
        if (!catdatum) {
                rc = -ENOMEM;
                goto out;
        }
-       memset(catdatum, 0, sizeof(*catdatum));
 
        rc = next_entry(buf, fp, sizeof buf);
        if (rc < 0)
@@ -1392,7 +1418,8 @@ int policydb_read(struct policydb *p, void *fp)
        struct ocontext *l, *c, *newc;
        struct genfs *genfs_p, *genfs, *newgenfs;
        int i, j, rc;
-       u32 buf[8], len, len2, config, nprim, nel, nel2;
+       __le32 buf[8];
+       u32 len, len2, config, nprim, nel, nel2;
        char *policydb_str;
        struct policydb_compat_info *info;
        struct range_trans *rt, *lrt;
@@ -1408,17 +1435,14 @@ int policydb_read(struct policydb *p, void *fp)
        if (rc < 0)
                goto bad;
 
-       for (i = 0; i < 2; i++)
-               buf[i] = le32_to_cpu(buf[i]);
-
-       if (buf[0] != POLICYDB_MAGIC) {
+       if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
                printk(KERN_ERR "security:  policydb magic number 0x%x does "
                       "not match expected magic number 0x%x\n",
-                      buf[0], POLICYDB_MAGIC);
+                      le32_to_cpu(buf[0]), POLICYDB_MAGIC);
                goto bad;
        }
 
-       len = buf[1];
+       len = le32_to_cpu(buf[1]);
        if (len != strlen(POLICYDB_STRING)) {
                printk(KERN_ERR "security:  policydb string length %d does not "
                       "match expected length %Zu\n",
@@ -1453,19 +1477,17 @@ int policydb_read(struct policydb *p, void *fp)
        rc = next_entry(buf, fp, sizeof(u32)*4);
        if (rc < 0)
                goto bad;
-       for (i = 0; i < 4; i++)
-               buf[i] = le32_to_cpu(buf[i]);
 
-       p->policyvers = buf[0];
+       p->policyvers = le32_to_cpu(buf[0]);
        if (p->policyvers < POLICYDB_VERSION_MIN ||
            p->policyvers > POLICYDB_VERSION_MAX) {
                printk(KERN_ERR "security:  policydb version %d does not match "
                       "my version range %d-%d\n",
-                      buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+                      le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
                goto bad;
        }
 
-       if ((buf[1] & POLICYDB_CONFIG_MLS)) {
+       if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
                if (ss_initialized && !selinux_mls_enabled) {
                        printk(KERN_ERR "Cannot switch between non-MLS and MLS "
                               "policies\n");
@@ -1494,9 +1516,11 @@ int policydb_read(struct policydb *p, void *fp)
                goto bad;
        }
 
-       if (buf[2] != info->sym_num || buf[3] != info->ocon_num) {
+       if (le32_to_cpu(buf[2]) != info->sym_num ||
+               le32_to_cpu(buf[3]) != info->ocon_num) {
                printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
-                      "not match mine (%d,%d)\n", buf[2], buf[3],
+                      "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
+                       le32_to_cpu(buf[3]),
                       info->sym_num, info->ocon_num);
                goto bad;
        }
@@ -1516,7 +1540,7 @@ int policydb_read(struct policydb *p, void *fp)
                p->symtab[i].nprim = nprim;
        }
 
-       rc = avtab_read(&p->te_avtab, fp, config);
+       rc = avtab_read(&p->te_avtab, fp, p->policyvers);
        if (rc)
                goto bad;
 
@@ -1532,12 +1556,11 @@ int policydb_read(struct policydb *p, void *fp)
        nel = le32_to_cpu(buf[0]);
        ltr = NULL;
        for (i = 0; i < nel; i++) {
-               tr = kmalloc(sizeof(*tr), GFP_KERNEL);
+               tr = kzalloc(sizeof(*tr), GFP_KERNEL);
                if (!tr) {
                        rc = -ENOMEM;
                        goto bad;
                }
-               memset(tr, 0, sizeof(*tr));
                if (ltr) {
                        ltr->next = tr;
                } else {
@@ -1558,12 +1581,11 @@ int policydb_read(struct policydb *p, void *fp)
        nel = le32_to_cpu(buf[0]);
        lra = NULL;
        for (i = 0; i < nel; i++) {
-               ra = kmalloc(sizeof(*ra), GFP_KERNEL);
+               ra = kzalloc(sizeof(*ra), GFP_KERNEL);
                if (!ra) {
                        rc = -ENOMEM;
                        goto bad;
                }
-               memset(ra, 0, sizeof(*ra));
                if (lra) {
                        lra->next = ra;
                } else {
@@ -1592,12 +1614,11 @@ int policydb_read(struct policydb *p, void *fp)
                nel = le32_to_cpu(buf[0]);
                l = NULL;
                for (j = 0; j < nel; j++) {
-                       c = kmalloc(sizeof(*c), GFP_KERNEL);
+                       c = kzalloc(sizeof(*c), GFP_KERNEL);
                        if (!c) {
                                rc = -ENOMEM;
                                goto bad;
                        }
-                       memset(c, 0, sizeof(*c));
                        if (l) {
                                l->next = c;
                        } else {
@@ -1708,12 +1729,11 @@ int policydb_read(struct policydb *p, void *fp)
                if (rc < 0)
                        goto bad;
                len = le32_to_cpu(buf[0]);
-               newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
+               newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
                if (!newgenfs) {
                        rc = -ENOMEM;
                        goto bad;
                }
-               memset(newgenfs, 0, sizeof(*newgenfs));
 
                newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
                if (!newgenfs->fstype) {
@@ -1755,12 +1775,11 @@ int policydb_read(struct policydb *p, void *fp)
                                goto bad;
                        len = le32_to_cpu(buf[0]);
 
-                       newc = kmalloc(sizeof(*newc), GFP_KERNEL);
+                       newc = kzalloc(sizeof(*newc), GFP_KERNEL);
                        if (!newc) {
                                rc = -ENOMEM;
                                goto bad;
                        }
-                       memset(newc, 0, sizeof(*newc));
 
                        newc->u.name = kmalloc(len + 1,GFP_KERNEL);
                        if (!newc->u.name) {
@@ -1808,12 +1827,11 @@ int policydb_read(struct policydb *p, void *fp)
                nel = le32_to_cpu(buf[0]);
                lrt = NULL;
                for (i = 0; i < nel; i++) {
-                       rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+                       rt = kzalloc(sizeof(*rt), GFP_KERNEL);
                        if (!rt) {
                                rc = -ENOMEM;
                                goto bad;
                        }
-                       memset(rt, 0, sizeof(*rt));
                        if (lrt)
                                lrt->next = rt;
                        else
@@ -1830,6 +1848,21 @@ int policydb_read(struct policydb *p, void *fp)
                }
        }
 
+       p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
+       if (!p->type_attr_map)
+               goto bad;
+
+       for (i = 0; i < p->p_types.nprim; i++) {
+               ebitmap_init(&p->type_attr_map[i]);
+               if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
+                       if (ebitmap_read(&p->type_attr_map[i], fp))
+                               goto bad;
+               }
+               /* add the type itself as the degenerate case */
+               if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
+                               goto bad;
+       }
+
        rc = 0;
 out:
        return rc;