From: Phil Sutter Date: Fri, 25 Jul 2025 15:28:29 +0000 (+0200) Subject: evaluate: Fix for 'meta hour' ranges spanning date boundaries X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6717ae094db29d1f4607107a2be0fa8042f7fe6;p=thirdparty%2Fnftables.git evaluate: Fix for 'meta hour' ranges spanning date boundaries 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 Reviewed-by: Pablo Neira Ayuso --- diff --git a/doc/primary-expression.txt b/doc/primary-expression.txt index 2266724e..d5495e2c 100644 --- a/doc/primary-expression.txt +++ b/doc/primary-expression.txt @@ -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 diff --git a/src/evaluate.c b/src/evaluate.c index c20a1d52..8f037601 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -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; diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t index 3f0ef121..74e4ba28 100644 --- a/tests/py/any/meta.t +++ b/tests/py/any/meta.t @@ -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 diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json index 65590388..8dcd1e13 100644 --- a/tests/py/any/meta.t.json +++ b/tests/py/any/meta.t.json @@ -2723,6 +2723,188 @@ } ] +# 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 [ { diff --git a/tests/py/any/meta.t.json.output b/tests/py/any/meta.t.json.output index d46935de..8f4d597a 100644 --- a/tests/py/any/meta.t.json.output +++ b/tests/py/any/meta.t.json.output @@ -646,3 +646,21 @@ } ] +# meta hour "23:59:60" drop +[ + { + "match": { + "left": { + "meta": { + "key": "hour" + } + }, + "op": "==", + "right": "00:00" + } + }, + { + "drop": null + } +] + diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload index 52c3efa8..3f9f3f22 100644 --- a/tests/py/any/meta.t.payload +++ b/tests/py/any/meta.t.payload @@ -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 ] diff --git a/tests/shell/testcases/listing/meta_time b/tests/shell/testcases/listing/meta_time index 96a9d557..91f94bdb 100755 --- a/tests/shell/testcases/listing/meta_time +++ b/tests/shell/testcases/listing/meta_time @@ -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 - < "$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