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