diff --git a/libsepol/src/hashtab.c b/libsepol/src/hashtab.c index 21143b7699..ff7ef63fcd 100644 --- a/libsepol/src/hashtab.c +++ b/libsepol/src/hashtab.c @@ -223,7 +223,7 @@ int hashtab_map(hashtab_t h, hashtab_datum_t d, void *args), void *args) { unsigned int i, ret; - hashtab_ptr_t cur; + hashtab_ptr_t cur, next; if (!h) return SEPOL_OK; @@ -231,10 +231,11 @@ int hashtab_map(hashtab_t h, for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { + next = cur->next; ret = apply(cur->key, cur->datum, args); if (ret) return ret; - cur = cur->next; + cur = next; } } return SEPOL_OK; diff --git a/libsepol/src/write.c b/libsepol/src/write.c index 84bcaf3f57..6a59a0c34b 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -2143,29 +2143,70 @@ static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) return rc; } -static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), - hashtab_datum_t datum, void *args) +static void role_write_destroy(hashtab_key_t key __attribute__ ((unused)), + hashtab_datum_t datum, + void *p __attribute__ ((unused))) { - type_datum_t *typdatum = datum; - uint32_t *p_nel = args; + role_datum_destroy((role_datum_t *) datum); + free(datum); +} + +static void type_write_destroy(hashtab_key_t key __attribute__ ((unused)), + hashtab_datum_t datum, + void *p __attribute__ ((unused))) +{ + type_datum_destroy((type_datum_t *) datum); + free(datum); +} + +static void scope_write_destroy(hashtab_key_t key __attribute__ ((unused)), + hashtab_datum_t datum, + void *p __attribute__ ((unused))) +{ + scope_datum_t *cur = (scope_datum_t *) datum; + if (cur != NULL) { + free(cur->decl_ids); + } + free(cur); +} + +static int type_attr_filter(hashtab_key_t key, + hashtab_datum_t datum, void *args) +{ + type_datum_t *typdatum = datum; + scope_datum_t *scope = NULL; + policydb_t *p = (policydb_t *)args; + hashtab_t typetbl = p->symtab[SYM_TYPES].table; + hashtab_t scopetbl = p->scope[SYM_TYPES].table; + + if (typdatum->flavor == TYPE_ATTRIB) { + /* Remove the entry from the hash table and scope table */ + hashtab_remove(typetbl, key, type_write_destroy, typdatum); + scope = (scope_datum_t *)hashtab_search(scopetbl, key); + if (scope) + hashtab_remove(scopetbl, key, scope_write_destroy, scope); + } - if (typdatum->flavor == TYPE_ATTRIB) { - /* uncount attribute from total number of types */ - (*p_nel)--; - } return 0; } -static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)), - hashtab_datum_t datum, void *args) +static int role_attr_filter(hashtab_key_t key, + hashtab_datum_t datum, void *args) { - role_datum_t *role = datum; - uint32_t *p_nel = args; + role_datum_t *role = datum; + scope_datum_t *scope = NULL; + policydb_t *p = (policydb_t *)args; + hashtab_t roletbl = p->symtab[SYM_ROLES].table; + hashtab_t scopetbl = p->scope[SYM_ROLES].table; + + if (role->flavor == ROLE_ATTRIB) { + /* Remove the entry from the hash table and scope table */ + hashtab_remove(roletbl, key, role_write_destroy, role); + scope = (scope_datum_t *)hashtab_search(scopetbl, key); + if (scope) + hashtab_remove(scopetbl, key, scope_write_destroy, scope); + } - if (role->flavor == ROLE_ATTRIB) { - /* uncount attribute from total number of roles */ - (*p_nel)--; - } return 0; } @@ -2301,28 +2342,35 @@ int policydb_write(policydb_t * p, struct policy_file *fp) buf[1] = p->symtab[i].table->nel; /* - * A special case when writing type/attribute symbol table. - * The kernel policy version less than 24 does not support - * to load entries of attribute, so we have to re-calculate - * the actual number of types except for attributes. - */ + * A special case when writing type/attribute symbol table. + * The kernel policy version less than 24 does not support + * to load entries of attribute, so we filter the entries + * from the table. + */ if (i == SYM_TYPES && - p->policyvers < POLICYDB_VERSION_BOUNDARY && - p->policy_type == POLICY_KERN) { - hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]); + p->policyvers < POLICYDB_VERSION_BOUNDARY && + p->policy_type == POLICY_KERN) { + (void)hashtab_map(p->symtab[i].table, type_attr_filter, p); + if (buf[1] != p->symtab[i].table->nel) + WARN(fp->handle, "Discarding type attribute rules"); + buf[1] = p->symtab[i].table->nel; } - /* - * Another special case when writing role/attribute symbol - * table, role attributes are redundant for policy.X, or - * when the pp's version is not big enough. So deduct - * their numbers from p_roles.table->nel. - */ + /* + * Another special case when writing role/attribute symbol + * table, role attributes are redundant for policy.X, or + * when the pp's version is not big enough. So filter the entries + * from the table. + */ if ((i == SYM_ROLES) && - ((p->policy_type == POLICY_KERN) || - (p->policy_type != POLICY_KERN && - p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) - (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]); + ((p->policy_type == POLICY_KERN) || + (p->policy_type != POLICY_KERN && + p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) { + (void)hashtab_map(p->symtab[i].table, role_attr_filter, p); + if (buf[1] != p->symtab[i].table->nel) + WARN(fp->handle, "Discarding role attribute rules"); + buf[1] = p->symtab[i].table->nel; + } buf[1] = cpu_to_le32(buf[1]); items = put_entry(buf, sizeof(uint32_t), 2, fp);