From 9d211d74380cbf796e10f1bc2af141270aad9e63 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Sat, 13 Jun 2015 21:26:14 +0200 Subject: Fix error path in mtype_resize() when new hash bucket cannot be allocated Signed-off-by: Jozsef Kadlecsik --- kernel/net/netfilter/ipset/ip_set_hash_gen.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'kernel/net/netfilter') diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h index 4094065..f8e82c2 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h @@ -595,6 +595,7 @@ retry: spin_lock_bh(&set->lock); orig = __ipset_dereference_protected(h->table, 1); + /* There can't be another parallel resizing, but dumping is possible */ atomic_set(&orig->ref, 1); atomic_inc(&orig->uref); pr_debug("attempt to resize set %s from %u to %u, t %p\n", @@ -622,8 +623,10 @@ retry: m = kzalloc(sizeof(*m) + AHASH_INIT_SIZE * dsize, GFP_ATOMIC); - if (!m) + if (!m) { ret = -ENOMEM; + goto cleanup; + } m->size = AHASH_INIT_SIZE; RCU_INIT_POINTER(hbucket(t, key), m); } else if (m->pos >= m->size) { @@ -639,15 +642,8 @@ retry: if (!ht) ret = -ENOMEM; } - if (ret < 0) { - atomic_set(&orig->ref, 0); - atomic_dec(&orig->uref); - spin_unlock_bh(&set->lock); - mtype_ahash_destroy(set, t, false); - if (ret == -EAGAIN) - goto retry; - goto out; - } + if (ret < 0) + goto cleanup; memcpy(ht, m, sizeof(struct hbucket) + m->size * dsize); ht->size = m->size + AHASH_INIT_SIZE; @@ -683,6 +679,15 @@ out: kfree(tmp); #endif return ret; + +cleanup: + atomic_set(&orig->ref, 0); + atomic_dec(&orig->uref); + spin_unlock_bh(&set->lock); + mtype_ahash_destroy(set, t, false); + if (ret == -EAGAIN) + goto retry; + goto out; } /* Add an element to a hash and update the internal counters when succeeded, -- cgit v1.2.3