📄 policydb.c
字号:
} 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]); key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; rc = ebitmap_read(&usrdatum->roles, fp); if (rc) goto bad; if (p->policyvers >= POLICYDB_VERSION_MLS) { rc = mls_read_range_helper(&usrdatum->range, fp); if (rc) goto bad; rc = mls_read_level(&usrdatum->dfltlevel, fp); if (rc) goto bad; } rc = hashtab_insert(h, key, usrdatum); if (rc) goto bad;out: return rc;bad: user_destroy(key, usrdatum, NULL); goto out;}static int sens_read(struct policydb *p, struct hashtab *h, void *fp){ char *key = NULL; struct level_datum *levdatum; int rc; __le32 buf[2]; u32 len; levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); if (!levdatum) { rc = -ENOMEM; goto out; } rc = next_entry(buf, fp, sizeof buf); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); levdatum->isalias = le32_to_cpu(buf[1]); key = kmalloc(len + 1,GFP_ATOMIC); if (!key) { rc = -ENOMEM; goto bad; } rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); if (!levdatum->level) { rc = -ENOMEM; goto bad; } if (mls_read_level(levdatum->level, fp)) { rc = -EINVAL; goto bad; } rc = hashtab_insert(h, key, levdatum); if (rc) goto bad;out: return rc;bad: sens_destroy(key, levdatum, NULL); goto out;}static int cat_read(struct policydb *p, struct hashtab *h, void *fp){ char *key = NULL; struct cat_datum *catdatum; int rc; __le32 buf[3]; u32 len; catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); if (!catdatum) { rc = -ENOMEM; goto out; } rc = next_entry(buf, fp, sizeof buf); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); catdatum->value = le32_to_cpu(buf[1]); catdatum->isalias = le32_to_cpu(buf[2]); key = kmalloc(len + 1,GFP_ATOMIC); if (!key) { rc = -ENOMEM; goto bad; } rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; rc = hashtab_insert(h, key, catdatum); if (rc) goto bad;out: return rc;bad: cat_destroy(key, catdatum, NULL); goto out;}static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) ={ common_read, class_read, role_read, type_read, user_read, cond_read_bool, sens_read, cat_read,};extern int ss_initialized;/* * Read the configuration data from a policy database binary * representation file into a policy database structure. */int policydb_read(struct policydb *p, void *fp){ struct role_allow *ra, *lra; struct role_trans *tr, *ltr; struct ocontext *l, *c, *newc; struct genfs *genfs_p, *genfs, *newgenfs; int i, j, rc; __le32 buf[8]; u32 len, len2, config, nprim, nel, nel2; char *policydb_str; struct policydb_compat_info *info; struct range_trans *rt, *lrt; config = 0; rc = policydb_init(p); if (rc) goto out; /* Read the magic number and string length. */ rc = next_entry(buf, fp, sizeof(u32)* 2); if (rc < 0) goto bad; 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", le32_to_cpu(buf[0]), POLICYDB_MAGIC); goto bad; } 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", len, strlen(POLICYDB_STRING)); goto bad; } policydb_str = kmalloc(len + 1,GFP_KERNEL); if (!policydb_str) { printk(KERN_ERR "security: unable to allocate memory for policydb " "string of length %d\n", len); rc = -ENOMEM; goto bad; } 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 " "my string %s\n", policydb_str, POLICYDB_STRING); kfree(policydb_str); goto bad; } /* Done with policydb_str. */ kfree(policydb_str); policydb_str = NULL; /* Read the version, config, and table sizes. */ rc = next_entry(buf, fp, sizeof(u32)*4); if (rc < 0) goto bad; 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", le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); goto bad; } 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"); goto bad; } selinux_mls_enabled = 1; config |= POLICYDB_CONFIG_MLS; if (p->policyvers < POLICYDB_VERSION_MLS) { printk(KERN_ERR "security policydb version %d (MLS) " "not backwards compatible\n", p->policyvers); goto bad; } } else { if (ss_initialized && selinux_mls_enabled) { printk(KERN_ERR "Cannot switch between MLS and non-MLS " "policies\n"); goto bad; } } p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); info = policydb_lookup_compat(p->policyvers); if (!info) { printk(KERN_ERR "security: unable to find policy compat info " "for version %d\n", p->policyvers); goto bad; } 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", le32_to_cpu(buf[2]), le32_to_cpu(buf[3]), info->sym_num, info->ocon_num); goto bad; } for (i = 0; i < info->sym_num; i++) { 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++) { rc = read_f[i](p, p->symtab[i].table, fp); if (rc) goto bad; } p->symtab[i].nprim = nprim; } rc = avtab_read(&p->te_avtab, fp, p); if (rc) goto bad; if (p->policyvers >= POLICYDB_VERSION_BOOL) { rc = cond_read_list(p, fp); if (rc) goto bad; } 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++) { tr = kzalloc(sizeof(*tr), GFP_KERNEL); if (!tr) { rc = -ENOMEM; goto bad; } if (ltr) { ltr->next = tr; } else { p->role_tr = tr; } 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]); if (!policydb_role_isvalid(p, tr->role) || !policydb_type_isvalid(p, tr->type) || !policydb_role_isvalid(p, tr->new_role)) { rc = -EINVAL; goto bad; } ltr = tr; } 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++) { ra = kzalloc(sizeof(*ra), GFP_KERNEL); if (!ra) { rc = -ENOMEM; goto bad; } if (lra) { lra->next = ra; } else { p->role_allow = ra; } 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]); if (!policydb_role_isvalid(p, ra->role) || !policydb_role_isvalid(p, ra->new_role)) { rc = -EINVAL; goto bad; } lra = ra; } rc = policydb_index_classes(p); if (rc) goto bad; rc = policydb_index_others(p); if (rc) goto bad; for (i = 0; i < info->ocon_num; i++) { 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++) { c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) { rc = -ENOMEM; goto bad; } if (l) { l->next = c; } else { p->ocontexts[i] = c; } l = c; rc = -EINVAL; switch (i) { case OCON_ISID: 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); if (rc) goto bad; break; case OCON_FS: case OCON_NETIF: rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } 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) goto bad; rc = context_read_and_validate(&c->context[1], p, fp); if (rc) goto bad; break; case OCON_PORT: 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]); c->u.port.high_port = le32_to_cpu(buf[2]); rc = context_read_and_validate(&c->context[0], p, fp); if (rc) goto bad; break; case OCON_NODE: 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]); rc = context_read_and_validate(&c->context[0], p, fp); if (rc) goto bad; break; case OCON_FSUSE: 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]); c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } 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) goto bad; break; case OCON_NODE6: { int k; 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]); for (k = 0; k < 4; k++) c->u.node6.mask[k] = le32_to_cpu(buf[k+4]); if (context_read_and_validate(&c->context[0], p, fp)) goto bad; break; } } } } 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++) { rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); if (!newgenfs) { rc = -ENOMEM; goto bad; } newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL); if (!newgenfs->fstype) { rc = -ENOMEM; kfree(newgenfs); goto bad; } 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) { if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { printk(KERN_ERR "security: dup genfs " "fstype %s\n", newgenfs->fstype); kfree(newgenfs->fstype); kfree(newgenfs); goto bad; } if (strcmp(newgenfs->fstype, genfs->fstype) < 0) break; } newgenfs->next = genfs; if (genfs_p) genfs_p->next = newgenfs; else p->genfs = newgenfs; rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); newc = kzalloc(sizeof(*newc), GFP_KERNEL); if (!newc) { rc = -ENOMEM; goto bad; } newc->u.name = kmalloc(len + 1,GFP_KERNEL); if (!newc->u.name) { rc = -ENOMEM; goto bad_newc; } rc = next_entry(newc->u.name, fp, len); if (rc < 0) goto bad_newc; newc->u.name[len] = 0; 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)) goto bad_newc; for (l = NULL, c = newgenfs->head; c; l = c, c = c->next) { if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || newc->v.sclass == c->v.sclass)) { printk(KERN_ERR "security: dup genfs " "entry (%s,%s)\n", newgenfs->fstype, c->u.name); goto bad_newc; } len = strlen(newc->u.name); len2 = strlen(c->u.name); if (len > len2) break; } newc->next = c; if (l) l->next = newc; else newgenfs->head = newc; } } 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; nel = le32_to_cpu(buf[0]); lrt = NULL; for (i = 0; i < nel; i++) { rt = kzalloc(sizeof(*rt), GFP_KERNEL); if (!rt) { rc = -ENOMEM; goto bad; } if (lrt) lrt->next = rt; else p->range_tr = rt; rc = next_entry(buf, fp, (sizeof(u32) * 2)); if (rc < 0) goto bad; 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; if (!policydb_type_isvalid(p, rt->source_type) || !policydb_type_isvalid(p, rt->target_type) || !policydb_class_isvalid(p, rt->target_class)) { rc = -EINVAL; goto bad; } rc = mls_read_range_helper(&rt->target_range, fp); if (rc) goto bad; if (!mls_range_isvalid(p, &rt->target_range)) { printk(KERN_WARNING "security: rangetrans: invalid range\n"); goto bad; } lrt = rt; } } 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;bad_newc: ocontext_destroy(newc,OCON_FSUSE);bad: if (!rc) rc = -EINVAL; policydb_destroy(p); goto out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -