Blame SOURCES/0016-segtree-Fix-segfault-when-restoring-a-huge-interval-.patch

954d1a
From 24d7383ca9e7f056153cc305ee16fa9fd8580909 Mon Sep 17 00:00:00 2001
954d1a
From: Phil Sutter <phil@nwl.cc>
954d1a
Date: Wed, 9 Jun 2021 15:49:52 +0200
954d1a
Subject: [PATCH] segtree: Fix segfault when restoring a huge interval set
954d1a
954d1a
Restoring a set of IPv4 prefixes with about 1.1M elements crashes nft as
954d1a
set_to_segtree() exhausts the stack. Prevent this by allocating the
954d1a
pointer array on heap and make sure it is freed before returning to
954d1a
caller.
954d1a
954d1a
With this patch in place, restoring said set succeeds with allocation of
954d1a
about 3GB of memory, according to valgrind.
954d1a
954d1a
Signed-off-by: Phil Sutter <phil@nwl.cc>
954d1a
(cherry picked from commit baecd1cf26851a4c5b7d469206a488f14fe5b147)
954d1a
---
954d1a
 src/segtree.c | 10 ++++++----
954d1a
 1 file changed, 6 insertions(+), 4 deletions(-)
954d1a
954d1a
diff --git a/src/segtree.c b/src/segtree.c
954d1a
index 9aa39e52d8a09..163a7bb755f9c 100644
954d1a
--- a/src/segtree.c
954d1a
+++ b/src/segtree.c
954d1a
@@ -429,10 +429,10 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
954d1a
 			  struct expr *init, struct seg_tree *tree,
954d1a
 			  bool add, bool merge)
954d1a
 {
954d1a
-	struct elementary_interval *intervals[init->size];
954d1a
+	struct elementary_interval **intervals;
954d1a
 	struct expr *i, *next;
954d1a
 	unsigned int n;
954d1a
-	int err;
954d1a
+	int err = 0;
954d1a
 
954d1a
 	/* We are updating an existing set with new elements, check if the new
954d1a
 	 * interval overlaps with any of the existing ones.
954d1a
@@ -443,6 +443,7 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
954d1a
 			return err;
954d1a
 	}
954d1a
 
954d1a
+	intervals = xmalloc_array(init->size, sizeof(intervals[0]));
954d1a
 	n = expr_to_intervals(init, tree->keylen, intervals);
954d1a
 
954d1a
 	list_for_each_entry_safe(i, next, &init->expressions, list) {
954d1a
@@ -461,10 +462,11 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
954d1a
 	for (n = 0; n < init->size; n++) {
954d1a
 		err = ei_insert(msgs, tree, intervals[n], merge);
954d1a
 		if (err < 0)
954d1a
-			return err;
954d1a
+			break;
954d1a
 	}
954d1a
 
954d1a
-	return 0;
954d1a
+	xfree(intervals);
954d1a
+	return err;
954d1a
 }
954d1a
 
954d1a
 static bool segtree_needs_first_segment(const struct set *set,
954d1a
-- 
954d1a
2.33.0
954d1a