|
|
195495 |
From 24d7383ca9e7f056153cc305ee16fa9fd8580909 Mon Sep 17 00:00:00 2001
|
|
|
195495 |
From: Phil Sutter <phil@nwl.cc>
|
|
|
195495 |
Date: Wed, 9 Jun 2021 15:49:52 +0200
|
|
|
195495 |
Subject: [PATCH] segtree: Fix segfault when restoring a huge interval set
|
|
|
195495 |
|
|
|
195495 |
Restoring a set of IPv4 prefixes with about 1.1M elements crashes nft as
|
|
|
195495 |
set_to_segtree() exhausts the stack. Prevent this by allocating the
|
|
|
195495 |
pointer array on heap and make sure it is freed before returning to
|
|
|
195495 |
caller.
|
|
|
195495 |
|
|
|
195495 |
With this patch in place, restoring said set succeeds with allocation of
|
|
|
195495 |
about 3GB of memory, according to valgrind.
|
|
|
195495 |
|
|
|
195495 |
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
195495 |
(cherry picked from commit baecd1cf26851a4c5b7d469206a488f14fe5b147)
|
|
|
195495 |
---
|
|
|
195495 |
src/segtree.c | 10 ++++++----
|
|
|
195495 |
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
|
195495 |
|
|
|
195495 |
diff --git a/src/segtree.c b/src/segtree.c
|
|
|
195495 |
index 9aa39e52d8a09..163a7bb755f9c 100644
|
|
|
195495 |
--- a/src/segtree.c
|
|
|
195495 |
+++ b/src/segtree.c
|
|
|
195495 |
@@ -429,10 +429,10 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
|
|
|
195495 |
struct expr *init, struct seg_tree *tree,
|
|
|
195495 |
bool add, bool merge)
|
|
|
195495 |
{
|
|
|
195495 |
- struct elementary_interval *intervals[init->size];
|
|
|
195495 |
+ struct elementary_interval **intervals;
|
|
|
195495 |
struct expr *i, *next;
|
|
|
195495 |
unsigned int n;
|
|
|
195495 |
- int err;
|
|
|
195495 |
+ int err = 0;
|
|
|
195495 |
|
|
|
195495 |
/* We are updating an existing set with new elements, check if the new
|
|
|
195495 |
* interval overlaps with any of the existing ones.
|
|
|
195495 |
@@ -443,6 +443,7 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
|
|
|
195495 |
return err;
|
|
|
195495 |
}
|
|
|
195495 |
|
|
|
195495 |
+ intervals = xmalloc_array(init->size, sizeof(intervals[0]));
|
|
|
195495 |
n = expr_to_intervals(init, tree->keylen, intervals);
|
|
|
195495 |
|
|
|
195495 |
list_for_each_entry_safe(i, next, &init->expressions, list) {
|
|
|
195495 |
@@ -461,10 +462,11 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
|
|
|
195495 |
for (n = 0; n < init->size; n++) {
|
|
|
195495 |
err = ei_insert(msgs, tree, intervals[n], merge);
|
|
|
195495 |
if (err < 0)
|
|
|
195495 |
- return err;
|
|
|
195495 |
+ break;
|
|
|
195495 |
}
|
|
|
195495 |
|
|
|
195495 |
- return 0;
|
|
|
195495 |
+ xfree(intervals);
|
|
|
195495 |
+ return err;
|
|
|
195495 |
}
|
|
|
195495 |
|
|
|
195495 |
static bool segtree_needs_first_segment(const struct set *set,
|
|
|
195495 |
--
|
|
|
195495 |
2.33.0
|
|
|
195495 |
|