Blob Blame History Raw
From 5566405cc171c8fa84e0a13ea96b89245a3fb512 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Sat, 8 Aug 2020 00:05:48 +0200
Subject: [PATCH] src: Set NFT_SET_CONCAT flag for sets with concatenated
 ranges

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820684
Upstream Status: nftables commit 09441b5e92cee

commit 09441b5e92ceea60198a35cd657904fa7a10ee54
Author: Stefano Brivio <sbrivio@redhat.com>
Date:   Mon Apr 13 21:48:03 2020 +0200

    src: Set NFT_SET_CONCAT flag for sets with concatenated ranges

    Pablo reports that nft, after commit 8ac2f3b2fca3 ("src: Add support
    for concatenated set ranges"), crashes with older kernels (< 5.6)
    without support for concatenated set ranges: those sets will be sent
    to the kernel, which adds them without notion of the fact that
    different concatenated fields are actually included, and nft crashes
    while trying to list this kind of malformed concatenation.

    Use the NFT_SET_CONCAT flag introduced by kernel commit ef516e8625dd
    ("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag") when
    sets including concatenated ranges are sent to the kernel, so that
    older kernels (with no knowledge of this flag itself) will refuse set
    creation.

    Note that, in expr_evaluate_set(), we have to check for the presence
    of the flag, also on empty sets that might carry it in context data,
    and actually set it in the actual set flags.

    Reported-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 0c84816..f66251b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1360,10 +1360,16 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
 			set->size      += i->size - 1;
 			set->set_flags |= i->set_flags;
 			expr_free(i);
-		} else if (!expr_is_singleton(i))
+		} else if (!expr_is_singleton(i)) {
 			set->set_flags |= NFT_SET_INTERVAL;
+			if (i->key->etype == EXPR_CONCAT)
+				set->set_flags |= NFT_SET_CONCAT;
+		}
 	}
 
+	if (ctx->set && (ctx->set->flags & NFT_SET_CONCAT))
+		set->set_flags |= NFT_SET_CONCAT;
+
 	set->set_flags |= NFT_SET_CONSTANT;
 
 	datatype_set(set, ctx->ectx.dtype);
@@ -3336,6 +3342,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 		memcpy(&set->desc.field_len, &set->key->field_len,
 		       sizeof(set->desc.field_len));
 		set->desc.field_count = set->key->field_count;
+		set->flags |= NFT_SET_CONCAT;
 	}
 
 	if (set_is_datamap(set->flags)) {
-- 
1.8.3.1