62 lines
1.9 KiB
Diff
62 lines
1.9 KiB
Diff
|
From 24d7383ca9e7f056153cc305ee16fa9fd8580909 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <phil@nwl.cc>
|
||
|
Date: Wed, 9 Jun 2021 15:49:52 +0200
|
||
|
Subject: [PATCH] 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>
|
||
|
(cherry picked from commit baecd1cf26851a4c5b7d469206a488f14fe5b147)
|
||
|
---
|
||
|
src/segtree.c | 10 ++++++----
|
||
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/src/segtree.c b/src/segtree.c
|
||
|
index 9aa39e52d8a09..163a7bb755f9c 100644
|
||
|
--- a/src/segtree.c
|
||
|
+++ b/src/segtree.c
|
||
|
@@ -429,10 +429,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.
|
||
|
@@ -443,6 +443,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) {
|
||
|
@@ -461,10 +462,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.33.0
|
||
|
|