Blame SOURCES/0013-netlink_delinearize-postprocess-binary-ands-in-conca.patch

1d03cd
From 29f041b93d7fc4e23c62c2e2e3cbbeaafa83b4ef Mon Sep 17 00:00:00 2001
1d03cd
From: Phil Sutter <psutter@redhat.com>
1d03cd
Date: Thu, 9 Feb 2023 10:27:57 +0100
1d03cd
Subject: [PATCH] netlink_delinearize: postprocess binary ands in
1d03cd
 concatenations
1d03cd
1d03cd
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2094887
1d03cd
Upstream Status: nftables commit 89688c947efc3
1d03cd
1d03cd
commit 89688c947efc36d25c58c85650414fa3a491732e
1d03cd
Author: Florian Westphal <fw@strlen.de>
1d03cd
Date:   Tue Jun 14 21:56:48 2022 +0200
1d03cd
1d03cd
    netlink_delinearize: postprocess binary ands in concatenations
1d03cd
1d03cd
    Input:
1d03cd
    update ether saddr . vlan id timeout 5s @macset
1d03cd
    ether saddr . vlan id @macset
1d03cd
1d03cd
    Before this patch, gets rendered as:
1d03cd
    update @macset { @ll,48,48 . @ll,112,16 & 0xfff timeout 5s }
1d03cd
    @ll,48,48 . @ll,112,16 & 0xfff @macset
1d03cd
1d03cd
    After this, listing will show:
1d03cd
    update @macset { @ll,48,48 . vlan id timeout 5s }
1d03cd
    @ll,48,48 . vlan id @macset
1d03cd
1d03cd
    The @ll, ... is due to vlan description replacing the ethernet one,
1d03cd
    so payload decode fails to take the concatenation apart (the ethernet
1d03cd
    header payload info is matched vs. vlan template).
1d03cd
1d03cd
    This will be adjusted by a followup patch.
1d03cd
1d03cd
    Signed-off-by: Florian Westphal <fw@strlen.de>
1d03cd
1d03cd
Signed-off-by: Phil Sutter <psutter@redhat.com>
1d03cd
---
1d03cd
 include/netlink.h         |  6 ++++++
1d03cd
 src/netlink_delinearize.c | 45 ++++++++++++++++++++++++++++++++++-----
1d03cd
 2 files changed, 46 insertions(+), 5 deletions(-)
1d03cd
1d03cd
diff --git a/include/netlink.h b/include/netlink.h
1d03cd
index e8e0f68..71c888f 100644
1d03cd
--- a/include/netlink.h
1d03cd
+++ b/include/netlink.h
1d03cd
@@ -42,10 +42,16 @@ struct netlink_parse_ctx {
1d03cd
 	struct netlink_ctx	*nlctx;
1d03cd
 };
1d03cd
 
1d03cd
+
1d03cd
+#define RULE_PP_IN_CONCATENATION	(1 << 0)
1d03cd
+
1d03cd
+#define RULE_PP_REMOVE_OP_AND		(RULE_PP_IN_CONCATENATION)
1d03cd
+
1d03cd
 struct rule_pp_ctx {
1d03cd
 	struct proto_ctx	pctx;
1d03cd
 	struct payload_dep_ctx	pdctx;
1d03cd
 	struct stmt		*stmt;
1d03cd
+	unsigned int		flags;
1d03cd
 };
1d03cd
 
1d03cd
 extern const struct input_descriptor indesc_netlink;
1d03cd
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
1d03cd
index 2f13990..cba419d 100644
1d03cd
--- a/src/netlink_delinearize.c
1d03cd
+++ b/src/netlink_delinearize.c
1d03cd
@@ -2259,12 +2259,13 @@ static void binop_adjust(const struct expr *binop, struct expr *right,
1d03cd
 	}
1d03cd
 }
1d03cd
 
