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

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