Blame SOURCES/0033-evaluate-Perform-set-evaluation-on-implicitly-declar.patch

acfc56
From 785823a1f607a7bcd32d4cb42655422c223fcad5 Mon Sep 17 00:00:00 2001
acfc56
From: Phil Sutter <psutter@redhat.com>
acfc56
Date: Mon, 7 Dec 2020 18:25:20 +0100
acfc56
Subject: [PATCH] evaluate: Perform set evaluation on implicitly declared
acfc56
 (anonymous) sets
acfc56
acfc56
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1877022
acfc56
Upstream Status: nftables commit 7aa08d45031ec
acfc56
acfc56
commit 7aa08d45031ec7ce5dadb4979471d626367c09cd
acfc56
Author: Stefano Brivio <sbrivio@redhat.com>
acfc56
Date:   Wed May 27 22:51:21 2020 +0200
acfc56
acfc56
    evaluate: Perform set evaluation on implicitly declared (anonymous) sets
acfc56
acfc56
    If a set is implicitly declared, set_evaluate() is not called as a
acfc56
    result of cmd_evaluate_add(), because we're adding in fact something
acfc56
    else (e.g. a rule). Expression-wise, evaluation still happens as the
acfc56
    implicit set expression is eventually found in the tree and handled
acfc56
    by expr_evaluate_set(), but context-wise evaluation (set_evaluate())
acfc56
    is skipped, and this might be relevant instead.
acfc56
acfc56
    This is visible in the reported case of an anonymous set including
acfc56
    concatenated ranges:
acfc56
acfc56
      # nft add rule t c ip saddr . tcp dport { 192.0.2.1 . 20-30 } accept
acfc56
      BUG: invalid range expression type concat
acfc56
      nft: expression.c:1160: range_expr_value_low: Assertion `0' failed.
acfc56
      Aborted
acfc56
acfc56
    because we reach do_add_set() without properly evaluated flags and
acfc56
    set description, and eventually end up in expr_to_intervals(), which
acfc56
    can't handle that expression.
acfc56
acfc56
    Explicitly call set_evaluate() as we add anonymous sets into the
acfc56
    context, and instruct the same function to:
acfc56
    - skip expression-wise set evaluation if the set is anonymous, as
acfc56
      that happens later anyway as part of the general tree evaluation
acfc56
    - skip the insertion in the set cache, as it makes no sense to have
acfc56
      sets that shouldn't be referenced there
acfc56
acfc56
    For object maps, the allocation of the expression for set->data is
acfc56
    already handled by set_evaluate(), so we can now drop that from
acfc56
    stmt_evaluate_objref_map().
acfc56
acfc56
    v2:
acfc56
     - skip insertion of set in cache (Pablo Neira Ayuso)
acfc56
     - drop double allocation of expression (and leak of the first
acfc56
       one) for object maps (Pablo Neira Ayuso)
acfc56
acfc56
    Reported-by: Pablo Neira Ayuso <pablo@netfilter.org>
acfc56
    Reported-by: Phil Sutter <phil@nwl.cc>
acfc56
    Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
acfc56
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
acfc56
---
acfc56
 src/evaluate.c | 20 ++++++++++----------
acfc56
 1 file changed, 10 insertions(+), 10 deletions(-)
acfc56
acfc56
diff --git a/src/evaluate.c b/src/evaluate.c
acfc56
index 578dcae..fc45cef 100644
acfc56
--- a/src/evaluate.c
acfc56
+++ b/src/evaluate.c
acfc56
@@ -75,6 +75,7 @@ static void key_fix_dtype_byteorder(struct expr *key)
acfc56
 	datatype_set(key, set_datatype_alloc(dtype, key->byteorder));
acfc56
 }
acfc56
 
acfc56
+static int set_evaluate(struct eval_ctx *ctx, struct set *set);
acfc56
 static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
acfc56
 					     const char *name,
acfc56
 					     struct expr *key,
acfc56
@@ -105,6 +106,8 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
acfc56
 		list_add_tail(&cmd->list, &ctx->cmd->list);
acfc56
 	}
acfc56
 
acfc56
+	set_evaluate(ctx, set);
acfc56
+
acfc56
 	return set_ref_expr_alloc(&expr->location, set);
acfc56
 }
acfc56
 
acfc56
@@ -3171,12 +3174,6 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
acfc56
 
acfc56
 		mappings = implicit_set_declaration(ctx, "__objmap%d",
acfc56
 						    key, mappings);
acfc56
-
acfc56
-		mappings->set->data = constant_expr_alloc(&netlink_location,
acfc56
-							  &string_type,
acfc56
-							  BYTEORDER_HOST_ENDIAN,
acfc56
-							  NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
acfc56
-							  NULL);
acfc56
 		mappings->set->objtype  = stmt->objref.type;
acfc56
 
acfc56
 		map->mappings = mappings;
acfc56
@@ -3381,6 +3378,13 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
acfc56
 
acfc56
 	}
acfc56
 
acfc56
+	/* Default timeout value implies timeout support */
acfc56
+	if (set->timeout)
acfc56
+		set->flags |= NFT_SET_TIMEOUT;
acfc56
+
acfc56
+	if (set_is_anonymous(set->flags))
acfc56
+		return 0;
acfc56
+
acfc56
 	ctx->set = set;
acfc56
 	if (set->init != NULL) {
acfc56
 		expr_set_context(&ctx->ectx, set->key->dtype, set->key->len);
acfc56
@@ -3392,10 +3396,6 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
acfc56
 	if (set_lookup(table, set->handle.set.name) == NULL)
acfc56
 		set_add_hash(set_get(set), table);
acfc56
 
acfc56
-	/* Default timeout value implies timeout support */
acfc56
-	if (set->timeout)
acfc56
-		set->flags |= NFT_SET_TIMEOUT;
acfc56
-
acfc56
 	return 0;
acfc56
 }
acfc56
 
acfc56
-- 
acfc56
1.8.3.1
acfc56