]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
expression: expr_build_udata_recurse should recurse
authorFlorian Westphal <fw@strlen.de>
Thu, 27 Feb 2025 14:52:10 +0000 (15:52 +0100)
committerFlorian Westphal <fw@strlen.de>
Thu, 6 Mar 2025 03:55:43 +0000 (04:55 +0100)
If we see EXPR_BINOP, recurse: ->left can be another EXPR_BINOP.

This is irrelevant for 'typeof' named sets, but for anonymous sets, the
key is derived from the concat expression that builds the lookup key for
the anonymous set.

 tcp option mptcp subtype . ip daddr { mp-join. 10.0.0.1, ..

 needs two binops back-to-back:

  [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000004 ) ]

This bug prevents concat_expr_build_udata() from creating the userdata key
at load time.

When listing the rules, we get an assertion:
 nft: src/mergesort.c:23: concat_expr_msort_value: Assertion `ilen > 0' failed.

because the set has a key with 0-length integers.

Signed-off-by: Florian Westphal <fw@strlen.de>
src/expression.c
tests/py/any/tcpopt.t
tests/py/any/tcpopt.t.json
tests/py/any/tcpopt.t.payload

index d2fa46509262bf5dd3c7c936cbe3323ff42243e8..8a90e09dd1c5ccf2efd78b8562441dfbb13cd49f 100644 (file)
@@ -1078,7 +1078,7 @@ static struct expr *expr_build_udata_recurse(struct expr *e)
 {
        switch (e->etype) {
        case EXPR_BINOP:
-               return e->left;
+               return expr_build_udata_recurse(e->left);
        default:
                break;
        }
index 79699e23a4b1efe4f74e9911c35b4b4baece67db..3d46c0efc23175459ba937111d75bb6f51ec6545 100644 (file)
@@ -54,6 +54,7 @@ tcp option mptcp exists;ok
 tcp option mptcp subtype mp-capable;ok
 tcp option mptcp subtype 1;ok;tcp option mptcp subtype mp-join
 tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst };ok
+tcp option mptcp subtype . tcp dport { mp-capable . 10, mp-join . 100, add-addr . 200, remove-addr . 300, mp-prio . 400, mp-fail . 500, mp-fastclose . 600, mp-tcprst . 700 };ok
 
 reset tcp option mptcp;ok
 reset tcp option 2;ok;reset tcp option maxseg
index a02e71b66c36b1ca1a77e00ba4ff07abd776a926..e712a5e0ed56f5470c1941139adaa0593d368340 100644 (file)
    }
 ]
 
+# tcp option mptcp subtype . tcp dport { mp-capable . 10, mp-join . 100, add-addr . 200, remove-addr . 300, mp-prio . 400, mp-fail . 500, mp-fastclose . 600, mp-tcprst . 700 }
+[
+    {
+        "match": {
+            "left": {
+                "concat": [
+                    {
+                        "tcp option": {
+                            "field": "subtype",
+                            "name": "mptcp"
+                        }
+                    },
+                    {
+                        "payload": {
+                            "field": "dport",
+                            "protocol": "tcp"
+                        }
+                    }
+                ]
+            },
+            "op": "==",
+            "right": {
+                "set": [
+                    {
+                        "concat": [
+                            "mp-capable",
+                            10
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "remove-addr",
+                            300
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "mp-fastclose",
+                            600
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "mp-join",
+                            100
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "mp-prio",
+                            400
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "mp-tcprst",
+                            700
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "add-addr",
+                            200
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "mp-fail",
+                            500
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+]
+
 # reset tcp option mptcp
 [
     {
index af8c4317e56764f85dd48c5702e68cdf0a53489a..437e073aae1c90c53041cdb8343db6bbbace93d3 100644 (file)
@@ -189,6 +189,19 @@ ip test-ip4 input
   [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
   [ lookup reg 1 set __set%d ]
 
+# tcp option mptcp subtype . tcp dport { mp-capable . 10, mp-join . 100, add-addr . 200, remove-addr . 300, mp-prio . 400, mp-fail . 500, mp-fastclose . 600, mp-tcprst . 700 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+        element 00000000 00000a00  : 0 [end]    element 00000001 00006400  : 0 [end]    element 00000003 0000c800  : 0 [end]    element 00000004 00002c01  : 0 [end]    element 00000005 00009001  : 0 [end]    element 00000006 0000f401  : 0 [end]    element 00000007 00005802  : 0 [end]    element 00000008 0000bc02  : 0 [end]
+ip test-ip4 input
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000004 ) ]
+  [ payload load 2b @ transport header + 2 => reg 9 ]
+  [ lookup reg 1 set __set%d ]
+
 # reset tcp option mptcp
 ip test-ip4 input
   [ exthdr reset tcpopt 30 ]