diff options
author | David S. Miller <davem@davemloft.net> | 2015-05-23 01:22:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-23 01:22:35 -0400 |
commit | 36583eb54d46c36a447afd6c379839f292397429 (patch) | |
tree | 70f5399529dc2135a986947b37c655194da60e9d /net | |
parent | fa7912be967102cdbecd8ef172571b28eb22099e (diff) | |
parent | cf539cbd8a81e12880735a0912de8b99f46c84fd (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/ethernet/cadence/macb.c
drivers/net/phy/phy.c
include/linux/skbuff.h
net/ipv4/tcp.c
net/switchdev/switchdev.c
Switchdev was a case of RTNH_H_{EXTERNAL --> OFFLOAD}
renaming overlapping with net-next changes of various
sorts.
phy.c was a case of two changes, one adding a local
variable to a function whilst the second was removing
one.
tcp.c overlapped a deadlock fix with the addition of new tcp_info
statistic values.
macb.c involved the addition of two zyncq device entries.
skbuff.h involved adding back ipv4_daddr to nf_bridge_info
whilst net-next changes put two other existing members of
that struct into a union.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
32 files changed, 207 insertions, 74 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 98a30a5b8664..59555f0f8fc8 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -443,7 +443,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
443 | case NETDEV_UP: | 443 | case NETDEV_UP: |
444 | /* Put all VLANs for this dev in the up state too. */ | 444 | /* Put all VLANs for this dev in the up state too. */ |
445 | vlan_group_for_each_dev(grp, i, vlandev) { | 445 | vlan_group_for_each_dev(grp, i, vlandev) { |
446 | flgs = vlandev->flags; | 446 | flgs = dev_get_flags(vlandev); |
447 | if (flgs & IFF_UP) | 447 | if (flgs & IFF_UP) |
448 | continue; | 448 | continue; |
449 | 449 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4663c3dad3f5..c4802f3bd4c5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2854,9 +2854,11 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status, | |||
2854 | * state. If we were running both LE and BR/EDR inquiry | 2854 | * state. If we were running both LE and BR/EDR inquiry |
2855 | * simultaneously, and BR/EDR inquiry is already | 2855 | * simultaneously, and BR/EDR inquiry is already |
2856 | * finished, stop discovery, otherwise BR/EDR inquiry | 2856 | * finished, stop discovery, otherwise BR/EDR inquiry |
2857 | * will stop discovery when finished. | 2857 | * will stop discovery when finished. If we will resolve |
2858 | * remote device name, do not change discovery state. | ||
2858 | */ | 2859 | */ |
2859 | if (!test_bit(HCI_INQUIRY, &hdev->flags)) | 2860 | if (!test_bit(HCI_INQUIRY, &hdev->flags) && |
2861 | hdev->discovery.state != DISCOVERY_RESOLVING) | ||
2860 | hci_discovery_set_state(hdev, | 2862 | hci_discovery_set_state(hdev, |
2861 | DISCOVERY_STOPPED); | 2863 | DISCOVERY_STOPPED); |
2862 | } else { | 2864 | } else { |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2d69d5cab52f..d7e103e3538a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -1069,7 +1069,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1069 | 1069 | ||
1070 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, | 1070 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, |
1071 | vid); | 1071 | vid); |
1072 | if (!err) | 1072 | if (err) |
1073 | break; | 1073 | break; |
1074 | } | 1074 | } |
1075 | 1075 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1d2eb32d8270..46660a28feef 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -37,10 +37,6 @@ | |||
37 | #include <net/route.h> | 37 | #include <net/route.h> |
38 | #include <net/netfilter/br_netfilter.h> | 38 | #include <net/netfilter/br_netfilter.h> |
39 | 39 | ||
40 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | ||
41 | #include <net/netfilter/nf_conntrack.h> | ||
42 | #endif | ||
43 | |||
44 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
45 | #include "br_private.h" | 41 | #include "br_private.h" |
46 | #ifdef CONFIG_SYSCTL | 42 | #ifdef CONFIG_SYSCTL |
@@ -358,24 +354,15 @@ free_skb: | |||
358 | return 0; | 354 | return 0; |
359 | } | 355 | } |
360 | 356 | ||
361 | static bool dnat_took_place(const struct sk_buff *skb) | 357 | static bool daddr_was_changed(const struct sk_buff *skb, |
358 | const struct nf_bridge_info *nf_bridge) | ||
362 | { | 359 | { |
363 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 360 | return ip_hdr(skb)->daddr != nf_bridge->ipv4_daddr; |
364 | enum ip_conntrack_info ctinfo; | ||
365 | struct nf_conn *ct; | ||
366 | |||
367 | ct = nf_ct_get(skb, &ctinfo); | ||
368 | if (!ct || nf_ct_is_untracked(ct)) | ||
369 | return false; | ||
370 | |||
371 | return test_bit(IPS_DST_NAT_BIT, &ct->status); | ||
372 | #else | ||
373 | return false; | ||
374 | #endif | ||
375 | } | 361 | } |
376 | 362 | ||
377 | /* This requires some explaining. If DNAT has taken place, | 363 | /* This requires some explaining. If DNAT has taken place, |
378 | * we will need to fix up the destination Ethernet address. | 364 | * we will need to fix up the destination Ethernet address. |
365 | * This is also true when SNAT takes place (for the reply direction). | ||
379 | * | 366 | * |
380 | * There are two cases to consider: | 367 | * There are two cases to consider: |
381 | * 1. The packet was DNAT'ed to a device in the same bridge | 368 | * 1. The packet was DNAT'ed to a device in the same bridge |
@@ -429,7 +416,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb) | |||
429 | nf_bridge->pkt_otherhost = false; | 416 | nf_bridge->pkt_otherhost = false; |
430 | } | 417 | } |
431 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 418 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
432 | if (dnat_took_place(skb)) { | 419 | if (daddr_was_changed(skb, nf_bridge)) { |
433 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { | 420 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { |
434 | struct in_device *in_dev = __in_dev_get_rcu(dev); | 421 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
435 | 422 | ||
@@ -640,6 +627,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
640 | struct sk_buff *skb, | 627 | struct sk_buff *skb, |
641 | const struct nf_hook_state *state) | 628 | const struct nf_hook_state *state) |
642 | { | 629 | { |
630 | struct nf_bridge_info *nf_bridge; | ||
643 | struct net_bridge_port *p; | 631 | struct net_bridge_port *p; |
644 | struct net_bridge *br; | 632 | struct net_bridge *br; |
645 | __u32 len = nf_bridge_encap_header_len(skb); | 633 | __u32 len = nf_bridge_encap_header_len(skb); |
@@ -677,6 +665,9 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
677 | if (!setup_pre_routing(skb)) | 665 | if (!setup_pre_routing(skb)) |
678 | return NF_DROP; | 666 | return NF_DROP; |
679 | 667 | ||
668 | nf_bridge = nf_bridge_info_get(skb); | ||
669 | nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; | ||
670 | |||
680 | skb->protocol = htons(ETH_P_IP); | 671 | skb->protocol = htons(ETH_P_IP); |
681 | 672 | ||
682 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, | 673 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 4fcaa67750fd..7caf7fae2d5b 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -97,7 +97,9 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
97 | netif_carrier_on(br->dev); | 97 | netif_carrier_on(br->dev); |
98 | } | 98 | } |
99 | br_log_state(p); | 99 | br_log_state(p); |
100 | rcu_read_lock(); | ||
100 | br_ifinfo_notify(RTM_NEWLINK, p); | 101 | br_ifinfo_notify(RTM_NEWLINK, p); |
102 | rcu_read_unlock(); | ||
101 | spin_unlock(&br->lock); | 103 | spin_unlock(&br->lock); |
102 | } | 104 | } |
103 | 105 | ||
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 5149d9e71114..d5aba394ff6f 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1117,6 +1117,8 @@ static int do_replace(struct net *net, const void __user *user, | |||
1117 | return -ENOMEM; | 1117 | return -ENOMEM; |
1118 | if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) | 1118 | if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) |
1119 | return -ENOMEM; | 1119 | return -ENOMEM; |
1120 | if (tmp.num_counters == 0) | ||
1121 | return -EINVAL; | ||
1120 | 1122 | ||
1121 | tmp.name[sizeof(tmp.name) - 1] = 0; | 1123 | tmp.name[sizeof(tmp.name) - 1] = 0; |
1122 | 1124 | ||
@@ -2159,6 +2161,8 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl, | |||
2159 | return -ENOMEM; | 2161 | return -ENOMEM; |
2160 | if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) | 2162 | if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) |
2161 | return -ENOMEM; | 2163 | return -ENOMEM; |
2164 | if (tmp.num_counters == 0) | ||
2165 | return -EINVAL; | ||
2162 | 2166 | ||
2163 | memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry)); | 2167 | memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry)); |
2164 | 2168 | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index eb0c3ace7458..4f6a17ef0710 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -358,7 +358,15 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | |||
358 | int err; | 358 | int err; |
359 | struct ethtool_cmd cmd; | 359 | struct ethtool_cmd cmd; |
360 | 360 | ||
361 | err = __ethtool_get_settings(dev, &cmd); | 361 | if (!dev->ethtool_ops->get_settings) |
362 | return -EOPNOTSUPP; | ||
363 | |||
364 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | ||
365 | return -EFAULT; | ||
366 | |||
367 | cmd.cmd = ETHTOOL_GSET; | ||
368 | |||
369 | err = dev->ethtool_ops->get_settings(dev, &cmd); | ||
362 | if (err < 0) | 370 | if (err < 0) |
363 | return err; | 371 | return err; |
364 | 372 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 141ccc357e2e..077b6d280371 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -2420,6 +2420,9 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, | |||
2420 | { | 2420 | { |
2421 | struct sk_buff *skb; | 2421 | struct sk_buff *skb; |
2422 | 2422 | ||
2423 | if (dev->reg_state != NETREG_REGISTERED) | ||
2424 | return; | ||
2425 | |||
2423 | skb = rtmsg_ifinfo_build_skb(type, dev, change, flags); | 2426 | skb = rtmsg_ifinfo_build_skb(type, dev, change, flags); |
2424 | if (skb) | 2427 | if (skb) |
2425 | rtmsg_ifinfo_send(skb, dev, flags); | 2428 | rtmsg_ifinfo_send(skb, dev, flags); |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 03444c6ae342..5a5d9bdeaeb4 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1164,6 +1164,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1164 | state = fa->fa_state; | 1164 | state = fa->fa_state; |
1165 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1165 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
1166 | new_fa->fa_slen = fa->fa_slen; | 1166 | new_fa->fa_slen = fa->fa_slen; |
1167 | new_fa->tb_id = tb->tb_id; | ||
1167 | 1168 | ||
1168 | err = switchdev_fib_ipv4_add(key, plen, fi, | 1169 | err = switchdev_fib_ipv4_add(key, plen, fi, |
1169 | new_fa->fa_tos, | 1170 | new_fa->fa_tos, |
@@ -1762,7 +1763,7 @@ void fib_table_flush_external(struct fib_table *tb) | |||
1762 | /* record local slen */ | 1763 | /* record local slen */ |
1763 | slen = fa->fa_slen; | 1764 | slen = fa->fa_slen; |
1764 | 1765 | ||
1765 | if (!fi || !(fi->fib_flags & RTNH_F_EXTERNAL)) | 1766 | if (!fi || !(fi->fib_flags & RTNH_F_OFFLOAD)) |
1766 | continue; | 1767 | continue; |
1767 | 1768 | ||
1768 | switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen, | 1769 | switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen, |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 13bfe84bf3ca..a61200754f4b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -1075,6 +1075,9 @@ static int do_replace(struct net *net, const void __user *user, | |||
1075 | /* overflow check */ | 1075 | /* overflow check */ |
1076 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1076 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1077 | return -ENOMEM; | 1077 | return -ENOMEM; |
1078 | if (tmp.num_counters == 0) | ||
1079 | return -EINVAL; | ||
1080 | |||
1078 | tmp.name[sizeof(tmp.name)-1] = 0; | 1081 | tmp.name[sizeof(tmp.name)-1] = 0; |
1079 | 1082 | ||
1080 | newinfo = xt_alloc_table_info(tmp.size); | 1083 | newinfo = xt_alloc_table_info(tmp.size); |
@@ -1499,6 +1502,9 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
1499 | return -ENOMEM; | 1502 | return -ENOMEM; |
1500 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1503 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1501 | return -ENOMEM; | 1504 | return -ENOMEM; |
1505 | if (tmp.num_counters == 0) | ||
1506 | return -EINVAL; | ||
1507 | |||
1502 | tmp.name[sizeof(tmp.name)-1] = 0; | 1508 | tmp.name[sizeof(tmp.name)-1] = 0; |
1503 | 1509 | ||
1504 | newinfo = xt_alloc_table_info(tmp.size); | 1510 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index c69db7fa25ee..2d0e265fef6e 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -1262,6 +1262,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
1262 | /* overflow check */ | 1262 | /* overflow check */ |
1263 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1263 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1264 | return -ENOMEM; | 1264 | return -ENOMEM; |
1265 | if (tmp.num_counters == 0) | ||
1266 | return -EINVAL; | ||
1267 | |||
1265 | tmp.name[sizeof(tmp.name)-1] = 0; | 1268 | tmp.name[sizeof(tmp.name)-1] = 0; |
1266 | 1269 | ||
1267 | newinfo = xt_alloc_table_info(tmp.size); | 1270 | newinfo = xt_alloc_table_info(tmp.size); |
@@ -1809,6 +1812,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1809 | return -ENOMEM; | 1812 | return -ENOMEM; |
1810 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1813 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1811 | return -ENOMEM; | 1814 | return -ENOMEM; |
1815 | if (tmp.num_counters == 0) | ||
1816 | return -EINVAL; | ||
1817 | |||
1812 | tmp.name[sizeof(tmp.name)-1] = 0; | 1818 | tmp.name[sizeof(tmp.name)-1] = 0; |
1813 | 1819 | ||
1814 | newinfo = xt_alloc_table_info(tmp.size); | 1820 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9e15f5ca4495..f6055984c307 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -900,6 +900,10 @@ static int ip_error(struct sk_buff *skb) | |||
900 | bool send; | 900 | bool send; |
901 | int code; | 901 | int code; |
902 | 902 | ||
903 | /* IP on this device is disabled. */ | ||
904 | if (!in_dev) | ||
905 | goto out; | ||
906 | |||
903 | net = dev_net(rt->dst.dev); | 907 | net = dev_net(rt->dst.dev); |
904 | if (!IN_DEV_FORWARD(in_dev)) { | 908 | if (!IN_DEV_FORWARD(in_dev)) { |
905 | switch (rt->dst.error) { | 909 | switch (rt->dst.error) { |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7f3e721b9e69..90afcec3f427 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -402,6 +402,7 @@ void tcp_init_sock(struct sock *sk) | |||
402 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; | 402 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; |
403 | tp->snd_cwnd_clamp = ~0; | 403 | tp->snd_cwnd_clamp = ~0; |
404 | tp->mss_cache = TCP_MSS_DEFAULT; | 404 | tp->mss_cache = TCP_MSS_DEFAULT; |
405 | u64_stats_init(&tp->syncp); | ||
405 | 406 | ||
406 | tp->reordering = sysctl_tcp_reordering; | 407 | tp->reordering = sysctl_tcp_reordering; |
407 | tcp_enable_early_retrans(tp); | 408 | tcp_enable_early_retrans(tp); |
@@ -2625,6 +2626,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2625 | const struct tcp_sock *tp = tcp_sk(sk); | 2626 | const struct tcp_sock *tp = tcp_sk(sk); |
2626 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2627 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2627 | u32 now = tcp_time_stamp; | 2628 | u32 now = tcp_time_stamp; |
2629 | unsigned int start; | ||
2628 | u32 rate; | 2630 | u32 rate; |
2629 | 2631 | ||
2630 | memset(info, 0, sizeof(*info)); | 2632 | memset(info, 0, sizeof(*info)); |
@@ -2692,12 +2694,13 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2692 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2694 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
2693 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2695 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; |
2694 | 2696 | ||
2695 | spin_lock_bh(&sk->sk_lock.slock); | 2697 | do { |
2696 | info->tcpi_bytes_acked = tp->bytes_acked; | 2698 | start = u64_stats_fetch_begin_irq(&tp->syncp); |
2697 | info->tcpi_bytes_received = tp->bytes_received; | 2699 | info->tcpi_bytes_acked = tp->bytes_acked; |
2700 | info->tcpi_bytes_received = tp->bytes_received; | ||
2701 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); | ||
2698 | info->tcpi_segs_out = tp->segs_out; | 2702 | info->tcpi_segs_out = tp->segs_out; |
2699 | info->tcpi_segs_in = tp->segs_in; | 2703 | info->tcpi_segs_in = tp->segs_in; |
2700 | spin_unlock_bh(&sk->sk_lock.slock); | ||
2701 | } | 2704 | } |
2702 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2705 | EXPORT_SYMBOL_GPL(tcp_get_info); |
2703 | 2706 | ||
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 3c673d5e6cff..46b087a27503 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
@@ -206,6 +206,10 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
206 | skb_set_owner_r(skb2, child); | 206 | skb_set_owner_r(skb2, child); |
207 | __skb_queue_tail(&child->sk_receive_queue, skb2); | 207 | __skb_queue_tail(&child->sk_receive_queue, skb2); |
208 | tp->syn_data_acked = 1; | 208 | tp->syn_data_acked = 1; |
209 | |||
210 | /* u64_stats_update_begin(&tp->syncp) not needed here, | ||
211 | * as we certainly are not changing upper 32bit value (0) | ||
212 | */ | ||
209 | tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1; | 213 | tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1; |
210 | } else { | 214 | } else { |
211 | end_seq = TCP_SKB_CB(skb)->seq + 1; | 215 | end_seq = TCP_SKB_CB(skb)->seq + 1; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40c435997e54..15c4536188a4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2695,16 +2695,21 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
2695 | struct tcp_sock *tp = tcp_sk(sk); | 2695 | struct tcp_sock *tp = tcp_sk(sk); |
2696 | bool recovered = !before(tp->snd_una, tp->high_seq); | 2696 | bool recovered = !before(tp->snd_una, tp->high_seq); |
2697 | 2697 | ||
2698 | if ((flag & FLAG_SND_UNA_ADVANCED) && | ||
2699 | tcp_try_undo_loss(sk, false)) | ||
2700 | return; | ||
2701 | |||
2698 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ | 2702 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ |
2699 | /* Step 3.b. A timeout is spurious if not all data are | 2703 | /* Step 3.b. A timeout is spurious if not all data are |
2700 | * lost, i.e., never-retransmitted data are (s)acked. | 2704 | * lost, i.e., never-retransmitted data are (s)acked. |
2701 | */ | 2705 | */ |
2702 | if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED)) | 2706 | if ((flag & FLAG_ORIG_SACK_ACKED) && |
2707 | tcp_try_undo_loss(sk, true)) | ||
2703 | return; | 2708 | return; |
2704 | 2709 | ||
2705 | if (after(tp->snd_nxt, tp->high_seq) && | 2710 | if (after(tp->snd_nxt, tp->high_seq)) { |
2706 | (flag & FLAG_DATA_SACKED || is_dupack)) { | 2711 | if (flag & FLAG_DATA_SACKED || is_dupack) |
2707 | tp->frto = 0; /* Loss was real: 2nd part of step 3.a */ | 2712 | tp->frto = 0; /* Step 3.a. loss was real */ |
2708 | } else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) { | 2713 | } else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) { |
2709 | tp->high_seq = tp->snd_nxt; | 2714 | tp->high_seq = tp->snd_nxt; |
2710 | __tcp_push_pending_frames(sk, tcp_current_mss(sk), | 2715 | __tcp_push_pending_frames(sk, tcp_current_mss(sk), |
@@ -2729,8 +2734,6 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
2729 | else if (flag & FLAG_SND_UNA_ADVANCED) | 2734 | else if (flag & FLAG_SND_UNA_ADVANCED) |
2730 | tcp_reset_reno_sack(tp); | 2735 | tcp_reset_reno_sack(tp); |
2731 | } | 2736 | } |
2732 | if (tcp_try_undo_loss(sk, false)) | ||
2733 | return; | ||
2734 | tcp_xmit_retransmit_queue(sk); | 2737 | tcp_xmit_retransmit_queue(sk); |
2735 | } | 2738 | } |
2736 | 2739 | ||
@@ -3281,7 +3284,9 @@ static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) | |||
3281 | { | 3284 | { |
3282 | u32 delta = ack - tp->snd_una; | 3285 | u32 delta = ack - tp->snd_una; |
3283 | 3286 | ||
3287 | u64_stats_update_begin(&tp->syncp); | ||
3284 | tp->bytes_acked += delta; | 3288 | tp->bytes_acked += delta; |
3289 | u64_stats_update_end(&tp->syncp); | ||
3285 | tp->snd_una = ack; | 3290 | tp->snd_una = ack; |
3286 | } | 3291 | } |
3287 | 3292 | ||
@@ -3290,7 +3295,9 @@ static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) | |||
3290 | { | 3295 | { |
3291 | u32 delta = seq - tp->rcv_nxt; | 3296 | u32 delta = seq - tp->rcv_nxt; |
3292 | 3297 | ||
3298 | u64_stats_update_begin(&tp->syncp); | ||
3293 | tp->bytes_received += delta; | 3299 | tp->bytes_received += delta; |
3300 | u64_stats_update_end(&tp->syncp); | ||
3294 | tp->rcv_nxt = seq; | 3301 | tp->rcv_nxt = seq; |
3295 | } | 3302 | } |
3296 | 3303 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index b62d15c86946..df7fe3c31162 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -300,7 +300,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
300 | tw->tw_v6_daddr = sk->sk_v6_daddr; | 300 | tw->tw_v6_daddr = sk->sk_v6_daddr; |
301 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; | 301 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
302 | tw->tw_tclass = np->tclass; | 302 | tw->tw_tclass = np->tclass; |
303 | tw->tw_flowlabel = np->flow_label >> 12; | 303 | tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK); |
304 | tw->tw_ipv6only = sk->sk_ipv6only; | 304 | tw->tw_ipv6only = sk->sk_ipv6only; |
305 | } | 305 | } |
306 | #endif | 306 | #endif |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 96dbffff5a24..bde57b113009 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -693,6 +693,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
693 | { | 693 | { |
694 | struct rt6_info *iter = NULL; | 694 | struct rt6_info *iter = NULL; |
695 | struct rt6_info **ins; | 695 | struct rt6_info **ins; |
696 | struct rt6_info **fallback_ins = NULL; | ||
696 | int replace = (info->nlh && | 697 | int replace = (info->nlh && |
697 | (info->nlh->nlmsg_flags & NLM_F_REPLACE)); | 698 | (info->nlh->nlmsg_flags & NLM_F_REPLACE)); |
698 | int add = (!info->nlh || | 699 | int add = (!info->nlh || |
@@ -716,8 +717,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
716 | (info->nlh->nlmsg_flags & NLM_F_EXCL)) | 717 | (info->nlh->nlmsg_flags & NLM_F_EXCL)) |
717 | return -EEXIST; | 718 | return -EEXIST; |
718 | if (replace) { | 719 | if (replace) { |
719 | found++; | 720 | if (rt_can_ecmp == rt6_qualify_for_ecmp(iter)) { |
720 | break; | 721 | found++; |
722 | break; | ||
723 | } | ||
724 | if (rt_can_ecmp) | ||
725 | fallback_ins = fallback_ins ?: ins; | ||
726 | goto next_iter; | ||
721 | } | 727 | } |
722 | 728 | ||
723 | if (iter->dst.dev == rt->dst.dev && | 729 | if (iter->dst.dev == rt->dst.dev && |
@@ -753,9 +759,17 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
753 | if (iter->rt6i_metric > rt->rt6i_metric) | 759 | if (iter->rt6i_metric > rt->rt6i_metric) |
754 | break; | 760 | break; |
755 | 761 | ||
762 | next_iter: | ||
756 | ins = &iter->dst.rt6_next; | 763 | ins = &iter->dst.rt6_next; |
757 | } | 764 | } |
758 | 765 | ||
766 | if (fallback_ins && !found) { | ||
767 | /* No ECMP-able route found, replace first non-ECMP one */ | ||
768 | ins = fallback_ins; | ||
769 | iter = *ins; | ||
770 | found++; | ||
771 | } | ||
772 | |||
759 | /* Reset round-robin state, if necessary */ | 773 | /* Reset round-robin state, if necessary */ |
760 | if (ins == &fn->leaf) | 774 | if (ins == &fn->leaf) |
761 | fn->rr_ptr = NULL; | 775 | fn->rr_ptr = NULL; |
@@ -815,6 +829,8 @@ add: | |||
815 | } | 829 | } |
816 | 830 | ||
817 | } else { | 831 | } else { |
832 | int nsiblings; | ||
833 | |||
818 | if (!found) { | 834 | if (!found) { |
819 | if (add) | 835 | if (add) |
820 | goto add; | 836 | goto add; |
@@ -835,8 +851,27 @@ add: | |||
835 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 851 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
836 | fn->fn_flags |= RTN_RTINFO; | 852 | fn->fn_flags |= RTN_RTINFO; |
837 | } | 853 | } |
854 | nsiblings = iter->rt6i_nsiblings; | ||
838 | fib6_purge_rt(iter, fn, info->nl_net); | 855 | fib6_purge_rt(iter, fn, info->nl_net); |
839 | rt6_release(iter); | 856 | rt6_release(iter); |
857 | |||
858 | if (nsiblings) { | ||
859 | /* Replacing an ECMP route, remove all siblings */ | ||
860 | ins = &rt->dst.rt6_next; | ||
861 | iter = *ins; | ||
862 | while (iter) { | ||
863 | if (rt6_qualify_for_ecmp(iter)) { | ||
864 | *ins = iter->dst.rt6_next; | ||
865 | fib6_purge_rt(iter, fn, info->nl_net); | ||
866 | rt6_release(iter); | ||
867 | nsiblings--; | ||
868 | } else { | ||
869 | ins = &iter->dst.rt6_next; | ||
870 | } | ||
871 | iter = *ins; | ||
872 | } | ||
873 | WARN_ON(nsiblings != 0); | ||
874 | } | ||
840 | } | 875 | } |
841 | 876 | ||
842 | return 0; | 877 | return 0; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index c21777565c58..bc09cb97b840 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1300,8 +1300,10 @@ emsgsize: | |||
1300 | 1300 | ||
1301 | /* If this is the first and only packet and device | 1301 | /* If this is the first and only packet and device |
1302 | * supports checksum offloading, let's use it. | 1302 | * supports checksum offloading, let's use it. |
1303 | * Use transhdrlen, same as IPv4, because partial | ||
1304 | * sums only work when transhdrlen is set. | ||
1303 | */ | 1305 | */ |
1304 | if (!skb && sk->sk_protocol == IPPROTO_UDP && | 1306 | if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && |
1305 | length + fragheaderlen < mtu && | 1307 | length + fragheaderlen < mtu && |
1306 | rt->dst.dev->features & NETIF_F_V6_CSUM && | 1308 | rt->dst.dev->features & NETIF_F_V6_CSUM && |
1307 | !exthdrlen) | 1309 | !exthdrlen) |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1a732a1d3c8e..62f5b0d0bc9b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1275,6 +1275,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
1275 | /* overflow check */ | 1275 | /* overflow check */ |
1276 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1276 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1277 | return -ENOMEM; | 1277 | return -ENOMEM; |
1278 | if (tmp.num_counters == 0) | ||
1279 | return -EINVAL; | ||
1280 | |||
1278 | tmp.name[sizeof(tmp.name)-1] = 0; | 1281 | tmp.name[sizeof(tmp.name)-1] = 0; |
1279 | 1282 | ||
1280 | newinfo = xt_alloc_table_info(tmp.size); | 1283 | newinfo = xt_alloc_table_info(tmp.size); |
@@ -1822,6 +1825,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1822 | return -ENOMEM; | 1825 | return -ENOMEM; |
1823 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1826 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1824 | return -ENOMEM; | 1827 | return -ENOMEM; |
1828 | if (tmp.num_counters == 0) | ||
1829 | return -EINVAL; | ||
1830 | |||
1825 | tmp.name[sizeof(tmp.name)-1] = 0; | 1831 | tmp.name[sizeof(tmp.name)-1] = 0; |
1826 | 1832 | ||
1827 | newinfo = xt_alloc_table_info(tmp.size); | 1833 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 98fce6f4a580..0c889cb89cc3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2515,9 +2515,9 @@ static int ip6_route_multipath(struct fib6_config *cfg, int add) | |||
2515 | int attrlen; | 2515 | int attrlen; |
2516 | int err = 0, last_err = 0; | 2516 | int err = 0, last_err = 0; |
2517 | 2517 | ||
2518 | remaining = cfg->fc_mp_len; | ||
2518 | beginning: | 2519 | beginning: |
2519 | rtnh = (struct rtnexthop *)cfg->fc_mp; | 2520 | rtnh = (struct rtnexthop *)cfg->fc_mp; |
2520 | remaining = cfg->fc_mp_len; | ||
2521 | 2521 | ||
2522 | /* Parse a Multipath Entry */ | 2522 | /* Parse a Multipath Entry */ |
2523 | while (rtnh_ok(rtnh, remaining)) { | 2523 | while (rtnh_ok(rtnh, remaining)) { |
@@ -2547,15 +2547,19 @@ beginning: | |||
2547 | * next hops that have been already added. | 2547 | * next hops that have been already added. |
2548 | */ | 2548 | */ |
2549 | add = 0; | 2549 | add = 0; |
2550 | remaining = cfg->fc_mp_len - remaining; | ||
2550 | goto beginning; | 2551 | goto beginning; |
2551 | } | 2552 | } |
2552 | } | 2553 | } |
2553 | /* Because each route is added like a single route we remove | 2554 | /* Because each route is added like a single route we remove |
2554 | * this flag after the first nexthop (if there is a collision, | 2555 | * these flags after the first nexthop: if there is a collision, |
2555 | * we have already fail to add the first nexthop: | 2556 | * we have already failed to add the first nexthop: |
2556 | * fib6_add_rt2node() has reject it). | 2557 | * fib6_add_rt2node() has rejected it; when replacing, old |
2558 | * nexthops have been replaced by first new, the rest should | ||
2559 | * be added to it. | ||
2557 | */ | 2560 | */ |
2558 | cfg->fc_nlinfo.nlh->nlmsg_flags &= ~NLM_F_EXCL; | 2561 | cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | |
2562 | NLM_F_REPLACE); | ||
2559 | rtnh = rtnh_next(rtnh, &remaining); | 2563 | rtnh = rtnh_next(rtnh, &remaining); |
2560 | } | 2564 | } |
2561 | 2565 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index beac6bf840b9..fefe4455e1f3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -914,7 +914,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
914 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 914 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
915 | tcp_time_stamp + tcptw->tw_ts_offset, | 915 | tcp_time_stamp + tcptw->tw_ts_offset, |
916 | tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), | 916 | tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), |
917 | tw->tw_tclass, (tw->tw_flowlabel << 12)); | 917 | tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); |
918 | 918 | ||
919 | inet_twsk_put(tw); | 919 | inet_twsk_put(tw); |
920 | } | 920 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 3477c919fcc8..c2ec41617a35 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -731,7 +731,9 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, | |||
731 | (inet->inet_dport && inet->inet_dport != rmt_port) || | 731 | (inet->inet_dport && inet->inet_dport != rmt_port) || |
732 | (!ipv6_addr_any(&sk->sk_v6_daddr) && | 732 | (!ipv6_addr_any(&sk->sk_v6_daddr) && |
733 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || | 733 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || |
734 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) | 734 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) || |
735 | (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && | ||
736 | !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr))) | ||
735 | return false; | 737 | return false; |
736 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | 738 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) |
737 | return false; | 739 | return false; |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index a4220e92f0cc..efa3f48f1ec5 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -98,8 +98,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | |||
98 | 98 | ||
99 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 99 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
100 | 100 | ||
101 | if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN || | 101 | if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) |
102 | skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) | ||
103 | return NULL; | 102 | return NULL; |
104 | 103 | ||
105 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 104 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -167,6 +166,9 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, | |||
167 | size_t len; | 166 | size_t len; |
168 | u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; | 167 | u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; |
169 | 168 | ||
169 | if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN)) | ||
170 | return -1; | ||
171 | |||
170 | iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); | 172 | iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); |
171 | if (!iv) | 173 | if (!iv) |
172 | return -1; | 174 | return -1; |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index db1c674397ad..1c78d7fb1da7 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -870,6 +870,7 @@ config NETFILTER_XT_TARGET_TPROXY | |||
870 | depends on NETFILTER_XTABLES | 870 | depends on NETFILTER_XTABLES |
871 | depends on NETFILTER_ADVANCED | 871 | depends on NETFILTER_ADVANCED |
872 | depends on (IPV6 || IPV6=n) | 872 | depends on (IPV6 || IPV6=n) |
873 | depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) | ||
873 | depends on IP_NF_MANGLE | 874 | depends on IP_NF_MANGLE |
874 | select NF_DEFRAG_IPV4 | 875 | select NF_DEFRAG_IPV4 |
875 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | 876 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES |
@@ -1363,6 +1364,7 @@ config NETFILTER_XT_MATCH_SOCKET | |||
1363 | depends on NETFILTER_ADVANCED | 1364 | depends on NETFILTER_ADVANCED |
1364 | depends on !NF_CONNTRACK || NF_CONNTRACK | 1365 | depends on !NF_CONNTRACK || NF_CONNTRACK |
1365 | depends on (IPV6 || IPV6=n) | 1366 | depends on (IPV6 || IPV6=n) |
1367 | depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) | ||
1366 | select NF_DEFRAG_IPV4 | 1368 | select NF_DEFRAG_IPV4 |
1367 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | 1369 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES |
1368 | help | 1370 | help |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 49532672f66d..285eae3a1454 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -3823,6 +3823,9 @@ static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | |||
3823 | cancel_work_sync(&ipvs->defense_work.work); | 3823 | cancel_work_sync(&ipvs->defense_work.work); |
3824 | unregister_net_sysctl_table(ipvs->sysctl_hdr); | 3824 | unregister_net_sysctl_table(ipvs->sysctl_hdr); |
3825 | ip_vs_stop_estimator(net, &ipvs->tot_stats); | 3825 | ip_vs_stop_estimator(net, &ipvs->tot_stats); |
3826 | |||
3827 | if (!net_eq(net, &init_net)) | ||
3828 | kfree(ipvs->sysctl_tbl); | ||
3826 | } | 3829 | } |
3827 | 3830 | ||
3828 | #else | 3831 | #else |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 5caa0c41bf26..70383de72054 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -202,7 +202,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
202 | * sES -> sES :-) | 202 | * sES -> sES :-) |
203 | * sFW -> sCW Normal close request answered by ACK. | 203 | * sFW -> sCW Normal close request answered by ACK. |
204 | * sCW -> sCW | 204 | * sCW -> sCW |
205 | * sLA -> sTW Last ACK detected. | 205 | * sLA -> sTW Last ACK detected (RFC5961 challenged) |
206 | * sTW -> sTW Retransmitted last ACK. Remain in the same state. | 206 | * sTW -> sTW Retransmitted last ACK. Remain in the same state. |
207 | * sCL -> sCL | 207 | * sCL -> sCL |
208 | */ | 208 | */ |
@@ -261,7 +261,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
261 | * sES -> sES :-) | 261 | * sES -> sES :-) |
262 | * sFW -> sCW Normal close request answered by ACK. | 262 | * sFW -> sCW Normal close request answered by ACK. |
263 | * sCW -> sCW | 263 | * sCW -> sCW |
264 | * sLA -> sTW Last ACK detected. | 264 | * sLA -> sTW Last ACK detected (RFC5961 challenged) |
265 | * sTW -> sTW Retransmitted last ACK. | 265 | * sTW -> sTW Retransmitted last ACK. |
266 | * sCL -> sCL | 266 | * sCL -> sCL |
267 | */ | 267 | */ |
@@ -906,6 +906,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
906 | 1 : ct->proto.tcp.last_win; | 906 | 1 : ct->proto.tcp.last_win; |
907 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = | 907 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = |
908 | ct->proto.tcp.last_wscale; | 908 | ct->proto.tcp.last_wscale; |
909 | ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK; | ||
909 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = | 910 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = |
910 | ct->proto.tcp.last_flags; | 911 | ct->proto.tcp.last_flags; |
911 | memset(&ct->proto.tcp.seen[dir], 0, | 912 | memset(&ct->proto.tcp.seen[dir], 0, |
@@ -923,7 +924,9 @@ static int tcp_packet(struct nf_conn *ct, | |||
923 | * may be in sync but we are not. In that case, we annotate | 924 | * may be in sync but we are not. In that case, we annotate |
924 | * the TCP options and let the packet go through. If it is a | 925 | * the TCP options and let the packet go through. If it is a |
925 | * valid SYN packet, the server will reply with a SYN/ACK, and | 926 | * valid SYN packet, the server will reply with a SYN/ACK, and |
926 | * then we'll get in sync. Otherwise, the server ignores it. */ | 927 | * then we'll get in sync. Otherwise, the server potentially |
928 | * responds with a challenge ACK if implementing RFC5961. | ||
929 | */ | ||
927 | if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { | 930 | if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { |
928 | struct ip_ct_tcp_state seen = {}; | 931 | struct ip_ct_tcp_state seen = {}; |
929 | 932 | ||
@@ -939,6 +942,13 @@ static int tcp_packet(struct nf_conn *ct, | |||
939 | ct->proto.tcp.last_flags |= | 942 | ct->proto.tcp.last_flags |= |
940 | IP_CT_TCP_FLAG_SACK_PERM; | 943 | IP_CT_TCP_FLAG_SACK_PERM; |
941 | } | 944 | } |
945 | /* Mark the potential for RFC5961 challenge ACK, | ||
946 | * this pose a special problem for LAST_ACK state | ||
947 | * as ACK is intrepretated as ACKing last FIN. | ||
948 | */ | ||
949 | if (old_state == TCP_CONNTRACK_LAST_ACK) | ||
950 | ct->proto.tcp.last_flags |= | ||
951 | IP_CT_EXP_CHALLENGE_ACK; | ||
942 | } | 952 | } |
943 | spin_unlock_bh(&ct->lock); | 953 | spin_unlock_bh(&ct->lock); |
944 | if (LOG_INVALID(net, IPPROTO_TCP)) | 954 | if (LOG_INVALID(net, IPPROTO_TCP)) |
@@ -970,6 +980,25 @@ static int tcp_packet(struct nf_conn *ct, | |||
970 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, | 980 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, |
971 | "nf_ct_tcp: invalid state "); | 981 | "nf_ct_tcp: invalid state "); |
972 | return -NF_ACCEPT; | 982 | return -NF_ACCEPT; |
983 | case TCP_CONNTRACK_TIME_WAIT: | ||
984 | /* RFC5961 compliance cause stack to send "challenge-ACK" | ||
985 | * e.g. in response to spurious SYNs. Conntrack MUST | ||
986 | * not believe this ACK is acking last FIN. | ||
987 | */ | ||
988 | if (old_state == TCP_CONNTRACK_LAST_ACK && | ||
989 | index == TCP_ACK_SET && | ||
990 | ct->proto.tcp.last_dir != dir && | ||
991 | ct->proto.tcp.last_index == TCP_SYN_SET && | ||
992 | (ct->proto.tcp.last_flags & IP_CT_EXP_CHALLENGE_ACK)) { | ||
993 | /* Detected RFC5961 challenge ACK */ | ||
994 | ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK; | ||
995 | spin_unlock_bh(&ct->lock); | ||
996 | if (LOG_INVALID(net, IPPROTO_TCP)) | ||
997 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, | ||
998 | "nf_ct_tcp: challenge-ACK ignored "); | ||
999 | return NF_ACCEPT; /* Don't change state */ | ||
1000 | } | ||
1001 | break; | ||
973 | case TCP_CONNTRACK_CLOSE: | 1002 | case TCP_CONNTRACK_CLOSE: |
974 | if (index == TCP_RST_SET | 1003 | if (index == TCP_RST_SET |
975 | && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) | 1004 | && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ad9d11fb29fd..34ded09317e7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -4472,9 +4472,9 @@ EXPORT_SYMBOL_GPL(nft_data_init); | |||
4472 | */ | 4472 | */ |
4473 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) | 4473 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) |
4474 | { | 4474 | { |
4475 | switch (type) { | 4475 | if (type < NFT_DATA_VERDICT) |
4476 | case NFT_DATA_VALUE: | ||
4477 | return; | 4476 | return; |
4477 | switch (type) { | ||
4478 | case NFT_DATA_VERDICT: | 4478 | case NFT_DATA_VERDICT: |
4479 | return nft_verdict_uninit(data); | 4479 | return nft_verdict_uninit(data); |
4480 | default: | 4480 | default: |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3ad91266c821..4ef1fae8445e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -1073,7 +1073,13 @@ static struct pernet_operations nfnl_log_net_ops = { | |||
1073 | 1073 | ||
1074 | static int __init nfnetlink_log_init(void) | 1074 | static int __init nfnetlink_log_init(void) |
1075 | { | 1075 | { |
1076 | int status = -ENOMEM; | 1076 | int status; |
1077 | |||
1078 | status = register_pernet_subsys(&nfnl_log_net_ops); | ||
1079 | if (status < 0) { | ||
1080 | pr_err("failed to register pernet ops\n"); | ||
1081 | goto out; | ||
1082 | } | ||
1077 | 1083 | ||
1078 | netlink_register_notifier(&nfulnl_rtnl_notifier); | 1084 | netlink_register_notifier(&nfulnl_rtnl_notifier); |
1079 | status = nfnetlink_subsys_register(&nfulnl_subsys); | 1085 | status = nfnetlink_subsys_register(&nfulnl_subsys); |
@@ -1088,28 +1094,23 @@ static int __init nfnetlink_log_init(void) | |||
1088 | goto cleanup_subsys; | 1094 | goto cleanup_subsys; |
1089 | } | 1095 | } |
1090 | 1096 | ||
1091 | status = register_pernet_subsys(&nfnl_log_net_ops); | ||
1092 | if (status < 0) { | ||
1093 | pr_err("failed to register pernet ops\n"); | ||
1094 | goto cleanup_logger; | ||
1095 | } | ||
1096 | return status; | 1097 | return status; |
1097 | 1098 | ||
1098 | cleanup_logger: | ||
1099 | nf_log_unregister(&nfulnl_logger); | ||
1100 | cleanup_subsys: | 1099 | cleanup_subsys: |
1101 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1100 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
1102 | cleanup_netlink_notifier: | 1101 | cleanup_netlink_notifier: |
1103 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 1102 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
1103 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
1104 | out: | ||
1104 | return status; | 1105 | return status; |
1105 | } | 1106 | } |
1106 | 1107 | ||
1107 | static void __exit nfnetlink_log_fini(void) | 1108 | static void __exit nfnetlink_log_fini(void) |
1108 | { | 1109 | { |
1109 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
1110 | nf_log_unregister(&nfulnl_logger); | 1110 | nf_log_unregister(&nfulnl_logger); |
1111 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1111 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
1112 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 1112 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
1113 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
1113 | } | 1114 | } |
1114 | 1115 | ||
1115 | MODULE_DESCRIPTION("netfilter userspace logging"); | 1116 | MODULE_DESCRIPTION("netfilter userspace logging"); |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index bec7c60fe4d0..22a5ac76683e 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -1317,7 +1317,13 @@ static struct pernet_operations nfnl_queue_net_ops = { | |||
1317 | 1317 | ||
1318 | static int __init nfnetlink_queue_init(void) | 1318 | static int __init nfnetlink_queue_init(void) |
1319 | { | 1319 | { |
1320 | int status = -ENOMEM; | 1320 | int status; |
1321 | |||
1322 | status = register_pernet_subsys(&nfnl_queue_net_ops); | ||
1323 | if (status < 0) { | ||
1324 | pr_err("nf_queue: failed to register pernet ops\n"); | ||
1325 | goto out; | ||
1326 | } | ||
1321 | 1327 | ||
1322 | netlink_register_notifier(&nfqnl_rtnl_notifier); | 1328 | netlink_register_notifier(&nfqnl_rtnl_notifier); |
1323 | status = nfnetlink_subsys_register(&nfqnl_subsys); | 1329 | status = nfnetlink_subsys_register(&nfqnl_subsys); |
@@ -1326,19 +1332,13 @@ static int __init nfnetlink_queue_init(void) | |||
1326 | goto cleanup_netlink_notifier; | 1332 | goto cleanup_netlink_notifier; |
1327 | } | 1333 | } |
1328 | 1334 | ||
1329 | status = register_pernet_subsys(&nfnl_queue_net_ops); | ||
1330 | if (status < 0) { | ||
1331 | pr_err("nf_queue: failed to register pernet ops\n"); | ||
1332 | goto cleanup_subsys; | ||
1333 | } | ||
1334 | register_netdevice_notifier(&nfqnl_dev_notifier); | 1335 | register_netdevice_notifier(&nfqnl_dev_notifier); |
1335 | nf_register_queue_handler(&nfqh); | 1336 | nf_register_queue_handler(&nfqh); |
1336 | return status; | 1337 | return status; |
1337 | 1338 | ||
1338 | cleanup_subsys: | ||
1339 | nfnetlink_subsys_unregister(&nfqnl_subsys); | ||
1340 | cleanup_netlink_notifier: | 1339 | cleanup_netlink_notifier: |
1341 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1340 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
1341 | out: | ||
1342 | return status; | 1342 | return status; |
1343 | } | 1343 | } |
1344 | 1344 | ||
@@ -1346,9 +1346,9 @@ static void __exit nfnetlink_queue_fini(void) | |||
1346 | { | 1346 | { |
1347 | nf_unregister_queue_handler(); | 1347 | nf_unregister_queue_handler(); |
1348 | unregister_netdevice_notifier(&nfqnl_dev_notifier); | 1348 | unregister_netdevice_notifier(&nfqnl_dev_notifier); |
1349 | unregister_pernet_subsys(&nfnl_queue_net_ops); | ||
1350 | nfnetlink_subsys_unregister(&nfqnl_subsys); | 1349 | nfnetlink_subsys_unregister(&nfqnl_subsys); |
1351 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1350 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
1351 | unregister_pernet_subsys(&nfnl_queue_net_ops); | ||
1352 | 1352 | ||
1353 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1353 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
1354 | } | 1354 | } |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 136056f0c62c..69d67c300b80 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -90,7 +90,7 @@ static inline int netlink_is_kernel(struct sock *sk) | |||
90 | return nlk_sk(sk)->flags & NETLINK_F_KERNEL_SOCKET; | 90 | return nlk_sk(sk)->flags & NETLINK_F_KERNEL_SOCKET; |
91 | } | 91 | } |
92 | 92 | ||
93 | struct netlink_table *nl_table; | 93 | struct netlink_table *nl_table __read_mostly; |
94 | EXPORT_SYMBOL_GPL(nl_table); | 94 | EXPORT_SYMBOL_GPL(nl_table); |
95 | 95 | ||
96 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); | 96 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); |
@@ -1083,6 +1083,7 @@ static int netlink_insert(struct sock *sk, u32 portid) | |||
1083 | if (err) { | 1083 | if (err) { |
1084 | if (err == -EEXIST) | 1084 | if (err == -EEXIST) |
1085 | err = -EADDRINUSE; | 1085 | err = -EADDRINUSE; |
1086 | nlk_sk(sk)->portid = 0; | ||
1086 | sock_put(sk); | 1087 | sock_put(sk); |
1087 | } | 1088 | } |
1088 | 1089 | ||
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index b6ef9a04de06..a75864d93142 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -81,6 +81,11 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops) | |||
81 | struct tcf_proto_ops *t; | 81 | struct tcf_proto_ops *t; |
82 | int rc = -ENOENT; | 82 | int rc = -ENOENT; |
83 | 83 | ||
84 | /* Wait for outstanding call_rcu()s, if any, from a | ||
85 | * tcf_proto_ops's destroy() handler. | ||
86 | */ | ||
87 | rcu_barrier(); | ||
88 | |||
84 | write_lock(&cls_mod_lock); | 89 | write_lock(&cls_mod_lock); |
85 | list_for_each_entry(t, &tcf_proto_base, head) { | 90 | list_for_each_entry(t, &tcf_proto_base, head) { |
86 | if (t == ops) { | 91 | if (t == ops) { |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index d4c8cf828240..ac853acbe211 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -851,7 +851,7 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | |||
851 | 851 | ||
852 | err = switchdev_port_obj_add(dev, &fib_obj); | 852 | err = switchdev_port_obj_add(dev, &fib_obj); |
853 | if (!err) | 853 | if (!err) |
854 | fi->fib_flags |= RTNH_F_EXTERNAL; | 854 | fi->fib_flags |= RTNH_F_OFFLOAD; |
855 | 855 | ||
856 | return err; | 856 | return err; |
857 | } | 857 | } |
@@ -887,7 +887,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | |||
887 | struct net_device *dev; | 887 | struct net_device *dev; |
888 | int err = 0; | 888 | int err = 0; |
889 | 889 | ||
890 | if (!(fi->fib_flags & RTNH_F_EXTERNAL)) | 890 | if (!(fi->fib_flags & RTNH_F_OFFLOAD)) |
891 | return 0; | 891 | return 0; |
892 | 892 | ||
893 | dev = switchdev_get_dev_by_nhs(fi); | 893 | dev = switchdev_get_dev_by_nhs(fi); |
@@ -896,7 +896,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | |||
896 | 896 | ||
897 | err = switchdev_port_obj_del(dev, &fib_obj); | 897 | err = switchdev_port_obj_del(dev, &fib_obj); |
898 | if (!err) | 898 | if (!err) |
899 | fi->fib_flags &= ~RTNH_F_EXTERNAL; | 899 | fi->fib_flags &= ~RTNH_F_OFFLOAD; |
900 | 900 | ||
901 | return err; | 901 | return err; |
902 | } | 902 | } |