Skip to content

Commit ee4e1ed

Browse files
author
Matthew Ife
committed
Fix bug in policydb_write when attempting to correct policy for older versions.
The current implementation fails as it doesn't remove scope declarations further in the modular policy. This fixes the problem by removing the offending entries in the hash table and the scope table. Steps to reproduce: Try to build the following module then make a module from an older release: module test 1.0.0; require { type default_t; } attribute_role new_atrole; checkmodule -M -m -c 12 -o test.mod test.te semodule_package -o test.pp -m test.mod semodule_package: Error while reading policy module from test.mod Failure occurs when the current module gets written out with the scope declaration intact. This is due to policydb.c:3913 doing a hashtab search on a scope key that is not in the symbol table. Signed-off-by: Matthew Ife <[email protected]>
1 parent fadcc83 commit ee4e1ed

File tree

2 files changed

+89
-44
lines changed

2 files changed

+89
-44
lines changed

libsepol/src/hashtab.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,19 @@ int hashtab_map(hashtab_t h,
223223
hashtab_datum_t d, void *args), void *args)
224224
{
225225
unsigned int i, ret;
226-
hashtab_ptr_t cur;
226+
hashtab_ptr_t cur, next;
227227

228228
if (!h)
229229
return SEPOL_OK;
230230

231231
for (i = 0; i < h->size; i++) {
232232
cur = h->htable[i];
233-
while (cur != NULL) {
233+
while (curi != NULL) {
234+
next = cur->next;
234235
ret = apply(cur->key, cur->datum, args);
235236
if (ret)
236237
return ret;
237-
cur = cur->next;
238+
cur = next;
238239
}
239240
}
240241
return SEPOL_OK;

libsepol/src/write.c

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,30 +2143,67 @@ static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
21432143
return rc;
21442144
}
21452145

2146-
static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2147-
hashtab_datum_t datum, void *args)
2146+
static void role_write_destroy(hashtab_key_t key __attribute__ ((unused)),
2147+
hashtab_datum_t datum,
2148+
void *p __attribute__ ((unused)))
21482149
{
2149-
type_datum_t *typdatum = datum;
2150-
uint32_t *p_nel = args;
2150+
role_datum_destroy((role_datum_t *) datum);
2151+
free(datum);
2152+
}
21512153

2152-
if (typdatum->flavor == TYPE_ATTRIB) {
2153-
/* uncount attribute from total number of types */
2154-
(*p_nel)--;
2155-
}
2156-
return 0;
2154+
static void type_write_destroy(hashtab_key_t key __attribute__ ((unused)),
2155+
hashtab_datum_t datum,
2156+
void *p __attribute__ ((unused)))
2157+
{
2158+
type_datum_destroy((type_datum_t *) datum);
2159+
free(datum);
21572160
}
21582161

2159-
static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2160-
hashtab_datum_t datum, void *args)
2162+
static void scope_write_destroy(hashtab_key_t key __attribute__ ((unused)),
2163+
hashtab_datum_t datum,
2164+
void *p __attribute__ ((unused)))
21612165
{
2162-
role_datum_t *role = datum;
2163-
uint32_t *p_nel = args;
2166+
scope_datum_t *cur = (scope_datum_t *) datum;
2167+
if (cur != NULL) {
2168+
free(cur->decl_ids);
2169+
}
2170+
free(cur);
2171+
}
21642172

