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

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