All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft] netlink_linearize: size nat register allocation by address expression
@ 2026-08-06 18:50 Adrian Moisey
  2026-08-20 11:15 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 2+ messages in thread
From: Adrian Moisey @ 2026-08-06 18:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Adrian Moisey

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 <adrian@changeover.za.net>
---
 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


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

* Re: [PATCH nft] netlink_linearize: size nat register allocation by address expression
  2026-08-06 18:50 [PATCH nft] netlink_linearize: size nat register allocation by address expression Adrian Moisey
@ 2026-08-20 11:15 ` Pablo Neira Ayuso
  0 siblings, 0 replies; 2+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-20 11:15 UTC (permalink / raw)
  To: Adrian Moisey; +Cc: netfilter-devel

On Thu, Aug 06, 2026 at 08:50:20PM +0200, Adrian Moisey wrote:
> 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.

Applied, thanks

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

end of thread, other threads:[~2026-08-20 11:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 18:50 [PATCH nft] netlink_linearize: size nat register allocation by address expression Adrian Moisey
2026-08-20 11:15 ` 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.