[PATCH nft] parser_bison: add selector_expr rule to restrict typeof_expr

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 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@xxxxxxxxx>
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/parser_bison.y                            | 43 +++++++++++--------
 ...valid_set_key_stmt_evaluate_nat_map_assert | 10 +++++
 2 files changed, 36 insertions(+), 17 deletions(-)
 create mode 100644 tests/shell/testcases/bogons/nft-f/invalid_set_key_stmt_evaluate_nat_map_assert

diff --git a/src/parser_bison.y b/src/parser_bison.y
index 4b2b51d4275c..ed6a24a15377 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 000000000000..d73dce8e5ce1
--- /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
+	}
+}
-- 
2.30.2





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux