]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink: swap byteorder of value component in concatenation of intervals
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 8 Dec 2022 00:35:05 +0000 (01:35 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 8 Dec 2022 02:12:32 +0000 (03:12 +0100)
Commit 1017d323cafa ("src: support for selectors with different byteorder with
interval concatenations") was incomplete.

Switch byteorder of singleton values in a set that contains
concatenation of intervals. This singleton value is actually represented
as a range in the kernel.

After this patch, if the set represents a concatenation of intervals:

- EXPR_F_INTERVAL denotes the lhs of the interval.
- EXPR_F_INTERVAL_END denotes the rhs of the interval (this flag was
  already used in this way before this patch).

If none of these flags are set on, then the set contains concatenations
of singleton values (no interval flag is set on), in such case, no
byteorder swap is required.

Update tests/shell and tests/py to cover the use-case breakage reported
by Eric.

Fixes: 1017d323cafa ("src: support for selectors with different byteorder with interval concatenations")
Reported-by: Eric Garver <eric@garver.life>
Tested-by: Eric Garver <eric@garver.life>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink.c
tests/py/inet/meta.t
tests/py/inet/meta.t.json
tests/py/inet/meta.t.payload
tests/shell/testcases/sets/concat_interval_0
tests/shell/testcases/sets/dumps/concat_interval_0.nft

index db5e79f235d0e451e2334c3106ef7aad31d58409..2ede25b9ce9df5c216d97d44ef5ccc860cdef641 100644 (file)
@@ -133,16 +133,23 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
        case EXPR_SET_ELEM_CATCHALL:
                break;
        default:
-               __netlink_gen_data(key, &nld, false);
-               nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
                if (set->set_flags & NFT_SET_INTERVAL &&
                    key->etype == EXPR_CONCAT && key->field_count > 1) {
+                       key->flags |= EXPR_F_INTERVAL;
+                       __netlink_gen_data(key, &nld, false);
+                       key->flags &= ~EXPR_F_INTERVAL;
+
+                       nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
+
                        key->flags |= EXPR_F_INTERVAL_END;
                        __netlink_gen_data(key, &nld, false);
                        key->flags &= ~EXPR_F_INTERVAL_END;
 
                        nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END,
                                           &nld.value, nld.len);
+               } else {
+                       __netlink_gen_data(key, &nld, false);
+                       nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
                }
                break;
        }
@@ -246,14 +253,14 @@ static int netlink_export_pad(unsigned char *data, const mpz_t v,
        return netlink_padded_len(i->len) / BITS_PER_BYTE;
 }
 
