All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.