2165-
if (role->flavor == ROLE_ATTRIB) {
2166-
/* uncount attribute from total number of roles */
2167-
(*p_nel)--;
2168-
}
2169-
return 0;
2173+
static void type_attr_filter(hashtab_key_t key,
2174+
hashtab_datum_t datum, void *args)
2175+
{
2176+
type_datum_t *typdatum = datum;
2177+
scope_datum_t *scope = NULL;
2178+
policydb_t *p = (policydb_t *)args;
2179+
hashtab_t typetbl = p->symtab[SYM_TYPES].table;
2180+
hashtab_t scopetbl = p->scope[SYM_TYPES].table;
2181+
2182+
if (typdatum->flavor == TYPE_ATTRIB) {
2183+
/* Remove the entry from the hash table and scope table */
2184+
hashtab_remove(typetbl, key, type_write_destroy, typdatum);
2185+
scope = (scope_datum_t *)hashtab_search(scopetbl, key);
2186+
if (scope)
2187+
hashtab_remove(scopetbl, key, scope_write_destroy, scope);
2188+
}
2189+
}
2190+
2191+
static void role_attr_filter(hashtab_key_t key,
2192+
hashtab_datum_t datum, void *args)
2193+
{
2194+
role_datum_t *role = datum;
2195+
scope_datum_t *scope = NULL;
2196+
policydb_t *p = (policydb_t *)args;
2197+
hashtab_t roletbl = p->symtab[SYM_ROLES].table;
2198+
hashtab_t scopetbl = p->scope[SYM_ROLES].table;
2199+
2200+
if (role->flavor == ROLE_ATTRIB) {
2201+
/* Remove the entry from the hash table and scope table */
2202+
hashtab_remove(roletbl, key, role_write_destroy, role);
2203+
scope = (scope_datum_t *)hashtab_search(scopetbl, key);
2204+
if (scope)
2205+
hashtab_remove(scopetbl, key, scope_write_destroy, scope);
2206+
}
21702207
}
21712208

21722209
/*
@@ -2300,29 +2337,36 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
23002337
buf[0] = cpu_to_le32(p->symtab[i].nprim);
23012338
buf[1] = p->symtab[i].table->nel;
23022339

2303-
/*
2304-
* A special case when writing type/attribute symbol table.
2305-
* The kernel policy version less than 24 does not support
2306-
* to load entries of attribute, so we have to re-calculate
2307-
* the actual number of types except for attributes.
2308-
*/
2309-
if (i == SYM_TYPES &&
2310-
p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2311-
p->policy_type == POLICY_KERN) {
2312-
hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2313-
}
2314-
2315-
/*
2316-
* Another special case when writing role/attribute symbol
2317-
* table, role attributes are redundant for policy.X, or
2318-
* when the pp's version is not big enough. So deduct
2319-
* their numbers from p_roles.table->nel.
2320-
*/
2321-
if ((i == SYM_ROLES) &&
2322-
((p->policy_type == POLICY_KERN) ||
2323-
(p->policy_type != POLICY_KERN &&
2324-
p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2325-
(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2340+
/*
2341+
* A special case when writing type/attribute symbol table.
2342+
* The kernel policy version less than 24 does not support
2343+
* to load entries of attribute, so we filter the entries
2344+
* from the table.
2345+
*/
2346+
if (i == SYM_TYPES &&
2347+
p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2348+
p->policy_type == POLICY_KERN) {
2349+
(void)hashtab_map(p->symtab[i].table, type_attr_filter, p);
2350+
if (buf[1] != p->symtab[i].table->nel)
2351+
WARN(fp->handle, "Discarding type attribute rules");
2352+
buf[1] = p->symtab[i].table->nel;
2353+
}
2354+
2355+
/*
2356+
* Another special case when writing role/attribute symbol
2357+
* table, role attributes are redundant for policy.X, or
2358+
* when the pp's version is not big enough. So filter the entries
2359+
* from the table.
2360+
*/
2361+
if ((i == SYM_ROLES) &&
2362+
((p->policy_type == POLICY_KERN) ||
2363+
(p->policy_type != POLICY_KERN &&
2364+
p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) {
2365+
(void)hashtab_map(p->symtab[i].table, role_attr_filter, p);
2366+
if (buf[1] != p->symtab[i].table->nel)
2367+
WARN(fp->handle, "Discarding role attribute rules");
2368+
buf[1] = p->symtab[i].table->nel;
2369+
}
23262370

23272371
buf[1] = cpu_to_le32(buf[1]);
23282372
items = put_entry(buf, sizeof(uint32_t), 2, fp);

0 commit comments

Comments
 (0)