aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-06-20 18:12:26 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-06-24 05:03:27 -0400
commit8eee54be73f4b938dbf48e95c0dbecb5f19b08ee (patch)
tree7e7be64d7f5e73d182327df710430ec37e5ee18b /net/netfilter
parent4e5001651f5e488eac378ebabc5bde2a8f1ea861 (diff)
netfilter: nft_hash: support deletion of inactive elements
New elements are inactive in the preparation phase, and its NFT_SET_ELEM_BUSY_MASK flag is set on. This busy flag doesn't allow us to delete it from the same transaction, following a sequence like: begin transaction add element X delete element X end transaction This sequence is valid and may be triggered by robots. To resolve this problem, allow deactivating elements that are active in the current generation (ie. those that has been just added in this batch). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nft_hash.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 6fa016564f90..d3a507d3f192 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -153,9 +153,10 @@ static void *nft_hash_deactivate(const struct nft_set *set,
153 const struct nft_set_elem *elem) 153 const struct nft_set_elem *elem)
154{ 154{
155 struct nft_hash *priv = nft_set_priv(set); 155 struct nft_hash *priv = nft_set_priv(set);
156 struct net *net = read_pnet(&set->pnet);
156 struct nft_hash_elem *he; 157 struct nft_hash_elem *he;
157 struct nft_hash_cmp_arg arg = { 158 struct nft_hash_cmp_arg arg = {
158 .genmask = nft_genmask_next(read_pnet(&set->pnet)), 159 .genmask = nft_genmask_next(net),
159 .set = set, 160 .set = set,
160 .key = elem->key.val.data, 161 .key = elem->key.val.data,
161 }; 162 };
@@ -163,7 +164,8 @@ static void *nft_hash_deactivate(const struct nft_set *set,
163 rcu_read_lock(); 164 rcu_read_lock();
164 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 165 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
165 if (he != NULL) { 166 if (he != NULL) {
166 if (!nft_set_elem_mark_busy(&he->ext)) 167 if (!nft_set_elem_mark_busy(&he->ext) ||
168 !nft_is_active(net, &he->ext))
167 nft_set_elem_change_active(set, &he->ext); 169 nft_set_elem_change_active(set, &he->ext);
168 else 170 else
169 he = NULL; 171 he = NULL;