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