summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2025-04-10 23:23:58 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2025-04-11 00:28:39 +0200
commit8bbdcb7346788a067968e3aa62ac7e5a670b08af (patch)
treef1cd52cba1854ffd970cdd6ada711fc742acc35d
parentba6985a1faf98e6b1c87938695a2093cd9b58468 (diff)
parser_bison: add selector_expr rule to restrict typeof_expr
typeof_expr allows for symbol, constant and bitwise expressions, restrict it to selector expressions. After this patch, input generated by fuzzer is rejected upfront: # nft -f test.nft test.nft:3:53-53: Error: syntax error, unexpected number typeof numgen inc mod 2 : ip daddr . 0 ^ test.nft:2:12-13: Error: set definition does not specify key map t2 { ^^ test.nft:8:65-67: Error: No such file or directory meta l4proto tcp dnat ip to numgen inc mod 2 map @t2 ^^^ test.nft:8:65-67: Error: No such file or directory meta l4proto tcp dnat ip to numgen inc mod 2 map @t2 ^^^ Revisit 4ab1e5e60779 ("src: allow use of 'verdict' in typeof definitions") to handle verdict as string, later a token can be added to the scanner and enable it via flex start conditions. Fixes: 14357cff40ed ("parser: add typeof keyword for declarations") Reported-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/parser_bison.y43
-rw-r--r--tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert10
2 files changed, 36 insertions, 17 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 4b2b51d4..ed6a24a1 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -818,8 +818,8 @@ int nft_lex(void *, void *, void *);
%type <expr> symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
-%type <expr> primary_expr shift_expr and_expr primary_typeof_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
-%destructor { expr_free($$); } primary_expr shift_expr and_expr primary_typeof_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
+%type <expr> primary_expr shift_expr and_expr primary_typeof_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr selector_expr
+%destructor { expr_free($$); } primary_expr shift_expr and_expr primary_typeof_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr selector_expr
%type <expr> exclusive_or_expr inclusive_or_expr
%destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
%type <expr> basic_expr
@@ -2097,19 +2097,10 @@ subchain_block : /* empty */ { $$ = $<chain>-1; }
}
;
-typeof_verdict_expr : primary_expr
+typeof_verdict_expr : selector_expr
{
struct expr *e = $1;
- if (e->etype == EXPR_SYMBOL &&
- strcmp("verdict", e->identifier) == 0) {
- struct expr *v = verdict_expr_alloc(&@1, NF_ACCEPT, NULL);
-
- expr_free(e);
- v->flags &= ~EXPR_F_CONSTANT;
- e = v;
- }
-
if (expr_ops(e)->build_udata == NULL) {
erec_queue(error(&@1, "map data type '%s' lacks typeof serialization", expr_ops(e)->name),
state->msgs);
@@ -2118,7 +2109,7 @@ typeof_verdict_expr : primary_expr
}
$$ = e;
}
- | typeof_expr DOT primary_expr
+ | typeof_expr DOT selector_expr
{
struct location rhs[] = {
[1] = @2,
@@ -2142,9 +2133,24 @@ typeof_data_expr : INTERVAL typeof_expr
{
$$ = constant_expr_alloc(&@$, &queue_type, BYTEORDER_HOST_ENDIAN, 16, NULL);
}
+ | STRING
+ {
+ struct expr *verdict;
+
+ if (strcmp("verdict", $1) != 0) {
+ erec_queue(error(&@1, "map data type '%s' lacks typeof serialization", $1),
+ state->msgs);
+ free_const($1);
+ YYERROR;
+ }
+ verdict = verdict_expr_alloc(&@1, NF_ACCEPT, NULL);
+ verdict->flags &= ~EXPR_F_CONSTANT;
+ $$ = verdict;
+ free_const($1);
+ }
;
-primary_typeof_expr : primary_expr
+primary_typeof_expr : selector_expr
{
if (expr_ops($1)->build_udata == NULL) {
erec_queue(error(&@1, "primary expression type '%s' lacks typeof serialization", expr_ops($1)->name),
@@ -4332,9 +4338,7 @@ integer_expr : NUM
}
;
-primary_expr : symbol_expr { $$ = $1; }
- | integer_expr { $$ = $1; }
- | payload_expr { $$ = $1; }
+selector_expr : payload_expr { $$ = $1; }
| exthdr_expr { $$ = $1; }
| exthdr_exists_expr { $$ = $1; }
| meta_expr { $$ = $1; }
@@ -4346,6 +4350,11 @@ primary_expr : symbol_expr { $$ = $1; }
| fib_expr { $$ = $1; }
| osf_expr { $$ = $1; }
| xfrm_expr { $$ = $1; }
+ ;
+
+primary_expr : symbol_expr { $$ = $1; }
+ | integer_expr { $$ = $1; }
+ | selector_expr { $$ = $1; }
| '(' basic_expr ')' { $$ = $2; }
;
diff --git a/tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert b/tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert
new file mode 100644
index 00000000..d73dce8e
--- /dev/null
+++ b/tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert
@@ -0,0 +1,10 @@
+table ip t {
+ map t2 {
+ typeof numgen inc mod 2 : ip daddr . 0
+ }
+
+ chain c {
+ type nat hook prerouting priority dstnat; policy accept;
+ meta l4proto tcp dnat ip to numgen inc mod 2 map @t2
+ }
+}