]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: bail out if anonymous concat set defines a non concat expression
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 10 Jan 2024 18:05:35 +0000 (19:05 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 12 Jan 2024 11:19:55 +0000 (12:19 +0100)
Iterate over the element list in the anonymous set to validate that all
expressions are concatenations, otherwise bail out.

  ruleset.nft:3:46-53: Error: expression is not a concatenation
               ip protocol . th dport vmap { tcp / 22 : accept, tcp . 80 : drop}
                                             ^^^^^^^^

This is based on a patch from Florian Westphal.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_map [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_vmap [new file with mode: 0644]

index eb55f6c0a429375a64c42a1769466796e8cdab48..e890585e2cfa1c403072b923da574aaf1477f8b3 100644 (file)
@@ -133,6 +133,13 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
        set->init       = expr;
        set->automerge  = set->flags & NFT_SET_INTERVAL;
 
+       if (set_evaluate(ctx, set) < 0) {
+               if (set->flags & NFT_SET_MAP)
+                       set->init = NULL;
+               set_free(set);
+               return NULL;
+       }
+
        if (ctx->table != NULL)
                list_add_tail(&set->list, &ctx->table->sets);
        else {
@@ -145,8 +152,6 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
                list_add_tail(&cmd->list, &ctx->cmd->list);
        }
 
-       set_evaluate(ctx, set);
-
        return set_ref_expr_alloc(&expr->location, set);
 }
 
@@ -2070,6 +2075,8 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
                mappings = implicit_set_declaration(ctx, "__map%d",
                                                    key, data,
                                                    mappings);
+               if (!mappings)
+                       return -1;
 
                if (ectx.len && mappings->set->data->len != ectx.len)
                        BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
@@ -2641,6 +2648,9 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
                                implicit_set_declaration(ctx, "__set%d",
                                                         expr_get(left), NULL,
                                                         right);
+                       if (!right)
+                               return -1;
+
                        /* fall through */
                case EXPR_SET_REF:
                        if (rel->left->etype == EXPR_CT &&
@@ -3283,6 +3293,8 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
 
        setref = implicit_set_declaration(ctx, stmt->meter.name,
                                          expr_get(key), NULL, set);
+       if (!setref)
+               return -1;
 
        setref->set->desc.size = stmt->meter.size;
        stmt->meter.set = setref;
@@ -4549,6 +4561,8 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
 
                mappings = implicit_set_declaration(ctx, "__objmap%d",
                                                    key, NULL, mappings);
+               if (!mappings)
+                       return -1;
                mappings->set->objtype  = stmt->objref.type;
 
                map->mappings = mappings;
@@ -4882,6 +4896,21 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
                set->flags |= NFT_SET_CONCAT;
        }
 
+       if (set_is_anonymous(set->flags) && set->key->etype == EXPR_CONCAT) {
+               struct expr *i;
+
+               list_for_each_entry(i, &set->init->expressions, list) {
+                       if ((i->etype == EXPR_SET_ELEM &&
+                            i->key->etype != EXPR_CONCAT &&
+                            i->key->etype != EXPR_SET_ELEM_CATCHALL) ||
+                           (i->etype == EXPR_MAPPING &&
+                            i->left->etype == EXPR_SET_ELEM &&
+                            i->left->key->etype != EXPR_CONCAT &&
+                            i->left->key->etype != EXPR_SET_ELEM_CATCHALL))
+                               return expr_error(ctx->msgs, i, "expression is not a concatenation");
+               }
+       }
+
        if (set_is_datamap(set->flags)) {
                if (set->data == NULL)
                        return set_error(ctx, set, "map definition does not "
diff --git a/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert b/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert
new file mode 100644 (file)
index 0000000..35eecf6
--- /dev/null
@@ -0,0 +1,5 @@
+table ip x {
+       chain y {
+               ip protocol . th dport { tcp / 22, udp . 67 }
+       }
+}
diff --git a/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_map b/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_map
new file mode 100644 (file)
index 0000000..3da16ce
--- /dev/null
@@ -0,0 +1,5 @@
+table ip x {
+       chain y {
+               meta mark set ip protocol . th dport map { tcp / 22 : 1234, udp . 67 : 1234 }
+       }
+}
diff --git a/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_vmap b/tests/shell/testcases/bogons/nft-f/unhandled_key_type_13_assert_vmap
new file mode 100644 (file)
index 0000000..f4dc273
--- /dev/null
@@ -0,0 +1,5 @@
+table ip x {
+       chain y {
+               ip protocol . th dport vmap { tcp / 22 : accept, udp . 67 : drop }
+       }
+}