Skip to content

Commit cf47a0b

Browse files
Julian Anastasovummakynes
authored andcommitted
ipvs: defer hook registration to avoid leaks
syzkaller reports for memory leak when registering hooks [1] As we moved the nf_unregister_net_hooks() call into __ip_vs_dev_cleanup(), defer the nf_register_net_hooks() call, so that hooks are allocated and freed from same pernet_operations (ipvs_core_dev_ops). [1] BUG: memory leak unreferenced object 0xffff88810acd8a80 (size 96): comm "syz-executor073", pid 7254, jiffies 4294950560 (age 22.250s) hex dump (first 32 bytes): 02 00 00 00 00 00 00 00 50 8b bb 82 ff ff ff ff ........P....... 00 00 00 00 00 00 00 00 00 77 bb 82 ff ff ff ff .........w...... backtrace: [<0000000013db61f1>] kmemleak_alloc_recursive include/linux/kmemleak.h:55 [inline] [<0000000013db61f1>] slab_post_alloc_hook mm/slab.h:439 [inline] [<0000000013db61f1>] slab_alloc_node mm/slab.c:3269 [inline] [<0000000013db61f1>] kmem_cache_alloc_node_trace+0x15b/0x2a0 mm/slab.c:3597 [<000000001a27307d>] __do_kmalloc_node mm/slab.c:3619 [inline] [<000000001a27307d>] __kmalloc_node+0x38/0x50 mm/slab.c:3627 [<0000000025054add>] kmalloc_node include/linux/slab.h:590 [inline] [<0000000025054add>] kvmalloc_node+0x4a/0xd0 mm/util.c:431 [<0000000050d1bc00>] kvmalloc include/linux/mm.h:637 [inline] [<0000000050d1bc00>] kvzalloc include/linux/mm.h:645 [inline] [<0000000050d1bc00>] allocate_hook_entries_size+0x3b/0x60 net/netfilter/core.c:61 [<00000000e8abe142>] nf_hook_entries_grow+0xae/0x270 net/netfilter/core.c:128 [<000000004b94797c>] __nf_register_net_hook+0x9a/0x170 net/netfilter/core.c:337 [<00000000d1545cbc>] nf_register_net_hook+0x34/0xc0 net/netfilter/core.c:464 [<00000000876c9b55>] nf_register_net_hooks+0x53/0xc0 net/netfilter/core.c:480 [<000000002ea868e0>] __ip_vs_init+0xe8/0x170 net/netfilter/ipvs/ip_vs_core.c:2280 [<000000002eb2d451>] ops_init+0x4c/0x140 net/core/net_namespace.c:130 [<000000000284ec48>] setup_net+0xde/0x230 net/core/net_namespace.c:316 [<00000000a70600fa>] copy_net_ns+0xf0/0x1e0 net/core/net_namespace.c:439 [<00000000ff26c15e>] create_new_namespaces+0x141/0x2a0 kernel/nsproxy.c:107 [<00000000b103dc79>] copy_namespaces+0xa1/0xe0 kernel/nsproxy.c:165 [<000000007cc008a2>] copy_process.part.0+0x11fd/0x2150 kernel/fork.c:2035 [<00000000c344af7c>] copy_process kernel/fork.c:1800 [inline] [<00000000c344af7c>] _do_fork+0x121/0x4f0 kernel/fork.c:2369 Reported-by: [email protected] Fixes: 719c7d5 ("ipvs: Fix use-after-free in ip_vs_in") Signed-off-by: Julian Anastasov <[email protected]> Acked-by: Simon Horman <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 85f9aa7 commit cf47a0b

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,7 +2245,6 @@ static const struct nf_hook_ops ip_vs_ops[] = {
22452245
static int __net_init __ip_vs_init(struct net *net)
22462246
{
22472247
struct netns_ipvs *ipvs;
2248-
int ret;
22492248

22502249
ipvs = net_generic(net, ip_vs_net_id);
22512250
if (ipvs == NULL)
@@ -2277,17 +2276,11 @@ static int __net_init __ip_vs_init(struct net *net)
22772276
if (ip_vs_sync_net_init(ipvs) < 0)
22782277
goto sync_fail;
22792278

2280-
ret = nf_register_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2281-
if (ret < 0)
2282-
goto hook_fail;
2283-
22842279
return 0;
22852280
/*
22862281
* Error handling
22872282
*/
22882283

2289-
hook_fail:
2290-
ip_vs_sync_net_cleanup(ipvs);
22912284
sync_fail:
22922285
ip_vs_conn_net_cleanup(ipvs);
22932286
conn_fail:
@@ -2317,6 +2310,19 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
23172310
net->ipvs = NULL;
23182311
}
23192312

2313+
static int __net_init __ip_vs_dev_init(struct net *net)
2314+
{
2315+
int ret;
2316+
2317+
ret = nf_register_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2318+
if (ret < 0)
2319+
goto hook_fail;
2320+
return 0;
2321+
2322+
hook_fail:
2323+
return ret;
2324+
}
2325+
23202326
static void __net_exit __ip_vs_dev_cleanup(struct net *net)
23212327
{
23222328
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -2336,6 +2342,7 @@ static struct pernet_operations ipvs_core_ops = {
23362342
};
23372343

23382344
static struct pernet_operations ipvs_core_dev_ops = {
2345+
.init = __ip_vs_dev_init,
23392346
.exit = __ip_vs_dev_cleanup,
23402347
};
23412348

0 commit comments

Comments
 (0)