netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nft 1/2] evaluate: do not skip evaluation of mapping set elements
@ 2021-06-16 18:09 Pablo Neira Ayuso
  2021-06-16 18:09 ` [PATCH nft 2/2] evaluate: unbreak verdict maps with implicit map with interval concatenations Pablo Neira Ayuso
  0 siblings, 1 reply; 2+ messages in thread
From: Pablo Neira Ayuso @ 2021-06-16 18:09 UTC (permalink / raw)
  To: netfilter-devel

Set element keys are of EXPR_SET_ELEM expression type, however, mappings
use the EXPR_MAPPING expression to wrap the EXPR_SET_ELEM key
(mapping->left) and the corresponding data (mapping->right).

This patch adds a wrapper function to fetch the EXPR_SET_ELEM expression
from the key in case of mappings and use it.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index aa7ec9bee4ae..d220c8e391ac 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1414,27 +1414,39 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
 	return 0;
 }
 
+static const struct expr *expr_set_elem(const struct expr *expr)
+{
+	if (expr->etype == EXPR_MAPPING)
+		return expr->left;
+
+	return expr;
+}
+
 static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
 {
 	struct expr *set = *expr, *i, *next;
+	const struct expr *elem;
 
 	list_for_each_entry_safe(i, next, &set->expressions, list) {
 		if (list_member_evaluate(ctx, &i) < 0)
 			return -1;
 
-		if (i->etype == EXPR_SET_ELEM &&
-		    i->key->etype == EXPR_SET_REF)
+		elem = expr_set_elem(i);
+
+		if (elem->etype == EXPR_SET_ELEM &&
+		    elem->key->etype == EXPR_SET_REF)
 			return expr_error(ctx->msgs, i,
 					  "Set reference cannot be part of another set");
 
-		if (i->etype == EXPR_SET_ELEM &&
-		    i->key->etype == EXPR_SET) {
-			struct expr *new = expr_clone(i->key);
+		if (elem->etype == EXPR_SET_ELEM &&
+		    elem->key->etype == EXPR_SET) {
+			struct expr *new = expr_clone(elem->key);
 
-			set->set_flags |= i->key->set_flags;
+			set->set_flags |= elem->key->set_flags;
 			list_replace(&i->list, &new->list);
 			expr_free(i);
 			i = new;
+			elem = expr_set_elem(i);
 		}
 
 		if (!expr_is_constant(i))
@@ -1450,7 +1462,7 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
 			expr_free(i);
 		} else if (!expr_is_singleton(i)) {
 			set->set_flags |= NFT_SET_INTERVAL;
-			if (i->key->etype == EXPR_CONCAT)
+			if (elem->key->etype == EXPR_CONCAT)
 				set->set_flags |= NFT_SET_CONCAT;
 		}
 	}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH nft 2/2] evaluate: unbreak verdict maps with implicit map with interval concatenations
  2021-06-16 18:09 [PATCH nft 1/2] evaluate: do not skip evaluation of mapping set elements Pablo Neira Ayuso
@ 2021-06-16 18:09 ` Pablo Neira Ayuso
  0 siblings, 0 replies; 2+ messages in thread
From: Pablo Neira Ayuso @ 2021-06-16 18:09 UTC (permalink / raw)
  To: netfilter-devel

Verdict maps in combination with interval concatenations are broken, e.g.

 # nft add rule x y tcp dport . ip saddr vmap { 1025-65535 . 192.168.10.2 : accept }

Retrieve the concatenation field length and count from the map->map
expressions that represents the key of the implicit map.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c                  |  8 ++++++
 tests/py/ip/ip.t                |  1 +
 tests/py/ip/ip.t.json           | 50 +++++++++++++++++++++++++++++++++
 tests/py/ip/ip.t.payload        |  8 ++++++
 tests/py/ip/ip.t.payload.bridge | 11 ++++++++
 tests/py/ip/ip.t.payload.inet   | 11 ++++++++
 tests/py/ip/ip.t.payload.netdev | 11 ++++++++
 7 files changed, 100 insertions(+)

diff --git a/src/evaluate.c b/src/evaluate.c
index d220c8e391ac..77fb24594735 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1564,6 +1564,14 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
 		ctx->set = NULL;
 		map = *expr;
 		map->mappings->set->flags |= map->mappings->set->init->set_flags;
+
+		if (map->mappings->set->flags & NFT_SET_INTERVAL &&
+		    map->map->etype == EXPR_CONCAT) {
+			memcpy(&map->mappings->set->desc.field_len, &map->map->field_len,
+			       sizeof(map->mappings->set->desc.field_len));
+			map->mappings->set->desc.field_count = map->map->field_count;
+			map->mappings->flags |= NFT_SET_CONCAT;
+		}
 		break;
 	case EXPR_SYMBOL:
 		if (expr_evaluate(ctx, &map->mappings) < 0)
