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

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