From: Florian Westphal Date: Thu, 16 Oct 2025 14:59:34 +0000 (+0200) Subject: src: tunnel src/dst must be a symbolic expression X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=667a618083f755eb12b73a69e32fe94e128ec8b3;p=thirdparty%2Fnftables.git src: tunnel src/dst must be a symbolic expression 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 Reviewed-by: Fernando Fernandez Mancera --- diff --git a/src/evaluate.c b/src/evaluate.c index ac482c83..a5cc4181 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -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 && diff --git a/src/parser_bison.y b/src/parser_bison.y index 100a5c87..b63c7df1 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -5068,22 +5068,22 @@ tunnel_config : ID NUM { $0->tunnel.id = $2; } - | IP SADDR expr close_scope_ip + | IP SADDR symbol_expr close_scope_ip { $0->tunnel.src = $3; datatype_set($3, &ipaddr_type); } - | IP DADDR expr close_scope_ip + | IP DADDR symbol_expr close_scope_ip { $0->tunnel.dst = $3; datatype_set($3, &ipaddr_type); } - | IP6 SADDR expr close_scope_ip6 + | IP6 SADDR symbol_expr close_scope_ip6 { $0->tunnel.src = $3; datatype_set($3, &ip6addr_type); } - | IP6 DADDR expr close_scope_ip6 + | IP6 DADDR symbol_expr close_scope_ip6 { $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 index 00000000..6f7b212a --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/tunnel_with_anon_set_assert @@ -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 index 00000000..85eb992c --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/tunnel_with_garbage_dst @@ -0,0 +1,5 @@ +table netdev x { + tunnel t { + ip saddr tcp dport { } + } +}