mirror of
git://slackware.nl/current.git
synced 2025-01-08 05:24:13 +01:00
249 lines
7.2 KiB
Diff
249 lines
7.2 KiB
Diff
|
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
|
||
|
|