]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Jul 2017 08:06:50 +0000 (10:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Jul 2017 08:06:50 +0000 (10:06 +0200)
added patches:
bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch
ipv6-avoid-unregistering-inet6_dev-for-loopback.patch
net-dp83640-avoid-null-pointer-dereference.patch
net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch
net-prevent-sign-extension-in-dev_get_stats.patch
net-sched-fix-one-possible-panic-when-no-destroy-callback.patch
net_sched-fix-error-recovery-at-qdisc-creation.patch
tcp-reset-sk_rx_dst-in-tcp_disconnect.patch

queue-3.18/series [new file with mode: 0644]
queue-4.9/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch [new file with mode: 0644]
queue-4.9/ipv6-avoid-unregistering-inet6_dev-for-loopback.patch [new file with mode: 0644]
queue-4.9/net-dp83640-avoid-null-pointer-dereference.patch [new file with mode: 0644]
queue-4.9/net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch [new file with mode: 0644]
queue-4.9/net-prevent-sign-extension-in-dev_get_stats.patch [new file with mode: 0644]
queue-4.9/net-sched-fix-one-possible-panic-when-no-destroy-callback.patch [new file with mode: 0644]
queue-4.9/net_sched-fix-error-recovery-at-qdisc-creation.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/tcp-reset-sk_rx_dst-in-tcp_disconnect.patch [new file with mode: 0644]

diff --git a/queue-3.18/series b/queue-3.18/series
new file mode 100644 (file)
index 0000000..8a23afe
--- /dev/null
@@ -0,0 +1,2 @@
+ipv6-avoid-unregistering-inet6_dev-for-loopback.patch
+tcp-reset-sk_rx_dst-in-tcp_disconnect.patch
diff --git a/queue-4.9/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch b/queue-4.9/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch
new file mode 100644 (file)
index 0000000..befe297
--- /dev/null
@@ -0,0 +1,57 @@
+From 1bfb159673957644951ab0a8d2aec44b93ddb1ae Mon Sep 17 00:00:00 2001
+From: Eduardo Valentin <eduval@amazon.com>
+Date: Tue, 11 Jul 2017 14:55:12 -0700
+Subject: bridge: mdb: fix leak on complete_info ptr on fail path
+
+From: Eduardo Valentin <eduval@amazon.com>
+
+commit 1bfb159673957644951ab0a8d2aec44b93ddb1ae upstream.
+
+We currently get the following kmemleak report:
+unreferenced object 0xffff8800039d9820 (size 32):
+  comm "softirq", pid 0, jiffies 4295212383 (age 792.416s)
+  hex dump (first 32 bytes):
+    00 0c e0 03 00 88 ff ff ff 02 00 00 00 00 00 00  ................
+    00 00 00 01 ff 11 00 02 86 dd 00 00 ff ff ff ff  ................
+  backtrace:
+    [<ffffffff8152b4aa>] kmemleak_alloc+0x4a/0xa0
+    [<ffffffff811d8ec8>] kmem_cache_alloc_trace+0xb8/0x1c0
+    [<ffffffffa0389683>] __br_mdb_notify+0x2a3/0x300 [bridge]
+    [<ffffffffa038a0ce>] br_mdb_notify+0x6e/0x70 [bridge]
+    [<ffffffffa0386479>] br_multicast_add_group+0x109/0x150 [bridge]
+    [<ffffffffa0386518>] br_ip6_multicast_add_group+0x58/0x60 [bridge]
+    [<ffffffffa0387fb5>] br_multicast_rcv+0x1d5/0xdb0 [bridge]
+    [<ffffffffa037d7cf>] br_handle_frame_finish+0xcf/0x510 [bridge]
+    [<ffffffffa03a236b>] br_nf_hook_thresh.part.27+0xb/0x10 [br_netfilter]
+    [<ffffffffa03a3738>] br_nf_hook_thresh+0x48/0xb0 [br_netfilter]
+    [<ffffffffa03a3fb9>] br_nf_pre_routing_finish_ipv6+0x109/0x1d0 [br_netfilter]
+    [<ffffffffa03a4400>] br_nf_pre_routing_ipv6+0xd0/0x14c [br_netfilter]
+    [<ffffffffa03a3c27>] br_nf_pre_routing+0x197/0x3d0 [br_netfilter]
+    [<ffffffff814a2952>] nf_iterate+0x52/0x60
+    [<ffffffff814a29bc>] nf_hook_slow+0x5c/0xb0
+    [<ffffffffa037ddf4>] br_handle_frame+0x1a4/0x2c0 [bridge]
+
+This happens when switchdev_port_obj_add() fails. This patch
+frees complete_info object in the fail path.
+
+Reviewed-by: Vallish Vaidyeshwara <vallish@amazon.com>
+Signed-off-by: Eduardo Valentin <eduval@amazon.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/bridge/br_mdb.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/bridge/br_mdb.c
++++ b/net/bridge/br_mdb.c
+@@ -323,7 +323,8 @@ static void __br_mdb_notify(struct net_d
+                       __mdb_entry_to_br_ip(entry, &complete_info->ip);
+                       mdb.obj.complete_priv = complete_info;
+                       mdb.obj.complete = br_mdb_complete;
+-                      switchdev_port_obj_add(port_dev, &mdb.obj);
++                      if (switchdev_port_obj_add(port_dev, &mdb.obj))
++                              kfree(complete_info);
+               }
+       } else if (port_dev && type == RTM_DELMDB) {
+               switchdev_port_obj_del(port_dev, &mdb.obj);
diff --git a/queue-4.9/ipv6-avoid-unregistering-inet6_dev-for-loopback.patch b/queue-4.9/ipv6-avoid-unregistering-inet6_dev-for-loopback.patch
new file mode 100644 (file)
index 0000000..928d218
--- /dev/null
@@ -0,0 +1,65 @@
+From 60abc0be96e00ca71bac083215ac91ad2e575096 Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Wed, 21 Jun 2017 14:34:58 -0700
+Subject: ipv6: avoid unregistering inet6_dev for loopback
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+commit 60abc0be96e00ca71bac083215ac91ad2e575096 upstream.
+
+The per netns loopback_dev->ip6_ptr is unregistered and set to
+NULL when its mtu is set to smaller than IPV6_MIN_MTU, this
+leads to that we could set rt->rt6i_idev NULL after a
+rt6_uncached_list_flush_dev() and then crash after another
+call.
+
+In this case we should just bring its inet6_dev down, rather
+than unregistering it, at least prior to commit 176c39af29bc
+("netns: fix addrconf_ifdown kernel panic") we always
+override the case for loopback.
+
+Thanks a lot to Andrey for finding a reliable reproducer.
+
+Fixes: 176c39af29bc ("netns: fix addrconf_ifdown kernel panic")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Cc: Andrey Konovalov <andreyknvl@google.com>
+Cc: Daniel Lezcano <dlezcano@fr.ibm.com>
+Cc: David Ahern <dsahern@gmail.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Acked-by: David Ahern <dsahern@gmail.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv6/addrconf.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -3316,6 +3316,7 @@ static int addrconf_notify(struct notifi
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct netdev_notifier_changeupper_info *info;
+       struct inet6_dev *idev = __in6_dev_get(dev);
++      struct net *net = dev_net(dev);
+       int run_pending = 0;
+       int err;
+@@ -3331,7 +3332,7 @@ static int addrconf_notify(struct notifi
+       case NETDEV_CHANGEMTU:
+               /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
+               if (dev->mtu < IPV6_MIN_MTU) {
+-                      addrconf_ifdown(dev, 1);
++                      addrconf_ifdown(dev, dev != net->loopback_dev);
+                       break;
+               }
+@@ -3447,7 +3448,7 @@ static int addrconf_notify(struct notifi
+                        * IPV6_MIN_MTU stop IPv6 on this interface.
+                        */
+                       if (dev->mtu < IPV6_MIN_MTU)
+-                              addrconf_ifdown(dev, 1);
++                              addrconf_ifdown(dev, dev != net->loopback_dev);
+               }
+               break;
diff --git a/queue-4.9/net-dp83640-avoid-null-pointer-dereference.patch b/queue-4.9/net-dp83640-avoid-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..08d6a1a
--- /dev/null
@@ -0,0 +1,43 @@
+From db9d8b29d19d2801793e4419f4c6272bf8951c62 Mon Sep 17 00:00:00 2001
+From: Richard Cochran <richardcochran@gmail.com>
+Date: Fri, 23 Jun 2017 17:51:31 +0200
+Subject: net: dp83640: Avoid NULL pointer dereference.
+
+From: Richard Cochran <richardcochran@gmail.com>
+
+commit db9d8b29d19d2801793e4419f4c6272bf8951c62 upstream.
+
+The function, skb_complete_tx_timestamp(), used to allow passing in a
+NULL pointer for the time stamps, but that was changed in commit
+62bccb8cdb69051b95a55ab0c489e3cab261c8ef ("net-timestamp: Make the
+clone operation stand-alone from phy timestamping"), and the existing
+call sites, all of which are in the dp83640 driver, were fixed up.
+
+Even though the kernel-doc was subsequently updated in commit
+7a76a021cd5a292be875fbc616daf03eab1e6996 ("net-timestamp: Update
+skb_complete_tx_timestamp comment"), still a bug fix from Manfred
+Rudigier came into the driver using the old semantics.  Probably
+Manfred derived that patch from an older kernel version.
+
+This fix should be applied to the stable trees as well.
+
+Fixes: 81e8f2e930fe ("net: dp83640: Fix tx timestamp overflow handling.")
+Signed-off-by: Richard Cochran <richardcochran@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/phy/dp83640.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/phy/dp83640.c
++++ b/drivers/net/phy/dp83640.c
+@@ -908,7 +908,7 @@ static void decode_txts(struct dp83640_p
+       if (overflow) {
+               pr_debug("tx timestamp queue overflow, count %d\n", overflow);
+               while (skb) {
+-                      skb_complete_tx_timestamp(skb, NULL);
++                      kfree_skb(skb);
+                       skb = skb_dequeue(&dp83640->tx_queue);
+               }
+               return;
diff --git a/queue-4.9/net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch b/queue-4.9/net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch
new file mode 100644 (file)
index 0000000..c065226
--- /dev/null
@@ -0,0 +1,38 @@
+From b866203d872d5deeafcecd25ea429d6748b5bd56 Mon Sep 17 00:00:00 2001
+From: Zach Brown <zach.brown@ni.com>
+Date: Tue, 20 Jun 2017 12:48:11 -0500
+Subject: net/phy: micrel: configure intterupts after autoneg workaround
+
+From: Zach Brown <zach.brown@ni.com>
+
+commit b866203d872d5deeafcecd25ea429d6748b5bd56 upstream.
+
+The commit ("net/phy: micrel: Add workaround for bad autoneg") fixes an
+autoneg failure case by resetting the hardware. This turns off
+intterupts. Things will work themselves out if the phy polls, as it will
+figure out it's state during a poll. However if the phy uses only
+intterupts, the phy will stall, since interrupts are off. This patch
+fixes the issue by calling config_intr after resetting the phy.
+
+Fixes: d2fd719bcb0e ("net/phy: micrel: Add workaround for bad autoneg ")
+Signed-off-by: Zach Brown <zach.brown@ni.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/phy/micrel.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -622,6 +622,8 @@ static int ksz9031_read_status(struct ph
+       if ((regval & 0xFF) == 0xFF) {
+               phy_init_hw(phydev);
+               phydev->link = 0;
++              if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
++                      phydev->drv->config_intr(phydev);
+       }
+       return 0;
diff --git a/queue-4.9/net-prevent-sign-extension-in-dev_get_stats.patch b/queue-4.9/net-prevent-sign-extension-in-dev_get_stats.patch
new file mode 100644 (file)
index 0000000..aa92e7f
--- /dev/null
@@ -0,0 +1,43 @@
+From 6f64ec74515925cced6df4571638b5a099a49aae Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 27 Jun 2017 07:02:20 -0700
+Subject: net: prevent sign extension in dev_get_stats()
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 6f64ec74515925cced6df4571638b5a099a49aae upstream.
+
+Similar to the fix provided by Dominik Heidler in commit
+9b3dc0a17d73 ("l2tp: cast l2tp traffic counter to unsigned")
+we need to take care of 32bit kernels in dev_get_stats().
+
+When using atomic_long_read(), we add a 'long' to u64 and
+might misinterpret high order bit, unless we cast to unsigned.
+
+Fixes: caf586e5f23ce ("net: add a core netdev->rx_dropped counter")
+Fixes: 015f0688f57ca ("net: net: add a core netdev->tx_dropped counter")
+Fixes: 6e7333d315a76 ("net: add rx_nohandler stat counter")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Jarod Wilson <jarod@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/core/dev.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -7563,9 +7563,9 @@ struct rtnl_link_stats64 *dev_get_stats(
+       } else {
+               netdev_stats_to_stats64(storage, &dev->stats);
+       }
+-      storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
+-      storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
+-      storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
++      storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped);
++      storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped);
++      storage->rx_nohandler += (unsigned long)atomic_long_read(&dev->rx_nohandler);
+       return storage;
+ }
+ EXPORT_SYMBOL(dev_get_stats);
diff --git a/queue-4.9/net-sched-fix-one-possible-panic-when-no-destroy-callback.patch b/queue-4.9/net-sched-fix-one-possible-panic-when-no-destroy-callback.patch
new file mode 100644 (file)
index 0000000..3aa03a8
--- /dev/null
@@ -0,0 +1,44 @@
+From c1a4872ebfb83b1af7144f7b29ac8c4b344a12a8 Mon Sep 17 00:00:00 2001
+From: Gao Feng <gfree.wind@vip.163.com>
+Date: Wed, 28 Jun 2017 12:53:54 +0800
+Subject: net: sched: Fix one possible panic when no destroy callback
+
+From: Gao Feng <gfree.wind@vip.163.com>
+
+commit c1a4872ebfb83b1af7144f7b29ac8c4b344a12a8 upstream.
+
+When qdisc fail to init, qdisc_create would invoke the destroy callback
+to cleanup. But there is no check if the callback exists really. So it
+would cause the panic if there is no real destroy callback like the qdisc
+codel, fq, and so on.
+
+Take codel as an example following:
+When a malicious user constructs one invalid netlink msg, it would cause
+codel_init->codel_change->nla_parse_nested failed.
+Then kernel would invoke the destroy callback directly but qdisc codel
+doesn't define one. It causes one panic as a result.
+
+Now add one the check for destroy to avoid the possible panic.
+
+Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation")
+Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sched/sch_api.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -1009,7 +1009,8 @@ static struct Qdisc *qdisc_create(struct
+               return sch;
+       }
+       /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
+-      ops->destroy(sch);
++      if (ops->destroy)
++              ops->destroy(sch);
+ err_out3:
+       dev_put(dev);
+       kfree((char *) sch - sch->padded);
diff --git a/queue-4.9/net_sched-fix-error-recovery-at-qdisc-creation.patch b/queue-4.9/net_sched-fix-error-recovery-at-qdisc-creation.patch
new file mode 100644 (file)
index 0000000..33e8e49
--- /dev/null
@@ -0,0 +1,199 @@
+From 87b60cfacf9f17cf71933c6e33b66e68160af71d Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 10 Feb 2017 10:31:49 -0800
+Subject: net_sched: fix error recovery at qdisc creation
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 87b60cfacf9f17cf71933c6e33b66e68160af71d upstream.
+
+Dmitry reported uses after free in qdisc code [1]
+
+The problem here is that ops->init() can return an error.
+
+qdisc_create_dflt() then call ops->destroy(),
+while qdisc_create() does _not_ call it.
+
+Four qdisc chose to call their own ops->destroy(), assuming their caller
+would not.
+
+This patch makes sure qdisc_create() calls ops->destroy()
+and fixes the four qdisc to avoid double free.
+
+[1]
+BUG: KASAN: use-after-free in mq_destroy+0x242/0x290 net/sched/sch_mq.c:33 at addr ffff8801d415d440
+Read of size 8 by task syz-executor2/5030
+CPU: 0 PID: 5030 Comm: syz-executor2 Not tainted 4.3.5-smp-DEV #119
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+ 0000000000000046 ffff8801b435b870 ffffffff81bbbed4 ffff8801db000400
+ ffff8801d415d440 ffff8801d415dc40 ffff8801c4988510 ffff8801b435b898
+ ffffffff816682b1 ffff8801b435b928 ffff8801d415d440 ffff8801c49880c0
+Call Trace:
+ [<ffffffff81bbbed4>] __dump_stack lib/dump_stack.c:15 [inline]
+ [<ffffffff81bbbed4>] dump_stack+0x6c/0x98 lib/dump_stack.c:51
+ [<ffffffff816682b1>] kasan_object_err+0x21/0x70 mm/kasan/report.c:158
+ [<ffffffff81668524>] print_address_description mm/kasan/report.c:196 [inline]
+ [<ffffffff81668524>] kasan_report_error+0x1b4/0x4b0 mm/kasan/report.c:285
+ [<ffffffff81668953>] kasan_report mm/kasan/report.c:305 [inline]
+ [<ffffffff81668953>] __asan_report_load8_noabort+0x43/0x50 mm/kasan/report.c:326
+ [<ffffffff82527b02>] mq_destroy+0x242/0x290 net/sched/sch_mq.c:33
+ [<ffffffff82524bdd>] qdisc_destroy+0x12d/0x290 net/sched/sch_generic.c:953
+ [<ffffffff82524e30>] qdisc_create_dflt+0xf0/0x120 net/sched/sch_generic.c:848
+ [<ffffffff8252550d>] attach_default_qdiscs net/sched/sch_generic.c:1029 [inline]
+ [<ffffffff8252550d>] dev_activate+0x6ad/0x880 net/sched/sch_generic.c:1064
+ [<ffffffff824b1db1>] __dev_open+0x221/0x320 net/core/dev.c:1403
+ [<ffffffff824b24ce>] __dev_change_flags+0x15e/0x3e0 net/core/dev.c:6858
+ [<ffffffff824b27de>] dev_change_flags+0x8e/0x140 net/core/dev.c:6926
+ [<ffffffff824f5bf6>] dev_ifsioc+0x446/0x890 net/core/dev_ioctl.c:260
+ [<ffffffff824f61fa>] dev_ioctl+0x1ba/0xb80 net/core/dev_ioctl.c:546
+ [<ffffffff82430509>] sock_do_ioctl+0x99/0xb0 net/socket.c:879
+ [<ffffffff82430d30>] sock_ioctl+0x2a0/0x390 net/socket.c:958
+ [<ffffffff816f3b68>] vfs_ioctl fs/ioctl.c:44 [inline]
+ [<ffffffff816f3b68>] do_vfs_ioctl+0x8a8/0xe50 fs/ioctl.c:611
+ [<ffffffff816f41a4>] SYSC_ioctl fs/ioctl.c:626 [inline]
+ [<ffffffff816f41a4>] SyS_ioctl+0x94/0xc0 fs/ioctl.c:617
+ [<ffffffff8123e357>] entry_SYSCALL_64_fastpath+0x12/0x17
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sched/sch_api.c    |    2 ++
+ net/sched/sch_hhf.c    |    8 ++++++--
+ net/sched/sch_mq.c     |   10 +++-------
+ net/sched/sch_mqprio.c |   19 ++++++-------------
+ net/sched/sch_sfq.c    |    3 ++-
+ 5 files changed, 19 insertions(+), 23 deletions(-)
+
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -1008,6 +1008,8 @@ static struct Qdisc *qdisc_create(struct
+               return sch;
+       }
++      /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
++      ops->destroy(sch);
+ err_out3:
+       dev_put(dev);
+       kfree((char *) sch - sch->padded);
+--- a/net/sched/sch_hhf.c
++++ b/net/sched/sch_hhf.c
+@@ -627,7 +627,9 @@ static int hhf_init(struct Qdisc *sch, s
+                       q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN *
+                                                     sizeof(u32));
+                       if (!q->hhf_arrays[i]) {
+-                              hhf_destroy(sch);
++                              /* Note: hhf_destroy() will be called
++                               * by our caller.
++                               */
+                               return -ENOMEM;
+                       }
+               }
+@@ -638,7 +640,9 @@ static int hhf_init(struct Qdisc *sch, s
+                       q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN /
+                                                         BITS_PER_BYTE);
+                       if (!q->hhf_valid_bits[i]) {
+-                              hhf_destroy(sch);
++                              /* Note: hhf_destroy() will be called
++                               * by our caller.
++                               */
+                               return -ENOMEM;
+                       }
+               }
+--- a/net/sched/sch_mq.c
++++ b/net/sched/sch_mq.c
+@@ -52,7 +52,7 @@ static int mq_init(struct Qdisc *sch, st
+       /* pre-allocate qdiscs, attachment can't fail */
+       priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
+                              GFP_KERNEL);
+-      if (priv->qdiscs == NULL)
++      if (!priv->qdiscs)
+               return -ENOMEM;
+       for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
+@@ -60,18 +60,14 @@ static int mq_init(struct Qdisc *sch, st
+               qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx),
+                                         TC_H_MAKE(TC_H_MAJ(sch->handle),
+                                                   TC_H_MIN(ntx + 1)));
+-              if (qdisc == NULL)
+-                      goto err;
++              if (!qdisc)
++                      return -ENOMEM;
+               priv->qdiscs[ntx] = qdisc;
+               qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
+       }
+       sch->flags |= TCQ_F_MQROOT;
+       return 0;
+-
+-err:
+-      mq_destroy(sch);
+-      return -ENOMEM;
+ }
+ static void mq_attach(struct Qdisc *sch)
+--- a/net/sched/sch_mqprio.c
++++ b/net/sched/sch_mqprio.c
+@@ -118,10 +118,8 @@ static int mqprio_init(struct Qdisc *sch
+       /* pre-allocate qdisc, attachment can't fail */
+       priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
+                              GFP_KERNEL);
+-      if (priv->qdiscs == NULL) {
+-              err = -ENOMEM;
+-              goto err;
+-      }
++      if (!priv->qdiscs)
++              return -ENOMEM;
+       for (i = 0; i < dev->num_tx_queues; i++) {
+               dev_queue = netdev_get_tx_queue(dev, i);
+@@ -129,10 +127,9 @@ static int mqprio_init(struct Qdisc *sch
+                                         get_default_qdisc_ops(dev, i),
+                                         TC_H_MAKE(TC_H_MAJ(sch->handle),
+                                                   TC_H_MIN(i + 1)));
+-              if (qdisc == NULL) {
+-                      err = -ENOMEM;
+-                      goto err;
+-              }
++              if (!qdisc)
++                      return -ENOMEM;
++
+               priv->qdiscs[i] = qdisc;
+               qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
+       }
+@@ -148,7 +145,7 @@ static int mqprio_init(struct Qdisc *sch
+               priv->hw_owned = 1;
+               err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
+               if (err)
+-                      goto err;
++                      return err;
+       } else {
+               netdev_set_num_tc(dev, qopt->num_tc);
+               for (i = 0; i < qopt->num_tc; i++)
+@@ -162,10 +159,6 @@ static int mqprio_init(struct Qdisc *sch
+       sch->flags |= TCQ_F_MQROOT;
+       return 0;
+-
+-err:
+-      mqprio_destroy(sch);
+-      return err;
+ }
+ static void mqprio_attach(struct Qdisc *sch)
+--- a/net/sched/sch_sfq.c
++++ b/net/sched/sch_sfq.c
+@@ -742,9 +742,10 @@ static int sfq_init(struct Qdisc *sch, s
+       q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
+       q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
+       if (!q->ht || !q->slots) {
+-              sfq_destroy(sch);
++              /* Note: sfq_destroy() will be called by our caller */
+               return -ENOMEM;
+       }
++
+       for (i = 0; i < q->divisor; i++)
+               q->ht[i] = SFQ_EMPTY_SLOT;
index 66b41553f86f02ec3f9b0deee2b54b00f3e342f6..770727eb557196bca7c6d881e3971c2c80d191be 100644 (file)
@@ -1 +1,9 @@
 xen-netfront-rework-the-fix-for-rx-stall-during-oom-and-network-stress.patch
+net_sched-fix-error-recovery-at-qdisc-creation.patch
+net-sched-fix-one-possible-panic-when-no-destroy-callback.patch
+net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch
+ipv6-avoid-unregistering-inet6_dev-for-loopback.patch
+net-dp83640-avoid-null-pointer-dereference.patch
+tcp-reset-sk_rx_dst-in-tcp_disconnect.patch
+net-prevent-sign-extension-in-dev_get_stats.patch
+bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch
diff --git a/queue-4.9/tcp-reset-sk_rx_dst-in-tcp_disconnect.patch b/queue-4.9/tcp-reset-sk_rx_dst-in-tcp_disconnect.patch
new file mode 100644 (file)
index 0000000..9d03e45
--- /dev/null
@@ -0,0 +1,40 @@
+From d747a7a51b00984127a88113cdbbc26f91e9d815 Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Sat, 24 Jun 2017 23:50:30 -0700
+Subject: tcp: reset sk_rx_dst in tcp_disconnect()
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+commit d747a7a51b00984127a88113cdbbc26f91e9d815 upstream.
+
+We have to reset the sk->sk_rx_dst when we disconnect a TCP
+connection, because otherwise when we re-connect it this
+dst reference is simply overridden in tcp_finish_connect().
+
+This fixes a dst leak which leads to a loopback dev refcnt
+leak. It is a long-standing bug, Kevin reported a very similar
+(if not same) bug before. Thanks to Andrei for providing such
+a reliable reproducer which greatly narrows down the problem.
+
+Fixes: 41063e9dd119 ("ipv4: Early TCP socket demux.")
+Reported-by: Andrei Vagin <avagin@gmail.com>
+Reported-by: Kevin Xu <kaiwen.xu@hulu.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv4/tcp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2300,6 +2300,8 @@ int tcp_disconnect(struct sock *sk, int
+       tcp_init_send_head(sk);
+       memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
+       __sk_dst_reset(sk);
++      dst_release(sk->sk_rx_dst);
++      sk->sk_rx_dst = NULL;
+       tcp_saved_syn_free(tp);
+       WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);