-static int netlink_gen_concat_data_expr(int end, const struct expr *i,
+static int netlink_gen_concat_data_expr(uint32_t flags, const struct expr *i,
                                        unsigned char *data)
 {
        struct expr *expr;
 
        switch (i->etype) {
        case EXPR_RANGE:
-               if (end)
+               if (flags & EXPR_F_INTERVAL_END)
                        expr = i->right;
                else
                        expr = i->left;
@@ -265,7 +272,7 @@ static int netlink_gen_concat_data_expr(int end, const struct expr *i,
                i = expr;
                break;
        case EXPR_PREFIX:
-               if (end) {
+               if (flags & EXPR_F_INTERVAL_END) {
                        int count;
                        mpz_t v;
 
@@ -281,6 +288,16 @@ static int netlink_gen_concat_data_expr(int end, const struct expr *i,
                }
                return netlink_export_pad(data, i->prefix->value, i);
        case EXPR_VALUE:
+               /* Switch byteorder only once for singleton values when the set
+                * contains concatenation of intervals.
+                */
+               if (!(flags & EXPR_F_INTERVAL))
+                       break;
+
+               expr = (struct expr *)i;
+               if (expr_basetype(expr)->type == TYPE_INTEGER &&
+                   expr->byteorder == BYTEORDER_HOST_ENDIAN)
+                       mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
                break;
        default:
                BUG("invalid expression type '%s' in set", expr_ops(i)->name);
@@ -293,14 +310,13 @@ static void __netlink_gen_concat(const struct expr *expr,
                                 struct nft_data_linearize *nld)
 {
        unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
-       int end = expr->flags & EXPR_F_INTERVAL_END;
        unsigned char data[len];
        const struct expr *i;
 
        memset(data, 0, len);
 
        list_for_each_entry(i, &expr->expressions, list)
-               offset += netlink_gen_concat_data_expr(end, i, data + offset);
+               offset += netlink_gen_concat_data_expr(expr->flags, i, data + offset);
 
        memcpy(nld->value, data, len);
        nld->len = len;
@@ -316,10 +332,10 @@ static void __netlink_gen_concat_expand(const struct expr *expr,
        memset(data, 0, len);
 
        list_for_each_entry(i, &expr->expressions, list)
-               offset += netlink_gen_concat_data_expr(false, i, data + offset);
+               offset += netlink_gen_concat_data_expr(0, i, data + offset);
 
        list_for_each_entry(i, &expr->expressions, list)
-               offset += netlink_gen_concat_data_expr(true, i, data + offset);
+               offset += netlink_gen_concat_data_expr(EXPR_F_INTERVAL_END, i, data + offset);
 
        memcpy(nld->value, data, len);
        nld->len = len;
index 0d7d5f255c00f0b17d095e1712d577f4b02b775a..374738a701d642adf1732411bb1c6caa65bcb101 100644 (file)
@@ -23,3 +23,5 @@ meta obrname "br0";fail
 meta mark set ct mark >> 8;ok
 
 meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 };ok
+ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 };ok
+ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 };ok
index bc268a2ef2aec1820c6d757271447ba211915944..92a1f9bff37352887a85bbb360bee15b167aef1f 100644 (file)
     }
 ]
 
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 }
+[
+    {
+        "match": {
+            "left": {
+                "concat": [
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ip"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "mark"
+                        }
+                    }
+                ]
+            },
+            "op": "==",
+            "right": {
+                "set": [
+                    {
+                        "concat": [
+                            "1.2.3.4",
+                            256
+                        ]
+                    },
+                    {
+                        "concat": [
+                            {
+                                "range": [
+                                    "1.2.3.6",
+                                    "1.2.3.8"
+                                ]
+                            },
+                            {
+                                "range": [
+                                    512,
+                                    768
+                                ]
+                            }
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 }
+[
+    {
+        "match": {
+            "left": {
+                "concat": [
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ip"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "mark"
+                        }
+                    }
+                ]
+            },
+            "op": "==",
+            "right": {
+                "set": [
+                    {
+                        "concat": [
+                            "1.2.3.4",
+                            256
+                        ]
+                    },
+                    {
+                        "concat": [
+                            "5.6.7.8",
+                            512
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+]
+
index 2b4e6c2d180ddf89c233303fb3c49c4eb2c49be3..ea54090727faa0f8d4821143466bf5c9abe8d579 100644 (file)
@@ -109,3 +109,27 @@ ip test-inet input
   [ byteorder reg 1 = hton(reg 1, 4, 4) ]
   [ payload load 2b @ transport header + 2 => reg 9 ]
   [ lookup reg 1 set __set%d ]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 }
+__set%d test-inet 87 size 2
+__set%d test-inet 0
+        element 04030201 00010000  - 04030201 00010000  : 0 [end]       element 06030201 00020000  - 08030201 00030000  : 0 [end]
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ meta load mark => reg 9 ]
+  [ byteorder reg 9 = hton(reg 9, 4, 4) ]
+  [ lookup reg 1 set __set%d ]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 }
+__set%d test-inet 3 size 2
+__set%d test-inet 0
+        element 04030201 00000100  : 0 [end]    element 08070605 00000200  : 0 [end]
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ meta load mark => reg 9 ]
+  [ lookup reg 1 set __set%d ]
+
index 3812a94d18c887c16509512e2a8682fdf18bf160..4d90af9a65579e5719e46f13618a24d441dc4073 100755 (executable)
@@ -9,6 +9,12 @@ RULESET="table ip t {
                counter
                elements = { 1.0.0.1 . udp . 53 }
        }
+       set s2 {
+               type ipv4_addr . mark
+               flags interval
+               elements = { 10.10.10.10 . 0x00000100,
+                            20.20.20.20 . 0x00000200 }
+       }
 }"
 
 $NFT -f - <<< $RULESET
index 875ec1d5c6a0172fd504b28792956b360d4fb37b..61547c5e75f99d521141701ee3a0b0ca4016cab7 100644 (file)
@@ -4,4 +4,11 @@ table ip t {
                flags interval
                counter
        }
+
+       set s2 {
+               type ipv4_addr . mark
+               flags interval
+               elements = { 10.10.10.10 . 0x00000100,
+                            20.20.20.20 . 0x00000200 }
+       }
 }