Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dab45060 authored by Liping Zhang's avatar Liping Zhang Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: fix race when create new element in dynset



Packets may race when create the new element in nft_hash_update:
       CPU0                 CPU1
  lookup_fast - fail     lookup_fast - fail
       new - ok             new - ok
     insert - ok         insert - fail(EEXIST)

So when race happened, we reuse the existing element. Otherwise,
these *racing* packets will not be handled properly.

Fixes: 22fe54d5 ("netfilter: nf_tables: add support for dynamic set updates")
Signed-off-by: default avatarLiping Zhang <zlpnobody@gmail.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 61f9e292
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ static bool nft_hash_update(struct nft_set *set, const u32 *key,
			    const struct nft_set_ext **ext)
{
	struct nft_hash *priv = nft_set_priv(set);
	struct nft_hash_elem *he;
	struct nft_hash_elem *he, *prev;
	struct nft_hash_cmp_arg arg = {
		.genmask = NFT_GENMASK_ANY,
		.set	 = set,
@@ -112,9 +112,18 @@ static bool nft_hash_update(struct nft_set *set, const u32 *key,
	he = new(set, expr, regs);
	if (he == NULL)
		goto err1;
	if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node,
					 nft_hash_params))

	prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node,
						nft_hash_params);
	if (IS_ERR(prev))
		goto err2;

	/* Another cpu may race to insert the element with the same key */
	if (prev) {
		nft_set_elem_destroy(set, he, true);
		he = prev;
	}

out:
	*ext = &he->ext;
	return true;