diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-14 20:38:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-14 20:38:24 -0400 |
commit | 7e703eccf02a4a6aac6574f5fd4680a0619fdbfb (patch) | |
tree | a2ef77eac1b0fd471629916c5ed82e6b3be8b36c /net | |
parent | 91174391bf5a368c9837b63b84d7f5a813efd719 (diff) | |
parent | f4c13c8ec56e70eeff3e365e0c5fcdad16845b32 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
"Things seem to be settling down as far as networking is concerned,
let's hope this trend continues...
1) Add iov_iter_revert() and use it to fix the behavior of
skb_copy_datagram_msg() et al., from Al Viro.
2) Fix the protocol used in the synthetic SKB we cons up for the
purposes of doing a simulated route lookup for RTM_GETROUTE
requests. From Florian Larysch.
3) Don't add noop_qdisc to the per-device qdisc hashes, from Cong
Wang.
4) Don't call netdev_change_features with the team lock held, from
Xin Long.
5) Revert TCP F-RTO extension to catch more spurious timeouts because
it interacts very badly with some middle-boxes. From Yuchung
Cheng.
6) Fix the loss of error values in l2tp {s,g}etsockopt calls, from
Guillaume Nault.
7) ctnetlink uses bit positions where it should be using bit masks,
fix from Liping Zhang.
8) Missing RCU locking in netfilter helper code, from Gao Feng.
9) Avoid double frees and use-after-frees in tcp_disconnect(), from
Eric Dumazet.
10) Don't do a changelink before we register the netdevice in
bridging, from Ido Schimmel.
11) Lock the ipv6 device address list properly, from Rabin Vincent"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (29 commits)
netfilter: ipt_CLUSTERIP: Fix wrong conntrack netns refcnt usage
netfilter: nft_hash: do not dump the auto generated seed
drivers: net: usb: qmi_wwan: add QMI_QUIRK_SET_DTR for Telit PID 0x1201
ipv6: Fix idev->addr_list corruption
net: xdp: don't export dev_change_xdp_fd()
bridge: netlink: register netdevice before executing changelink
bridge: implement missing ndo_uninit()
bpf: reference may_access_skb() from __bpf_prog_run()
tcp: clear saved_syn in tcp_disconnect()
netfilter: nf_ct_expect: use proper RCU list traversal/update APIs
netfilter: ctnetlink: skip dumping expect when nfct_help(ct) is NULL
netfilter: make it safer during the inet6_dev->addr_list traversal
netfilter: ctnetlink: make it safer when checking the ct helper name
netfilter: helper: Add the rcu lock when call __nf_conntrack_helper_find
netfilter: ctnetlink: using bit to represent the ct event
netfilter: xt_TCPMSS: add more sanity tests on tcph->doff
net: tcp: Increase TCP_MIB_OUTRSTS even though fail to alloc skb
l2tp: don't mask errors in pppol2tp_getsockopt()
l2tp: don't mask errors in pppol2tp_setsockopt()
tcp: restrict F-RTO to work-around broken middle-boxes
...
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_device.c | 20 | ||||
-rw-r--r-- | net/bridge/br_if.c | 1 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 7 | ||||
-rw-r--r-- | net/bridge/br_netlink.c | 7 | ||||
-rw-r--r-- | net/bridge/br_private.h | 5 | ||||
-rw-r--r-- | net/core/datagram.c | 23 | ||||
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 | ||||
-rw-r--r-- | net/ipv4/route.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 20 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 4 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 11 | ||||
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 9 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 17 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 41 | ||||
-rw-r--r-- | net/netfilter/nf_nat_redirect.c | 2 | ||||
-rw-r--r-- | net/netfilter/nft_hash.c | 10 | ||||
-rw-r--r-- | net/netfilter/xt_TCPMSS.c | 6 | ||||
-rw-r--r-- | net/netfilter/xt_TPROXY.c | 5 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 3 |
23 files changed, 135 insertions, 68 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ea71513fca21..90f49a194249 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -119,6 +119,15 @@ static int br_dev_init(struct net_device *dev) | |||
119 | return err; | 119 | return err; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void br_dev_uninit(struct net_device *dev) | ||
123 | { | ||
124 | struct net_bridge *br = netdev_priv(dev); | ||
125 | |||
126 | br_multicast_uninit_stats(br); | ||
127 | br_vlan_flush(br); | ||
128 | free_percpu(br->stats); | ||
129 | } | ||
130 | |||
122 | static int br_dev_open(struct net_device *dev) | 131 | static int br_dev_open(struct net_device *dev) |
123 | { | 132 | { |
124 | struct net_bridge *br = netdev_priv(dev); | 133 | struct net_bridge *br = netdev_priv(dev); |
@@ -332,6 +341,7 @@ static const struct net_device_ops br_netdev_ops = { | |||
332 | .ndo_open = br_dev_open, | 341 | .ndo_open = br_dev_open, |
333 | .ndo_stop = br_dev_stop, | 342 | .ndo_stop = br_dev_stop, |
334 | .ndo_init = br_dev_init, | 343 | .ndo_init = br_dev_init, |
344 | .ndo_uninit = br_dev_uninit, | ||
335 | .ndo_start_xmit = br_dev_xmit, | 345 | .ndo_start_xmit = br_dev_xmit, |
336 | .ndo_get_stats64 = br_get_stats64, | 346 | .ndo_get_stats64 = br_get_stats64, |
337 | .ndo_set_mac_address = br_set_mac_address, | 347 | .ndo_set_mac_address = br_set_mac_address, |
@@ -356,14 +366,6 @@ static const struct net_device_ops br_netdev_ops = { | |||
356 | .ndo_features_check = passthru_features_check, | 366 | .ndo_features_check = passthru_features_check, |
357 | }; | 367 | }; |
358 | 368 | ||
359 | static void br_dev_free(struct net_device *dev) | ||
360 | { | ||
361 | struct net_bridge *br = netdev_priv(dev); | ||
362 | |||
363 | free_percpu(br->stats); | ||
364 | free_netdev(dev); | ||
365 | } | ||
366 | |||
367 | static struct device_type br_type = { | 369 | static struct device_type br_type = { |
368 | .name = "bridge", | 370 | .name = "bridge", |
369 | }; | 371 | }; |
@@ -376,7 +378,7 @@ void br_dev_setup(struct net_device *dev) | |||
376 | ether_setup(dev); | 378 | ether_setup(dev); |
377 | 379 | ||
378 | dev->netdev_ops = &br_netdev_ops; | 380 | dev->netdev_ops = &br_netdev_ops; |
379 | dev->destructor = br_dev_free; | 381 | dev->destructor = free_netdev; |
380 | dev->ethtool_ops = &br_ethtool_ops; | 382 | dev->ethtool_ops = &br_ethtool_ops; |
381 | SET_NETDEV_DEVTYPE(dev, &br_type); | 383 | SET_NETDEV_DEVTYPE(dev, &br_type); |
382 | dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; | 384 | dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 8ac1770aa222..56a2a72e7738 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -311,7 +311,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head) | |||
311 | 311 | ||
312 | br_fdb_delete_by_port(br, NULL, 0, 1); | 312 | br_fdb_delete_by_port(br, NULL, 0, 1); |
313 | 313 | ||
314 | br_vlan_flush(br); | ||
315 | br_multicast_dev_del(br); | 314 | br_multicast_dev_del(br); |
316 | cancel_delayed_work_sync(&br->gc_work); | 315 | cancel_delayed_work_sync(&br->gc_work); |
317 | 316 | ||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index b760f2620abf..faa7261a992f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -2031,8 +2031,6 @@ void br_multicast_dev_del(struct net_bridge *br) | |||
2031 | 2031 | ||
2032 | out: | 2032 | out: |
2033 | spin_unlock_bh(&br->multicast_lock); | 2033 | spin_unlock_bh(&br->multicast_lock); |
2034 | |||
2035 | free_percpu(br->mcast_stats); | ||
2036 | } | 2034 | } |
2037 | 2035 | ||
2038 | int br_multicast_set_router(struct net_bridge *br, unsigned long val) | 2036 | int br_multicast_set_router(struct net_bridge *br, unsigned long val) |
@@ -2531,6 +2529,11 @@ int br_multicast_init_stats(struct net_bridge *br) | |||
2531 | return 0; | 2529 | return 0; |
2532 | } | 2530 | } |
2533 | 2531 | ||
2532 | void br_multicast_uninit_stats(struct net_bridge *br) | ||
2533 | { | ||
2534 | free_percpu(br->mcast_stats); | ||
2535 | } | ||
2536 | |||
2534 | static void mcast_stats_add_dir(u64 *dst, u64 *src) | 2537 | static void mcast_stats_add_dir(u64 *dst, u64 *src) |
2535 | { | 2538 | { |
2536 | dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX]; | 2539 | dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX]; |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index a8f6acd23e30..225ef7d53701 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -1165,11 +1165,14 @@ static int br_dev_newlink(struct net *src_net, struct net_device *dev, | |||
1165 | spin_unlock_bh(&br->lock); | 1165 | spin_unlock_bh(&br->lock); |
1166 | } | 1166 | } |
1167 | 1167 | ||
1168 | err = br_changelink(dev, tb, data); | 1168 | err = register_netdevice(dev); |
1169 | if (err) | 1169 | if (err) |
1170 | return err; | 1170 | return err; |
1171 | 1171 | ||
1172 | return register_netdevice(dev); | 1172 | err = br_changelink(dev, tb, data); |
1173 | if (err) | ||
1174 | unregister_netdevice(dev); | ||
1175 | return err; | ||
1173 | } | 1176 | } |
1174 | 1177 | ||
1175 | static size_t br_get_size(const struct net_device *brdev) | 1178 | static size_t br_get_size(const struct net_device *brdev) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 61368186edea..0d177280aa84 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -620,6 +620,7 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, | |||
620 | void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, | 620 | void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, |
621 | const struct sk_buff *skb, u8 type, u8 dir); | 621 | const struct sk_buff *skb, u8 type, u8 dir); |
622 | int br_multicast_init_stats(struct net_bridge *br); | 622 | int br_multicast_init_stats(struct net_bridge *br); |
623 | void br_multicast_uninit_stats(struct net_bridge *br); | ||
623 | void br_multicast_get_stats(const struct net_bridge *br, | 624 | void br_multicast_get_stats(const struct net_bridge *br, |
624 | const struct net_bridge_port *p, | 625 | const struct net_bridge_port *p, |
625 | struct br_mcast_stats *dest); | 626 | struct br_mcast_stats *dest); |
@@ -760,6 +761,10 @@ static inline int br_multicast_init_stats(struct net_bridge *br) | |||
760 | return 0; | 761 | return 0; |
761 | } | 762 | } |
762 | 763 | ||
764 | static inline void br_multicast_uninit_stats(struct net_bridge *br) | ||
765 | { | ||
766 | } | ||
767 | |||
763 | static inline int br_multicast_igmp_type(const struct sk_buff *skb) | 768 | static inline int br_multicast_igmp_type(const struct sk_buff *skb) |
764 | { | 769 | { |
765 | return 0; | 770 | return 0; |
diff --git a/net/core/datagram.c b/net/core/datagram.c index ea633342ab0d..f4947e737f34 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -398,7 +398,7 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset, | |||
398 | struct iov_iter *to, int len) | 398 | struct iov_iter *to, int len) |
399 | { | 399 | { |
400 | int start = skb_headlen(skb); | 400 | int start = skb_headlen(skb); |
401 | int i, copy = start - offset; | 401 | int i, copy = start - offset, start_off = offset, n; |
402 | struct sk_buff *frag_iter; | 402 | struct sk_buff *frag_iter; |
403 | 403 | ||
404 | trace_skb_copy_datagram_iovec(skb, len); | 404 | trace_skb_copy_datagram_iovec(skb, len); |
@@ -407,11 +407,12 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset, | |||
407 | if (copy > 0) { | 407 | if (copy > 0) { |
408 | if (copy > len) | 408 | if (copy > len) |
409 | copy = len; | 409 | copy = len; |
410 | if (copy_to_iter(skb->data + offset, copy, to) != copy) | 410 | n = copy_to_iter(skb->data + offset, copy, to); |
411 | offset += n; | ||
412 | if (n != copy) | ||
411 | goto short_copy; | 413 | goto short_copy; |
412 | if ((len -= copy) == 0) | 414 | if ((len -= copy) == 0) |
413 | return 0; | 415 | return 0; |
414 | offset += copy; | ||
415 | } | 416 | } |
416 | 417 | ||
417 | /* Copy paged appendix. Hmm... why does this look so complicated? */ | 418 | /* Copy paged appendix. Hmm... why does this look so complicated? */ |
@@ -425,13 +426,14 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset, | |||
425 | if ((copy = end - offset) > 0) { | 426 | if ((copy = end - offset) > 0) { |
426 | if (copy > len) | 427 | if (copy > len) |
427 | copy = len; | 428 | copy = len; |
428 | if (copy_page_to_iter(skb_frag_page(frag), | 429 | n = copy_page_to_iter(skb_frag_page(frag), |
429 | frag->page_offset + offset - | 430 | frag->page_offset + offset - |
430 | start, copy, to) != copy) | 431 | start, copy, to); |
432 | offset += n; | ||
433 | if (n != copy) | ||
431 | goto short_copy; | 434 | goto short_copy; |
432 | if (!(len -= copy)) | 435 | if (!(len -= copy)) |
433 | return 0; | 436 | return 0; |
434 | offset += copy; | ||
435 | } | 437 | } |
436 | start = end; | 438 | start = end; |
437 | } | 439 | } |
@@ -463,6 +465,7 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset, | |||
463 | */ | 465 | */ |
464 | 466 | ||
465 | fault: | 467 | fault: |
468 | iov_iter_revert(to, offset - start_off); | ||
466 | return -EFAULT; | 469 | return -EFAULT; |
467 | 470 | ||
468 | short_copy: | 471 | short_copy: |
@@ -613,7 +616,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
613 | __wsum *csump) | 616 | __wsum *csump) |
614 | { | 617 | { |
615 | int start = skb_headlen(skb); | 618 | int start = skb_headlen(skb); |
616 | int i, copy = start - offset; | 619 | int i, copy = start - offset, start_off = offset; |
617 | struct sk_buff *frag_iter; | 620 | struct sk_buff *frag_iter; |
618 | int pos = 0; | 621 | int pos = 0; |
619 | int n; | 622 | int n; |
@@ -623,11 +626,11 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
623 | if (copy > len) | 626 | if (copy > len) |
624 | copy = len; | 627 | copy = len; |
625 | n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to); | 628 | n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to); |
629 | offset += n; | ||
626 | if (n != copy) | 630 | if (n != copy) |
627 | goto fault; | 631 | goto fault; |
628 | if ((len -= copy) == 0) | 632 | if ((len -= copy) == 0) |
629 | return 0; | 633 | return 0; |
630 | offset += copy; | ||
631 | pos = copy; | 634 | pos = copy; |
632 | } | 635 | } |
633 | 636 | ||
@@ -649,12 +652,12 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
649 | offset - start, copy, | 652 | offset - start, copy, |
650 | &csum2, to); | 653 | &csum2, to); |
651 | kunmap(page); | 654 | kunmap(page); |
655 | offset += n; | ||
652 | if (n != copy) | 656 | if (n != copy) |
653 | goto fault; | 657 | goto fault; |
654 | *csump = csum_block_add(*csump, csum2, pos); | 658 | *csump = csum_block_add(*csump, csum2, pos); |
655 | if (!(len -= copy)) | 659 | if (!(len -= copy)) |
656 | return 0; | 660 | return 0; |
657 | offset += copy; | ||
658 | pos += copy; | 661 | pos += copy; |
659 | } | 662 | } |
660 | start = end; | 663 | start = end; |
@@ -687,6 +690,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
687 | return 0; | 690 | return 0; |
688 | 691 | ||
689 | fault: | 692 | fault: |
693 | iov_iter_revert(to, offset - start_off); | ||
690 | return -EFAULT; | 694 | return -EFAULT; |
691 | } | 695 | } |
692 | 696 | ||
@@ -771,6 +775,7 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, | |||
771 | } | 775 | } |
772 | return 0; | 776 | return 0; |
773 | csum_error: | 777 | csum_error: |
778 | iov_iter_revert(&msg->msg_iter, chunk); | ||
774 | return -EINVAL; | 779 | return -EINVAL; |
775 | fault: | 780 | fault: |
776 | return -EFAULT; | 781 | return -EFAULT; |
diff --git a/net/core/dev.c b/net/core/dev.c index 7869ae3837ca..533a6d6f6092 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -6757,7 +6757,6 @@ int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags) | |||
6757 | 6757 | ||
6758 | return err; | 6758 | return err; |
6759 | } | 6759 | } |
6760 | EXPORT_SYMBOL(dev_change_xdp_fd); | ||
6761 | 6760 | ||
6762 | /** | 6761 | /** |
6763 | * dev_new_index - allocate an ifindex | 6762 | * dev_new_index - allocate an ifindex |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 52f26459efc3..9b8841316e7b 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -461,7 +461,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par) | |||
461 | 461 | ||
462 | clusterip_config_put(cipinfo->config); | 462 | clusterip_config_put(cipinfo->config); |
463 | 463 | ||
464 | nf_ct_netns_get(par->net, par->family); | 464 | nf_ct_netns_put(par->net, par->family); |
465 | } | 465 | } |
466 | 466 | ||
467 | #ifdef CONFIG_COMPAT | 467 | #ifdef CONFIG_COMPAT |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8471dd116771..acd69cfe2951 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -2620,7 +2620,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) | |||
2620 | skb_reset_network_header(skb); | 2620 | skb_reset_network_header(skb); |
2621 | 2621 | ||
2622 | /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */ | 2622 | /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */ |
2623 | ip_hdr(skb)->protocol = IPPROTO_ICMP; | 2623 | ip_hdr(skb)->protocol = IPPROTO_UDP; |
2624 | skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); | 2624 | skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); |
2625 | 2625 | ||
2626 | src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0; | 2626 | src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1e319a525d51..40ba4249a586 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2322,6 +2322,7 @@ int tcp_disconnect(struct sock *sk, int flags) | |||
2322 | tcp_init_send_head(sk); | 2322 | tcp_init_send_head(sk); |
2323 | memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); | 2323 | memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); |
2324 | __sk_dst_reset(sk); | 2324 | __sk_dst_reset(sk); |
2325 | tcp_saved_syn_free(tp); | ||
2325 | 2326 | ||
2326 | /* Clean up fastopen related fields */ | 2327 | /* Clean up fastopen related fields */ |
2327 | tcp_free_fastopen_req(tp); | 2328 | tcp_free_fastopen_req(tp); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2c1f59386a7b..659d1baefb2b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1935,6 +1935,7 @@ void tcp_enter_loss(struct sock *sk) | |||
1935 | struct tcp_sock *tp = tcp_sk(sk); | 1935 | struct tcp_sock *tp = tcp_sk(sk); |
1936 | struct net *net = sock_net(sk); | 1936 | struct net *net = sock_net(sk); |
1937 | struct sk_buff *skb; | 1937 | struct sk_buff *skb; |
1938 | bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; | ||
1938 | bool is_reneg; /* is receiver reneging on SACKs? */ | 1939 | bool is_reneg; /* is receiver reneging on SACKs? */ |
1939 | bool mark_lost; | 1940 | bool mark_lost; |
1940 | 1941 | ||
@@ -1994,15 +1995,18 @@ void tcp_enter_loss(struct sock *sk) | |||
1994 | tp->high_seq = tp->snd_nxt; | 1995 | tp->high_seq = tp->snd_nxt; |
1995 | tcp_ecn_queue_cwr(tp); | 1996 | tcp_ecn_queue_cwr(tp); |
1996 | 1997 | ||
1997 | /* F-RTO RFC5682 sec 3.1 step 1 mandates to disable F-RTO | 1998 | /* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous |
1998 | * if a previous recovery is underway, otherwise it may incorrectly | 1999 | * loss recovery is underway except recurring timeout(s) on |
1999 | * call a timeout spurious if some previously retransmitted packets | 2000 | * the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing |
2000 | * are s/acked (sec 3.2). We do not apply that retriction since | 2001 | * |
2001 | * retransmitted skbs are permanently tagged with TCPCB_EVER_RETRANS | 2002 | * In theory F-RTO can be used repeatedly during loss recovery. |
2002 | * so FLAG_ORIG_SACK_ACKED is always correct. But we do disable F-RTO | 2003 | * In practice this interacts badly with broken middle-boxes that |
2003 | * on PTMU discovery to avoid sending new data. | 2004 | * falsely raise the receive window, which results in repeated |
2005 | * timeouts and stop-and-go behavior. | ||
2004 | */ | 2006 | */ |
2005 | tp->frto = sysctl_tcp_frto && !inet_csk(sk)->icsk_mtup.probe_size; | 2007 | tp->frto = sysctl_tcp_frto && |
2008 | (new_recovery || icsk->icsk_retransmits) && | ||
2009 | !inet_csk(sk)->icsk_mtup.probe_size; | ||
2006 | } | 2010 | } |
2007 | 2011 | ||
2008 | /* If ACK arrived pointing to a remembered SACK, it means that our | 2012 | /* If ACK arrived pointing to a remembered SACK, it means that our |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 22548b5f05cb..c3c082ed3879 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2999,6 +2999,8 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) | |||
2999 | { | 2999 | { |
3000 | struct sk_buff *skb; | 3000 | struct sk_buff *skb; |
3001 | 3001 | ||
3002 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTRSTS); | ||
3003 | |||
3002 | /* NOTE: No TCP options attached and we never retransmit this. */ | 3004 | /* NOTE: No TCP options attached and we never retransmit this. */ |
3003 | skb = alloc_skb(MAX_TCP_HEADER, priority); | 3005 | skb = alloc_skb(MAX_TCP_HEADER, priority); |
3004 | if (!skb) { | 3006 | if (!skb) { |
@@ -3014,8 +3016,6 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) | |||
3014 | /* Send it off. */ | 3016 | /* Send it off. */ |
3015 | if (tcp_transmit_skb(sk, skb, 0, priority)) | 3017 | if (tcp_transmit_skb(sk, skb, 0, priority)) |
3016 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED); | 3018 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED); |
3017 | |||
3018 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTRSTS); | ||
3019 | } | 3019 | } |
3020 | 3020 | ||
3021 | /* Send a crossed SYN-ACK during socket establishment. | 3021 | /* Send a crossed SYN-ACK during socket establishment. |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 363172527e43..80ce478c4851 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3626,14 +3626,19 @@ restart: | |||
3626 | INIT_LIST_HEAD(&del_list); | 3626 | INIT_LIST_HEAD(&del_list); |
3627 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { | 3627 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { |
3628 | struct rt6_info *rt = NULL; | 3628 | struct rt6_info *rt = NULL; |
3629 | bool keep; | ||
3629 | 3630 | ||
3630 | addrconf_del_dad_work(ifa); | 3631 | addrconf_del_dad_work(ifa); |
3631 | 3632 | ||
3633 | keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) && | ||
3634 | !addr_is_local(&ifa->addr); | ||
3635 | if (!keep) | ||
3636 | list_move(&ifa->if_list, &del_list); | ||
3637 | |||
3632 | write_unlock_bh(&idev->lock); | 3638 | write_unlock_bh(&idev->lock); |
3633 | spin_lock_bh(&ifa->lock); | 3639 | spin_lock_bh(&ifa->lock); |
3634 | 3640 | ||
3635 | if (keep_addr && (ifa->flags & IFA_F_PERMANENT) && | 3641 | if (keep) { |
3636 | !addr_is_local(&ifa->addr)) { | ||
3637 | /* set state to skip the notifier below */ | 3642 | /* set state to skip the notifier below */ |
3638 | state = INET6_IFADDR_STATE_DEAD; | 3643 | state = INET6_IFADDR_STATE_DEAD; |
3639 | ifa->state = 0; | 3644 | ifa->state = 0; |
@@ -3645,8 +3650,6 @@ restart: | |||
3645 | } else { | 3650 | } else { |
3646 | state = ifa->state; | 3651 | state = ifa->state; |
3647 | ifa->state = INET6_IFADDR_STATE_DEAD; | 3652 | ifa->state = INET6_IFADDR_STATE_DEAD; |
3648 | |||
3649 | list_move(&ifa->if_list, &del_list); | ||
3650 | } | 3653 | } |
3651 | 3654 | ||
3652 | spin_unlock_bh(&ifa->lock); | 3655 | spin_unlock_bh(&ifa->lock); |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 861b255a2d51..32ea0f3d868c 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -1383,8 +1383,6 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | |||
1383 | } else | 1383 | } else |
1384 | err = pppol2tp_session_setsockopt(sk, session, optname, val); | 1384 | err = pppol2tp_session_setsockopt(sk, session, optname, val); |
1385 | 1385 | ||
1386 | err = 0; | ||
1387 | |||
1388 | end_put_sess: | 1386 | end_put_sess: |
1389 | sock_put(sk); | 1387 | sock_put(sk); |
1390 | end: | 1388 | end: |
@@ -1507,8 +1505,13 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, | |||
1507 | 1505 | ||
1508 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); | 1506 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); |
1509 | sock_put(ps->tunnel_sock); | 1507 | sock_put(ps->tunnel_sock); |
1510 | } else | 1508 | if (err) |
1509 | goto end_put_sess; | ||
1510 | } else { | ||
1511 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); | 1511 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); |
1512 | if (err) | ||
1513 | goto end_put_sess; | ||
1514 | } | ||
1512 | 1515 | ||
1513 | err = -EFAULT; | 1516 | err = -EFAULT; |
1514 | if (put_user(len, optlen)) | 1517 | if (put_user(len, optlen)) |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 4b2e1fb28bb4..d80073037856 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -57,7 +57,7 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, | |||
57 | hlist_del_rcu(&exp->hnode); | 57 | hlist_del_rcu(&exp->hnode); |
58 | net->ct.expect_count--; | 58 | net->ct.expect_count--; |
59 | 59 | ||
60 | hlist_del(&exp->lnode); | 60 | hlist_del_rcu(&exp->lnode); |
61 | master_help->expecting[exp->class]--; | 61 | master_help->expecting[exp->class]--; |
62 | 62 | ||
63 | nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report); | 63 | nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report); |
@@ -363,7 +363,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) | |||
363 | /* two references : one for hash insert, one for the timer */ | 363 | /* two references : one for hash insert, one for the timer */ |
364 | atomic_add(2, &exp->use); | 364 | atomic_add(2, &exp->use); |
365 | 365 | ||
366 | hlist_add_head(&exp->lnode, &master_help->expectations); | 366 | hlist_add_head_rcu(&exp->lnode, &master_help->expectations); |
367 | master_help->expecting[exp->class]++; | 367 | master_help->expecting[exp->class]++; |
368 | 368 | ||
369 | hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]); | 369 | hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]); |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 6dc44d9b4190..4eeb3418366a 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -158,16 +158,25 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum) | |||
158 | { | 158 | { |
159 | struct nf_conntrack_helper *h; | 159 | struct nf_conntrack_helper *h; |
160 | 160 | ||
161 | rcu_read_lock(); | ||
162 | |||
161 | h = __nf_conntrack_helper_find(name, l3num, protonum); | 163 | h = __nf_conntrack_helper_find(name, l3num, protonum); |
162 | #ifdef CONFIG_MODULES | 164 | #ifdef CONFIG_MODULES |
163 | if (h == NULL) { | 165 | if (h == NULL) { |
164 | if (request_module("nfct-helper-%s", name) == 0) | 166 | rcu_read_unlock(); |
167 | if (request_module("nfct-helper-%s", name) == 0) { | ||
168 | rcu_read_lock(); | ||
165 | h = __nf_conntrack_helper_find(name, l3num, protonum); | 169 | h = __nf_conntrack_helper_find(name, l3num, protonum); |
170 | } else { | ||
171 | return h; | ||
172 | } | ||
166 | } | 173 | } |
167 | #endif | 174 | #endif |
168 | if (h != NULL && !try_module_get(h->me)) | 175 | if (h != NULL && !try_module_get(h->me)) |
169 | h = NULL; | 176 | h = NULL; |
170 | 177 | ||
178 | rcu_read_unlock(); | ||
179 | |||
171 | return h; | 180 | return h; |
172 | } | 181 | } |
173 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); | 182 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); |
@@ -311,38 +320,36 @@ void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n) | |||
311 | } | 320 | } |
312 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); | 321 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); |
313 | 322 | ||
323 | /* Caller should hold the rcu lock */ | ||
314 | struct nf_ct_helper_expectfn * | 324 | struct nf_ct_helper_expectfn * |
315 | nf_ct_helper_expectfn_find_by_name(const char *name) | 325 | nf_ct_helper_expectfn_find_by_name(const char *name) |
316 | { | 326 | { |
317 | struct nf_ct_helper_expectfn *cur; | 327 | struct nf_ct_helper_expectfn *cur; |
318 | bool found = false; | 328 | bool found = false; |
319 | 329 | ||
320 | rcu_read_lock(); | ||
321 | list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { | 330 | list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { |
322 | if (!strcmp(cur->name, name)) { | 331 | if (!strcmp(cur->name, name)) { |
323 | found = true; | 332 | found = true; |
324 | break; | 333 | break; |
325 | } | 334 | } |
326 | } | 335 | } |
327 | rcu_read_unlock(); | ||
328 | return found ? cur : NULL; | 336 | return found ? cur : NULL; |
329 | } | 337 | } |
330 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name); | 338 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name); |
331 | 339 | ||
340 | /* Caller should hold the rcu lock */ | ||
332 | struct nf_ct_helper_expectfn * | 341 | struct nf_ct_helper_expectfn * |
333 | nf_ct_helper_expectfn_find_by_symbol(const void *symbol) | 342 | nf_ct_helper_expectfn_find_by_symbol(const void *symbol) |
334 | { | 343 | { |
335 | struct nf_ct_helper_expectfn *cur; | 344 | struct nf_ct_helper_expectfn *cur; |
336 | bool found = false; | 345 | bool found = false; |
337 | 346 | ||
338 | rcu_read_lock(); | ||
339 | list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { | 347 | list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { |
340 | if (cur->expectfn == symbol) { | 348 | if (cur->expectfn == symbol) { |
341 | found = true; | 349 | found = true; |
342 | break; | 350 | break; |
343 | } | 351 | } |
344 | } | 352 | } |
345 | rcu_read_unlock(); | ||
346 | return found ? cur : NULL; | 353 | return found ? cur : NULL; |
347 | } | 354 | } |
348 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); | 355 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 908d858034e4..dc7dfd68fafe 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1488,11 +1488,16 @@ static int ctnetlink_change_helper(struct nf_conn *ct, | |||
1488 | * treat the second attempt as a no-op instead of returning | 1488 | * treat the second attempt as a no-op instead of returning |
1489 | * an error. | 1489 | * an error. |
1490 | */ | 1490 | */ |
1491 | if (help && help->helper && | 1491 | err = -EBUSY; |
1492 | !strcmp(help->helper->name, helpname)) | 1492 | if (help) { |
1493 | return 0; | 1493 | rcu_read_lock(); |
1494 | else | 1494 | helper = rcu_dereference(help->helper); |
1495 | return -EBUSY; | 1495 | if (helper && !strcmp(helper->name, helpname)) |
1496 | err = 0; | ||
1497 | rcu_read_unlock(); | ||
1498 | } | ||
1499 | |||
1500 | return err; | ||
1496 | } | 1501 | } |
1497 | 1502 | ||
1498 | if (!strcmp(helpname, "")) { | 1503 | if (!strcmp(helpname, "")) { |
@@ -1929,9 +1934,9 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl, | |||
1929 | 1934 | ||
1930 | err = 0; | 1935 | err = 0; |
1931 | if (test_bit(IPS_EXPECTED_BIT, &ct->status)) | 1936 | if (test_bit(IPS_EXPECTED_BIT, &ct->status)) |
1932 | events = IPCT_RELATED; | 1937 | events = 1 << IPCT_RELATED; |
1933 | else | 1938 | else |
1934 | events = IPCT_NEW; | 1939 | events = 1 << IPCT_NEW; |
1935 | 1940 | ||
1936 | if (cda[CTA_LABELS] && | 1941 | if (cda[CTA_LABELS] && |
1937 | ctnetlink_attach_labels(ct, cda) == 0) | 1942 | ctnetlink_attach_labels(ct, cda) == 0) |
@@ -2675,8 +2680,8 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
2675 | last = (struct nf_conntrack_expect *)cb->args[1]; | 2680 | last = (struct nf_conntrack_expect *)cb->args[1]; |
2676 | for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { | 2681 | for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { |
2677 | restart: | 2682 | restart: |
2678 | hlist_for_each_entry(exp, &nf_ct_expect_hash[cb->args[0]], | 2683 | hlist_for_each_entry_rcu(exp, &nf_ct_expect_hash[cb->args[0]], |
2679 | hnode) { | 2684 | hnode) { |
2680 | if (l3proto && exp->tuple.src.l3num != l3proto) | 2685 | if (l3proto && exp->tuple.src.l3num != l3proto) |
2681 | continue; | 2686 | continue; |
2682 | 2687 | ||
@@ -2727,7 +2732,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
2727 | rcu_read_lock(); | 2732 | rcu_read_lock(); |
2728 | last = (struct nf_conntrack_expect *)cb->args[1]; | 2733 | last = (struct nf_conntrack_expect *)cb->args[1]; |
2729 | restart: | 2734 | restart: |
2730 | hlist_for_each_entry(exp, &help->expectations, lnode) { | 2735 | hlist_for_each_entry_rcu(exp, &help->expectations, lnode) { |
2731 | if (l3proto && exp->tuple.src.l3num != l3proto) | 2736 | if (l3proto && exp->tuple.src.l3num != l3proto) |
2732 | continue; | 2737 | continue; |
2733 | if (cb->args[1]) { | 2738 | if (cb->args[1]) { |
@@ -2789,6 +2794,12 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, | |||
2789 | return -ENOENT; | 2794 | return -ENOENT; |
2790 | 2795 | ||
2791 | ct = nf_ct_tuplehash_to_ctrack(h); | 2796 | ct = nf_ct_tuplehash_to_ctrack(h); |
2797 | /* No expectation linked to this connection tracking. */ | ||
2798 | if (!nfct_help(ct)) { | ||
2799 | nf_ct_put(ct); | ||
2800 | return 0; | ||
2801 | } | ||
2802 | |||
2792 | c.data = ct; | 2803 | c.data = ct; |
2793 | 2804 | ||
2794 | err = netlink_dump_start(ctnl, skb, nlh, &c); | 2805 | err = netlink_dump_start(ctnl, skb, nlh, &c); |
@@ -3133,23 +3144,27 @@ ctnetlink_create_expect(struct net *net, | |||
3133 | return -ENOENT; | 3144 | return -ENOENT; |
3134 | ct = nf_ct_tuplehash_to_ctrack(h); | 3145 | ct = nf_ct_tuplehash_to_ctrack(h); |
3135 | 3146 | ||
3147 | rcu_read_lock(); | ||
3136 | if (cda[CTA_EXPECT_HELP_NAME]) { | 3148 | if (cda[CTA_EXPECT_HELP_NAME]) { |
3137 | const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]); | 3149 | const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]); |
3138 | 3150 | ||
3139 | helper = __nf_conntrack_helper_find(helpname, u3, | 3151 | helper = __nf_conntrack_helper_find(helpname, u3, |
3140 | nf_ct_protonum(ct)); | 3152 | nf_ct_protonum(ct)); |
3141 | if (helper == NULL) { | 3153 | if (helper == NULL) { |
3154 | rcu_read_unlock(); | ||
3142 | #ifdef CONFIG_MODULES | 3155 | #ifdef CONFIG_MODULES |
3143 | if (request_module("nfct-helper-%s", helpname) < 0) { | 3156 | if (request_module("nfct-helper-%s", helpname) < 0) { |
3144 | err = -EOPNOTSUPP; | 3157 | err = -EOPNOTSUPP; |
3145 | goto err_ct; | 3158 | goto err_ct; |
3146 | } | 3159 | } |
3160 | rcu_read_lock(); | ||
3147 | helper = __nf_conntrack_helper_find(helpname, u3, | 3161 | helper = __nf_conntrack_helper_find(helpname, u3, |
3148 | nf_ct_protonum(ct)); | 3162 | nf_ct_protonum(ct)); |
3149 | if (helper) { | 3163 | if (helper) { |
3150 | err = -EAGAIN; | 3164 | err = -EAGAIN; |
3151 | goto err_ct; | 3165 | goto err_rcu; |
3152 | } | 3166 | } |
3167 | rcu_read_unlock(); | ||
3153 | #endif | 3168 | #endif |
3154 | err = -EOPNOTSUPP; | 3169 | err = -EOPNOTSUPP; |
3155 | goto err_ct; | 3170 | goto err_ct; |
@@ -3159,11 +3174,13 @@ ctnetlink_create_expect(struct net *net, | |||
3159 | exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask); | 3174 | exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask); |
3160 | if (IS_ERR(exp)) { | 3175 | if (IS_ERR(exp)) { |
3161 | err = PTR_ERR(exp); | 3176 | err = PTR_ERR(exp); |
3162 | goto err_ct; | 3177 | goto err_rcu; |
3163 | } | 3178 | } |
3164 | 3179 | ||
3165 | err = nf_ct_expect_related_report(exp, portid, report); | 3180 | err = nf_ct_expect_related_report(exp, portid, report); |
3166 | nf_ct_expect_put(exp); | 3181 | nf_ct_expect_put(exp); |
3182 | err_rcu: | ||
3183 | rcu_read_unlock(); | ||
3167 | err_ct: | 3184 | err_ct: |
3168 | nf_ct_put(ct); | 3185 | nf_ct_put(ct); |
3169 | return err; | 3186 | return err; |
diff --git a/net/netfilter/nf_nat_redirect.c b/net/netfilter/nf_nat_redirect.c index d43869879fcf..86067560a318 100644 --- a/net/netfilter/nf_nat_redirect.c +++ b/net/netfilter/nf_nat_redirect.c | |||
@@ -101,11 +101,13 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, | |||
101 | rcu_read_lock(); | 101 | rcu_read_lock(); |
102 | idev = __in6_dev_get(skb->dev); | 102 | idev = __in6_dev_get(skb->dev); |
103 | if (idev != NULL) { | 103 | if (idev != NULL) { |
104 | read_lock_bh(&idev->lock); | ||
104 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | 105 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
105 | newdst = ifa->addr; | 106 | newdst = ifa->addr; |
106 | addr = true; | 107 | addr = true; |
107 | break; | 108 | break; |
108 | } | 109 | } |
110 | read_unlock_bh(&idev->lock); | ||
109 | } | 111 | } |
110 | rcu_read_unlock(); | 112 | rcu_read_unlock(); |
111 | 113 | ||
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index eb2721af898d..c4dad1254ead 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -21,6 +21,7 @@ struct nft_hash { | |||
21 | enum nft_registers sreg:8; | 21 | enum nft_registers sreg:8; |
22 | enum nft_registers dreg:8; | 22 | enum nft_registers dreg:8; |
23 | u8 len; | 23 | u8 len; |
24 | bool autogen_seed:1; | ||
24 | u32 modulus; | 25 | u32 modulus; |
25 | u32 seed; | 26 | u32 seed; |
26 | u32 offset; | 27 | u32 offset; |
@@ -82,10 +83,12 @@ static int nft_hash_init(const struct nft_ctx *ctx, | |||
82 | if (priv->offset + priv->modulus - 1 < priv->offset) | 83 | if (priv->offset + priv->modulus - 1 < priv->offset) |
83 | return -EOVERFLOW; | 84 | return -EOVERFLOW; |
84 | 85 | ||
85 | if (tb[NFTA_HASH_SEED]) | 86 | if (tb[NFTA_HASH_SEED]) { |
86 | priv->seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED])); | 87 | priv->seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED])); |
87 | else | 88 | } else { |
89 | priv->autogen_seed = true; | ||
88 | get_random_bytes(&priv->seed, sizeof(priv->seed)); | 90 | get_random_bytes(&priv->seed, sizeof(priv->seed)); |
91 | } | ||
89 | 92 | ||
90 | return nft_validate_register_load(priv->sreg, len) && | 93 | return nft_validate_register_load(priv->sreg, len) && |
91 | nft_validate_register_store(ctx, priv->dreg, NULL, | 94 | nft_validate_register_store(ctx, priv->dreg, NULL, |
@@ -105,7 +108,8 @@ static int nft_hash_dump(struct sk_buff *skb, | |||
105 | goto nla_put_failure; | 108 | goto nla_put_failure; |
106 | if (nla_put_be32(skb, NFTA_HASH_MODULUS, htonl(priv->modulus))) | 109 | if (nla_put_be32(skb, NFTA_HASH_MODULUS, htonl(priv->modulus))) |
107 | goto nla_put_failure; | 110 | goto nla_put_failure; |
108 | if (nla_put_be32(skb, NFTA_HASH_SEED, htonl(priv->seed))) | 111 | if (!priv->autogen_seed && |
112 | nla_put_be32(skb, NFTA_HASH_SEED, htonl(priv->seed))) | ||
109 | goto nla_put_failure; | 113 | goto nla_put_failure; |
110 | if (priv->offset != 0) | 114 | if (priv->offset != 0) |
111 | if (nla_put_be32(skb, NFTA_HASH_OFFSET, htonl(priv->offset))) | 115 | if (nla_put_be32(skb, NFTA_HASH_OFFSET, htonl(priv->offset))) |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 27241a767f17..c64aca611ac5 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
104 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 104 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
105 | tcp_hdrlen = tcph->doff * 4; | 105 | tcp_hdrlen = tcph->doff * 4; |
106 | 106 | ||
107 | if (len < tcp_hdrlen) | 107 | if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) |
108 | return -1; | 108 | return -1; |
109 | 109 | ||
110 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 110 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
@@ -152,6 +152,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
152 | if (len > tcp_hdrlen) | 152 | if (len > tcp_hdrlen) |
153 | return 0; | 153 | return 0; |
154 | 154 | ||
155 | /* tcph->doff has 4 bits, do not wrap it to 0 */ | ||
156 | if (tcp_hdrlen >= 15 * 4) | ||
157 | return 0; | ||
158 | |||
155 | /* | 159 | /* |
156 | * MSS Option not found ?! add it.. | 160 | * MSS Option not found ?! add it.. |
157 | */ | 161 | */ |
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c index 80cb7babeb64..df7f1df00330 100644 --- a/net/netfilter/xt_TPROXY.c +++ b/net/netfilter/xt_TPROXY.c | |||
@@ -393,7 +393,8 @@ tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, | |||
393 | 393 | ||
394 | rcu_read_lock(); | 394 | rcu_read_lock(); |
395 | indev = __in6_dev_get(skb->dev); | 395 | indev = __in6_dev_get(skb->dev); |
396 | if (indev) | 396 | if (indev) { |
397 | read_lock_bh(&indev->lock); | ||
397 | list_for_each_entry(ifa, &indev->addr_list, if_list) { | 398 | list_for_each_entry(ifa, &indev->addr_list, if_list) { |
398 | if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) | 399 | if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) |
399 | continue; | 400 | continue; |
@@ -401,6 +402,8 @@ tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, | |||
401 | laddr = &ifa->addr; | 402 | laddr = &ifa->addr; |
402 | break; | 403 | break; |
403 | } | 404 | } |
405 | read_unlock_bh(&indev->lock); | ||
406 | } | ||
404 | rcu_read_unlock(); | 407 | rcu_read_unlock(); |
405 | 408 | ||
406 | return laddr ? laddr : daddr; | 409 | return laddr ? laddr : daddr; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b052b27a984e..1a2f9e964330 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -794,7 +794,7 @@ static void attach_default_qdiscs(struct net_device *dev) | |||
794 | } | 794 | } |
795 | } | 795 | } |
796 | #ifdef CONFIG_NET_SCHED | 796 | #ifdef CONFIG_NET_SCHED |
797 | if (dev->qdisc) | 797 | if (dev->qdisc != &noop_qdisc) |
798 | qdisc_hash_add(dev->qdisc); | 798 | qdisc_hash_add(dev->qdisc); |
799 | #endif | 799 | #endif |
800 | } | 800 | } |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c1401f43d40f..d9d4c92e06b3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -7034,6 +7034,9 @@ int sctp_inet_listen(struct socket *sock, int backlog) | |||
7034 | if (sock->state != SS_UNCONNECTED) | 7034 | if (sock->state != SS_UNCONNECTED) |
7035 | goto out; | 7035 | goto out; |
7036 | 7036 | ||
7037 | if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED)) | ||
7038 | goto out; | ||
7039 | |||
7037 | /* If backlog is zero, disable listening. */ | 7040 | /* If backlog is zero, disable listening. */ |
7038 | if (!backlog) { | 7041 | if (!backlog) { |
7039 | if (sctp_sstate(sk, CLOSED)) | 7042 | if (sctp_sstate(sk, CLOSED)) |