diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 19:52:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 19:52:32 -0400 |
commit | de8856d2c11f562c60ed9340a83db4a4f829a6e6 (patch) | |
tree | 0b871e5f4cf3204c4c6243c7622c4787d56d48ee /net | |
parent | 66f03c614c0902ccf7d6160459362a9352f33271 (diff) | |
parent | 94f826b8076e2cb92242061e92f21b5baa3eccc2 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) Name string overrun fix in gianfar driver from Joe Perches.
2) VHOST bug fixes from Michael S. Tsirkin and Nadav Har'El
3) Fix dependencies on xt_LOG netfilter module, from Pablo Neira Ayuso.
4) Fix RCU locking in xt_CT, also from Pablo Neira Ayuso.
5) Add a parameter to skb_add_rx_frag() so we can fix the truesize
adjustments in the drivers that use it. The individual drivers
aren't fixed by this commit, but will be dealt with using follow-on
commits. From Eric Dumazet.
6) Add some device IDs to qmi_wwan driver, from Andrew Bird.
7) Fix a potential rcu_read_lock() imbalancein rt6_fill_node(). From
Eric Dumazet.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
net: fix a potential rcu_read_lock() imbalance in rt6_fill_node()
net: add a truesize parameter to skb_add_rx_frag()
gianfar: Fix possible overrun and simplify interrupt name field creation
USB: qmi_wwan: Add ZTE (Vodafone) K3570-Z and K3571-Z net interfaces
USB: option: Ignore ZTE (Vodafone) K3570/71 net interfaces
USB: qmi_wwan: Add ZTE (Vodafone) K3565-Z and K4505-Z net interfaces
qlcnic: Bug fix for LRO
netfilter: nf_conntrack: permanently attach timeout policy to conntrack
netfilter: xt_CT: fix assignation of the generic protocol tracker
netfilter: xt_CT: missing rcu_read_lock section in timeout assignment
netfilter: cttimeout: fix dependency with l4protocol conntrack module
netfilter: xt_LOG: use CONFIG_IP6_NF_IPTABLES instead of CONFIG_IPV6
vhost: fix release path lockdep checks
vhost: don't forget to schedule()
tools/virtio: stub out strong barriers
tools/virtio: add linux/hrtimer.h stub
tools/virtio: add linux/module.h stub
Diffstat (limited to 'net')
-rw-r--r-- | net/core/skbuff.c | 4 | ||||
-rw-r--r-- | net/ipv6/route.c | 8 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 39 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 21 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_cttimeout.c | 45 | ||||
-rw-r--r-- | net/netfilter/xt_CT.c | 31 | ||||
-rw-r--r-- | net/netfilter/xt_LOG.c | 12 |
7 files changed, 103 insertions, 57 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6eb656acdfe5..a690cae91cdd 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -321,12 +321,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
321 | EXPORT_SYMBOL(__netdev_alloc_skb); | 321 | EXPORT_SYMBOL(__netdev_alloc_skb); |
322 | 322 | ||
323 | void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, | 323 | void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, |
324 | int size) | 324 | int size, unsigned int truesize) |
325 | { | 325 | { |
326 | skb_fill_page_desc(skb, i, page, off, size); | 326 | skb_fill_page_desc(skb, i, page, off, size); |
327 | skb->len += size; | 327 | skb->len += size; |
328 | skb->data_len += size; | 328 | skb->data_len += size; |
329 | skb->truesize += size; | 329 | skb->truesize += truesize; |
330 | } | 330 | } |
331 | EXPORT_SYMBOL(skb_add_rx_frag); | 331 | EXPORT_SYMBOL(skb_add_rx_frag); |
332 | 332 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 24c456e8aa1d..496b62712fe8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2474,8 +2474,12 @@ static int rt6_fill_node(struct net *net, | |||
2474 | 2474 | ||
2475 | rcu_read_lock(); | 2475 | rcu_read_lock(); |
2476 | n = dst_get_neighbour_noref(&rt->dst); | 2476 | n = dst_get_neighbour_noref(&rt->dst); |
2477 | if (n) | 2477 | if (n) { |
2478 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); | 2478 | if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { |
2479 | rcu_read_unlock(); | ||
2480 | goto nla_put_failure; | ||
2481 | } | ||
2482 | } | ||
2479 | rcu_read_unlock(); | 2483 | rcu_read_unlock(); |
2480 | 2484 | ||
2481 | if (rt->dst.dev) | 2485 | if (rt->dst.dev) |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7b48035826ee..cbdb754dbb10 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -768,8 +768,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
768 | struct nf_conntrack_l3proto *l3proto, | 768 | struct nf_conntrack_l3proto *l3proto, |
769 | struct nf_conntrack_l4proto *l4proto, | 769 | struct nf_conntrack_l4proto *l4proto, |
770 | struct sk_buff *skb, | 770 | struct sk_buff *skb, |
771 | unsigned int dataoff, u32 hash, | 771 | unsigned int dataoff, u32 hash) |
772 | unsigned int *timeouts) | ||
773 | { | 772 | { |
774 | struct nf_conn *ct; | 773 | struct nf_conn *ct; |
775 | struct nf_conn_help *help; | 774 | struct nf_conn_help *help; |
@@ -777,6 +776,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
777 | struct nf_conntrack_ecache *ecache; | 776 | struct nf_conntrack_ecache *ecache; |
778 | struct nf_conntrack_expect *exp; | 777 | struct nf_conntrack_expect *exp; |
779 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | 778 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; |
779 | struct nf_conn_timeout *timeout_ext; | ||
780 | unsigned int *timeouts; | ||
780 | 781 | ||
781 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { | 782 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { |
782 | pr_debug("Can't invert tuple.\n"); | 783 | pr_debug("Can't invert tuple.\n"); |
@@ -788,12 +789,21 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
788 | if (IS_ERR(ct)) | 789 | if (IS_ERR(ct)) |
789 | return (struct nf_conntrack_tuple_hash *)ct; | 790 | return (struct nf_conntrack_tuple_hash *)ct; |
790 | 791 | ||
792 | timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL; | ||
793 | if (timeout_ext) | ||
794 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
795 | else | ||
796 | timeouts = l4proto->get_timeouts(net); | ||
797 | |||
791 | if (!l4proto->new(ct, skb, dataoff, timeouts)) { | 798 | if (!l4proto->new(ct, skb, dataoff, timeouts)) { |
792 | nf_conntrack_free(ct); | 799 | nf_conntrack_free(ct); |
793 | pr_debug("init conntrack: can't track with proto module\n"); | 800 | pr_debug("init conntrack: can't track with proto module\n"); |
794 | return NULL; | 801 | return NULL; |
795 | } | 802 | } |
796 | 803 | ||
804 | if (timeout_ext) | ||
805 | nf_ct_timeout_ext_add(ct, timeout_ext->timeout, GFP_ATOMIC); | ||
806 | |||
797 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); | 807 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); |
798 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); | 808 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); |
799 | 809 | ||
@@ -854,8 +864,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
854 | struct nf_conntrack_l3proto *l3proto, | 864 | struct nf_conntrack_l3proto *l3proto, |
855 | struct nf_conntrack_l4proto *l4proto, | 865 | struct nf_conntrack_l4proto *l4proto, |
856 | int *set_reply, | 866 | int *set_reply, |
857 | enum ip_conntrack_info *ctinfo, | 867 | enum ip_conntrack_info *ctinfo) |
858 | unsigned int *timeouts) | ||
859 | { | 868 | { |
860 | struct nf_conntrack_tuple tuple; | 869 | struct nf_conntrack_tuple tuple; |
861 | struct nf_conntrack_tuple_hash *h; | 870 | struct nf_conntrack_tuple_hash *h; |
@@ -875,7 +884,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
875 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); | 884 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); |
876 | if (!h) { | 885 | if (!h) { |
877 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, | 886 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, |
878 | skb, dataoff, hash, timeouts); | 887 | skb, dataoff, hash); |
879 | if (!h) | 888 | if (!h) |
880 | return NULL; | 889 | return NULL; |
881 | if (IS_ERR(h)) | 890 | if (IS_ERR(h)) |
@@ -964,19 +973,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
964 | goto out; | 973 | goto out; |
965 | } | 974 | } |
966 | 975 | ||
967 | /* Decide what timeout policy we want to apply to this flow. */ | ||
968 | if (tmpl) { | ||
969 | timeout_ext = nf_ct_timeout_find(tmpl); | ||
970 | if (timeout_ext) | ||
971 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
972 | else | ||
973 | timeouts = l4proto->get_timeouts(net); | ||
974 | } else | ||
975 | timeouts = l4proto->get_timeouts(net); | ||
976 | |||
977 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, | 976 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, |
978 | l3proto, l4proto, &set_reply, &ctinfo, | 977 | l3proto, l4proto, &set_reply, &ctinfo); |
979 | timeouts); | ||
980 | if (!ct) { | 978 | if (!ct) { |
981 | /* Not valid part of a connection */ | 979 | /* Not valid part of a connection */ |
982 | NF_CT_STAT_INC_ATOMIC(net, invalid); | 980 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
@@ -993,6 +991,13 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
993 | 991 | ||
994 | NF_CT_ASSERT(skb->nfct); | 992 | NF_CT_ASSERT(skb->nfct); |
995 | 993 | ||
994 | /* Decide what timeout policy we want to apply to this flow. */ | ||
995 | timeout_ext = nf_ct_timeout_find(ct); | ||
996 | if (timeout_ext) | ||
997 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
998 | else | ||
999 | timeouts = l4proto->get_timeouts(net); | ||
1000 | |||
996 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); | 1001 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); |
997 | if (ret <= 0) { | 1002 | if (ret <= 0) { |
998 | /* Invalid: inverse of the return code tells | 1003 | /* Invalid: inverse of the return code tells |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 5701c8dd783c..be3da2c8cdc5 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -127,6 +127,27 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) | |||
127 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); | 128 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); |
129 | 129 | ||
130 | struct nf_conntrack_l4proto * | ||
131 | nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num) | ||
132 | { | ||
133 | struct nf_conntrack_l4proto *p; | ||
134 | |||
135 | rcu_read_lock(); | ||
136 | p = __nf_ct_l4proto_find(l3num, l4num); | ||
137 | if (!try_module_get(p->me)) | ||
138 | p = &nf_conntrack_l4proto_generic; | ||
139 | rcu_read_unlock(); | ||
140 | |||
141 | return p; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get); | ||
144 | |||
145 | void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p) | ||
146 | { | ||
147 | module_put(p->me); | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_put); | ||
150 | |||
130 | static int kill_l3proto(struct nf_conn *i, void *data) | 151 | static int kill_l3proto(struct nf_conn *i, void *data) |
131 | { | 152 | { |
132 | return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto; | 153 | return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto; |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index fec29a43de4d..2b9e79f5ef05 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -98,11 +98,13 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
98 | break; | 98 | break; |
99 | } | 99 | } |
100 | 100 | ||
101 | l4proto = __nf_ct_l4proto_find(l3num, l4num); | 101 | l4proto = nf_ct_l4proto_find_get(l3num, l4num); |
102 | 102 | ||
103 | /* This protocol is not supportted, skip. */ | 103 | /* This protocol is not supportted, skip. */ |
104 | if (l4proto->l4proto != l4num) | 104 | if (l4proto->l4proto != l4num) { |
105 | return -EOPNOTSUPP; | 105 | ret = -EOPNOTSUPP; |
106 | goto err_proto_put; | ||
107 | } | ||
106 | 108 | ||
107 | if (matching) { | 109 | if (matching) { |
108 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | 110 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { |
@@ -110,20 +112,25 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
110 | * different kind, sorry. | 112 | * different kind, sorry. |
111 | */ | 113 | */ |
112 | if (matching->l3num != l3num || | 114 | if (matching->l3num != l3num || |
113 | matching->l4num != l4num) | 115 | matching->l4proto->l4proto != l4num) { |
114 | return -EINVAL; | 116 | ret = -EINVAL; |
117 | goto err_proto_put; | ||
118 | } | ||
115 | 119 | ||
116 | ret = ctnl_timeout_parse_policy(matching, l4proto, | 120 | ret = ctnl_timeout_parse_policy(matching, l4proto, |
117 | cda[CTA_TIMEOUT_DATA]); | 121 | cda[CTA_TIMEOUT_DATA]); |
118 | return ret; | 122 | return ret; |
119 | } | 123 | } |
120 | return -EBUSY; | 124 | ret = -EBUSY; |
125 | goto err_proto_put; | ||
121 | } | 126 | } |
122 | 127 | ||
123 | timeout = kzalloc(sizeof(struct ctnl_timeout) + | 128 | timeout = kzalloc(sizeof(struct ctnl_timeout) + |
124 | l4proto->ctnl_timeout.obj_size, GFP_KERNEL); | 129 | l4proto->ctnl_timeout.obj_size, GFP_KERNEL); |
125 | if (timeout == NULL) | 130 | if (timeout == NULL) { |
126 | return -ENOMEM; | 131 | ret = -ENOMEM; |
132 | goto err_proto_put; | ||
133 | } | ||
127 | 134 | ||
128 | ret = ctnl_timeout_parse_policy(timeout, l4proto, | 135 | ret = ctnl_timeout_parse_policy(timeout, l4proto, |
129 | cda[CTA_TIMEOUT_DATA]); | 136 | cda[CTA_TIMEOUT_DATA]); |
@@ -132,13 +139,15 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
132 | 139 | ||
133 | strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); | 140 | strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); |
134 | timeout->l3num = l3num; | 141 | timeout->l3num = l3num; |
135 | timeout->l4num = l4num; | 142 | timeout->l4proto = l4proto; |
136 | atomic_set(&timeout->refcnt, 1); | 143 | atomic_set(&timeout->refcnt, 1); |
137 | list_add_tail_rcu(&timeout->head, &cttimeout_list); | 144 | list_add_tail_rcu(&timeout->head, &cttimeout_list); |
138 | 145 | ||
139 | return 0; | 146 | return 0; |
140 | err: | 147 | err: |
141 | kfree(timeout); | 148 | kfree(timeout); |
149 | err_proto_put: | ||
150 | nf_ct_l4proto_put(l4proto); | ||
142 | return ret; | 151 | return ret; |
143 | } | 152 | } |
144 | 153 | ||
@@ -149,7 +158,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
149 | struct nlmsghdr *nlh; | 158 | struct nlmsghdr *nlh; |
150 | struct nfgenmsg *nfmsg; | 159 | struct nfgenmsg *nfmsg; |
151 | unsigned int flags = pid ? NLM_F_MULTI : 0; | 160 | unsigned int flags = pid ? NLM_F_MULTI : 0; |
152 | struct nf_conntrack_l4proto *l4proto; | 161 | struct nf_conntrack_l4proto *l4proto = timeout->l4proto; |
153 | 162 | ||
154 | event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; | 163 | event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; |
155 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | 164 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); |
@@ -163,20 +172,10 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
163 | 172 | ||
164 | NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); | 173 | NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); |
165 | NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); | 174 | NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); |
166 | NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num); | 175 | NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto); |
167 | NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, | 176 | NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, |
168 | htonl(atomic_read(&timeout->refcnt))); | 177 | htonl(atomic_read(&timeout->refcnt))); |
169 | 178 | ||
170 | l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num); | ||
171 | |||
172 | /* If the timeout object does not match the layer 4 protocol tracker, | ||
173 | * then skip dumping the data part since we don't know how to | ||
174 | * interpret it. This may happen for UPDlite, SCTP and DCCP since | ||
175 | * you can unload the module. | ||
176 | */ | ||
177 | if (timeout->l4num != l4proto->l4proto) | ||
178 | goto out; | ||
179 | |||
180 | if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { | 179 | if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { |
181 | struct nlattr *nest_parms; | 180 | struct nlattr *nest_parms; |
182 | int ret; | 181 | int ret; |
@@ -192,7 +191,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
192 | 191 | ||
193 | nla_nest_end(skb, nest_parms); | 192 | nla_nest_end(skb, nest_parms); |
194 | } | 193 | } |
195 | out: | 194 | |
196 | nlmsg_end(skb, nlh); | 195 | nlmsg_end(skb, nlh); |
197 | return skb->len; | 196 | return skb->len; |
198 | 197 | ||
@@ -293,6 +292,7 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) | |||
293 | if (atomic_dec_and_test(&timeout->refcnt)) { | 292 | if (atomic_dec_and_test(&timeout->refcnt)) { |
294 | /* We are protected by nfnl mutex. */ | 293 | /* We are protected by nfnl mutex. */ |
295 | list_del_rcu(&timeout->head); | 294 | list_del_rcu(&timeout->head); |
295 | nf_ct_l4proto_put(timeout->l4proto); | ||
296 | kfree_rcu(timeout, rcu_head); | 296 | kfree_rcu(timeout, rcu_head); |
297 | } else { | 297 | } else { |
298 | /* still in use, restore reference counter. */ | 298 | /* still in use, restore reference counter. */ |
@@ -417,6 +417,7 @@ static void __exit cttimeout_exit(void) | |||
417 | /* We are sure that our objects have no clients at this point, | 417 | /* We are sure that our objects have no clients at this point, |
418 | * it's safe to release them all without checking refcnt. | 418 | * it's safe to release them all without checking refcnt. |
419 | */ | 419 | */ |
420 | nf_ct_l4proto_put(cur->l4proto); | ||
420 | kfree_rcu(cur, rcu_head); | 421 | kfree_rcu(cur, rcu_head); |
421 | } | 422 | } |
422 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 423 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index b873445df444..0c8e43810ce3 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -14,8 +14,10 @@ | |||
14 | #include <linux/netfilter/x_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter/xt_CT.h> | 15 | #include <linux/netfilter/xt_CT.h> |
16 | #include <net/netfilter/nf_conntrack.h> | 16 | #include <net/netfilter/nf_conntrack.h> |
17 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
17 | #include <net/netfilter/nf_conntrack_helper.h> | 18 | #include <net/netfilter/nf_conntrack_helper.h> |
18 | #include <net/netfilter/nf_conntrack_ecache.h> | 19 | #include <net/netfilter/nf_conntrack_ecache.h> |
20 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
19 | #include <net/netfilter/nf_conntrack_timeout.h> | 21 | #include <net/netfilter/nf_conntrack_timeout.h> |
20 | #include <net/netfilter/nf_conntrack_zones.h> | 22 | #include <net/netfilter/nf_conntrack_zones.h> |
21 | 23 | ||
@@ -217,50 +219,59 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | |||
217 | struct ctnl_timeout *timeout; | 219 | struct ctnl_timeout *timeout; |
218 | struct nf_conn_timeout *timeout_ext; | 220 | struct nf_conn_timeout *timeout_ext; |
219 | 221 | ||
222 | rcu_read_lock(); | ||
220 | timeout_find_get = | 223 | timeout_find_get = |
221 | rcu_dereference(nf_ct_timeout_find_get_hook); | 224 | rcu_dereference(nf_ct_timeout_find_get_hook); |
222 | 225 | ||
223 | if (timeout_find_get) { | 226 | if (timeout_find_get) { |
224 | const struct ipt_entry *e = par->entryinfo; | 227 | const struct ipt_entry *e = par->entryinfo; |
228 | struct nf_conntrack_l4proto *l4proto; | ||
225 | 229 | ||
226 | if (e->ip.invflags & IPT_INV_PROTO) { | 230 | if (e->ip.invflags & IPT_INV_PROTO) { |
227 | ret = -EINVAL; | 231 | ret = -EINVAL; |
228 | pr_info("You cannot use inversion on " | 232 | pr_info("You cannot use inversion on " |
229 | "L4 protocol\n"); | 233 | "L4 protocol\n"); |
230 | goto err3; | 234 | goto err4; |
231 | } | 235 | } |
232 | timeout = timeout_find_get(info->timeout); | 236 | timeout = timeout_find_get(info->timeout); |
233 | if (timeout == NULL) { | 237 | if (timeout == NULL) { |
234 | ret = -ENOENT; | 238 | ret = -ENOENT; |
235 | pr_info("No such timeout policy \"%s\"\n", | 239 | pr_info("No such timeout policy \"%s\"\n", |
236 | info->timeout); | 240 | info->timeout); |
237 | goto err3; | 241 | goto err4; |
238 | } | 242 | } |
239 | if (timeout->l3num != par->family) { | 243 | if (timeout->l3num != par->family) { |
240 | ret = -EINVAL; | 244 | ret = -EINVAL; |
241 | pr_info("Timeout policy `%s' can only be " | 245 | pr_info("Timeout policy `%s' can only be " |
242 | "used by L3 protocol number %d\n", | 246 | "used by L3 protocol number %d\n", |
243 | info->timeout, timeout->l3num); | 247 | info->timeout, timeout->l3num); |
244 | goto err3; | 248 | goto err4; |
245 | } | 249 | } |
246 | if (timeout->l4num != e->ip.proto) { | 250 | /* Make sure the timeout policy matches any existing |
251 | * protocol tracker, otherwise default to generic. | ||
252 | */ | ||
253 | l4proto = __nf_ct_l4proto_find(par->family, | ||
254 | e->ip.proto); | ||
255 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
247 | ret = -EINVAL; | 256 | ret = -EINVAL; |
248 | pr_info("Timeout policy `%s' can only be " | 257 | pr_info("Timeout policy `%s' can only be " |
249 | "used by L4 protocol number %d\n", | 258 | "used by L4 protocol number %d\n", |
250 | info->timeout, timeout->l4num); | 259 | info->timeout, |
251 | goto err3; | 260 | timeout->l4proto->l4proto); |
261 | goto err4; | ||
252 | } | 262 | } |
253 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, | 263 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, |
254 | GFP_KERNEL); | 264 | GFP_KERNEL); |
255 | if (timeout_ext == NULL) { | 265 | if (timeout_ext == NULL) { |
256 | ret = -ENOMEM; | 266 | ret = -ENOMEM; |
257 | goto err3; | 267 | goto err4; |
258 | } | 268 | } |
259 | } else { | 269 | } else { |
260 | ret = -ENOENT; | 270 | ret = -ENOENT; |
261 | pr_info("Timeout policy base is empty\n"); | 271 | pr_info("Timeout policy base is empty\n"); |
262 | goto err3; | 272 | goto err4; |
263 | } | 273 | } |
274 | rcu_read_unlock(); | ||
264 | } | 275 | } |
265 | #endif | 276 | #endif |
266 | 277 | ||
@@ -270,6 +281,8 @@ out: | |||
270 | info->ct = ct; | 281 | info->ct = ct; |
271 | return 0; | 282 | return 0; |
272 | 283 | ||
284 | err4: | ||
285 | rcu_read_unlock(); | ||
273 | err3: | 286 | err3: |
274 | nf_conntrack_free(ct); | 287 | nf_conntrack_free(ct); |
275 | err2: | 288 | err2: |
@@ -311,6 +324,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
311 | nf_ct_l3proto_module_put(par->family); | 324 | nf_ct_l3proto_module_put(par->family); |
312 | 325 | ||
313 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 326 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
327 | rcu_read_lock(); | ||
314 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | 328 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); |
315 | 329 | ||
316 | if (timeout_put) { | 330 | if (timeout_put) { |
@@ -318,6 +332,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
318 | if (timeout_ext) | 332 | if (timeout_ext) |
319 | timeout_put(timeout_ext->timeout); | 333 | timeout_put(timeout_ext->timeout); |
320 | } | 334 | } |
335 | rcu_read_unlock(); | ||
321 | #endif | 336 | #endif |
322 | } | 337 | } |
323 | nf_ct_put(info->ct); | 338 | nf_ct_put(info->ct); |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index f99f8dee238b..ff5f75fddb15 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -480,7 +480,7 @@ ipt_log_packet(u_int8_t pf, | |||
480 | sb_close(m); | 480 | sb_close(m); |
481 | } | 481 | } |
482 | 482 | ||
483 | #if IS_ENABLED(CONFIG_IPV6) | 483 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
484 | /* One level of recursion won't kill us */ | 484 | /* One level of recursion won't kill us */ |
485 | static void dump_ipv6_packet(struct sbuff *m, | 485 | static void dump_ipv6_packet(struct sbuff *m, |
486 | const struct nf_loginfo *info, | 486 | const struct nf_loginfo *info, |
@@ -824,7 +824,7 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
824 | if (par->family == NFPROTO_IPV4) | 824 | if (par->family == NFPROTO_IPV4) |
825 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, | 825 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, |
826 | par->out, &li, loginfo->prefix); | 826 | par->out, &li, loginfo->prefix); |
827 | #if IS_ENABLED(CONFIG_IPV6) | 827 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
828 | else if (par->family == NFPROTO_IPV6) | 828 | else if (par->family == NFPROTO_IPV6) |
829 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, | 829 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, |
830 | par->out, &li, loginfo->prefix); | 830 | par->out, &li, loginfo->prefix); |
@@ -864,7 +864,7 @@ static struct xt_target log_tg_regs[] __read_mostly = { | |||
864 | .checkentry = log_tg_check, | 864 | .checkentry = log_tg_check, |
865 | .me = THIS_MODULE, | 865 | .me = THIS_MODULE, |
866 | }, | 866 | }, |
867 | #if IS_ENABLED(CONFIG_IPV6) | 867 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
868 | { | 868 | { |
869 | .name = "LOG", | 869 | .name = "LOG", |
870 | .family = NFPROTO_IPV6, | 870 | .family = NFPROTO_IPV6, |
@@ -882,7 +882,7 @@ static struct nf_logger ipt_log_logger __read_mostly = { | |||
882 | .me = THIS_MODULE, | 882 | .me = THIS_MODULE, |
883 | }; | 883 | }; |
884 | 884 | ||
885 | #if IS_ENABLED(CONFIG_IPV6) | 885 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
886 | static struct nf_logger ip6t_log_logger __read_mostly = { | 886 | static struct nf_logger ip6t_log_logger __read_mostly = { |
887 | .name = "ip6t_LOG", | 887 | .name = "ip6t_LOG", |
888 | .logfn = &ip6t_log_packet, | 888 | .logfn = &ip6t_log_packet, |
@@ -899,7 +899,7 @@ static int __init log_tg_init(void) | |||
899 | return ret; | 899 | return ret; |
900 | 900 | ||
901 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); | 901 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); |
902 | #if IS_ENABLED(CONFIG_IPV6) | 902 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
903 | nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); | 903 | nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); |
904 | #endif | 904 | #endif |
905 | return 0; | 905 | return 0; |
@@ -908,7 +908,7 @@ static int __init log_tg_init(void) | |||
908 | static void __exit log_tg_exit(void) | 908 | static void __exit log_tg_exit(void) |
909 | { | 909 | { |
910 | nf_log_unregister(&ipt_log_logger); | 910 | nf_log_unregister(&ipt_log_logger); |
911 | #if IS_ENABLED(CONFIG_IPV6) | 911 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
912 | nf_log_unregister(&ip6t_log_logger); | 912 | nf_log_unregister(&ip6t_log_logger); |
913 | #endif | 913 | #endif |
914 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); | 914 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); |