All of lore.kernel.org
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH nft v2 1/3] netlink_delinearize: add missing icmp id/sequence support
Date: Tue, 15 Jun 2021 18:01:49 +0200	[thread overview]
Message-ID: <20210615160151.10594-2-fw@strlen.de> (raw)
In-Reply-To: <20210615160151.10594-1-fw@strlen.de>

Pablo reports following input and output:
in: icmpv6 id 1
out: icmpv6 type { echo-request, echo-reply } icmpv6 parameter-problem 65536/16

Reason is that icmp fields overlap, decoding of the correct name requires
check of the icmpv6 type.  This only works for equality tests, for
instance

in: icmpv6 type echo-request icmpv6 id 1
will be listed as "icmpv6 id 1" (which is not correct either, since the
input only matches on echo-request).

with this patch, output of 'icmpv6 id 1' is
icmpv6 type { echo-request, echo-reply } icmpv6 id 1

The second problem, the removal of a single check (request OR reply),
is resolved in the followup patch.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 v2: make sure dependency set candidate a) has elements and b) is
 anonymous.

 src/netlink_delinearize.c | 68 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 3 deletions(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 9a1cf3c4f7d9..2785a9490682 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1819,9 +1819,6 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
 	enum proto_bases base = left->payload.base;
 	bool stacked;
 
-	if (ctx->pdctx.icmp_type)
-		ctx->pctx.th_dep.icmp.type = ctx->pdctx.icmp_type;
-
 	payload_expr_expand(&list, left, &ctx->pctx);
 
 	list_for_each_entry(left, &list, list) {
@@ -1868,6 +1865,58 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
 	ctx->stmt = NULL;
 }
 
+static void payload_icmp_check(struct rule_pp_ctx *rctx, struct expr *expr, const struct expr *value)
+{
+	const struct proto_hdr_template *tmpl;
+	const struct proto_desc *desc;
+	uint8_t icmp_type;
+	unsigned int i;
+
+	assert(expr->etype == EXPR_PAYLOAD);
+	assert(value->etype == EXPR_VALUE);
+
+	if (expr->payload.base != PROTO_BASE_TRANSPORT_HDR)
+		return;
+
+	/* icmp(v6) type is 8 bit, if value is smaller or larger, this is not
+	 * a protocol dependency.
+	 */
+	if (expr->len != 8 || value->len != 8 || rctx->pctx.th_dep.icmp.type)
+		return;
+
+	desc = rctx->pctx.protocol[expr->payload.base].desc;
+	if (desc == NULL)
+		return;
+
+	/* not icmp? ignore. */
+	if (desc != &proto_icmp && desc != &proto_icmp6)
+		return;
+
+	assert(desc->base == expr->payload.base);
+
+	icmp_type = mpz_get_uint8(value->value);
+
+	for (i = 1; i < array_size(desc->templates); i++) {
+		tmpl = &desc->templates[i];
+
+		if (tmpl->len == 0)
+			return;
+
+		if (tmpl->offset != expr->payload.offset ||
+		    tmpl->len != expr->len)
+			continue;
+
+		/* Matches but doesn't load a protocol key -> ignore. */
+		if (desc->protocol_key != i)
+			return;
+
+		expr->payload.desc = desc;
+		expr->payload.tmpl = tmpl;
+		rctx->pctx.th_dep.icmp.type = icmp_type;
+		return;
+	}
+}
+
 static void payload_match_postprocess(struct rule_pp_ctx *ctx,
 				      struct expr *expr,
 				      struct expr *payload)
@@ -1883,6 +1932,19 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
 		if (expr->right->etype == EXPR_VALUE) {
 			payload_match_expand(ctx, expr, payload);
 			break;
+		} else if (expr->right->etype == EXPR_SET_REF) {
+			struct set *set = expr->right->set;
+
+			if (set_is_anonymous(set->flags) &&
+			    !list_empty(&set->init->expressions)) {
+				struct expr *elem;
+
+				elem = list_first_entry(&set->init->expressions, struct expr, list);
+
+				if (elem->etype == EXPR_SET_ELEM &&
+				    elem->key->etype == EXPR_VALUE)
+					payload_icmp_check(ctx, payload, elem->key);
+			}
 		}
 		/* Fall through */
 	default:
-- 
2.31.1


  reply	other threads:[~2021-06-15 16:02 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-15 16:01 [PATCH nft v2 0/3] fix icmpv6 id dependeny handling Florian Westphal
2021-06-15 16:01 ` Florian Westphal [this message]
2021-06-30 15:13   ` [PATCH nft v2 1/3] netlink_delinearize: add missing icmp id/sequence support Phil Sutter
2021-06-30 15:34     ` Florian Westphal
2021-06-30 15:58     ` Florian Westphal
2021-06-30 17:12       ` Phil Sutter
2021-06-15 16:01 ` [PATCH nft v2 2/3] payload: do not remove icmp echo dependency Florian Westphal
2021-06-15 16:01 ` [PATCH nft v2 3/3] tests: add a icmp-reply only and icmpv6 id test cases Florian Westphal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210615160151.10594-2-fw@strlen.de \
    --to=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.