aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2008-01-19 02:53:31 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:08:05 -0500
commit869e58f87094b1e8a0df49232e4a5172678d46c9 (patch)
tree9ac2dc45be284ac66099e3e71b16a03fb5c21b8d /net/netlink/af_netlink.c
parent7d460db953d6d205e4c8ecc2017aea1ec22b6c9a (diff)
[NETNS]: Double free in netlink_release.
Netlink protocol table is global for all namespaces. Some netlink protocols have been virtualized, i.e. they have per/namespace netlink socket. This difference can easily lead to double free if more than 1 namespace is started. Count the number of kernel netlink sockets to track that this table is not used any more. Signed-off-by: Denis V. Lunev <den@openvz.org> Tested-by: Alexey Dobriyan <adobriyan@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 21f9e30184e2..29fef558aab6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -498,9 +498,12 @@ static int netlink_release(struct socket *sock)
498 498
499 netlink_table_grab(); 499 netlink_table_grab();
500 if (netlink_is_kernel(sk)) { 500 if (netlink_is_kernel(sk)) {
501 kfree(nl_table[sk->sk_protocol].listeners); 501 BUG_ON(nl_table[sk->sk_protocol].registered == 0);
502 nl_table[sk->sk_protocol].module = NULL; 502 if (--nl_table[sk->sk_protocol].registered == 0) {
503 nl_table[sk->sk_protocol].registered = 0; 503 kfree(nl_table[sk->sk_protocol].listeners);
504 nl_table[sk->sk_protocol].module = NULL;
505 nl_table[sk->sk_protocol].registered = 0;
506 }
504 } else if (nlk->subscriptions) 507 } else if (nlk->subscriptions)
505 netlink_update_listeners(sk); 508 netlink_update_listeners(sk);
506 netlink_table_ungrab(); 509 netlink_table_ungrab();
@@ -1389,6 +1392,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
1389 nl_table[unit].registered = 1; 1392 nl_table[unit].registered = 1;
1390 } else { 1393 } else {
1391 kfree(listeners); 1394 kfree(listeners);
1395 nl_table[unit].registered++;
1392 } 1396 }
1393 netlink_table_ungrab(); 1397 netlink_table_ungrab();
1394 1398