From: Christian Göttsche Date: Sun, 11 May 2025 17:30:07 +0000 (+0200) Subject: selinux: check type attr map overflows X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=259915b053b88bae525024f85f36e49c1f903a4b;p=thirdparty%2Fkernel%2Flinux.git selinux: check type attr map overflows Validate that no types with an invalid too high ID are present in the attribute map. Gaps are still not checked. Signed-off-by: Christian Göttsche Acked-by: Stephen Smalley [PM: changed name to ebitmap_get_highest_set_bit()] Signed-off-by: Paul Moore --- diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 43bc19e219609..ea894361fed64 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -257,6 +257,33 @@ int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, return 1; } +u32 ebitmap_get_highest_set_bit(const struct ebitmap *e) +{ + const struct ebitmap_node *n; + unsigned long unit; + u32 pos = 0; + + n = e->node; + if (!n) + return 0; + + while (n->next) + n = n->next; + + for (unsigned int i = EBITMAP_UNIT_NUMS; i > 0; i--) { + unit = n->maps[i - 1]; + if (unit == 0) + continue; + + pos = (i - 1) * EBITMAP_UNIT_SIZE; + while (unit >>= 1) + pos++; + break; + } + + return n->startbit + pos; +} + int ebitmap_get_bit(const struct ebitmap *e, u32 bit) { const struct ebitmap_node *n; diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index c9569998f287d..ae05cc8e46721 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -126,6 +126,7 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2); int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit); +u32 ebitmap_get_highest_set_bit(const struct ebitmap *e); int ebitmap_get_bit(const struct ebitmap *e, u32 bit); int ebitmap_set_bit(struct ebitmap *e, u32 bit, int value); void ebitmap_destroy(struct ebitmap *e); diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 39065418bed91..6bb66eda9fc01 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2900,6 +2900,11 @@ int policydb_read(struct policydb *p, struct policy_file *fp) if (rc) goto bad; } + + rc = -EINVAL; + if (ebitmap_get_highest_set_bit(e) >= p->p_types.nprim) + goto bad; + /* add the type itself as the degenerate case */ rc = ebitmap_set_bit(e, i, 1); if (rc)