X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fselinux%2Fss%2Fpolicydb.c;h=46bc7b6bc79eee1741c07aa0c1f3510f9420f4ad;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=e10ed0e1e9a9e435a7d92aa87a1db00a742dadc9;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index e10ed0e1e..46bc7b6bc 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -38,8 +38,6 @@ static char *symtab_name[SYM_NUM] = { }; #endif -int policydb_loaded_version; - static unsigned int symtab_sizes[SYM_NUM] = { 2, 32, @@ -633,13 +631,12 @@ static int context_read_and_validate(struct context *c, struct policydb *p, void *fp) { - u32 *buf; - int rc = 0; + u32 buf[3]; + int rc; - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) { printk(KERN_ERR "security: context truncated\n"); - rc = -EINVAL; goto out; } c->user = le32_to_cpu(buf[0]); @@ -672,7 +669,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct perm_datum *perdatum; int rc; - u32 *buf, len; + u32 buf[2], len; perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); if (!perdatum) { @@ -681,11 +678,9 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) } memset(perdatum, 0, sizeof(*perdatum)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); perdatum->value = le32_to_cpu(buf[1]); @@ -693,17 +688,14 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) if (rc) goto bad; - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = hashtab_insert(h, key, perdatum); @@ -720,7 +712,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct common_datum *comdatum; - u32 *buf, len, nel; + u32 buf[4], len, nel; int i, rc; comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); @@ -730,11 +722,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) } memset(comdatum, 0, sizeof(*comdatum)); - buf = next_entry(fp, sizeof(u32)*4); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); comdatum->value = le32_to_cpu(buf[1]); @@ -745,17 +735,14 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) comdatum->permissions.nprim = le32_to_cpu(buf[2]); nel = le32_to_cpu(buf[3]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; for (i = 0; i < nel; i++) { @@ -780,21 +767,19 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) struct class_datum *cladatum; struct constraint_node *c, *lc; struct constraint_expr *e, *le; - u32 *buf, len, len2, ncons, nexpr, nel; + u32 buf[6], len, len2, ncons, nexpr, nel; int i, j, depth, rc; cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); if (!cladatum) { rc = -ENOMEM; - goto bad; + goto out; } memset(cladatum, 0, sizeof(*cladatum)); - buf = next_entry(fp, sizeof(u32)*6); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*6); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); len2 = le32_to_cpu(buf[1]); @@ -808,17 +793,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ncons = le32_to_cpu(buf[5]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; if (len2) { @@ -827,12 +809,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = -ENOMEM; goto bad; } - buf = next_entry(fp, len2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(cladatum->comkey, fp, len2); + if (rc < 0) goto bad; - } - memcpy(cladatum->comkey, buf, len2); cladatum->comkey[len2] = 0; cladatum->comdatum = hashtab_search(p->p_commons.table, @@ -851,7 +830,6 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) } lc = NULL; - rc = -EINVAL; for (i = 0; i < ncons; i++) { c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) { @@ -866,8 +844,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) cladatum->constraints = c; } - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; c->permissions = le32_to_cpu(buf[0]); nexpr = le32_to_cpu(buf[1]); @@ -887,13 +865,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) c->expr = e; } - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*3); + if (rc < 0) goto bad; e->expr_type = le32_to_cpu(buf[0]); e->attr = le32_to_cpu(buf[1]); e->op = le32_to_cpu(buf[2]); + rc = -EINVAL; switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) @@ -934,6 +913,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = hashtab_insert(h, key, cladatum); if (rc) goto bad; + + rc = 0; out: return rc; bad: @@ -946,7 +927,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct role_datum *role; int rc; - u32 *buf, len; + u32 buf[2], len; role = kmalloc(sizeof(*role), GFP_KERNEL); if (!role) { @@ -955,26 +936,21 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) } memset(role, 0, sizeof(*role)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); role->value = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = ebitmap_read(&role->dominates, fp); @@ -1011,7 +987,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct type_datum *typdatum; int rc; - u32 *buf, len; + u32 buf[3], len; typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); if (!typdatum) { @@ -1020,27 +996,22 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) } memset(typdatum, 0, sizeof(*typdatum)); - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); typdatum->value = le32_to_cpu(buf[1]); typdatum->primary = le32_to_cpu(buf[2]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = hashtab_insert(h, key, typdatum); @@ -1058,7 +1029,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct user_datum *usrdatum; int rc; - u32 *buf, len; + u32 buf[2], len; usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); @@ -1068,26 +1039,21 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) } memset(usrdatum, 0, sizeof(*usrdatum)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); usrdatum->value = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = ebitmap_read(&usrdatum->roles, fp); @@ -1132,8 +1098,8 @@ int policydb_read(struct policydb *p, void *fp) struct role_trans *tr, *ltr; struct ocontext *l, *c, *newc; struct genfs *genfs_p, *genfs, *newgenfs; - int i, j, rc, r_policyvers = 0; - u32 *buf, len, len2, config, nprim, nel, nel2; + int i, j, rc; + u32 buf[8], len, len2, config, nprim, nel, nel2; char *policydb_str; struct policydb_compat_info *info; @@ -1144,10 +1110,9 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto out; - rc = -EINVAL; /* Read the magic number and string length. */ - buf = next_entry(fp, sizeof(u32)* 2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)* 2); + if (rc < 0) goto bad; for (i = 0; i < 2; i++) @@ -1167,11 +1132,6 @@ int policydb_read(struct policydb *p, void *fp) len, strlen(POLICYDB_STRING)); goto bad; } - buf = next_entry(fp, len); - if (!buf) { - printk(KERN_ERR "security: truncated policydb string identifier\n"); - goto bad; - } policydb_str = kmalloc(len + 1,GFP_KERNEL); if (!policydb_str) { printk(KERN_ERR "security: unable to allocate memory for policydb " @@ -1179,7 +1139,12 @@ int policydb_read(struct policydb *p, void *fp) rc = -ENOMEM; goto bad; } - memcpy(policydb_str, buf, len); + rc = next_entry(policydb_str, fp, len); + if (rc < 0) { + printk(KERN_ERR "security: truncated policydb string identifier\n"); + kfree(policydb_str); + goto bad; + } policydb_str[len] = 0; if (strcmp(policydb_str, POLICYDB_STRING)) { printk(KERN_ERR "security: policydb string %s does not match " @@ -1192,15 +1157,15 @@ int policydb_read(struct policydb *p, void *fp) policydb_str = NULL; /* Read the version, config, and table sizes. */ - buf = next_entry(fp, sizeof(u32)*4); - if (!buf) + 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]); - r_policyvers = buf[0]; - if (r_policyvers < POLICYDB_VERSION_MIN || - r_policyvers > POLICYDB_VERSION_MAX) { + p->policyvers = 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); @@ -1216,10 +1181,10 @@ int policydb_read(struct policydb *p, void *fp) } - info = policydb_lookup_compat(r_policyvers); + info = policydb_lookup_compat(p->policyvers); if (!info) { printk(KERN_ERR "security: unable to find policy compat info " - "for version %d\n", r_policyvers); + "for version %d\n", p->policyvers); goto bad; } @@ -1235,11 +1200,9 @@ int policydb_read(struct policydb *p, void *fp) goto bad; for (i = 0; i < info->sym_num; i++) { - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; - } nprim = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[1]); for (j = 0; j < nel; j++) { @@ -1255,17 +1218,15 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto bad; - if (r_policyvers >= POLICYDB_VERSION_BOOL) { + if (p->policyvers >= POLICYDB_VERSION_BOOL) { rc = cond_read_list(p, fp); if (rc) goto bad; } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { @@ -1280,22 +1241,18 @@ int policydb_read(struct policydb *p, void *fp) } else { p->role_tr = tr; } - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*3); + if (rc < 0) goto bad; - } tr->role = le32_to_cpu(buf[0]); tr->type = le32_to_cpu(buf[1]); tr->new_role = le32_to_cpu(buf[2]); ltr = tr; } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { @@ -1310,11 +1267,9 @@ int policydb_read(struct policydb *p, void *fp) } else { p->role_allow = ra; } - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; - } ra->role = le32_to_cpu(buf[0]); ra->new_role = le32_to_cpu(buf[1]); lra = ra; @@ -1329,11 +1284,9 @@ int policydb_read(struct policydb *p, void *fp) goto bad; for (i = 0; i < info->ocon_num; i++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { @@ -1352,8 +1305,8 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; switch (i) { case OCON_ISID: - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; c->sid[0] = le32_to_cpu(buf[0]); rc = context_read_and_validate(&c->context[0], p, fp); @@ -1362,19 +1315,18 @@ int policydb_read(struct policydb *p, void *fp) break; case OCON_FS: case OCON_NETIF: - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } - memcpy(c->u.name, buf, len); + rc = next_entry(c->u.name, fp, len); + if (rc < 0) + goto bad; c->u.name[len] = 0; rc = context_read_and_validate(&c->context[0], p, fp); if (rc) @@ -1384,8 +1336,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_PORT: - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*3); + if (rc < 0) goto bad; c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.low_port = le32_to_cpu(buf[1]); @@ -1395,8 +1347,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_NODE: - buf = next_entry(fp, sizeof(u32)* 2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)* 2); + if (rc < 0) goto bad; c->u.node.addr = le32_to_cpu(buf[0]); c->u.node.mask = le32_to_cpu(buf[1]); @@ -1405,22 +1357,21 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_FSUSE: - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; c->v.behavior = le32_to_cpu(buf[0]); if (c->v.behavior > SECURITY_FS_USE_NONE) goto bad; len = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) - goto bad; c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } - memcpy(c->u.name, buf, len); + rc = next_entry(c->u.name, fp, len); + if (rc < 0) + goto bad; c->u.name[len] = 0; rc = context_read_and_validate(&c->context[0], p, fp); if (rc) @@ -1429,8 +1380,8 @@ int policydb_read(struct policydb *p, void *fp) case OCON_NODE6: { int k; - buf = next_entry(fp, sizeof(u32) * 8); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32) * 8); + if (rc < 0) goto bad; for (k = 0; k < 4; k++) c->u.node6.addr[k] = le32_to_cpu(buf[k]); @@ -1444,22 +1395,17 @@ int policydb_read(struct policydb *p, void *fp) } } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); genfs_p = NULL; rc = -EINVAL; for (i = 0; i < nel; i++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); if (!newgenfs) { rc = -ENOMEM; @@ -1473,7 +1419,12 @@ int policydb_read(struct policydb *p, void *fp) kfree(newgenfs); goto bad; } - memcpy(newgenfs->fstype, buf, len); + rc = next_entry(newgenfs->fstype, fp, len); + if (rc < 0) { + kfree(newgenfs->fstype); + kfree(newgenfs); + goto bad; + } newgenfs->fstype[len] = 0; for (genfs_p = NULL, genfs = p->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { @@ -1492,18 +1443,15 @@ int policydb_read(struct policydb *p, void *fp) genfs_p->next = newgenfs; else p->genfs = newgenfs; - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; newc = kmalloc(sizeof(*newc), GFP_KERNEL); if (!newc) { @@ -1517,10 +1465,12 @@ int policydb_read(struct policydb *p, void *fp) rc = -ENOMEM; goto bad_newc; } - memcpy(newc->u.name, buf, len); + rc = next_entry(newc->u.name, fp, len); + if (rc < 0) + goto bad_newc; newc->u.name[len] = 0; - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad_newc; newc->v.sclass = le32_to_cpu(buf[0]); if (context_read_and_validate(&newc->context[0], p, fp)) @@ -1552,12 +1502,15 @@ int policydb_read(struct policydb *p, void *fp) rc = mls_read_trusted(p, fp); if (rc) goto bad; + + rc = 0; out: - policydb_loaded_version = r_policyvers; return rc; bad_newc: ocontext_destroy(newc,OCON_FSUSE); bad: + if (!rc) + rc = -EINVAL; policydb_destroy(p); goto out; }