* [nft PATCH] evaluate: Fix for 'meta hour' ranges spanning date boundaries
@ 2025-07-25 21:26 Phil Sutter
2025-07-28 23:36 ` Pablo Neira Ayuso
0 siblings, 1 reply; 3+ messages in thread
From: Phil Sutter @ 2025-07-25 21:26 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
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.
Restore the conditional match and op inversion by matching on the new
RHS expression type and also expand 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.
Fixes: 347039f64509e ("src: add symbol range expression to further compact intervals")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/evaluate.c | 25 +++--
tests/py/any/meta.t | 6 ++
tests/py/any/meta.t.json | 123 ++++++++++++++++++++++++
tests/py/any/meta.t.json.output | 66 +++++++++++++
tests/py/any/meta.t.payload | 38 ++++++++
tests/shell/testcases/listing/meta_time | 11 +++
6 files changed, 262 insertions(+), 7 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 9c90590860585..b67c81f01c0e2 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2421,10 +2421,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,
@@ -2433,7 +2432,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);
@@ -2772,12 +2780,15 @@ 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)) {
- ret = __expr_evaluate_range(ctx, &rel->right);
+ if (lhs_is_meta_hour(rel->left) &&
+ rel->right->etype == EXPR_RANGE_SYMBOL) {
+ range = symbol_range_expand(rel->right);
+ ret = __expr_evaluate_range(ctx, &range);
if (ret)
return ret;
- range = rel->right;
+ expr_free(rel->right);
+ rel->right = range;
/*
* We may need to do this for proper cross-day ranges,
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index 3f0ef121a8c03..0d0c268636705 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -218,6 +218,12 @@ 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 "00:00"-"02:02" drop;ok
+meta hour "01:01"-"03:03" drop;ok
+meta hour "02:02"-"04:04" 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
diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json
index 65590388bb80d..b11aae86396c9 100644
--- a/tests/py/any/meta.t.json
+++ b/tests/py/any/meta.t.json
@@ -2723,6 +2723,129 @@
}
]
+# 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 "00:00"-"02:02" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ "00:00",
+ "02:02"
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "01:01"-"03:03" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "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
+ }
+]
+
# time < "2022-07-01 11:00:00" accept
[
{
diff --git a/tests/py/any/meta.t.json.output b/tests/py/any/meta.t.json.output
index d46935dee513d..ecb211335b576 100644
--- a/tests/py/any/meta.t.json.output
+++ b/tests/py/any/meta.t.json.output
@@ -646,3 +646,69 @@
}
]
+# meta hour "00:00"-"02:02" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ "02:00",
+ "02:02"
+ ]
+ },
+ {
+ "range": [
+ "00:00",
+ "02:00"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "01:01"-"03:03" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ "02:00",
+ "03:03"
+ ]
+ },
+ {
+ "range": [
+ "01:01",
+ "02:00"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
index 52c3efa84eb5d..2abb44ea2e868 100644
--- a/tests/py/any/meta.t.payload
+++ b/tests/py/any/meta.t.payload
@@ -1052,6 +1052,44 @@ 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 "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 ]
+
# time < "2022-07-01 11:00:00" accept
ip test-ip4 input
[ meta load time => reg 1 ]
diff --git a/tests/shell/testcases/listing/meta_time b/tests/shell/testcases/listing/meta_time
index 96a9d5570fd14..61314a99c6498 100755
--- a/tests/shell/testcases/listing/meta_time
+++ b/tests/shell/testcases/listing/meta_time
@@ -65,3 +65,14 @@ 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 { \"02:00\"-\"03:00\", \"00:00\"-\"02:00\" }\n" >> "$TMP1"
+printf "\t\tmeta hour { \"02:00\"-\"04:00\", \"01:00\"-\"02:00\" }\n" >> "$TMP1"
+
+check_decode UTC-2
--
2.49.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [nft PATCH] evaluate: Fix for 'meta hour' ranges spanning date boundaries
2025-07-25 21:26 [nft PATCH] evaluate: Fix for 'meta hour' ranges spanning date boundaries Phil Sutter
@ 2025-07-28 23:36 ` Pablo Neira Ayuso
2025-07-29 13:04 ` Phil Sutter
0 siblings, 1 reply; 3+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-28 23:36 UTC (permalink / raw)
To: Phil Sutter; +Cc: netfilter-devel
On Fri, Jul 25, 2025 at 11:26:40PM +0200, Phil Sutter wrote:
> 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.
>
> Restore the conditional match and op inversion by matching on the new
> RHS expression type and also expand it so values are comparable. Since
> this replaces the whole range expression, make it replace the
> relational's RHS entirely.
Thanks, I suspect this bug is related to this recent ticket:
https://bugzilla.netfilter.org/show_bug.cgi?id=1805
> While at it extend testsuites to cover these corner-cases.
Thanks for improving coverage for this.
> 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>
> @@ -2772,12 +2780,15 @@ 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)) {
> - ret = __expr_evaluate_range(ctx, &rel->right);
> + if (lhs_is_meta_hour(rel->left) &&
> + rel->right->etype == EXPR_RANGE_SYMBOL) {
Side note, thanks for reversing this check.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [nft PATCH] evaluate: Fix for 'meta hour' ranges spanning date boundaries
2025-07-28 23:36 ` Pablo Neira Ayuso
@ 2025-07-29 13:04 ` Phil Sutter
0 siblings, 0 replies; 3+ messages in thread
From: Phil Sutter @ 2025-07-29 13:04 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
On Tue, Jul 29, 2025 at 01:36:08AM +0200, Pablo Neira Ayuso wrote:
> On Fri, Jul 25, 2025 at 11:26:40PM +0200, Phil Sutter wrote:
> > 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.
> >
> > Restore the conditional match and op inversion by matching on the new
> > RHS expression type and also expand it so values are comparable. Since
> > this replaces the whole range expression, make it replace the
> > relational's RHS entirely.
>
> Thanks, I suspect this bug is related to this recent ticket:
>
> https://bugzilla.netfilter.org/show_bug.cgi?id=1805
Ah yes, I forgot the "Closes:" tag, sorry!
> > While at it extend testsuites to cover these corner-cases.
>
> Thanks for improving coverage for this.
Above ticket also mentions how "23:59:60" is accepted when "24:00" is
not. I'll send a v2 which describes the expected values in nft.8 to
cover for this oddity in strptime() implementation.
> > 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>
>
> > @@ -2772,12 +2780,15 @@ 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)) {
> > - ret = __expr_evaluate_range(ctx, &rel->right);
> > + if (lhs_is_meta_hour(rel->left) &&
> > + rel->right->etype == EXPR_RANGE_SYMBOL) {
>
> Side note, thanks for reversing this check.
I did it merely because consecutive lines being longer than the former
ones seem more readable to me. What do you like about it? :)
Thanks, Phil
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-29 13:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-25 21:26 [nft PATCH] evaluate: Fix for 'meta hour' ranges spanning date boundaries Phil Sutter
2025-07-28 23:36 ` Pablo Neira Ayuso
2025-07-29 13:04 ` Phil Sutter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).