1d03cd
-static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
1d03cd
-			      struct expr **expr_binop)
1d03cd
+static void __binop_postprocess(struct rule_pp_ctx *ctx,
1d03cd
+				struct expr *expr,
1d03cd
+				struct expr *left,
1d03cd
+				struct expr *mask,
1d03cd
+				struct expr **expr_binop)
1d03cd
 {
1d03cd
 	struct expr *binop = *expr_binop;
1d03cd
-	struct expr *left = binop->left;
1d03cd
-	struct expr *mask = binop->right;
1d03cd
 	unsigned int shift;
1d03cd
 
1d03cd
 	assert(binop->etype == EXPR_BINOP);
1d03cd
@@ -2300,15 +2301,26 @@ static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
1d03cd
 
1d03cd
 		assert(binop->left == left);
1d03cd
 		*expr_binop = expr_get(left);
1d03cd
-		expr_free(binop);
1d03cd
 
1d03cd
 		if (left->etype == EXPR_PAYLOAD)
1d03cd
 			payload_match_postprocess(ctx, expr, left);
1d03cd
 		else if (left->etype == EXPR_EXTHDR && right)
1d03cd
 			expr_set_type(right, left->dtype, left->byteorder);
1d03cd
+
1d03cd
+		expr_free(binop);
1d03cd
 	}
1d03cd
 }
1d03cd
 
1d03cd
+static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
1d03cd
+			      struct expr **expr_binop)
1d03cd
+{
1d03cd
+	struct expr *binop = *expr_binop;
1d03cd
+	struct expr *left = binop->left;
1d03cd
+	struct expr *mask = binop->right;
1d03cd
+
1d03cd
+	__binop_postprocess(ctx, expr, left, mask, expr_binop);
1d03cd
+}
1d03cd
+
1d03cd
 static void map_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr)
1d03cd
 {
1d03cd
 	struct expr *binop = expr->map;
1d03cd
@@ -2541,6 +2553,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
1d03cd
 		LIST_HEAD(tmp);
1d03cd
 		struct expr *n;
1d03cd
 
1d03cd
+		ctx->flags |= RULE_PP_IN_CONCATENATION;
1d03cd
 		list_for_each_entry_safe(i, n, &expr->expressions, list) {
1d03cd
 			if (type) {
1d03cd
 				dtype = concat_subtype_lookup(type, --off);
1d03cd
@@ -2552,6 +2565,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
1d03cd
 
1d03cd
 			ntype = concat_subtype_add(ntype, i->dtype->type);
1d03cd
 		}
1d03cd
+		ctx->flags &= ~RULE_PP_IN_CONCATENATION;
1d03cd
 		list_splice(&tmp, &expr->expressions);
1d03cd
 		datatype_set(expr, concat_type_alloc(ntype));
1d03cd
 		break;
1d03cd
@@ -2568,6 +2582,27 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
1d03cd
 			expr_set_type(expr->right, &integer_type,
1d03cd
 				      BYTEORDER_HOST_ENDIAN);
1d03cd
 			break;
1d03cd
+		case OP_AND:
1d03cd
+			expr_set_type(expr->right, expr->left->dtype,
1d03cd
+				      expr->left->byteorder);
1d03cd
+
1d03cd
+			/* Do not process OP_AND in ordinary rule context.
1d03cd
+			 *
1d03cd
+			 * Removal needs to be performed as part of the relational
1d03cd
+			 * operation because the RHS constant might need to be adjusted
1d03cd
+			 * (shifted).
1d03cd
+			 *
1d03cd
+			 * This is different in set element context or concatenations:
1d03cd
+			 * There is no relational operation (eq, neq and so on), thus
1d03cd
+			 * it needs to be processed right away.
1d03cd
+			 */
1d03cd
+			if ((ctx->flags & RULE_PP_REMOVE_OP_AND) &&
1d03cd
+			    expr->left->etype == EXPR_PAYLOAD &&
1d03cd
+			    expr->right->etype == EXPR_VALUE) {
1d03cd
+				__binop_postprocess(ctx, expr, expr->left, expr->right, exprp);
1d03cd
+				return;
1d03cd
+			}
1d03cd
+			break;
1d03cd
 		default:
1d03cd
 			expr_set_type(expr->right, expr->left->dtype,
1d03cd
 				      expr->left->byteorder);
1d03cd
-- 
1d03cd
2.39.1
1d03cd