diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index ac5cdddfbf783a659fbefb8b39fa2fff2cf679d8..86ccb8715bd9de04fc94b0a71e03f5a961d3b31e 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -29,6 +29,18 @@ static u32 hashtab_compute_size(u32 nel) return nel == 0 ? 0 : roundup_pow_of_two(nel); } +static bool is_order_out_of_range(u32 size, struct hashtab *h) +{ + size_t bytes; + u32 order; + + if (unlikely(check_mul_overflow(size, sizeof(*h->htable), &bytes))) + return true; + + order = get_order(bytes); + return order > MAX_ORDER; +} + int hashtab_init(struct hashtab *h, u32 nel_hint) { u32 size = hashtab_compute_size(nel_hint); @@ -39,6 +51,9 @@ int hashtab_init(struct hashtab *h, u32 nel_hint) h->htable = NULL; if (size) { + if (is_order_out_of_range(size, h)) + return -ENOMEM; + h->htable = kcalloc(size, sizeof(*h->htable), GFP_KERNEL); if (!h->htable) return -ENOMEM;