diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index e8960a59586cb64e0d1bb8ba7175fa3016bfb8cc..91cfb07a3e51158725ecabf485f57c5cc33de947 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -28,6 +28,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 = 0; + u32 order; + + if (unlikely(check_mul_overflow((size_t)size, sizeof(*h->htable), &bytes))) + return true; + + order = (u32)get_order(bytes); + return order >= MAX_ORDER; +} + int hashtab_init(struct hashtab *h, u32 nel_hint) { u32 size = hashtab_compute_size(nel_hint); @@ -38,6 +50,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;