diff mbox series

[nft,2/2] src: Set NFT_SET_CONCAT flag for sets with concatenated ranges

Message ID 12dd79d1d0ff6697fcc609056808abef4b53311a.1586806931.git.sbrivio@redhat.com
State Accepted
Delegated to: Pablo Neira
Headers show
Series Prevent kernel from adding concatenated ranges if they're not supported | expand

Commit Message

Stefano Brivio April 13, 2020, 7:48 p.m. UTC
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>
---
 src/evaluate.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/src/evaluate.c b/src/evaluate.c
index fcc79386b325..91901921155f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1382,10 +1382,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);
@@ -3463,6 +3469,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)) {