diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2025-04-10 23:23:58 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2025-04-11 00:28:39 +0200 |
commit | 8bbdcb7346788a067968e3aa62ac7e5a670b08af (patch) | |
tree | f1cd52cba1854ffd970cdd6ada711fc742acc35d | |
parent | ba6985a1faf98e6b1c87938695a2093cd9b58468 (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.y | 43 | ||||
-rw-r--r-- | tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert | 10 |
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 + } +} |