mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
![Helmut Schaa](/assets/img/avatar_default.png)
When having nf_conntrack_timestamp enabled deleting a netns can lead to the following BUG being triggered: [63836.660000] Kernel bug detected[#1]: [63836.660000] CPU: 0 PID: 0 Comm: swapper Not tainted 3.10.18 #14 [63836.660000] task: 802d9420 ti: 802d2000 task.ti: 802d2000 [63836.660000] $ 0 : 00000000 00000000 00000000 00000000 [63836.660000] $ 4 : 00000001 00000004 00000020 00000020 [63836.660000] $ 8 : 00000000 80064910 00000000 00000000 [63836.660000] $12 : 0bff0002 00000001 00000000 0a0a0abe [63836.660000] $16 : 802e70a0 85f29d80 00000000 00000004 [63836.660000] $20 :85fb62a0
00000002 802d3bc085fb62a0
[63836.660000] $24 : 00000000 87138110 [63836.660000] $28 : 802d2000 802d3b40 00000014 871327cc [63836.660000] Hi : 000005ff [63836.660000] Lo : f2edd000 [63836.660000] epc : 87138794 __nf_ct_ext_add_length+0xe8/0x1ec [nf_conntrack] [63836.660000] Not tainted [63836.660000] ra : 871327cc nf_conntrack_in+0x31c/0x7b8 [nf_conntrack] [63836.660000] Status: 1100d403 KERNEL EXL IE [63836.660000] Cause : 00800034 [63836.660000] PrId : 0001974c (MIPS 74Kc) [63836.660000] Modules linked in: ath9k ath9k_common pppoe ppp_async iptable_nat ath9k_hw ath pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv4 mac80211 ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_quota xt_policy xt_pkttype xt_owner xt_nat xt_multiport xt_mark xh [63836.660000] Process swapper (pid: 0, threadinfo=802d2000, task=802d9420, tls=00000000) [63836.660000] Stack : 802e70a0 871323d4 00000005 87080234 802e70a0 86d2a840 00000000 00000000 [63836.660000] Call Trace: [63836.660000] [<87138794>] __nf_ct_ext_add_length+0xe8/0x1ec [nf_conntrack] [63836.660000] [<871327cc>] nf_conntrack_in+0x31c/0x7b8 [nf_conntrack] [63836.660000] [<801ff63c>] nf_iterate+0x90/0xec [63836.660000] [<801ff730>] nf_hook_slow+0x98/0x164 [63836.660000] [<80205968>] ip_rcv+0x3e8/0x40c [63836.660000] [<801d9754>] __netif_receive_skb_core+0x624/0x6a4 [63836.660000] [<801da124>] process_backlog+0xa4/0x16c [63836.660000] [<801d9bb4>] net_rx_action+0x10c/0x1e0 [63836.660000] [<8007c5a4>] __do_softirq+0xd0/0x1bc [63836.660000] [<8007c730>] do_softirq+0x48/0x68 [63836.660000] [<8007c964>] irq_exit+0x54/0x70 [63836.660000] [<80060830>] ret_from_irq+0x0/0x4 [63836.660000] [<8006a9f8>] r4k_wait_irqoff+0x18/0x1c [63836.660000] [<8009cfb8>] cpu_startup_entry+0xa4/0x104 [63836.660000] [<802eb918>] start_kernel+0x394/0x3ac [63836.660000] [63836.660000] Code: 00821021 8c420000 2c440001 <00040336> 90440011 92350010 90560010 2485ffff 02a5a821 [63837.040000] ---[ end trace ebf660c3ce3b55e7 ]--- [63837.050000] Kernel panic - not syncing: Fatal exception in interrupt [63837.050000] Rebooting in 3 seconds.. Fix this by not unregistering the conntrack extension in the per-netns cleanup code. This bug was introduced in (73f4001
netfilter: nf_ct_tstamp: move initialization out of pernet_operations). Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
114 lines
2.6 KiB
C
114 lines
2.6 KiB
C
/*
|
|
* (C) 2010 Pablo Neira Ayuso <pablo@netfilter.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation (or any later at your option).
|
|
*/
|
|
|
|
#include <linux/netfilter.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/moduleparam.h>
|
|
|
|
#include <net/netfilter/nf_conntrack.h>
|
|
#include <net/netfilter/nf_conntrack_extend.h>
|
|
#include <net/netfilter/nf_conntrack_timestamp.h>
|
|
|
|
static bool nf_ct_tstamp __read_mostly;
|
|
|
|
module_param_named(tstamp, nf_ct_tstamp, bool, 0644);
|
|
MODULE_PARM_DESC(tstamp, "Enable connection tracking flow timestamping.");
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
static struct ctl_table tstamp_sysctl_table[] = {
|
|
{
|
|
.procname = "nf_conntrack_timestamp",
|
|
.data = &init_net.ct.sysctl_tstamp,
|
|
.maxlen = sizeof(unsigned int),
|
|
.mode = 0644,
|
|
.proc_handler = proc_dointvec,
|
|
},
|
|
{}
|
|
};
|
|
#endif /* CONFIG_SYSCTL */
|
|
|
|
static struct nf_ct_ext_type tstamp_extend __read_mostly = {
|
|
.len = sizeof(struct nf_conn_tstamp),
|
|
.align = __alignof__(struct nf_conn_tstamp),
|
|
.id = NF_CT_EXT_TSTAMP,
|
|
};
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
static int nf_conntrack_tstamp_init_sysctl(struct net *net)
|
|
{
|
|
struct ctl_table *table;
|
|
|
|
table = kmemdup(tstamp_sysctl_table, sizeof(tstamp_sysctl_table),
|
|
GFP_KERNEL);
|
|
if (!table)
|
|
goto out;
|
|
|
|
table[0].data = &net->ct.sysctl_tstamp;
|
|
|
|
/* Don't export sysctls to unprivileged users */
|
|
if (net->user_ns != &init_user_ns)
|
|
table[0].procname = NULL;
|
|
|
|
net->ct.tstamp_sysctl_header = register_net_sysctl(net, "net/netfilter",
|
|
table);
|
|
if (!net->ct.tstamp_sysctl_header) {
|
|
printk(KERN_ERR "nf_ct_tstamp: can't register to sysctl.\n");
|
|
goto out_register;
|
|
}
|
|
return 0;
|
|
|
|
out_register:
|
|
kfree(table);
|
|
out:
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static void nf_conntrack_tstamp_fini_sysctl(struct net *net)
|
|
{
|
|
struct ctl_table *table;
|
|
|
|
table = net->ct.tstamp_sysctl_header->ctl_table_arg;
|
|
unregister_net_sysctl_table(net->ct.tstamp_sysctl_header);
|
|
kfree(table);
|
|
}
|
|
#else
|
|
static int nf_conntrack_tstamp_init_sysctl(struct net *net)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void nf_conntrack_tstamp_fini_sysctl(struct net *net)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
int nf_conntrack_tstamp_pernet_init(struct net *net)
|
|
{
|
|
net->ct.sysctl_tstamp = nf_ct_tstamp;
|
|
return nf_conntrack_tstamp_init_sysctl(net);
|
|
}
|
|
|
|
void nf_conntrack_tstamp_pernet_fini(struct net *net)
|
|
{
|
|
nf_conntrack_tstamp_fini_sysctl(net);
|
|
}
|
|
|
|
int nf_conntrack_tstamp_init(void)
|
|
{
|
|
int ret;
|
|
ret = nf_ct_extend_register(&tstamp_extend);
|
|
if (ret < 0)
|
|
pr_err("nf_ct_tstamp: Unable to register extension\n");
|
|
return ret;
|
|
}
|
|
|
|
void nf_conntrack_tstamp_fini(void)
|
|
{
|
|
nf_ct_extend_unregister(&tstamp_extend);
|
|
}
|