int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, int (*insertf)(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *p), void *p) { __le16 buf16[4]; u16 enabled; __le32 buf32[7]; u32 items, items2, val, vers = pol->policyvers; struct avtab_key key; struct avtab_datum datum; int i, rc; unsigned set; memset(&key, 0, sizeof(struct avtab_key)); memset(&datum, 0, sizeof(struct avtab_datum)); if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(u32)); if (rc) { printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return rc; } items2 = le32_to_cpu(buf32[0]); if (items2 > ARRAY_SIZE(buf32)) { printk(KERN_ERR "SELinux: avtab: entry overflow\n"); return -EINVAL; } rc = next_entry(buf32, fp, sizeof(u32)*items2); if (rc) { printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return rc; } items = 0; val = le32_to_cpu(buf32[items++]); key.source_type = (u16)val; if (key.source_type != val) { printk(KERN_ERR "SELinux: avtab: truncated source type\n"); return -EINVAL; } val = le32_to_cpu(buf32[items++]); key.target_type = (u16)val; if (key.target_type != val) { printk(KERN_ERR "SELinux: avtab: truncated target type\n"); return -EINVAL; } val = le32_to_cpu(buf32[items++]); key.target_class = (u16)val; if (key.target_class != val) { printk(KERN_ERR "SELinux: avtab: truncated target class\n"); return -EINVAL; } val = le32_to_cpu(buf32[items++]); enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { printk(KERN_ERR "SELinux: avtab: null entry\n"); return -EINVAL; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (val & spec_order[i]) { key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); rc = insertf(a, &key, &datum, p); if (rc) return rc; } } if (items != items2) { printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); return -EINVAL; } return 0; } rc = next_entry(buf16, fp, sizeof(u16)*4); if (rc) { printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return rc; } items = 0; key.source_type = le16_to_cpu(buf16[items++]); key.target_type = le16_to_cpu(buf16[items++]); key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); if (!policydb_type_isvalid(pol, key.source_type) || !policydb_type_isvalid(pol, key.target_type) || !policydb_class_isvalid(pol, key.target_class)) { printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); return -EINVAL; } set = 0; for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (key.specified & spec_order[i]) set++; } if (!set || set > 1) { printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); return -EINVAL; } rc = next_entry(buf32, fp, sizeof(u32)); if (rc) { printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return rc; } datum.data = le32_to_cpu(*buf32); if ((key.specified & AVTAB_TYPE) && !policydb_type_isvalid(pol, datum.data)) { printk(KERN_ERR "SELinux: avtab: invalid type\n"); return -EINVAL; } return insertf(a, &key, &datum, p); }
int avtab_read_item(void *fp, u32 vers, struct avtab *a, int (*insertf)(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *p), void *p) { __le16 buf16[4]; u16 enabled; __le32 buf32[7]; u32 items, items2, val; struct avtab_key key; struct avtab_datum datum; int i, rc; memset(&key, 0, sizeof(struct avtab_key)); memset(&datum, 0, sizeof(struct avtab_datum)); if ( vers < POLICYDB_VERSION_AVTAB ) { rc = next_entry(buf32, fp, sizeof(u32)); if ( rc < 0 ) { printk(KERN_ERR "security: avtab: truncated entry\n"); return -1; } items2 = le32_to_cpu(buf32[0]); if ( items2 > ARRAY_SIZE(buf32) ) { printk(KERN_ERR "security: avtab: entry overflow\n"); return -1; } rc = next_entry(buf32, fp, sizeof(u32)*items2); if ( rc < 0 ) { printk(KERN_ERR "security: avtab: truncated entry\n"); return -1; } items = 0; val = le32_to_cpu(buf32[items++]); key.source_type = (u16)val; if ( key.source_type != val ) { printk("security: avtab: truncated source type\n"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_type = (u16)val; if ( key.target_type != val ) { printk("security: avtab: truncated target type\n"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_class = (u16)val; if ( key.target_class != val ) { printk("security: avtab: truncated target class\n"); return -1; } val = le32_to_cpu(buf32[items++]); enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if ( !(val & (AVTAB_AV | AVTAB_TYPE)) ) { printk("security: avtab: null entry\n"); return -1; } if ( (val & AVTAB_AV) && (val & AVTAB_TYPE) ) { printk("security: avtab: entry has both access vectors and types\n"); return -1; } for ( i = 0; i < sizeof(spec_order)/sizeof(u16); i++ ) { if ( val & spec_order[i] ) { key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); rc = insertf(a, &key, &datum, p); if ( rc ) return rc; } } if ( items != items2 ) { printk("security: avtab: entry only had %d items, expected %d\n", items2, items); return -1; } return 0; } rc = next_entry(buf16, fp, sizeof(u16)*4); if ( rc < 0 ) { printk("security: avtab: truncated entry\n"); return -1; } items = 0; key.source_type = le16_to_cpu(buf16[items++]); key.target_type = le16_to_cpu(buf16[items++]); key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); rc = next_entry(buf32, fp, sizeof(u32)); if ( rc < 0 ) { printk("security: avtab: truncated entry\n"); return -1; } datum.data = le32_to_cpu(*buf32); return insertf(a, &key, &datum, p); }
int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, int (*insertf) (avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p), void *p) { uint8_t buf8; uint16_t buf16[4], enabled; uint32_t buf32[8], items, items2, val; avtab_key_t key; avtab_datum_t datum; avtab_extended_perms_t xperms; unsigned set; unsigned int i; int rc; memset(&key, 0, sizeof(avtab_key_t)); memset(&datum, 0, sizeof(avtab_datum_t)); memset(&xperms, 0, sizeof(avtab_extended_perms_t)); if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items2 = le32_to_cpu(buf32[0]); if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) { ERR(fp->handle, "invalid item count"); return -1; } rc = next_entry(buf32, fp, sizeof(uint32_t) * items2); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; val = le32_to_cpu(buf32[items++]); key.source_type = (uint16_t) val; if (key.source_type != val) { ERR(fp->handle, "truncated source type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_type = (uint16_t) val; if (key.target_type != val) { ERR(fp->handle, "truncated target type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_class = (uint16_t) val; if (key.target_class != val) { ERR(fp->handle, "truncated target class"); return -1; } val = le32_to_cpu(buf32[items++]); enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { ERR(fp->handle, "null entry"); return -1; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { ERR(fp->handle, "entry has both access " "vectors and types"); return -1; } for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (val & spec_order[i]) { key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); rc = insertf(a, &key, &datum, p); if (rc) return rc; } } if (items != items2) { ERR(fp->handle, "entry only had %d items, " "expected %d", items2, items); return -1; } return 0; } rc = next_entry(buf16, fp, sizeof(uint16_t) * 4); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; key.source_type = le16_to_cpu(buf16[items++]); key.target_type = le16_to_cpu(buf16[items++]); key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); set = 0; for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (key.specified & spec_order[i]) set++; } if (!set || set > 1) { ERR(fp->handle, "more than one specifier"); return -1; } if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && (key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "policy version %u does not support extended " "permissions rules and one was specified\n", vers); return -1; } else if (key.specified & AVTAB_XPERMS) { rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.specified = buf8; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.driver = buf8; rc = next_entry(buf32, fp, sizeof(uint32_t)*8); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } for (i = 0; i < ARRAY_SIZE(xperms.perms); i++) xperms.perms[i] = le32_to_cpu(buf32[i]); datum.xperms = &xperms; } else { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } datum.data = le32_to_cpu(*buf32); } return insertf(a, &key, &datum, p); }