Blame SOURCES/0026-parser_bison-Fix-for-ECN-keyword-in-LHS-of-relationa.patch

34625f
From 64b101f4a124f39b494dc5906159a8890568d1f9 Mon Sep 17 00:00:00 2001
34625f
From: Phil Sutter <phil@nwl.cc>
34625f
Date: Fri, 24 Aug 2018 13:26:57 +0200
34625f
Subject: [PATCH] parser_bison: Fix for ECN keyword in LHS of relational
34625f
34625f
Of all possible TCP flags, 'ecn' is special since it is recognized by
34625f
lex as a keyword (there is a a field in IPv4 and IPv6 headers with the
34625f
same name). Therefore it is listed in keyword_expr, but that was
34625f
sufficient for RHS only. The following statement reproduces the issue:
34625f
34625f
| tcp flags & (syn | ecn) == (syn | ecn)
34625f
34625f
The solution is to limit binop expressions to accept an RHS expression
34625f
on RHS ("real" LHS expressions don't make much sense there anyway),
34625f
which then allows keyword_expr to occur there. In order to maintain the
34625f
recursive behaviour if braces are present, allow primary_rhs_expr to
34625f
consist of a basic_rhs_expr enclosed in braces. This in turn requires
34625f
for braced RHS part in relational_expr to be dropped, otherwise bison
34625f
complains about shift/reduce conflict.
34625f
34625f
Signed-off-by: Phil Sutter <phil@nwl.cc>
34625f
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
34625f
(cherry picked from commit 14a9968a56f8b35138bab172aa7ce796f5d98e03)
34625f
Signed-off-by: Phil Sutter <psutter@redhat.com>
34625f
---
34625f
 src/parser_bison.y              | 15 ++++++---------
34625f
 tests/py/inet/tcp.t             |  1 +
34625f
 tests/py/inet/tcp.t.json        | 23 +++++++++++++++++++++++
34625f
 tests/py/inet/tcp.t.json.output | 16 ++++++++++++++++
34625f
 tests/py/inet/tcp.t.payload     |  8 ++++++++
34625f
 5 files changed, 54 insertions(+), 9 deletions(-)
34625f
34625f
diff --git a/src/parser_bison.y b/src/parser_bison.y
34625f
index d75cd50fa29b9..a6b6fc1745a72 100644
34625f
--- a/src/parser_bison.y
34625f
+++ b/src/parser_bison.y
34625f
@@ -2948,32 +2948,32 @@ fib_tuple		:  	fib_flag	DOT	fib_tuple
34625f
 			;
34625f
 
34625f
 shift_expr		:	primary_expr
34625f
-			|	shift_expr		LSHIFT		primary_expr
34625f
+			|	shift_expr		LSHIFT		primary_rhs_expr
34625f
 			{
34625f
 				$$ = binop_expr_alloc(&@$, OP_LSHIFT, $1, $3);
34625f
 			}
34625f
-			|	shift_expr		RSHIFT		primary_expr
34625f
+			|	shift_expr		RSHIFT		primary_rhs_expr
34625f
 			{
34625f
 				$$ = binop_expr_alloc(&@$, OP_RSHIFT, $1, $3);
34625f
 			}
34625f
 			;
34625f
 
34625f
 and_expr		:	shift_expr
34625f
-			|	and_expr		AMPERSAND	shift_expr
34625f
+			|	and_expr		AMPERSAND	shift_rhs_expr
34625f
 			{
34625f
 				$$ = binop_expr_alloc(&@$, OP_AND, $1, $3);
34625f
 			}
34625f
 			;
34625f
 
34625f
 exclusive_or_expr	:	and_expr
34625f
-			|	exclusive_or_expr	CARET		and_expr
34625f
+			|	exclusive_or_expr	CARET		and_rhs_expr
34625f
 			{
34625f
 				$$ = binop_expr_alloc(&@$, OP_XOR, $1, $3);
34625f
 			}
34625f
 			;
34625f
 
34625f
 inclusive_or_expr	:	exclusive_or_expr
34625f
-			|	inclusive_or_expr	'|'		exclusive_or_expr
34625f
+			|	inclusive_or_expr	'|'		exclusive_or_rhs_expr
34625f
 			{
34625f
 				$$ = binop_expr_alloc(&@$, OP_OR, $1, $3);
34625f
 			}
34625f
@@ -3252,10 +3252,6 @@ relational_expr		:	expr	/* implicit */	rhs_expr
34625f
 			{
34625f
 				$$ = relational_expr_alloc(&@2, $2, $1, $3);
34625f
 			}
34625f
-			|	expr	relational_op	'(' rhs_expr ')'
34625f
-			{
34625f
-				$$ = relational_expr_alloc(&@2, $2, $1, $4);
34625f
-			}
34625f
 			;
34625f
 
34625f
 list_rhs_expr		:	basic_rhs_expr		COMMA		basic_rhs_expr
34625f
@@ -3439,6 +3435,7 @@ primary_rhs_expr	:	symbol_expr		{ $$ = $1; }
34625f
 							 BYTEORDER_HOST_ENDIAN,
34625f
 							 sizeof(data) * BITS_PER_BYTE, &data);
