diff options
| author | Christian Göttsche <cgzones@googlemail.com> | 2025-05-11 19:30:07 +0200 |
|---|---|---|
| committer | Paul Moore <paul@paul-moore.com> | 2026-05-06 19:43:19 -0400 |
| commit | 259915b053b88bae525024f85f36e49c1f903a4b (patch) | |
| tree | 1b7e9d3ca14726b791974b101f4b6a167c5e7270 /security | |
| parent | 9f515660c8297246c4e3565c814ccd16368d74e9 (diff) | |
| download | linux-next-history-259915b053b88bae525024f85f36e49c1f903a4b.tar.gz | |
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 <cgzones@googlemail.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
[PM: changed name to ebitmap_get_highest_set_bit()]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security')
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 27 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.h | 1 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 5 |
3 files changed, 33 insertions, 0 deletions
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) |
