]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: perform mark datatype compatibility check from maps
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 18 Sep 2023 13:08:28 +0000 (15:08 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Jan 2025 23:05:48 +0000 (00:05 +0100)
commit 7b491e0c068c9881accfb571db3fb8f2f5799ca2 upstream.

Wrap datatype compatibility check into a helper function and use it for
map evaluation, otherwise the following bogus error message is
displayed:

  Error: datatype mismatch, map expects packet mark, mapping expression has type integer

Add unit tests to improve coverage for this usecase.

Fixes: 5d8e33ddb112 ("evaluate: relax type-checking for integer arguments in mark statements")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/vmap_mark_bitwise_0 [new file with mode: 0755]

index 3724509ee9bd13e7cdd47392239d7dca34beb919..f307b5975f047f24d393c97759ec5c181acdd2be 100644 (file)
@@ -1769,6 +1769,13 @@ static int mapping_expr_expand(struct eval_ctx *ctx)
        return 0;
 }
 
+static bool datatype_compatible(const struct datatype *a, const struct datatype *b)
+{
+       return (a->type == TYPE_MARK &&
+               datatype_equal(datatype_basetype(a), datatype_basetype(b))) ||
+               datatype_equal(a, b);
+}
+
 static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
 {
        struct expr *map = *expr, *mappings;
@@ -1880,7 +1887,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
                                         "invalid mapping expression %s", expr_name(map->mappings));
        }
 
-       if (!datatype_equal(map->map->dtype, map->mappings->set->key->dtype))
+       if (!datatype_compatible(map->mappings->set->key->dtype, map->map->dtype))
                return expr_binary_error(ctx->msgs, map->mappings, map->map,
                                         "datatype mismatch, map expects %s, "
                                         "mapping expression has type %s",
@@ -2732,11 +2739,7 @@ static int __stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
                                         dtype->desc, (*expr)->dtype->desc,
                                         (*expr)->len);
 
-       if ((dtype->type == TYPE_MARK &&
-            !datatype_equal(datatype_basetype(dtype), datatype_basetype((*expr)->dtype))) ||
-           (dtype->type != TYPE_MARK &&
-            (*expr)->dtype->type != TYPE_INTEGER &&
-            !datatype_equal((*expr)->dtype, dtype)))
+       if (!datatype_compatible(dtype, (*expr)->dtype))
                return stmt_binary_error(ctx, *expr, stmt,              /* verdict vs invalid? */
                                         "datatype mismatch: expected %s, "
                                         "expression has type %s",
@@ -4256,7 +4259,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
                    expr_name(map->mappings));
        }
 
-       if (!datatype_equal(map->map->dtype, map->mappings->set->key->dtype))
+       if (!datatype_compatible(map->mappings->set->key->dtype, map->map->dtype))
                return expr_binary_error(ctx->msgs, map->mappings, map->map,
                                         "datatype mismatch, map expects %s, "
                                         "mapping expression has type %s",
diff --git a/tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.nft b/tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.nft
new file mode 100644 (file)
index 0000000..beb5ffb
--- /dev/null
@@ -0,0 +1,26 @@
+table ip x {
+       counter c_o0_0 {
+               packets 0 bytes 0
+       }
+
+       map sctm_o0 {
+               type mark : verdict
+               elements = { 0x00000000 : jump sctm_o0_0, 0x00000001 : jump sctm_o0_1 }
+       }
+
+       map sctm_o1 {
+               type mark : counter
+               elements = { 0x00000000 : "c_o0_0" }
+       }
+
+       chain sctm_o0_0 {
+       }
+
+       chain sctm_o0_1 {
+       }
+
+       chain SET_ctmark_RPLYroute {
+               meta mark >> 8 & 0xf vmap @sctm_o0
+               counter name meta mark >> 8 & 0xf map @sctm_o1
+       }
+}
diff --git a/tests/shell/testcases/maps/vmap_mark_bitwise_0 b/tests/shell/testcases/maps/vmap_mark_bitwise_0
new file mode 100755 (executable)
index 0000000..0d93355
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+set -e
+
+RULESET="table ip x {
+       chain sctm_o0_0 {
+       }
+
+       chain sctm_o0_1 {
+       }
+
+       map sctm_o0 {
+               type mark : verdict
+               elements = {
+                       0x0 : jump sctm_o0_0,
+                       0x1 : jump sctm_o0_1,
+               }
+       }
+
+       counter c_o0_0 {}
+
+       map sctm_o1 {
+               type mark : counter
+               elements = {
+                       0x0 : \"c_o0_0\",
+               }
+       }
+
+       chain SET_ctmark_RPLYroute {
+               meta mark >> 8 & 0xf vmap @sctm_o0
+       }
+
+       chain SET_ctmark_RPLYroute {
+               counter name meta mark >> 8 & 0xf map @sctm_o1
+       }
+}"
+
+$NFT -f - <<< $RULESET