diff --git a/tests/py/ip/ip.t b/tests/py/ip/ip.t
index b74d465fcbe6..f4a3667ceab5 100644
--- a/tests/py/ip/ip.t
+++ b/tests/py/ip/ip.t
@@ -125,3 +125,4 @@ iif "lo" ip dscp set af23;ok
 iif "lo" ip dscp set cs0;ok
 
 ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 };ok
+ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept };ok
diff --git a/tests/py/ip/ip.t.json b/tests/py/ip/ip.t.json
index 32312b152ccf..b1085035a000 100644
--- a/tests/py/ip/ip.t.json
+++ b/tests/py/ip/ip.t.json
@@ -1635,3 +1635,53 @@
         }
     }
 ]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+[
+    {
+        "vmap": {
+            "data": {
+                "set": [
+                    [
+                        {
+                            "concat": [
+                                {
+                                    "range": [
+                                        "192.168.5.1",
+                                        "192.168.5.128"
+                                    ]
+                                },
+                                {
+                                    "range": [
+                                        "192.168.6.1",
+                                        "192.168.6.128"
+                                    ]
+                                }
+                            ]
+                        },
+                        {
+                            "accept": null
+                        }
+                    ]
+                ]
+            },
+            "key": {
+                "concat": [
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ip"
+                        }
+                    },
+                    {
+                        "payload": {
+                            "field": "daddr",
+                            "protocol": "ip"
+                        }
+                    }
+                ]
+            }
+        }
+    }
+]
+
diff --git a/tests/py/ip/ip.t.payload b/tests/py/ip/ip.t.payload
index 4bb177526971..49d1a0fb03e8 100644
--- a/tests/py/ip/ip.t.payload
+++ b/tests/py/ip/ip.t.payload
@@ -515,3 +515,11 @@ ip
   [ payload load 4b @ network header + 16 => reg 9 ]
   [ lookup reg 1 set __set%d ]
 
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-ip4 8f size 1
+__map%d test-ip4 0
+        element 0105a8c0 0106a8c0  - 8005a8c0 8006a8c0  : accept 0 [end]
+ip
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ payload load 4b @ network header + 16 => reg 9 ]
+  [ lookup reg 1 set __map%d dreg 0 ]
diff --git a/tests/py/ip/ip.t.payload.bridge b/tests/py/ip/ip.t.payload.bridge
index c8c1dbadee14..dac8654395f4 100644
--- a/tests/py/ip/ip.t.payload.bridge
+++ b/tests/py/ip/ip.t.payload.bridge
@@ -673,3 +673,14 @@ bridge
   [ payload load 4b @ network header + 16 => reg 9 ]
   [ lookup reg 1 set __set%d ]
 
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-bridge 8f size 1
+__map%d test-bridge 0
+        element 0105a8c0 0106a8c0  - 8005a8c0 8006a8c0  : accept 0 [end]
+bridge
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ payload load 4b @ network header + 16 => reg 9 ]
+  [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/ip/ip.t.payload.inet b/tests/py/ip/ip.t.payload.inet
index 55304fc9d871..64371650480f 100644
--- a/tests/py/ip/ip.t.payload.inet
+++ b/tests/py/ip/ip.t.payload.inet
@@ -673,3 +673,14 @@ inet
   [ payload load 4b @ network header + 16 => reg 9 ]
   [ lookup reg 1 set __set%d ]
 
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-inet 8f size 1
+__map%d test-inet 0
+        element 0105a8c0 0106a8c0  - 8005a8c0 8006a8c0  : accept 0 [end]
+inet
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ payload load 4b @ network header + 16 => reg 9 ]
+  [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/ip/ip.t.payload.netdev b/tests/py/ip/ip.t.payload.netdev
index 712cb3756149..65f8c96a9470 100644
--- a/tests/py/ip/ip.t.payload.netdev
+++ b/tests/py/ip/ip.t.payload.netdev
@@ -673,3 +673,14 @@ netdev
   [ payload load 4b @ network header + 16 => reg 9 ]
   [ lookup reg 1 set __set%d ]
 
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-netdev 8f size 1
+__map%d test-netdev 0
+        element 0105a8c0 0106a8c0  - 8005a8c0 8006a8c0  : accept 0 [end]
+netdev
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ payload load 4b @ network header + 16 => reg 9 ]
+  [ lookup reg 1 set __map%d dreg 0 ]
+
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-06-16 18:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-16 18:09 [PATCH nft 1/2] evaluate: do not skip evaluation of mapping set elements Pablo Neira Ayuso
2021-06-16 18:09 ` [PATCH nft 2/2] evaluate: unbreak verdict maps with implicit map with interval concatenations Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).