From patchwork Tue Nov 26 12:09:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Popovich X-Patchwork-Id: 294312 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 59D2F2C00A9 for ; Tue, 26 Nov 2013 23:14:38 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755926Ab3KZMOe (ORCPT ); Tue, 26 Nov 2013 07:14:34 -0500 Received: from smtp9.mail.ru ([94.100.176.54]:53281 "EHLO smtp9.mail.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755276Ab3KZMOd (ORCPT ); Tue, 26 Nov 2013 07:14:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:To:From; bh=ePXvzkev/uBytHf5mdxvVq/nOo+zEwjT/fzxkzdRbv8=; b=Y1qCMwwmOEGVuCZpP0bD/xbYMa/j9TawIknUCM8iqUlP78gCJs1FwM9tFwLmhJX5IHEbqkf0zbZmKXYfjRWcgBY23Jm9WcSlXodtY9mhKmcdo4jkxz7AIcOxhT4Ysexf+D8zTGC0DXB1+45v6S1/y/U3K8ZRjTeRmQrSeOoaCBI=; Received: from [2a01:6d80:103:13::c3ea:4404] (port=51330 helo=tuxracer.localnet) by smtp9.mail.ru with esmtpa (envelope-from ) id 1VlHXC-0003vR-EL for netdev@vger.kernel.org; Tue, 26 Nov 2013 16:14:30 +0400 From: Sergey Popovich To: netdev@vger.kernel.org Subject: netfilter: xt_hashlimit: fix proc entry leak in netns destroy path Date: Tue, 26 Nov 2013 14:09:47 +0200 Message-ID: <2088236.yE4m0nz1sa@tuxracer> User-Agent: KMail/4.11.3 (Linux/3.10.16-std-def-alt1; KDE/4.11.3; x86_64; ; ) MIME-Version: 1.0 X-Spam: Not detected X-Mras: Ok Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org commit 32263dd1b43378b4f7d7796ed713f77e95f27e8a Author: Vitaly E. Lavrov <> Date: Mon Dec 24 14:42:17 2012 +0100 netfilter: xt_hashlimit: fix namespace destroy path Takes into account fact, that hashlimit_net_exit() called right before hashlimit_mt_destroy() and fixes destroy path for netns. However using xt_hashlimit for IPv4 and IPv6 together produces following output on netconsole from one of our servers on netns destroy: Pid: 9499, comm: kworker/u:0 Tainted: G WC O 3.2.0-5-netctl-amd64- core2 Call Trace: [] ? warn_slowpath_common+0x78/0x8c [] ? warn_slowpath_fmt+0x45/0x4a [] ? remove_proc_entry+0xd8/0x22e [] ? kfree+0x5b/0x6c [] ? hashlimit_net_exit+0x45/0x8d [xt_hashlimit] [] ? ops_exit_list+0x1c/0x44 [] ? cleanup_net+0xf1/0x180 [] ? should_resched+0x5/0x23 [] ? process_one_work+0x161/0x269 [] ? cwq_activate_delayed_work+0x3c/0x48 [] ? worker_thread+0xc2/0x145 [] ? manage_workers.isra.25+0x15b/0x15b [] ? kthread+0x76/0x7e [] ? kernel_thread_helper+0x4/0x10 [] ? kthread_worker_fn+0x139/0x139 [] ? gs_change+0x13/0x13 ---[ end trace d8c3cc0ad163ef79 ]--- ------------[ cut here ]------------ WARNING: at /usr/src/linux-3.2.52/debian/build/source_netctl/fs/proc/generic.c:849 remove_proc_entry+0x217/0x22e() Hardware name: remove_proc_entry: removing non-empty directory 'net/ip6t_hashlimit', leaking at least 'IN-REJECT' This is due to lack of removal net/ip6t_hashlimit/* entries in hashlimit_proc_net_exit(). Found and tested with custom build 3.2.x and backported commits 32263dd1b (netfilter: xt_hashlimit: fix namespace destroy path) and commit 665e205c1 (netfilter: xt_recent: fix namespace destroy path), which seems not currently in linux-stable (at least for 3.2.x series). Signed-off-by: Sergey Popovich --- net/netfilter/xt_hashlimit.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) mutex_unlock(&hashlimit_mutex); diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 9ff035c..a3910fc 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -325,21 +325,24 @@ static void htable_gc(unsigned long htlong) add_timer(&ht->timer); } -static void htable_destroy(struct xt_hashlimit_htable *hinfo) +static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) { struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net); struct proc_dir_entry *parent; - del_timer_sync(&hinfo->timer); - if (hinfo->family == NFPROTO_IPV4) parent = hashlimit_net->ipt_hashlimit; else parent = hashlimit_net->ip6t_hashlimit; - if(parent != NULL) + if (parent != NULL) remove_proc_entry(hinfo->name, parent); +} +static void htable_destroy(struct xt_hashlimit_htable *hinfo) +{ + del_timer_sync(&hinfo->timer); + htable_remove_proc_entry(hinfo); htable_selective_cleanup(hinfo, select_all); kfree(hinfo->name); vfree(hinfo); @@ -883,21 +886,15 @@ static int __net_init hashlimit_proc_net_init(struct net *net) static void __net_exit hashlimit_proc_net_exit(struct net *net) { struct xt_hashlimit_htable *hinfo; - struct proc_dir_entry *pde; struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); - /* recent_net_exit() is called before recent_mt_destroy(). Make sure - * that the parent xt_recent proc entry is is empty before trying to - * remove it. + /* hashlimit_net_exit() is called before hashlimit_mt_destroy(). + * Make sure that the parent ipt_hashlimit and ip6t_hashlimit proc + * entries is empty before trying to remove it. */ mutex_lock(&hashlimit_mutex); - pde = hashlimit_net->ipt_hashlimit; - if (pde == NULL) - pde = hashlimit_net->ip6t_hashlimit; - hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) - remove_proc_entry(hinfo->name, pde); - + htable_remove_proc_entry(hinfo); hashlimit_net->ipt_hashlimit = NULL; hashlimit_net->ip6t_hashlimit = NULL;