]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: Fix for 'meta hour' ranges spanning date boundaries
authorPhil Sutter <phil@nwl.cc>
Fri, 25 Jul 2025 15:28:29 +0000 (17:28 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 31 Jul 2025 11:27:11 +0000 (13:27 +0200)
Introduction of EXPR_RANGE_SYMBOL type inadvertently disabled sanitizing
of meta hour ranges where the lower boundary has a higher value than the
upper boundary. This may happen outside of user control due to the fact
that given ranges are converted to UTC which is the kernel's native
timezone.

Perform the conditional match and op inversion with the new RHS
expression type as well after expanding it so values are comparable.
Since this replaces the whole range expression, make it replace the
relational's RHS entirely.

While at it extend testsuites to cover these corner-cases.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1805
Fixes: 347039f64509e ("src: add symbol range expression to further compact intervals")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
doc/primary-expression.txt
src/evaluate.c
tests/py/any/meta.t
tests/py/any/meta.t.json
tests/py/any/meta.t.json.output
tests/py/any/meta.t.payload
tests/shell/testcases/listing/meta_time

index 2266724e72598c56ed2f3befeb6139785d74a006..d5495e2c862918237636a8de9bf4b6dc0daa4de0 100644 (file)
@@ -137,7 +137,8 @@ Day of week|
 Integer (8 bit) or string
 |hour|
 Hour of day|
-String
+String value in the form HH:MM or HH:MM:SS. Values are expected to be less than
+24:00, although for technical reasons, 23:59:60 is accepted, too.
 |====================
 
 .Meta expression specific types
index c20a1d526c1ebacd2420c89843edd84cbaf3c16c..8f037601c45fe985d20ccbc4386c74c086b13710 100644 (file)
@@ -2441,10 +2441,9 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
        return 0;
 }
 
-static int expr_evaluate_symbol_range(struct eval_ctx *ctx, struct expr **exprp)
+static struct expr *symbol_range_expand(struct expr *expr)
 {
-       struct expr *left, *right, *range, *constant_range;
-       struct expr *expr = *exprp;
+       struct expr *left, *right;
 
        /* expand to symbol and range expressions to consolidate evaluation. */
        left = symbol_expr_alloc(&expr->location, expr->symtype,
@@ -2453,7 +2452,16 @@ static int expr_evaluate_symbol_range(struct eval_ctx *ctx, struct expr **exprp)
        right = symbol_expr_alloc(&expr->location, expr->symtype,
                                  (struct scope *)expr->scope,
                                  expr->identifier_range[1]);
-       range = range_expr_alloc(&expr->location, left, right);
+       return range_expr_alloc(&expr->location, left, right);
+}
+
+static int expr_evaluate_symbol_range(struct eval_ctx *ctx, struct expr **exprp)
+{
+       struct expr *left, *right, *range, *constant_range;
+       struct expr *expr = *exprp;
+
+       /* expand to symbol and range expressions to consolidate evaluation. */
+       range = symbol_range_expand(expr);
 
        if (expr_evaluate(ctx, &range) < 0) {
                expr_free(range);
@@ -2792,7 +2800,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 
        pctx = eval_proto_ctx(ctx);
 
-       if (rel->right->etype == EXPR_RANGE && lhs_is_meta_hour(rel->left)) {
+       if (lhs_is_meta_hour(rel->left) &&
+           (rel->right->etype == EXPR_RANGE ||
+            rel->right->etype == EXPR_RANGE_SYMBOL)) {
+               if (rel->right->etype == EXPR_RANGE_SYMBOL) {
+                       range = symbol_range_expand(rel->right);
+                       expr_free(rel->right);
+                       rel->right = range;
+               }
                ret = __expr_evaluate_range(ctx, &rel->right);
                if (ret)
                        return ret;
index 3f0ef121a8c03d7623bc7bb1e97654bb04093e30..74e4ba28343d96e8bc590b298214f15c38a8daaa 100644 (file)
@@ -218,6 +218,15 @@ meta hour "17:00:00" drop;ok;meta hour "17:00" drop
 meta hour "17:00:01" drop;ok
 meta hour "00:00" drop;ok
 meta hour "00:01" drop;ok
+meta hour "01:01" drop;ok
+meta hour "02:02" drop;ok
+meta hour "03:03" drop;ok
+meta hour "24:00" drop;fail
+meta hour "23:59:60" drop;ok;meta hour "00:00" drop
+meta hour "00:00"-"02:02" drop;ok
+meta hour "01:01"-"03:03" drop;ok
+meta hour "02:02"-"04:04" drop;ok
+meta hour "21:00"-"02:00" drop;ok
 time < "2022-07-01 11:00:00" accept;ok;meta time < "2022-07-01 11:00:00" accept
 time > "2022-07-01 11:00:00" accept;ok;meta time > "2022-07-01 11:00:00" accept
 
index 65590388bb80d3967a6c31ee1b6b685fcd589c52..8dcd1e13243de6c66edf367ba492b2095769d022 100644 (file)
     }
 ]
 
+# meta hour "01:01" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "01:01"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "02:02" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "02:02"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "03:03" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "03:03"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "24:00" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "24:00"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "23:59:60" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "23:59:60"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "00:00"-"02:02" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "in",
+            "right": {
+               "range": [
+                   "00:00",
+                   "02:02"
+               ]
+           }
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "01:01"-"03:03" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "in",
+            "right": {
+               "range": [
+                   "01:01",
+                   "03:03"
+               ]
+            }
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "02:02"-"04:04" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": {
+                "range": [
+                    "02:02",
+                    "04:04"
+                ]
+            }
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
+# meta hour "21:00"-"02:00" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "in",
+            "right": {
+                "range": [
+                    "21:00",
+                    "02:00"
+                ]
+            }
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
 # time < "2022-07-01 11:00:00" accept
 [
     {
index d46935dee513db561e04bfc6c15eb7a428c30767..8f4d597a5034eb54ad33fbca1dcffa45c0524f79 100644 (file)
     }
 ]
 
+# meta hour "23:59:60" drop
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "hour"
+                }
+            },
+            "op": "==",
+            "right": "00:00"
+        }
+    },
+    {
+        "drop": null
+    }
+]
+
index 52c3efa84eb5d03950026b02c1d904a149ef870d..3f9f3f22aecf94c8ac37f6f8f1bf06704c2a9532 100644 (file)
@@ -1052,6 +1052,57 @@ ip meta-test input
   [ cmp eq reg 1 0x0001359c ]
   [ immediate reg 0 drop ]
 
