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

d95e8a
From 36cf5177c724540aea5a42f9dc6ef5476f86179a Mon Sep 17 00:00:00 2001
d95e8a
From: Phil Sutter <psutter@redhat.com>
d95e8a
Date: Fri, 5 Nov 2021 16:06:45 +0100
d95e8a
Subject: [PATCH] segtree: Fix segfault when restoring a huge interval set
d95e8a
d95e8a
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1908127
d95e8a
Upstream Status: nftables commit baecd1cf26851
d95e8a
d95e8a
commit baecd1cf26851a4c5b7d469206a488f14fe5b147
d95e8a
Author: Phil Sutter <phil@nwl.cc>
d95e8a
Date:   Wed Jun 9 15:49:52 2021 +0200
d95e8a
d95e8a
    segtree: Fix segfault when restoring a huge interval set
d95e8a
d95e8a
    Restoring a set of IPv4 prefixes with about 1.1M elements crashes nft as
d95e8a
    set_to_segtree() exhausts the stack. Prevent this by allocating the
d95e8a
    pointer array on heap and make sure it is freed before returning to
d95e8a
    caller.
d95e8a
d95e8a
    With this patch in place, restoring said set succeeds with allocation of
d95e8a
    about 3GB of memory, according to valgrind.
d95e8a
d95e8a
    Signed-off-by: Phil Sutter <phil@nwl.cc>
d95e8a
---
d95e8a
 src/segtree.c | 10 ++++++----
d95e8a
 1 file changed, 6 insertions(+), 4 deletions(-)
d95e8a
d95e8a
diff --git a/src/segtree.c b/src/segtree.c
d95e8a
index d6e3ce2..b852961 100644
d95e8a
--- a/src/segtree.c
d95e8a
+++ b/src/segtree.c
d95e8a
@@ -414,10 +414,10 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
d95e8a
 			  struct expr *init, struct seg_tree *tree,
d95e8a
 			  bool add, bool merge)
d95e8a
 {
d95e8a
-	struct elementary_interval *intervals[init->size];
d95e8a
+	struct elementary_interval **intervals;
d95e8a
 	struct expr *i, *next;
d95e8a
 	unsigned int n;
d95e8a
-	int err;
d95e8a
+	int err = 0;
d95e8a
 
d95e8a
 	/* We are updating an existing set with new elements, check if the new
d95e8a
 	 * interval overlaps with any of the existing ones.
d95e8a
@@ -428,6 +428,7 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
d95e8a
 			return err;
d95e8a
 	}
d95e8a
 
d95e8a
+	intervals = xmalloc_array(init->size, sizeof(intervals[0]));
d95e8a
 	n = expr_to_intervals(init, tree->keylen, intervals);
d95e8a
 
d95e8a
 	list_for_each_entry_safe(i, next, &init->expressions, list) {
d95e8a
@@ -446,10 +447,11 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
d95e8a
 	for (n = 0; n < init->size; n++) {
d95e8a
 		err = ei_insert(msgs, tree, intervals[n], merge);
d95e8a
 		if (err < 0)
d95e8a
-			return err;
d95e8a
+			break;
d95e8a
 	}
d95e8a
 
d95e8a
-	return 0;
d95e8a
+	xfree(intervals);
d95e8a
+	return err;
d95e8a
 }
d95e8a
 
d95e8a
 static bool segtree_needs_first_segment(const struct set *set,
d95e8a
-- 
d95e8a
2.31.1
d95e8a