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

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