aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c11
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c56
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c38
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c5
-rw-r--r--net/netfilter/nf_conntrack_core.c3
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c4
-rw-r--r--net/netfilter/nfnetlink_acct.c2
-rw-r--r--net/netfilter/xt_CT.c30
13 files changed, 118 insertions, 49 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 2555816e7788..00bdb1d9d690 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1924,6 +1924,7 @@ protocol_fail:
1924control_fail: 1924control_fail:
1925 ip_vs_estimator_net_cleanup(net); 1925 ip_vs_estimator_net_cleanup(net);
1926estimator_fail: 1926estimator_fail:
1927 net->ipvs = NULL;
1927 return -ENOMEM; 1928 return -ENOMEM;
1928} 1929}
1929 1930
@@ -1936,6 +1937,7 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
1936 ip_vs_control_net_cleanup(net); 1937 ip_vs_control_net_cleanup(net);
1937 ip_vs_estimator_net_cleanup(net); 1938 ip_vs_estimator_net_cleanup(net);
1938 IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); 1939 IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
1940 net->ipvs = NULL;
1939} 1941}
1940 1942
1941static void __net_exit __ip_vs_dev_cleanup(struct net *net) 1943static void __net_exit __ip_vs_dev_cleanup(struct net *net)
@@ -1993,10 +1995,18 @@ static int __init ip_vs_init(void)
1993 goto cleanup_dev; 1995 goto cleanup_dev;
1994 } 1996 }
1995 1997
1998 ret = ip_vs_register_nl_ioctl();
1999 if (ret < 0) {
2000 pr_err("can't register netlink/ioctl.\n");
2001 goto cleanup_hooks;
2002 }
2003
1996 pr_info("ipvs loaded.\n"); 2004 pr_info("ipvs loaded.\n");
1997 2005
1998 return ret; 2006 return ret;
1999 2007
2008cleanup_hooks:
2009 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2000cleanup_dev: 2010cleanup_dev:
2001 unregister_pernet_device(&ipvs_core_dev_ops); 2011 unregister_pernet_device(&ipvs_core_dev_ops);
2002cleanup_sub: 2012cleanup_sub:
@@ -2012,6 +2022,7 @@ exit:
2012 2022
2013static void __exit ip_vs_cleanup(void) 2023static void __exit ip_vs_cleanup(void)
2014{ 2024{
2025 ip_vs_unregister_nl_ioctl();
2015 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); 2026 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2016 unregister_pernet_device(&ipvs_core_dev_ops); 2027 unregister_pernet_device(&ipvs_core_dev_ops);
2017 unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ 2028 unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index b3afe189af61..f5589987fc80 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3680,7 +3680,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net)
3680 return 0; 3680 return 0;
3681} 3681}
3682 3682
3683void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) 3683void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
3684{ 3684{
3685 struct netns_ipvs *ipvs = net_ipvs(net); 3685 struct netns_ipvs *ipvs = net_ipvs(net);
3686 3686
@@ -3692,7 +3692,7 @@ void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
3692#else 3692#else
3693 3693
3694int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } 3694int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
3695void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { } 3695void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { }
3696 3696
3697#endif 3697#endif
3698 3698
@@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
3750 free_percpu(ipvs->tot_stats.cpustats); 3750 free_percpu(ipvs->tot_stats.cpustats);
3751} 3751}
3752 3752
3753int __init ip_vs_control_init(void) 3753int __init ip_vs_register_nl_ioctl(void)
3754{ 3754{
3755 int idx;
3756 int ret; 3755 int ret;
3757 3756
3758 EnterFunction(2);
3759
3760 /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
3761 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
3762 INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
3763 INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
3764 }
3765
3766 smp_wmb(); /* Do we really need it now ? */
3767
3768 ret = nf_register_sockopt(&ip_vs_sockopts); 3757 ret = nf_register_sockopt(&ip_vs_sockopts);
3769 if (ret) { 3758 if (ret) {
3770 pr_err("cannot register sockopt.\n"); 3759 pr_err("cannot register sockopt.\n");
@@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void)
3776 pr_err("cannot register Generic Netlink interface.\n"); 3765 pr_err("cannot register Generic Netlink interface.\n");
3777 goto err_genl; 3766 goto err_genl;
3778 } 3767 }
3779
3780 ret = register_netdevice_notifier(&ip_vs_dst_notifier);
3781 if (ret < 0)
3782 goto err_notf;
3783
3784 LeaveFunction(2);
3785 return 0; 3768 return 0;
3786 3769
3787err_notf:
3788 ip_vs_genl_unregister();
3789err_genl: 3770err_genl:
3790 nf_unregister_sockopt(&ip_vs_sockopts); 3771 nf_unregister_sockopt(&ip_vs_sockopts);
3791err_sock: 3772err_sock:
3792 return ret; 3773 return ret;
3793} 3774}
3794 3775
3776void ip_vs_unregister_nl_ioctl(void)
3777{
3778 ip_vs_genl_unregister();
3779 nf_unregister_sockopt(&ip_vs_sockopts);
3780}
3781
3782int __init ip_vs_control_init(void)
3783{
3784 int idx;
3785 int ret;
3786
3787 EnterFunction(2);
3788
3789 /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
3790 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
3791 INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
3792 INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
3793 }
3794
3795 smp_wmb(); /* Do we really need it now ? */
3796
3797 ret = register_netdevice_notifier(&ip_vs_dst_notifier);
3798 if (ret < 0)
3799 return ret;
3800
3801 LeaveFunction(2);
3802 return 0;
3803}
3804
3795 3805
3796void ip_vs_control_cleanup(void) 3806void ip_vs_control_cleanup(void)
3797{ 3807{
3798 EnterFunction(2); 3808 EnterFunction(2);
3799 unregister_netdevice_notifier(&ip_vs_dst_notifier); 3809 unregister_netdevice_notifier(&ip_vs_dst_notifier);
3800 ip_vs_genl_unregister();
3801 nf_unregister_sockopt(&ip_vs_sockopts);
3802 LeaveFunction(2); 3810 LeaveFunction(2);
3803} 3811}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 538d74ee4f68..e39f693dd3e4 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -439,6 +439,8 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
439 struct ip_vs_app *app; 439 struct ip_vs_app *app;
440 struct netns_ipvs *ipvs = net_ipvs(net); 440 struct netns_ipvs *ipvs = net_ipvs(net);
441 441
442 if (!ipvs)
443 return -ENOENT;
442 app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL); 444 app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL);
443 if (!app) 445 if (!app)
444 return -ENOMEM; 446 return -ENOMEM;
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 0f16283fd058..caa43704e55e 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -551,6 +551,9 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
551{ 551{
552 struct netns_ipvs *ipvs = net_ipvs(net); 552 struct netns_ipvs *ipvs = net_ipvs(net);
553 553
554 if (!ipvs)
555 return -ENOENT;
556
554 if (!net_eq(net, &init_net)) { 557 if (!net_eq(net, &init_net)) {
555 ipvs->lblc_ctl_table = kmemdup(vs_vars_table, 558 ipvs->lblc_ctl_table = kmemdup(vs_vars_table,
556 sizeof(vs_vars_table), 559 sizeof(vs_vars_table),
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index eec797f8cce7..548bf37aa29e 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -745,6 +745,9 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
745{ 745{
746 struct netns_ipvs *ipvs = net_ipvs(net); 746 struct netns_ipvs *ipvs = net_ipvs(net);
747 747
748 if (!ipvs)
749 return -ENOENT;
750
748 if (!net_eq(net, &init_net)) { 751 if (!net_eq(net, &init_net)) {
749 ipvs->lblcr_ctl_table = kmemdup(vs_vars_table, 752 ipvs->lblcr_ctl_table = kmemdup(vs_vars_table,
750 sizeof(vs_vars_table), 753 sizeof(vs_vars_table),
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index f843a8833250..ed835e67a07e 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -59,9 +59,6 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
59 return 0; 59 return 0;
60} 60}
61 61
62#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
63 defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
64 defined(CONFIG_IP_VS_PROTO_ESP)
65/* 62/*
66 * register an ipvs protocols netns related data 63 * register an ipvs protocols netns related data
67 */ 64 */
@@ -81,12 +78,18 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
81 ipvs->proto_data_table[hash] = pd; 78 ipvs->proto_data_table[hash] = pd;
82 atomic_set(&pd->appcnt, 0); /* Init app counter */ 79 atomic_set(&pd->appcnt, 0); /* Init app counter */
83 80
84 if (pp->init_netns != NULL) 81 if (pp->init_netns != NULL) {
85 pp->init_netns(net, pd); 82 int ret = pp->init_netns(net, pd);
83 if (ret) {
84 /* unlink an free proto data */
85 ipvs->proto_data_table[hash] = pd->next;
86 kfree(pd);
87 return ret;
88 }
89 }
86 90
87 return 0; 91 return 0;
88} 92}
89#endif
90 93
91/* 94/*
92 * unregister an ipvs protocol 95 * unregister an ipvs protocol
@@ -316,22 +319,35 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
316 */ 319 */
317int __net_init ip_vs_protocol_net_init(struct net *net) 320int __net_init ip_vs_protocol_net_init(struct net *net)
318{ 321{
322 int i, ret;
323 static struct ip_vs_protocol *protos[] = {
319#ifdef CONFIG_IP_VS_PROTO_TCP 324#ifdef CONFIG_IP_VS_PROTO_TCP
320 register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); 325 &ip_vs_protocol_tcp,
321#endif 326#endif
322#ifdef CONFIG_IP_VS_PROTO_UDP 327#ifdef CONFIG_IP_VS_PROTO_UDP
323 register_ip_vs_proto_netns(net, &ip_vs_protocol_udp); 328 &ip_vs_protocol_udp,
324#endif 329#endif
325#ifdef CONFIG_IP_VS_PROTO_SCTP 330#ifdef CONFIG_IP_VS_PROTO_SCTP
326 register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp); 331 &ip_vs_protocol_sctp,
327#endif 332#endif
328#ifdef CONFIG_IP_VS_PROTO_AH 333#ifdef CONFIG_IP_VS_PROTO_AH
329 register_ip_vs_proto_netns(net, &ip_vs_protocol_ah); 334 &ip_vs_protocol_ah,
330#endif 335#endif
331#ifdef CONFIG_IP_VS_PROTO_ESP 336#ifdef CONFIG_IP_VS_PROTO_ESP
332 register_ip_vs_proto_netns(net, &ip_vs_protocol_esp); 337 &ip_vs_protocol_esp,
333#endif 338#endif
339 };
340
341 for (i = 0; i < ARRAY_SIZE(protos); i++) {
342 ret = register_ip_vs_proto_netns(net, protos[i]);
343 if (ret < 0)
344 goto cleanup;
345 }
334 return 0; 346 return 0;
347
348cleanup:
349 ip_vs_protocol_net_cleanup(net);
350 return ret;
335} 351}
336 352
337void __net_exit ip_vs_protocol_net_cleanup(struct net *net) 353void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 1fbf7a2816f5..9f3fb751c491 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -1090,7 +1090,7 @@ out:
1090 * timeouts is netns related now. 1090 * timeouts is netns related now.
1091 * --------------------------------------------- 1091 * ---------------------------------------------
1092 */ 1092 */
1093static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd) 1093static int __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
1094{ 1094{
1095 struct netns_ipvs *ipvs = net_ipvs(net); 1095 struct netns_ipvs *ipvs = net_ipvs(net);
1096 1096
@@ -1098,6 +1098,9 @@ static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
1098 spin_lock_init(&ipvs->sctp_app_lock); 1098 spin_lock_init(&ipvs->sctp_app_lock);
1099 pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts, 1099 pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
1100 sizeof(sctp_timeouts)); 1100 sizeof(sctp_timeouts));
1101 if (!pd->timeout_table)
1102 return -ENOMEM;
1103 return 0;
1101} 1104}
1102 1105
1103static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd) 1106static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index ef8641f7af83..cd609cc62721 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -677,7 +677,7 @@ void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp)
677 * timeouts is netns related now. 677 * timeouts is netns related now.
678 * --------------------------------------------- 678 * ---------------------------------------------
679 */ 679 */
680static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd) 680static int __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
681{ 681{
682 struct netns_ipvs *ipvs = net_ipvs(net); 682 struct netns_ipvs *ipvs = net_ipvs(net);
683 683
@@ -685,7 +685,10 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
685 spin_lock_init(&ipvs->tcp_app_lock); 685 spin_lock_init(&ipvs->tcp_app_lock);
686 pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts, 686 pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
687 sizeof(tcp_timeouts)); 687 sizeof(tcp_timeouts));
688 if (!pd->timeout_table)
689 return -ENOMEM;
688 pd->tcp_state_table = tcp_states; 690 pd->tcp_state_table = tcp_states;
691 return 0;
689} 692}
690 693
691static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd) 694static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index f4b7262896bb..2fedb2dcb3d1 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -467,7 +467,7 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
467 cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL]; 467 cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
468} 468}
469 469
470static void __udp_init(struct net *net, struct ip_vs_proto_data *pd) 470static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
471{ 471{
472 struct netns_ipvs *ipvs = net_ipvs(net); 472 struct netns_ipvs *ipvs = net_ipvs(net);
473 473
@@ -475,6 +475,9 @@ static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
475 spin_lock_init(&ipvs->udp_app_lock); 475 spin_lock_init(&ipvs->udp_app_lock);
476 pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts, 476 pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
477 sizeof(udp_timeouts)); 477 sizeof(udp_timeouts));
478 if (!pd->timeout_table)
479 return -ENOMEM;
480 return 0;
478} 481}
479 482
480static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd) 483static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index cbdb754dbb10..729f157a0efa 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -735,6 +735,7 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
735 735
736#ifdef CONFIG_NF_CONNTRACK_ZONES 736#ifdef CONFIG_NF_CONNTRACK_ZONES
737out_free: 737out_free:
738 atomic_dec(&net->ct.count);
738 kmem_cache_free(net->ct.nf_conntrack_cachep, ct); 739 kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
739 return ERR_PTR(-ENOMEM); 740 return ERR_PTR(-ENOMEM);
740#endif 741#endif
@@ -1591,7 +1592,7 @@ static int nf_conntrack_init_net(struct net *net)
1591 return 0; 1592 return 0;
1592 1593
1593err_timeout: 1594err_timeout:
1594 nf_conntrack_timeout_fini(net); 1595 nf_conntrack_ecache_fini(net);
1595err_ecache: 1596err_ecache:
1596 nf_conntrack_tstamp_fini(net); 1597 nf_conntrack_tstamp_fini(net);
1597err_tstamp: 1598err_tstamp:
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 361eade62a09..0d07a1dcf605 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -584,8 +584,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
584 * Let's try to use the data from the packet. 584 * Let's try to use the data from the packet.
585 */ 585 */
586 sender->td_end = end; 586 sender->td_end = end;
587 win <<= sender->td_scale; 587 swin = win << sender->td_scale;
588 sender->td_maxwin = (win == 0 ? 1 : win); 588 sender->td_maxwin = (swin == 0 ? 1 : swin);
589 sender->td_maxend = end + sender->td_maxwin; 589 sender->td_maxend = end + sender->td_maxwin;
590 /* 590 /*
591 * We haven't seen traffic in the other direction yet 591 * We haven't seen traffic in the other direction yet
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 3eb348bfc4fb..d98c868c148b 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <linux/atomic.h>
13#include <linux/netlink.h> 14#include <linux/netlink.h>
14#include <linux/rculist.h> 15#include <linux/rculist.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
@@ -17,7 +18,6 @@
17#include <linux/errno.h> 18#include <linux/errno.h>
18#include <net/netlink.h> 19#include <net/netlink.h>
19#include <net/sock.h> 20#include <net/sock.h>
20#include <asm/atomic.h>
21 21
22#include <linux/netfilter.h> 22#include <linux/netfilter.h>
23#include <linux/netfilter/nfnetlink.h> 23#include <linux/netfilter/nfnetlink.h>
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 0c8e43810ce3..3746d8b9a478 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -150,6 +150,17 @@ err1:
150 return ret; 150 return ret;
151} 151}
152 152
153#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
154static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
155{
156 typeof(nf_ct_timeout_put_hook) timeout_put;
157
158 timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
159 if (timeout_put)
160 timeout_put(timeout);
161}
162#endif
163
153static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 164static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
154{ 165{
155 struct xt_ct_target_info_v1 *info = par->targinfo; 166 struct xt_ct_target_info_v1 *info = par->targinfo;
@@ -158,7 +169,9 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
158 struct nf_conn *ct; 169 struct nf_conn *ct;
159 int ret = 0; 170 int ret = 0;
160 u8 proto; 171 u8 proto;
161 172#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
173 struct ctnl_timeout *timeout;
174#endif
162 if (info->flags & ~XT_CT_NOTRACK) 175 if (info->flags & ~XT_CT_NOTRACK)
163 return -EINVAL; 176 return -EINVAL;
164 177
@@ -214,9 +227,8 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
214 } 227 }
215 228
216#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 229#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
217 if (info->timeout) { 230 if (info->timeout[0]) {
218 typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 231 typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
219 struct ctnl_timeout *timeout;
220 struct nf_conn_timeout *timeout_ext; 232 struct nf_conn_timeout *timeout_ext;
221 233
222 rcu_read_lock(); 234 rcu_read_lock();
@@ -245,7 +257,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
245 pr_info("Timeout policy `%s' can only be " 257 pr_info("Timeout policy `%s' can only be "
246 "used by L3 protocol number %d\n", 258 "used by L3 protocol number %d\n",
247 info->timeout, timeout->l3num); 259 info->timeout, timeout->l3num);
248 goto err4; 260 goto err5;
249 } 261 }
250 /* Make sure the timeout policy matches any existing 262 /* Make sure the timeout policy matches any existing
251 * protocol tracker, otherwise default to generic. 263 * protocol tracker, otherwise default to generic.
@@ -258,13 +270,13 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
258 "used by L4 protocol number %d\n", 270 "used by L4 protocol number %d\n",
259 info->timeout, 271 info->timeout,
260 timeout->l4proto->l4proto); 272 timeout->l4proto->l4proto);
261 goto err4; 273 goto err5;
262 } 274 }
263 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, 275 timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
264 GFP_KERNEL); 276 GFP_ATOMIC);
265 if (timeout_ext == NULL) { 277 if (timeout_ext == NULL) {
266 ret = -ENOMEM; 278 ret = -ENOMEM;
267 goto err4; 279 goto err5;
268 } 280 }
269 } else { 281 } else {
270 ret = -ENOENT; 282 ret = -ENOENT;
@@ -281,8 +293,12 @@ out:
281 info->ct = ct; 293 info->ct = ct;
282 return 0; 294 return 0;
283 295
296#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
297err5:
298 __xt_ct_tg_timeout_put(timeout);
284err4: 299err4:
285 rcu_read_unlock(); 300 rcu_read_unlock();
301#endif
286err3: 302err3:
287 nf_conntrack_free(ct); 303 nf_conntrack_free(ct);
288err2: 304err2: