[PATCH nft] optimize: clone counter before insertion into set element

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

 



The counter statement that is zapped from the rule needs to be cloned
before inserting it into each set element.

Fixes: 686ab8b6996e ("optimize: do not remove counter in verdict maps")
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/optimize.c                                | 24 +++++++++++++------
 .../optimizations/dumps/merge_counter.nft     |  8 +++++++
 .../testcases/optimizations/merge_counter     | 20 ++++++++++++++++
 3 files changed, 45 insertions(+), 7 deletions(-)
 create mode 100644 tests/shell/testcases/optimizations/dumps/merge_counter.nft
 create mode 100755 tests/shell/testcases/optimizations/merge_counter

diff --git a/src/optimize.c b/src/optimize.c
index 1dd08586f326..62dd9082a587 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -692,29 +692,36 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
 			      struct expr *set, struct stmt *counter)
 {
 	struct expr *item, *elem, *mapping;
+	struct stmt *counter_elem;
 
 	switch (expr->etype) {
 	case EXPR_LIST:
 		list_for_each_entry(item, &expr->expressions, list) {
 			elem = set_elem_expr_alloc(&internal_location, expr_get(item));
-			if (counter)
-				list_add_tail(&counter->list, &elem->stmt_list);
+			if (counter) {
+				counter_elem = counter_stmt_alloc(&counter->location);
+				list_add_tail(&counter_elem->list, &elem->stmt_list);
+			}
 
 			mapping = mapping_expr_alloc(&internal_location, elem,
 						     expr_get(verdict->expr));
 			compound_expr_add(set, mapping);
 		}
+		stmt_free(counter);
 		break;
 	case EXPR_SET:
 		list_for_each_entry(item, &expr->expressions, list) {
 			elem = set_elem_expr_alloc(&internal_location, expr_get(item->key));
-			if (counter)
-				list_add_tail(&counter->list, &elem->stmt_list);
+			if (counter) {
+				counter_elem = counter_stmt_alloc(&counter->location);
+				list_add_tail(&counter_elem->list, &elem->stmt_list);
+			}
 
 			mapping = mapping_expr_alloc(&internal_location, elem,
 						     expr_get(verdict->expr));
 			compound_expr_add(set, mapping);
 		}
+		stmt_free(counter);
 		break;
 	case EXPR_PREFIX:
 	case EXPR_RANGE:
@@ -819,8 +826,8 @@ static void __merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
 				      struct expr *set, struct stmt *verdict)
 {
 	struct expr *concat, *next, *elem, *mapping;
+	struct stmt *counter, *counter_elem;
 	LIST_HEAD(concat_list);
-	struct stmt *counter;
 
 	counter = zap_counter(ctx, i);
 	__merge_concat(ctx, i, merge, &concat_list);
@@ -828,13 +835,16 @@ static void __merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
 	list_for_each_entry_safe(concat, next, &concat_list, list) {
 		list_del(&concat->list);
 		elem = set_elem_expr_alloc(&internal_location, concat);
-		if (counter)
-			list_add_tail(&counter->list, &elem->stmt_list);
+		if (counter) {
+			counter_elem = counter_stmt_alloc(&counter->location);
+			list_add_tail(&counter_elem->list, &elem->stmt_list);
+		}
 
 		mapping = mapping_expr_alloc(&internal_location, elem,
 					     expr_get(verdict->expr));
 		compound_expr_add(set, mapping);
 	}
+	stmt_free(counter);
 }
 
 static void merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
diff --git a/tests/shell/testcases/optimizations/dumps/merge_counter.nft b/tests/shell/testcases/optimizations/dumps/merge_counter.nft
new file mode 100644
index 000000000000..72eed5d0f148
--- /dev/null
+++ b/tests/shell/testcases/optimizations/dumps/merge_counter.nft
@@ -0,0 +1,8 @@
+table ip x {
+	chain y {
+		type filter hook input priority filter; policy drop;
+		ct state vmap { invalid counter packets 0 bytes 0 : drop, established counter packets 0 bytes 0 : accept, related counter packets 0 bytes 0 : accept }
+		tcp dport { 80, 123 } counter packets 0 bytes 0 accept
+		ip saddr . ip daddr vmap { 1.1.1.1 . 2.2.2.2 counter packets 0 bytes 0 : accept, 1.1.1.2 . 3.3.3.3 counter packets 0 bytes 0 : drop }
+	}
+}
diff --git a/tests/shell/testcases/optimizations/merge_counter b/tests/shell/testcases/optimizations/merge_counter
new file mode 100755
index 000000000000..3b8bbadd6126
--- /dev/null
+++ b/tests/shell/testcases/optimizations/merge_counter
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
+set -e
+
+RULESET="table ip x {
+        chain y {
+                type filter hook input priority 0; policy drop;
+
+                ct state invalid counter drop
+                ct state established,related counter accept
+                tcp dport 80 counter accept
+                tcp dport 123 counter accept
+                ip saddr 1.1.1.1 ip daddr 2.2.2.2 counter accept
+                ip saddr 1.1.1.2 ip daddr 3.3.3.3 counter drop
+        }
+}"
+
+$NFT -o -f - <<< $RULESET
-- 
2.30.2





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

  Powered by Linux