summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasily Averin <vvs@virtuozzo.com>2020-12-20 13:17:01 +0100
committerJozsef Kadlecsik <kadlec@netfilter.org>2020-12-20 13:17:01 +0100
commite2ae0d23953c4e04a38f9848eed84529a401b02e (patch)
tree132ffdf1f7cdb1fbedce1879b410e2bb8d07752d
parentb8d8272491282741797ef7eceec366451713655e (diff)
netfilter: ipset: fixes possible oops in mtype_resize
currently mtype_resize() can cause oops t = ip_set_alloc(htable_size(htable_bits)); if (!t) { ret = -ENOMEM; goto out; } t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits)); Increased htable_bits can force htable_size() to return 0. In own turn ip_set_alloc(0) returns not 0 but ZERO_SIZE_PTR, so follwoing access to t->hregion should trigger an OOPS. Signed-off-by: Vasily Averin <vvs@virtuozzo.com> Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_gen.h26
1 files changed, 17 insertions, 9 deletions
diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h
index acfe0c8..4a4062e 100644
--- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h
@@ -149,6 +149,10 @@ htable_bits(u32 hashsize)
/* Assume that hashsize == 2^htable_bits */
u8 bits = fls(hashsize - 1);
+ /* We must fit both into u32 in jhash and size_t */
+ if (bits >= 31)
+ return 31;
+
if (jhash_size(bits) != hashsize)
/* Round up to the first 2^n value */
bits = fls(hashsize);
@@ -640,7 +644,7 @@ mtype_resize(struct ip_set *set, bool retried)
struct htype *h = set->data;
struct htable *t, *orig;
u8 htable_bits;
- size_t dsize = set->dsize;
+ size_t hsize, dsize = set->dsize;
#ifdef IP_SET_HASH_WITH_NETS
u8 flags;
struct mtype_elem *tmp;
@@ -664,14 +668,12 @@ mtype_resize(struct ip_set *set, bool retried)
retry:
ret = 0;
htable_bits++;
- if (!htable_bits) {
- /* In case we have plenty of memory :-) */
- pr_warn("Cannot increase the hashsize of set %s further\n",
- set->name);
- ret = -IPSET_ERR_HASH_FULL;
- goto out;
- }
- t = ip_set_alloc(htable_size(htable_bits));
+ if (!htable_bits)
+ goto hbwarn;
+ hsize = htable_size(htable_bits);
+ if (!hsize)
+ goto hbwarn;
+ t = ip_set_alloc(hsize);
if (!t) {
ret = -ENOMEM;
goto out;
@@ -813,6 +815,12 @@ cleanup:
if (ret == -EAGAIN)
goto retry;
goto out;
+
+hbwarn:
+ /* In case we have plenty of memory :-) */
+ pr_warn("Cannot increase the hashsize of set %s further\n", set->name);
+ ret = -IPSET_ERR_HASH_FULL;
+ goto out;
}
/* Get the current number of elements and ext_size in the set */