>> Hmm.... >> It seems to me what you pointed out is a bug of my patch. It prevents to deliver >> actual number of type/attribute symbols to policy file, but it is unclear why does >> it makes libsepol ignore the policyvers. >> (I guess it may be a separated matter.) >> >>> Rather than trying to calculate the length without attributes I just removed >>> the attribute check. This causes attributes to be written for all versions, >>> but this should not cause any problems at all. >> The reason why I injected such an ad-hoc code is that we cannot decide the policy >> version written when type_attr_remove() is invoked. >> Is it impossible to move it to policydb_write()? >> It is invoked after the policyvers is fixed by caller. > > It isn't impossible. You are going to have to make it walk to type > symbol table to calculate the length without attributes, then write > that length instead of the total symtab length. The attached patch enables to fixup the number of type/attribute entries to be written. The type_attr_uncount() decrements the number of attribute entries skipped at type_write(). At first, I had a plan to invoke type_attr_remove() with hashtab_map_remove_on_error(), but it means the given policydb structure is modified at policydb_write() and implicit changes to external interface. Differences from the previous version are here: $ diff -NU3 thread-context-libsepol.6.patch thread-context-libsepol.7.patch --- thread-context-libsepol.6.patch 2008-09-09 10:24:41.000000000 +0900 +++ thread-context-libsepol.7.patch 2008-10-07 14:50:32.000000000 +0900 @@ -1086,6 +1086,45 @@ items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; +@@ -1515,6 +1551,19 @@ + return POLICYDB_SUCCESS; + } + ++static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), ++ hashtab_datum_t datum, void *args) ++{ ++ type_datum_t *typdatum = datum; ++ uint32_t *p_nel = args; ++ ++ if (typdatum->flavor == TYPE_ATTRIB) { ++ /* uncount attribute from total number of types */ ++ (*p_nel)--; ++ } ++ return 0; ++} ++ + /* + * Write the configuration data in a policy database + * structure to a policy database binary representation +@@ -1646,6 +1695,18 @@ + for (i = 0; i < num_syms; i++) { + buf[0] = cpu_to_le32(p->symtab[i].nprim); + buf[1] = cpu_to_le32(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. ++ */ ++ 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]); ++ } + items = put_entry(buf, sizeof(uint32_t), 2, fp); + if (items != 2) + return POLICYDB_ERROR; Index: libsepol/src/link.c =================================================================== --- libsepol/src/link.c (revision 2950) -- OSS Platform Development Division, NEC KaiGai Kohei