diff options
Diffstat (limited to 'source/n/nftables/5f1676ac9f1aeb36d7695c3c354dade013a1e4f3.patch')
-rw-r--r-- | source/n/nftables/5f1676ac9f1aeb36d7695c3c354dade013a1e4f3.patch | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/source/n/nftables/5f1676ac9f1aeb36d7695c3c354dade013a1e4f3.patch b/source/n/nftables/5f1676ac9f1aeb36d7695c3c354dade013a1e4f3.patch new file mode 100644 index 000000000..26eb9b2fc --- /dev/null +++ b/source/n/nftables/5f1676ac9f1aeb36d7695c3c354dade013a1e4f3.patch @@ -0,0 +1,248 @@ +From 5f1676ac9f1aeb36d7695c3c354dade013a1e4f3 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso <pablo@netfilter.org> +Date: Tue, 18 Jul 2023 23:10:01 +0200 +Subject: meta: stash context statement length when generating payload/meta + dependency + +... meta mark set ip dscp + +generates an implicit dependency from the inet family to match on meta +nfproto ip. + +The length of this implicit expression is incorrectly adjusted to the +statement length, ie. relational to compare meta nfproto takes 4 bytes +instead of 1 byte. The evaluation of 'ip dscp' under the meta mark +statement triggers this implicit dependency which should not consider +the context statement length since it is added before the statement +itself. + +This problem shows when listing the ruleset, since netlink_parse_cmp() +where left->len < right->len, hence handling the implicit dependency as +a concatenation, but it is actually a bug in the evaluation step that +leads to incorrect bytecode. + +Fixes: 3c64ea7995cb ("evaluate: honor statement length in integer evaluation") +Fixes: edecd58755a8 ("evaluate: support shifts larger than the width of the left operand") +Tested-by: Brian Davidson <davidson.brian@gmail.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + src/payload.c | 13 +++++++ + tests/py/inet/meta.t | 5 +++ + tests/py/inet/meta.t.json | 86 ++++++++++++++++++++++++++++++++++++++++++++ + tests/py/inet/meta.t.payload | 40 +++++++++++++++++++++ + 4 files changed, 144 insertions(+) + +diff --git a/src/payload.c b/src/payload.c +index f67b5407..7862745b 100644 +--- a/src/payload.c ++++ b/src/payload.c +@@ -409,6 +409,7 @@ static int payload_add_dependency(struct eval_ctx *ctx, + const struct proto_hdr_template *tmpl; + struct expr *dep, *left, *right; + struct proto_ctx *pctx; ++ unsigned int stmt_len; + struct stmt *stmt; + int protocol; + +@@ -429,11 +430,16 @@ static int payload_add_dependency(struct eval_ctx *ctx, + constant_data_ptr(protocol, tmpl->len)); + + dep = relational_expr_alloc(&expr->location, OP_EQ, left, right); ++ ++ stmt_len = ctx->stmt_len; ++ ctx->stmt_len = 0; ++ + stmt = expr_stmt_alloc(&dep->location, dep); + if (stmt_evaluate(ctx, stmt) < 0) { + return expr_error(ctx->msgs, expr, + "dependency statement is invalid"); + } ++ ctx->stmt_len = stmt_len; + + if (ctx->inner_desc) { + if (tmpl->meta_key) +@@ -543,6 +549,7 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr, + const struct hook_proto_desc *h; + const struct proto_desc *desc; + struct proto_ctx *pctx; ++ unsigned int stmt_len; + struct stmt *stmt; + uint16_t type; + +@@ -559,12 +566,18 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr, + "protocol specification is invalid " + "for this family"); + ++ stmt_len = ctx->stmt_len; ++ ctx->stmt_len = 0; ++ + stmt = meta_stmt_meta_iiftype(&expr->location, type); + if (stmt_evaluate(ctx, stmt) < 0) { + return expr_error(ctx->msgs, expr, + "dependency statement is invalid"); + } + *res = stmt; ++ ++ ctx->stmt_len = stmt_len; ++ + return 0; + } + +diff --git a/tests/py/inet/meta.t b/tests/py/inet/meta.t +index 374738a7..5c062b39 100644 +--- a/tests/py/inet/meta.t ++++ b/tests/py/inet/meta.t +@@ -25,3 +25,8 @@ 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 ++ ++meta mark set ip dscp;ok ++meta mark set ip dscp | 0x40;ok ++meta mark set ip6 dscp;ok ++meta mark set ip6 dscp | 0x40;ok +diff --git a/tests/py/inet/meta.t.json b/tests/py/inet/meta.t.json +index 92a1f9bf..3ba0fd1d 100644 +--- a/tests/py/inet/meta.t.json ++++ b/tests/py/inet/meta.t.json +@@ -440,3 +440,89 @@ + } + ] + ++# meta mark set ip dscp ++[ ++ { ++ "mangle": { ++ "key": { ++ "meta": { ++ "key": "mark" ++ } ++ }, ++ "value": { ++ "payload": { ++ "field": "dscp", ++ "protocol": "ip" ++ } ++ } ++ } ++ } ++] ++ ++# meta mark set ip dscp | 0x40 ++[ ++ { ++ "mangle": { ++ "key": { ++ "meta": { ++ "key": "mark" ++ } ++ }, ++ "value": { ++ "|": [ ++ { ++ "payload": { ++ "field": "dscp", ++ "protocol": "ip" ++ } ++ }, ++ 64 ++ ] ++ } ++ } ++ } ++] ++ ++# meta mark set ip6 dscp ++[ ++ { ++ "mangle": { ++ "key": { ++ "meta": { ++ "key": "mark" ++ } ++ }, ++ "value": { ++ "payload": { ++ "field": "dscp", ++ "protocol": "ip6" ++ } ++ } ++ } ++ } ++] ++ ++# meta mark set ip6 dscp | 0x40 ++[ ++ { ++ "mangle": { ++ "key": { ++ "meta": { ++ "key": "mark" ++ } ++ }, ++ "value": { ++ "|": [ ++ { ++ "payload": { ++ "field": "dscp", ++ "protocol": "ip6" ++ } ++ }, ++ 64 ++ ] ++ } ++ } ++ } ++] ++ +diff --git a/tests/py/inet/meta.t.payload b/tests/py/inet/meta.t.payload +index ea540907..c53b5077 100644 +--- a/tests/py/inet/meta.t.payload ++++ b/tests/py/inet/meta.t.payload +@@ -133,3 +133,43 @@ inet test-inet input + [ meta load mark => reg 9 ] + [ lookup reg 1 set __set%d ] + ++# meta mark set ip dscp ++inet test-inet input ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x00000002 ] ++ [ payload load 1b @ network header + 1 => reg 1 ] ++ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ] ++ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ] ++ [ meta set mark with reg 1 ] ++ ++# meta mark set ip dscp | 0x40 ++inet test-inet input ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x00000002 ] ++ [ payload load 1b @ network header + 1 => reg 1 ] ++ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ] ++ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ] ++ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ] ++ [ meta set mark with reg 1 ] ++ ++# meta mark set ip6 dscp ++inet test-inet input ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x0000000a ] ++ [ payload load 2b @ network header + 0 => reg 1 ] ++ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ] ++ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ] ++ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ] ++ [ meta set mark with reg 1 ] ++ ++# meta mark set ip6 dscp | 0x40 ++inet test-inet input ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x0000000a ] ++ [ payload load 2b @ network header + 0 => reg 1 ] ++ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ] ++ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ] ++ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ] ++ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ] ++ [ meta set mark with reg 1 ] ++ +-- +cgit v1.2.3 + |