]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink_delinearize: add postprocessing for payload binops
authorJeremy Sowden <jeremy@azazel.net>
Mon, 4 Apr 2022 12:13:47 +0000 (13:13 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Jan 2025 21:10:04 +0000 (22:10 +0100)
commit b3d4028a27edff0684a47356b13da494f7ec08ff upstream.

If a user uses a payload expression as a statement argument:

  nft add rule t c meta mark set ip dscp lshift 2 or 0x10

we may need to undo munging during delinearization.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
src/netlink_delinearize.c

index 2695fa9349c4e44d40233d30b612312b5646221d..b37ac5fdd964670f892d58ce7ca14f6dc07c09f1 100644 (file)
@@ -2465,6 +2465,42 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx,
        }
 }
 
+static bool payload_binop_postprocess(struct rule_pp_ctx *ctx,
+                                     struct expr **exprp)
+{
+       struct expr *expr = *exprp;
+
+       if (expr->op != OP_RSHIFT)
+               return false;
+
+       if (expr->left->etype == EXPR_UNARY) {
+               /*
+                * If the payload value was originally in a different byte-order
+                * from the payload expression, there will be a byte-order
+                * conversion to remove.
+                */
+               struct expr *left = expr_get(expr->left->arg);
+               expr_free(expr->left);
+               expr->left = left;
+       }
+
+       if (expr->left->etype != EXPR_BINOP || expr->left->op != OP_AND)
+               return false;
+
+       if (expr->left->left->etype != EXPR_PAYLOAD)
+               return false;
+
+       expr_set_type(expr->right, &integer_type,
+                     BYTEORDER_HOST_ENDIAN);
+       expr_postprocess(ctx, &expr->right);
+
+       binop_postprocess(ctx, expr, &expr->left);
+       *exprp = expr_get(expr->left);
+       expr_free(expr);
+
+       return true;
+}
+
 static struct expr *string_wildcard_expr_alloc(struct location *loc,
                                               const struct expr *mask,
                                               const struct expr *expr)
@@ -2584,6 +2620,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
                expr_set_type(expr, expr->arg->dtype, !expr->arg->byteorder);
                break;
        case EXPR_BINOP:
+               if (payload_binop_postprocess(ctx, exprp))
+                       break;
+
                expr_postprocess(ctx, &expr->left);
                switch (expr->op) {
                case OP_LSHIFT: