]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
segtree: add missing non-matching segment to set in flat representation
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 5 Mar 2019 23:51:03 +0000 (00:51 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 6 Mar 2019 10:12:41 +0000 (11:12 +0100)
 # cat test.nft
 add set x y { type ipv4_addr; }
 add element x y { 10.0.24.0/24 }
 # nft -f test.nft
 # nft delete element x y { 10.0.24.0/24 }

bogusly returns -ENOENT. The non-matching segment (0.0.0.0 with end-flag
set on) is not added to the set in the example above.

This patch also adds a test to cover this case.

Fixes: 4935a0d561b5 ("segtree: special handling for the first non-matching segment")
Reported-by: Václav Zindulka <vaclav.zindulka@tlapnet.cz>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/segtree.c
tests/shell/testcases/sets/0035add_set_elements_flat_0 [new file with mode: 0755]

index 939c30d2c83fbd9c18a005831b56b7f71b772f3c..6ee655238b7dba48a44061137a65ac9364625e22 100644 (file)
@@ -431,16 +431,19 @@ static bool segtree_needs_first_segment(const struct set *set,
                                        const struct expr *init, bool add)
 {
        if (add) {
-               /* Add the first segment in three situations:
+               /* Add the first segment in four situations:
                 *
                 * 1) This is an anonymous set.
                 * 2) This set exists and it is empty.
-                * 3) This set is created with a number of initial elements.
+                * 3) New empty set and, separately, new elements are added.
+                * 4) This set is created with a number of initial elements.
                 */
                if ((set->flags & NFT_SET_ANONYMOUS) ||
                    (set->init && set->init->size == 0) ||
-                   (set->init == init))
+                   (set->init == NULL && init) ||
+                   (set->init == init)) {
                        return true;
+               }
        } else {
                /* If the set is empty after the removal, we have to
                 * remove the first non-matching segment too.
diff --git a/tests/shell/testcases/sets/0035add_set_elements_flat_0 b/tests/shell/testcases/sets/0035add_set_elements_flat_0
new file mode 100755 (executable)
index 0000000..d914ba9
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+RULESET="add table ip x
+add set x y {type ipv4_addr; flags interval;}
+add element x y { 10.0.24.0/24 }
+"
+
+set -e
+$NFT -f - <<< "$RULESET"
+$NFT delete element x y { 10.0.24.0/24 }