]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
intervals: set internal element location with the deletion trigger
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 4 Dec 2024 22:36:05 +0000 (23:36 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 2 Jan 2025 18:58:11 +0000 (19:58 +0100)
set location of internal elements (already in the kernel) to the one
that partial or fully deletes it.

Otherwise, error reporting refers to internal location.

Before this patch:

 # nft delete element x y { 1.1.1.3 }
 Error: Could not process rule: Too many open files in system
 delete element x y { 1.1.1.3 }
                      ^^^^^^^

After this patch:

 # nft delete element x y { 1.1.1.3 }
 Error: Could not process rule: Too many open files in system
 delete element x y { 1.1.1.3 }
                      ^^^^^^^

This occurs after splitting an existing interval in two:

 remove: [1010100-10101ff]
 add: [1010100-1010102]
 add: [1010104-10101ff]

which results in two additions after removing the existing interval
that is split.

Fixes: 81e36530fcac ("src: replace interval segment tree overlap and automerge")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/intervals.c

index ff202be9375bee3f1c5d124d3db74f0f8ba91c73..a58ec5b26397712b515cf80571d16cb8f2ce1188 100644 (file)
@@ -86,6 +86,7 @@ static void remove_overlapping_range(struct set_automerge_ctx *ctx,
                                     struct expr *prev, struct expr *i)
 {
        if (i->flags & EXPR_F_KERNEL) {
+               i->location = prev->location;
                purge_elem(ctx, i);
                return;
        }
@@ -104,12 +105,14 @@ static bool merge_ranges(struct set_automerge_ctx *ctx,
                         struct range *prev_range, struct range *range)
 {
        if (prev->flags & EXPR_F_KERNEL) {
+               prev->location = i->location;
                purge_elem(ctx, prev);
                expr_free(i->key->left);
                i->key->left = expr_get(prev->key->left);
                mpz_set(prev_range->high, range->high);
                return true;
        } else if (i->flags & EXPR_F_KERNEL) {
+               i->location = prev->location;
                purge_elem(ctx, i);
                expr_free(prev->key->right);
                prev->key->right = expr_get(i->key->right);
@@ -304,6 +307,7 @@ static void __adjust_elem_left(struct set *set, struct expr *prev, struct expr *
 static void adjust_elem_left(struct set *set, struct expr *prev, struct expr *i,
                             struct expr *purge)
 {
+       prev->location = i->location;
        remove_elem(prev, set, purge);
        __adjust_elem_left(set, prev, i);
 
@@ -323,6 +327,7 @@ static void __adjust_elem_right(struct set *set, struct expr *prev, struct expr
 static void adjust_elem_right(struct set *set, struct expr *prev, struct expr *i,
                              struct expr *purge)
 {
+       prev->location = i->location;
        remove_elem(prev, set, purge);
        __adjust_elem_right(set, prev, i);
 
@@ -335,6 +340,8 @@ static void split_range(struct set *set, struct expr *prev, struct expr *i,
 {
        struct expr *clone;
 
+       prev->location = i->location;
+
        if (prev->flags & EXPR_F_KERNEL) {
                clone = expr_clone(prev);
                list_move_tail(&clone->list, &purge->expressions);
@@ -422,8 +429,10 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
                if (mpz_cmp(prev_range.low, range.low) == 0 &&
                    mpz_cmp(prev_range.high, range.high) == 0) {
                        if (elem->flags & EXPR_F_REMOVE) {
-                               if (prev->flags & EXPR_F_KERNEL)
+                               if (prev->flags & EXPR_F_KERNEL) {
+                                       prev->location = elem->location;
                                        list_move_tail(&prev->list, &purge->expressions);
+                               }
 
                                list_del(&elem->list);
                                expr_free(elem);