diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h index 83ff54c23f..9aa81a8c2e 100644 --- a/libsepol/include/sepol/policydb/ebitmap.h +++ b/libsepol/include/sepol/policydb/ebitmap.h @@ -104,6 +104,7 @@ extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e); extern void ebitmap_destroy(ebitmap_t * e); extern int ebitmap_read(ebitmap_t * e, void *fp); +extern int ebitmap_read_bounded(ebitmap_t * e, uint32_t bound, void *fp); #ifdef __cplusplus } diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c index bd98c0f8cb..d5f2b64694 100644 --- a/libsepol/src/ebitmap.c +++ b/libsepol/src/ebitmap.c @@ -493,4 +493,37 @@ int ebitmap_read(ebitmap_t * e, void *fp) goto out; } +int ebitmap_read_bounded(ebitmap_t * e, uint32_t bound, void *fp) +{ + int rc; + struct ebitmap_node *n; + unsigned int bit; + + rc = ebitmap_read(e, fp); + if (rc < 0) + return rc; + + /* Go to the last node, to compare its bits with bound */ + n = e->node; + if (!n) + return 0; + while (n->next) { + n = n->next; + } + if (n->startbit + MAPSIZE <= bound) { + /* All bits are below the bound. No overflow is possible */ + return 0; + } + /* There may be bits enabled over the bound */ + for (bit = 0; bit < MAPSIZE; bit++) { + if (n->startbit + bit >= bound && (n->map & (MAPBIT << bit ))) { + printf + ("security: ebitmap: bitmap bit %u over the bound %u\n", + n->startbit + bit, bound); + ebitmap_destroy(e); + return -EINVAL; + } + } + return 0; +} /* FLASK */ diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index a59543273a..45536f543e 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -3979,7 +3979,7 @@ static int range_trans_rule_read(range_trans_rule_t ** r, return 0; } -static int scope_index_read(scope_index_t * scope_index, +static int scope_index_read(policydb_t * p, scope_index_t * scope_index, unsigned int num_scope_syms, struct policy_file *fp) { unsigned int i; @@ -3987,7 +3987,7 @@ static int scope_index_read(scope_index_t * scope_index, int rc; for (i = 0; i < num_scope_syms; i++) { - if (ebitmap_read(scope_index->scope + i, fp) < 0) { + if (ebitmap_read_bounded(scope_index->scope + i, p->symtab[i].nprim, fp) < 0) { return -1; } } @@ -4041,8 +4041,8 @@ static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl, range_trans_rule_read(&decl->range_tr_rules, fp) == -1) { return -1; } - if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 || - scope_index_read(&decl->declared, num_scope_syms, fp) == -1) { + if (scope_index_read(p, &decl->required, num_scope_syms, fp) == -1 || + scope_index_read(p, &decl->declared, num_scope_syms, fp) == -1) { return -1; }