]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: tunnel src/dst must be a symbolic expression
authorFlorian Westphal <fw@strlen.de>
Thu, 16 Oct 2025 14:59:34 +0000 (16:59 +0200)
committerFlorian Westphal <fw@strlen.de>
Fri, 17 Oct 2025 07:41:47 +0000 (09:41 +0200)
Included bogons crash with segfault and assertion.  After fix:

tunnel_with_garbage_dst:3:12-14: Error: syntax error, unexpected tcp, expecting string or quoted string or string with a trailing asterisk or '$'
  ip saddr tcp dport { }
           ^^^
The parser change restricts the grammar to no longer allow this,
we would crash here because we enter payload evaluation path that
tries to insert a dependency into the rule, but we don't have one
(ctx->rule and ctx->stmt are NULL as expected here).

The eval stage change makes sure we will reject non-value symbols:

tunnel_with_anon_set_assert:1:12-31: Error: must be a value, not set
define s = { 1.2.3.4, 5.6.7.8 }
           ^^^^^^^^^^^^^^^^^^^^

Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
src/evaluate.c
src/parser_bison.y
tests/shell/testcases/bogons/nft-f/tunnel_with_anon_set_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/tunnel_with_garbage_dst [new file with mode: 0644]

index ac482c83cce2ae91ad9db41a8ae27e7f3aa19735..a5cc4181919897a4d7c4e679730eb20d1408c438 100644 (file)
@@ -5851,19 +5851,35 @@ static int ct_timeout_evaluate(struct eval_ctx *ctx, struct obj *obj)
        return 0;
 }
 
+static int tunnel_evaluate_addr(struct eval_ctx *ctx, struct expr **exprp)
+{
+       struct expr *e;
+       int ret;
+
+       ret = expr_evaluate(ctx, exprp);
+       if (ret < 0)
+               return ret;
+
+       e = *exprp;
+       if (e->etype != EXPR_VALUE)
+               return expr_error(ctx->msgs, e, "must be a value, not %s", expr_name(e));
+
+       return 0;
+}
+
 static int tunnel_evaluate(struct eval_ctx *ctx, struct obj *obj)
 {
        if (obj->tunnel.src) {
                expr_set_context(&ctx->ectx, obj->tunnel.src->dtype,
                                 obj->tunnel.src->dtype->size);
-               if (expr_evaluate(ctx, &obj->tunnel.src) < 0)
+               if (tunnel_evaluate_addr(ctx, &obj->tunnel.src) < 0)
                        return -1;
        }
 
        if (obj->tunnel.dst) {
                expr_set_context(&ctx->ectx, obj->tunnel.dst->dtype,
                                 obj->tunnel.dst->dtype->size);
-               if (expr_evaluate(ctx, &obj->tunnel.dst) < 0)
+               if (tunnel_evaluate_addr(ctx, &obj->tunnel.dst) < 0)
                        return -1;
 
                if (obj->tunnel.src &&
index 100a5c871e615fedb68fc9e22dfbe60ab5b23e20..b63c7df18a35e408e4260c5ccce02ff9693d3658 100644 (file)
@@ -5068,22 +5068,22 @@ tunnel_config           :       ID      NUM
                        {
                                $<obj>0->tunnel.id = $2;
                        }
-                       |       IP      SADDR   expr    close_scope_ip
+                       |       IP      SADDR   symbol_expr     close_scope_ip
                        {
                                $<obj>0->tunnel.src = $3;
                                datatype_set($3, &ipaddr_type);
                        }
-                       |       IP      DADDR   expr    close_scope_ip
+                       |       IP      DADDR   symbol_expr     close_scope_ip
                        {
                                $<obj>0->tunnel.dst = $3;
                                datatype_set($3, &ipaddr_type);
                        }
-                       |       IP6     SADDR   expr    close_scope_ip6
+                       |       IP6     SADDR   symbol_expr     close_scope_ip6
                        {
                                $<obj>0->tunnel.src = $3;
                                datatype_set($3, &ip6addr_type);
                        }
-                       |       IP6     DADDR   expr    close_scope_ip6
+                       |       IP6     DADDR   symbol_expr     close_scope_ip6
                        {
                                $<obj>0->tunnel.dst = $3;
                                datatype_set($3, &ip6addr_type);
diff --git a/tests/shell/testcases/bogons/nft-f/tunnel_with_anon_set_assert b/tests/shell/testcases/bogons/nft-f/tunnel_with_anon_set_assert
new file mode 100644 (file)
index 0000000..6f7b212
--- /dev/null
@@ -0,0 +1,8 @@
+define s = { 1.2.3.4, 5.6.7.8 }
+
+table netdev x {
+       tunnel t {
+               ip saddr $s
+       }
+       }
+
diff --git a/tests/shell/testcases/bogons/nft-f/tunnel_with_garbage_dst b/tests/shell/testcases/bogons/nft-f/tunnel_with_garbage_dst
new file mode 100644 (file)
index 0000000..85eb992
--- /dev/null
@@ -0,0 +1,5 @@
+table netdev x {
+       tunnel t {
+               ip saddr tcp dport { }
+       }
+}