Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug in Checkmodule when downwriting to Module version 12 or lower. #273

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions libsepol/src/hashtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,19 @@ 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;

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;
Expand Down
116 changes: 82 additions & 34 deletions libsepol/src/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down