]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: add missing range checks for dup,fwd and payload statements
authorFlorian Westphal <fw@strlen.de>
Thu, 11 Jan 2024 17:14:16 +0000 (18:14 +0100)
committerFlorian Westphal <fw@strlen.de>
Thu, 11 Jan 2024 20:34:08 +0000 (21:34 +0100)
Else we assert with:
BUG: unknown expression type range
nft: src/netlink_linearize.c:912: netlink_gen_expr: Assertion `0' failed.

While at it, condense meta and exthdr to reuse the same helper.

Signed-off-by: Florian Westphal <fw@strlen.de>
src/evaluate.c
tests/shell/testcases/bogons/nft-f/dup_fwd_ranges [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/unknown_expr_type_range_assert

index d11bed0144ddfb786c1bfeb501a12a533285a2cd..b13e7c02caa5c660f2015fdbec75fbe904410ab0 100644 (file)
@@ -74,6 +74,33 @@ static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx,
        return -1;
 }
 
+static const char *stmt_name(const struct stmt *stmt)
+{
+       switch (stmt->ops->type) {
+       case STMT_NAT:
+               switch (stmt->nat.type) {
+               case NFT_NAT_SNAT:
+                       return "snat";
+               case NFT_NAT_DNAT:
+                       return "dnat";
+               case NFT_NAT_REDIR:
+                       return "redirect";
+               case NFT_NAT_MASQ:
+                       return "masquerade";
+               }
+               break;
+       default:
+               break;
+       }
+
+       return stmt->ops->name;
+}
+
+static int stmt_error_range(struct eval_ctx *ctx, const struct stmt *stmt, const struct expr *e)
+{
+       return expr_error(ctx->msgs, e, "%s: range argument not supported", stmt_name(stmt));
+}
+
 static void key_fix_dtype_byteorder(struct expr *key)
 {
        const struct datatype *dtype = key->dtype;
@@ -3085,13 +3112,8 @@ static int stmt_evaluate_exthdr(struct eval_ctx *ctx, struct stmt *stmt)
        if (ret < 0)
                return ret;
 
-       switch (stmt->exthdr.val->etype) {
-       case EXPR_RANGE:
-               return expr_error(ctx->msgs, stmt->exthdr.val,
-                                  "cannot be a range");
-       default:
-               break;
-       }
+       if (stmt->exthdr.val->etype == EXPR_RANGE)
+               return stmt_error_range(ctx, stmt, stmt->exthdr.val);
 
        return 0;
 }
@@ -3124,6 +3146,9 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
                                 payload->byteorder) < 0)
                return -1;
 
+       if (stmt->payload.val->etype == EXPR_RANGE)
+               return stmt_error_range(ctx, stmt, stmt->payload.val);
+
        need_csum = stmt_evaluate_payload_need_csum(payload);
 
        if (!payload_needs_adjustment(payload)) {
@@ -3283,15 +3308,8 @@ static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
        if (ret < 0)
                return ret;
 
-       switch (stmt->meta.expr->etype) {
-       case EXPR_RANGE:
-               ret = expr_error(ctx->msgs, stmt->meta.expr,
-                                "Meta expression cannot be a range");
-               break;
-       default:
-               break;
-
-       }
+       if (stmt->meta.expr->etype == EXPR_RANGE)
+               return stmt_error_range(ctx, stmt, stmt->meta.expr);
 
        return ret;
 }
@@ -3314,6 +3332,9 @@ static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
                return stmt_error(ctx, stmt,
                                  "ct secmark must not be set to constant value");
 
+       if (stmt->ct.expr->etype == EXPR_RANGE)
+               return stmt_error_range(ctx, stmt, stmt->ct.expr);
+
        return 0;
 }
 
@@ -3831,28 +3852,6 @@ static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt,
        return 0;
 }
 
-static const char *stmt_name(const struct stmt *stmt)
-{
-       switch (stmt->ops->type) {
-       case STMT_NAT:
-               switch (stmt->nat.type) {
-               case NFT_NAT_SNAT:
-                       return "snat";
-               case NFT_NAT_DNAT:
-                       return "dnat";
-               case NFT_NAT_REDIR:
-                       return "redirect";
-               case NFT_NAT_MASQ:
-                       return "masquerade";
-               }
-               break;
-       default:
-               break;
-       }
-
-       return stmt->ops->name;
-}
-
 static int stmt_evaluate_l3proto(struct eval_ctx *ctx,
                                 struct stmt *stmt, uint8_t family)
 {
@@ -4250,6 +4249,9 @@ static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
                                                &stmt->dup.dev);
                        if (err < 0)
                                return err;
+
+                       if (stmt->dup.dev->etype == EXPR_RANGE)
+                               return stmt_error_range(ctx, stmt, stmt->dup.dev);
                }
                break;
        case NFPROTO_NETDEV:
@@ -4268,6 +4270,10 @@ static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
        default:
                return stmt_error(ctx, stmt, "unsupported family");
        }
+
+       if (stmt->dup.to->etype == EXPR_RANGE)
+               return stmt_error_range(ctx, stmt, stmt->dup.to);
+
        return 0;
 }
 
@@ -4289,6 +4295,9 @@ static int stmt_evaluate_fwd(struct eval_ctx *ctx, struct stmt *stmt)
                if (err < 0)
                        return err;
 
+               if (stmt->fwd.dev->etype == EXPR_RANGE)
+                       return stmt_error_range(ctx, stmt, stmt->fwd.dev);
+
                if (stmt->fwd.addr != NULL) {
                        switch (stmt->fwd.family) {
                        case NFPROTO_IPV4:
@@ -4307,6 +4316,9 @@ static int stmt_evaluate_fwd(struct eval_ctx *ctx, struct stmt *stmt)
                                                &stmt->fwd.addr);
                        if (err < 0)
                                return err;
+
+                       if (stmt->fwd.addr->etype == EXPR_RANGE)
+                               return stmt_error_range(ctx, stmt, stmt->fwd.addr);
                }
                break;
        default:
diff --git a/tests/shell/testcases/bogons/nft-f/dup_fwd_ranges b/tests/shell/testcases/bogons/nft-f/dup_fwd_ranges
new file mode 100644 (file)
index 0000000..efaff9e
--- /dev/null
@@ -0,0 +1,14 @@
+define dev = "1"-"2"
+
+table netdev t {
+       chain c {
+               fwd to 1-2
+               dup to 1-2
+       }
+}
+
+table ip t {
+       chain c {
+               dup to 1-2 device $dev
+       }
+}
index 234dd623167dc89a7be8bed92cac9af794d175d1..e6206736f1209b8f10080415581c5c5cdd094d97 100644 (file)
@@ -1,5 +1,7 @@
 table ip x {
-        chain k {
-                meta mark set 0x001-3434
-        }
+       chain k {
+               meta mark set 0x001-3434
+               ct mark set 0x001-3434
+               tcp dport set 1-3
+       }
 }