libsepol: reject avtab entries with invalid specifier

Neverallow avtab entries are not supported (normal and extended). Reject
them to avoid lookup confusions via avtab_search(), e.g. when searching
for a invalid key of AVTAB_TRANSITION|AVTAB_NEVERALLOW and the result of
only AVTAB_NEVERALLOW has no transition value.

Simplify the check for the number of specifiers by using the compiler
popcount builtin (already used in libsepol).

Reported-by: oss-fuzz (issue 60568), caused at the time by the filetrans
             prefix proposal
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
Christian Göttsche 2023-11-01 17:37:24 +01:00 committed by James Carter
parent 84e0884260
commit b1b3467a47
1 changed files with 6 additions and 7 deletions

View File

@ -441,7 +441,6 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
avtab_key_t key;
avtab_datum_t datum;
avtab_extended_perms_t xperms;
unsigned set;
unsigned int i;
int rc;
@ -535,13 +534,13 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
key.target_class = le16_to_cpu(buf16[items++]);
key.specified = le16_to_cpu(buf16[items++]);
set = 0;
for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
if (key.specified & spec_order[i])
set++;
if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) {
ERR(fp->handle, "invalid specifier");
return -1;
}
if (!set || set > 1) {
ERR(fp->handle, "more than one specifier");
if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) {
ERR(fp->handle, "not exactly one specifier");
return -1;
}