+# meta hour "01:01" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ cmp eq reg 1 0x000143ac ]
+  [ immediate reg 0 drop ]
+
+# meta hour "02:02" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ cmp eq reg 1 0x00000078 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "03:03" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ cmp eq reg 1 0x00000ec4 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "23:59:60" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ cmp eq reg 1 0x00013560 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "00:00"-"02:02" drop
+  [ meta load hour => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ range neq reg 1 0x78000000 0x60350100 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "01:01"-"03:03" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ range neq reg 1 0xc40e0000 0xac430100 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "02:02"-"04:04" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ range eq reg 1 0x78000000 0x101d0000 ]
+  [ immediate reg 0 drop ]
+
+# meta hour "21:00"-"02:00" drop
+ip test-ip4 input
+  [ meta load hour => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ range neq reg 1 0x00000000 0x300b0100 ]
+  [ immediate reg 0 drop ]
+
 # time < "2022-07-01 11:00:00" accept
 ip test-ip4 input
   [ meta load time => reg 1 ]
index 96a9d5570fd14bf0de3a2671d7864f5e42aa1ea8..91f94bdb1743221d65f7942ea4cb9275ec0dd339 100755 (executable)
@@ -65,3 +65,33 @@ printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 5 0 16 0 >> "$TMP1"
 printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 6 0 17 0 >> "$TMP1"
 
 check_decode EADT
+
+$NFT flush chain t c
+TZ=UTC-2 $NFT add rule t c meta hour "00:00"-"01:00"
+TZ=UTC-2 $NFT add rule t c meta hour "00:00"-"03:00"
+TZ=UTC-2 $NFT add rule t c meta hour "01:00"-"04:00"
+
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 1 0 > "$TMP1"
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 3 0 >> "$TMP1"
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 1 0 4 0 >> "$TMP1"
+
+check_decode UTC-2
+
+$NFT flush chain t c
+TZ=UTC-2 $NFT --debug=eval -f - <<EOF
+define midnight="00:00"
+define threeam="03:00"
+table t {
+       chain c {
+               meta hour \$midnight - "03:00"
+               meta hour 00:00 - \$threeam
+               meta hour \$midnight - \$threeam
+       }
+}
+EOF
+
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 3 0 > "$TMP1"
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 3 0 >> "$TMP1"
+printf "\t\tmeta hour \"%02d:%02d\"-\"%02d:%02d\"\n" 0 0 3 0 >> "$TMP1"
+
+check_decode UTC-2