Skip to content

Commit

Permalink
netfilter: x_tables: fix percpu counter block leak on error path when…
Browse files Browse the repository at this point in the history
… creating new netns

Here is the stack where we allocate percpu counter block:

  +-< __alloc_percpu
    +-< xt_percpu_counter_alloc
      +-< find_check_entry # {arp,ip,ip6}_tables.c
        +-< translate_table

And it can be leaked on this code path:

  +-> ip6t_register_table
    +-> translate_table # allocates percpu counter block
    +-> xt_register_table # fails

there is no freeing of the counter block on xt_register_table fail.
Note: xt_percpu_counter_free should be called to free it like we do in
do_replace through cleanup_entry helper (or in __ip6t_unregister_table).

Probability of hitting this error path is low AFAICS (xt_register_table
can only return ENOMEM here, as it is not replacing anything, as we are
creating new netns, and it is hard to imagine that all previous
allocations succeeded and after that one in xt_register_table failed).
But it's worth fixing even the rare leak.

Fixes: 71ae0df ("netfilter: xtables: use percpu rule counters")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Pavel Tikhomirov authored and Pablo Neira Ayuso committed Feb 22, 2023
1 parent fdf6491 commit 0af8c09
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 0 deletions.
4 changes: 4 additions & 0 deletions net/ipv4/netfilter/arp_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,10 @@ int arpt_register_table(struct net *net,

new_table = xt_register_table(net, table, &bootstrap, newinfo);
if (IS_ERR(new_table)) {
struct arpt_entry *iter;

xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
cleanup_entry(iter, net);
xt_free_table_info(newinfo);
return PTR_ERR(new_table);
}
Expand Down
4 changes: 4 additions & 0 deletions net/ipv4/netfilter/ip_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,10 @@ int ipt_register_table(struct net *net, const struct xt_table *table,

new_table = xt_register_table(net, table, &bootstrap, newinfo);
if (IS_ERR(new_table)) {
struct ipt_entry *iter;

xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
cleanup_entry(iter, net);
xt_free_table_info(newinfo);
return PTR_ERR(new_table);
}
Expand Down
4 changes: 4 additions & 0 deletions net/ipv6/netfilter/ip6_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,10 @@ int ip6t_register_table(struct net *net, const struct xt_table *table,

new_table = xt_register_table(net, table, &bootstrap, newinfo);
if (IS_ERR(new_table)) {
struct ip6t_entry *iter;

xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
cleanup_entry(iter, net);
xt_free_table_info(newinfo);
return PTR_ERR(new_table);
}
Expand Down

0 comments on commit 0af8c09

Please sign in to comment.