Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ip6mr: fix static mfc/dev leaks on table destruction

Similar to ipv4, when destroying an mrt table the static mfc entries and
the static devices are kept, which leads to devices that can never be
destroyed (because of refcnt taken) and leaked memory. Make sure that
everything is cleaned up on netns destruction.

Fixes: 8229efdaef1e ("netns: ip6mr: enable namespace support in ipv6 multicast forwarding code")
CC: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Reviewed-by: Cong Wang <cwang@twopensource.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Nikolay Aleksandrov and committed by
David S. Miller
4c698046 0e615e96

+8 -7
+8 -7
net/ipv6/ip6mr.c
··· 118 118 int cmd); 119 119 static int ip6mr_rtm_dumproute(struct sk_buff *skb, 120 120 struct netlink_callback *cb); 121 - static void mroute_clean_tables(struct mr6_table *mrt); 121 + static void mroute_clean_tables(struct mr6_table *mrt, bool all); 122 122 static void ipmr_expire_process(unsigned long arg); 123 123 124 124 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES ··· 334 334 static void ip6mr_free_table(struct mr6_table *mrt) 335 335 { 336 336 del_timer_sync(&mrt->ipmr_expire_timer); 337 - mroute_clean_tables(mrt); 337 + mroute_clean_tables(mrt, true); 338 338 kfree(mrt); 339 339 } 340 340 ··· 1542 1542 * Close the multicast socket, and clear the vif tables etc 1543 1543 */ 1544 1544 1545 - static void mroute_clean_tables(struct mr6_table *mrt) 1545 + static void mroute_clean_tables(struct mr6_table *mrt, bool all) 1546 1546 { 1547 1547 int i; 1548 1548 LIST_HEAD(list); ··· 1552 1552 * Shut down all active vif entries 1553 1553 */ 1554 1554 for (i = 0; i < mrt->maxvif; i++) { 1555 - if (!(mrt->vif6_table[i].flags & VIFF_STATIC)) 1556 - mif6_delete(mrt, i, &list); 1555 + if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC)) 1556 + continue; 1557 + mif6_delete(mrt, i, &list); 1557 1558 } 1558 1559 unregister_netdevice_many(&list); 1559 1560 ··· 1563 1562 */ 1564 1563 for (i = 0; i < MFC6_LINES; i++) { 1565 1564 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { 1566 - if (c->mfc_flags & MFC_STATIC) 1565 + if (!all && (c->mfc_flags & MFC_STATIC)) 1567 1566 continue; 1568 1567 write_lock_bh(&mrt_lock); 1569 1568 list_del(&c->list); ··· 1626 1625 net->ipv6.devconf_all); 1627 1626 write_unlock_bh(&mrt_lock); 1628 1627 1629 - mroute_clean_tables(mrt); 1628 + mroute_clean_tables(mrt, false); 1630 1629 err = 0; 1631 1630 break; 1632 1631 }