[PATCH nft] netlink_linearize: size nat register allocation by address expression

Adrian Moisey <[email protected]>
Newsgroups gmane.comp.security.firewalls.netfilter.devel
Message-ID <[email protected]>
nat statements with a literal concatenation of address and port, e.g.

  dnat ip6 addr . port to fd00:10:244::4 . 6443

allocated a fixed 128-bit register block for the address, but the ip6
address . port concatenation is 144 bits (5 registers), so
netlink_gen_concat overran into unallocated registers and hit the
assertion 'dreg < ctx->reg_low' in netlink_gen_expr. IPv4 escaped by
luck since its 48-bit concatenation fits into the padded block.

Allocate the register based on the address expression instead, which
sizes by expr->len for concatenations, and add the matching
release_register() call. Extend the nat_addr_port test with literal
concatenation rules for ip and ip6.

Signed-off-by: Adrian Moisey <[email protected]>
---
 src/netlink_linearize.c                       |  6 ++-
 .../maps/dumps/nat_addr_port.json-nft         | 54 +++++++++++++++++++
 .../testcases/maps/dumps/nat_addr_port.nft    |  2 +
 tests/shell/testcases/maps/nat_addr_port      |  2 +
 4 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index ac0eaff9..dfa841c6 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1292,8 +1292,7 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u32(nle, nftnl_flag_attr, stmt->nat.flags);
 
 	if (stmt->nat.addr) {
-		amin_reg = get_register(ctx, NULL);
-		registers++;
+		amin_reg = get_register(ctx, stmt->nat.addr);
 
 		if (stmt->nat.addr->etype == EXPR_RANGE) {
 			amax_reg = get_register(ctx, NULL);
@@ -1374,6 +1373,9 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
 		registers--;
 	}
 
+	if (stmt->nat.addr)
+		release_register(ctx, stmt->nat.addr);
+
 	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
diff --git a/tests/shell/testcases/maps/dumps/nat_addr_port.json-nft b/tests/shell/testcases/maps/dumps/nat_addr_port.json-nft
index 38b01e69..09052c43 100644
--- a/tests/shell/testcases/maps/dumps/nat_addr_port.json-nft
+++ b/tests/shell/testcases/maps/dumps/nat_addr_port.json-nft
@@ -320,6 +320,33 @@
         ]
       }
     },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "ipfoo",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "tcp"
+            }
+          },
+          {
+            "dnat": {
+              "addr": "10.2.3.4",
+              "port": 4242
+            }
+          }
+        ]
+      }
+    },
     {
       "rule": {
         "family": "ip",
@@ -670,6 +697,33 @@
         ]
       }
     },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "ip6foo",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "tcp"
+            }
+          },
+          {
+            "dnat": {
+              "addr": "fd00:10:244::4",
+              "port": 6443
+            }
+          }
+        ]
+      }
+    },
     {
       "rule": {
         "family": "ip6",
diff --git a/tests/shell/testcases/maps/dumps/nat_addr_port.nft b/tests/shell/testcases/maps/dumps/nat_addr_port.nft
index c8493b3a..fb1c190a 100644
--- a/tests/shell/testcases/maps/dumps/nat_addr_port.nft
+++ b/tests/shell/testcases/maps/dumps/nat_addr_port.nft
@@ -29,6 +29,7 @@ table ip ipfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat to 10.2.3.4:4242
 		meta l4proto tcp dnat ip to ip saddr map @y
 		dnat ip to ip saddr . tcp dport map @z
+		meta l4proto tcp dnat to 10.2.3.4:4242
 		dnat to numgen inc mod 2 map @t1
 		meta l4proto tcp dnat ip to numgen inc mod 2 map @t2
 	}
@@ -62,6 +63,7 @@ table ip6 ip6foo {
 		ip6 saddr dead::2 tcp dport 42 dnat to [c0::1a]:4242
 		meta l4proto tcp dnat ip6 to ip6 saddr map @y
 		dnat ip6 to ip6 saddr . tcp dport map @z
+		meta l4proto tcp dnat to [fd00:10:244::4]:6443
 		dnat to numgen inc mod 2 map @t1
 		meta l4proto tcp dnat ip6 to numgen inc mod 2 map @t2
 	}
diff --git a/tests/shell/testcases/maps/nat_addr_port b/tests/shell/testcases/maps/nat_addr_port
index 703a2ad9..5f6ff1c4 100755
--- a/tests/shell/testcases/maps/nat_addr_port
+++ b/tests/shell/testcases/maps/nat_addr_port
@@ -31,6 +31,7 @@ table ip ipfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat to 10.2.3.4:4242
 		meta l4proto tcp dnat ip addr . port to ip saddr map @y
 		meta l4proto tcp dnat ip addr . port to ip saddr . tcp dport map @z
+		meta l4proto tcp dnat ip addr . port to 10.2.3.4 . 4242
 		dnat ip to numgen inc mod 2 map @t1
 		meta l4proto tcp dnat ip addr . port to numgen inc mod 2 map @t2
 	}
@@ -72,6 +73,7 @@ table ip6 ip6foo {
 		ip6 saddr dead::2 tcp dport 42 dnat to [c0::1a]:4242
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr map @y
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr . tcp dport map @z
+		meta l4proto tcp dnat ip6 addr . port to fd00:10:244::4 . 6443
 		dnat ip6 to numgen inc mod 2 map @t1
 		meta l4proto tcp dnat ip6 addr . port to numgen inc mod 2 map @t2
 	}
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.