34625f
 			}
34625f
+			|	'('	basic_rhs_expr	')'	{ $$ = $2; }
34625f
 			;
34625f
 
34625f
 relational_op		:	EQ		{ $$ = OP_EQ; }
34625f
diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t
34625f
index d66ba8438a32f..f96e3634f41ed 100644
34625f
--- a/tests/py/inet/tcp.t
34625f
+++ b/tests/py/inet/tcp.t
34625f
@@ -78,6 +78,7 @@ tcp flags cwr;ok
34625f
 tcp flags != cwr;ok
34625f
 tcp flags == syn;ok
34625f
 tcp flags & (syn|fin) == (syn|fin);ok;tcp flags & (fin | syn) == fin | syn
34625f
+tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff
34625f
 
34625f
 tcp window 22222;ok
34625f
 tcp window 22;ok
34625f
diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json
34625f
index f5df72aa252a6..9ae51018e93ee 100644
34625f
--- a/tests/py/inet/tcp.t.json
34625f
+++ b/tests/py/inet/tcp.t.json
34625f
@@ -1068,6 +1068,29 @@
34625f
     }
34625f
 ]
34625f
 
34625f
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
34625f
+[
34625f
+    {
34625f
+        "match": {
34625f
+            "left": {
34625f
+                "&": [
34625f
+                    {
34625f
+                        "payload": {
34625f
+                            "field": "flags",
34625f
+                            "protocol": "tcp"
34625f
+                        }
34625f
+                    },
34625f
+                    {
34625f
+                        "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ]
34625f
+                    }
34625f
+                ]
34625f
+            },
34625f
+            "op": "==",
34625f
+            "right": { "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] }
34625f
+        }
34625f
+    }
34625f
+]
34625f
+
34625f
 # tcp window 22222
34625f
 [
34625f
     {
34625f
diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output
34625f
index d099d6febb122..ff58756cf596d 100644
34625f
--- a/tests/py/inet/tcp.t.json.output
34625f
+++ b/tests/py/inet/tcp.t.json.output
34625f
@@ -132,3 +132,19 @@
34625f
     }
34625f
 ]
34625f
 
34625f
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
34625f
+[
34625f
+    {
34625f
+        "match": {
34625f
+            "left": {
34625f
+                "payload": {
34625f
+                    "field": "flags",
34625f
+                    "protocol": "tcp"
34625f
+                }
34625f
+            },
34625f
+            "op": "==",
34625f
+            "right": 255
34625f
+        }
34625f
+    }
34625f
+]
34625f
+
34625f
diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload
34625f
index 09538aed746c9..2390a24ead15c 100644
34625f
--- a/tests/py/inet/tcp.t.payload
34625f
+++ b/tests/py/inet/tcp.t.payload
34625f
@@ -436,6 +436,14 @@ inet test-inet input
34625f
   [ bitwise reg 1 = (reg=1 & 0x00000003 ) ^ 0x00000000 ]
34625f
   [ cmp eq reg 1 0x00000003 ]
34625f
 
34625f
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
34625f
+inet test-inet input
34625f
+  [ meta load l4proto => reg 1 ]
34625f
+  [ cmp eq reg 1 0x00000006 ]
34625f
+  [ payload load 1b @ transport header + 13 => reg 1 ]
34625f
+  [ bitwise reg 1 = (reg=1 & 0x000000ff ) ^ 0x00000000 ]
34625f
+  [ cmp eq reg 1 0x000000ff ]
34625f
+
34625f
 # tcp window 22222
34625f
 inet test-inet input
34625f
   [ meta load l4proto => reg 1 ]
34625f
-- 
34625f
2.19.0
34625f