Skip to content

Commit

Permalink
libsepol: validate access vector permissions
Browse files Browse the repository at this point in the history
Since commit c205b92 ("libsepol: Fix buffer overflow when using
sepol_av_to_string()") writing an access vector with no valid permission
results in an error instead of an empty string being written.

Validate that at least one permission of an access vector is valid.
There might be invalid bits set, e.g. by previous versions of
checkpolicy setting all bits for the wildcard (*) permission.

Reported-by: oss-fuzz (issue 67730)
Signed-off-by: Christian Göttsche <[email protected]>
Acked-by: James Carter <[email protected]>
  • Loading branch information
cgzones authored and jwcart2 committed Apr 4, 2024
1 parent f07fc2a commit 8c64e5b
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions libsepol/src/policydb_validate.c
Expand Up @@ -876,13 +876,66 @@ static int validate_xperms(const avtab_extended_perms_t *xperms)
bad:
return -1;
}

static int perm_match(__attribute__ ((unused)) hashtab_key_t key, hashtab_datum_t datum, void *data)
{
const uint32_t *v = data;
const perm_datum_t *perdatum = datum;

return *v == perdatum->s.value;
}

static int validate_access_vector(sepol_handle_t *handle, const policydb_t *p, sepol_security_class_t tclass,
sepol_access_vector_t av)
{
const class_datum_t *cladatum = p->class_val_to_struct[tclass - 1];
uint32_t i;

/*
* Check that at least one permission bit is valid.
* Older compilers might set invalid bits for the wildcard permission.
*/
for (i = 0; i < cladatum->permissions.nprim; i++) {
if (av & (UINT32_C(1) << i)) {
uint32_t v = i + 1;
int rc;

rc = hashtab_map(cladatum->permissions.table, perm_match, &v);
if (rc == 1)
goto good;

if (cladatum->comdatum) {
rc = hashtab_map(cladatum->comdatum->permissions.table, perm_match, &v);
if (rc == 1)
goto good;
}
}
}

ERR(handle, "Invalid access vector");
return -1;

good:
return 0;
}

static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args)
{
map_arg_t *margs = args;

if (validate_avtab_key(k, 0, margs->policy, margs->flavors))
return -1;

if (k->specified & AVTAB_AV) {
uint32_t data = d->data;

if ((0xFFF & k->specified) == AVTAB_AUDITDENY)
data = ~data;

if (validate_access_vector(margs->handle, margs->policy, k->target_class, data))
return -1;
}

if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors))
return -1;

Expand Down Expand Up @@ -915,6 +968,15 @@ static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *c

if (validate_avtab_key(key, 1, p, flavors))
goto bad;
if (key->specified & AVTAB_AV) {
uint32_t data = datum->data;

if ((0xFFF & key->specified) == AVTAB_AUDITDENY)
data = ~data;

if (validate_access_vector(handle, p, key->target_class, data))
goto bad;
}
if ((key->specified & AVTAB_TYPE) && validate_simpletype(datum->data, p, flavors))
goto bad;
}
Expand Down

0 comments on commit 8c64e5b

Please sign in to comment.