From: Greg Kroah-Hartman Date: Tue, 18 Jul 2017 08:06:50 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.12.3~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=606a81867bd4558e2bd33da9e20d3177a7b1cf35;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches 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 --- diff --git a/queue-3.18/series b/queue-3.18/series new file mode 100644 index 00000000000..8a23afeffd0 --- /dev/null +++ b/queue-3.18/series @@ -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 index 00000000000..befe297cb37 --- /dev/null +++ b/queue-4.9/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch @@ -0,0 +1,57 @@ +From 1bfb159673957644951ab0a8d2aec44b93ddb1ae Mon Sep 17 00:00:00 2001 +From: Eduardo Valentin +Date: Tue, 11 Jul 2017 14:55:12 -0700 +Subject: bridge: mdb: fix leak on complete_info ptr on fail path + +From: Eduardo Valentin + +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: + [] kmemleak_alloc+0x4a/0xa0 + [] kmem_cache_alloc_trace+0xb8/0x1c0 + [] __br_mdb_notify+0x2a3/0x300 [bridge] + [] br_mdb_notify+0x6e/0x70 [bridge] + [] br_multicast_add_group+0x109/0x150 [bridge] + [] br_ip6_multicast_add_group+0x58/0x60 [bridge] + [] br_multicast_rcv+0x1d5/0xdb0 [bridge] + [] br_handle_frame_finish+0xcf/0x510 [bridge] + [] br_nf_hook_thresh.part.27+0xb/0x10 [br_netfilter] + [] br_nf_hook_thresh+0x48/0xb0 [br_netfilter] + [] br_nf_pre_routing_finish_ipv6+0x109/0x1d0 [br_netfilter] + [] br_nf_pre_routing_ipv6+0xd0/0x14c [br_netfilter] + [] br_nf_pre_routing+0x197/0x3d0 [br_netfilter] + [] nf_iterate+0x52/0x60 + [] nf_hook_slow+0x5c/0xb0 + [] 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 +Signed-off-by: Eduardo Valentin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..928d218d658 --- /dev/null +++ b/queue-4.9/ipv6-avoid-unregistering-inet6_dev-for-loopback.patch @@ -0,0 +1,65 @@ +From 60abc0be96e00ca71bac083215ac91ad2e575096 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Wed, 21 Jun 2017 14:34:58 -0700 +Subject: ipv6: avoid unregistering inet6_dev for loopback + +From: WANG Cong + +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 +Cc: Andrey Konovalov +Cc: Daniel Lezcano +Cc: David Ahern +Signed-off-by: Cong Wang +Acked-by: David Ahern +Tested-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..08d6a1ada66 --- /dev/null +++ b/queue-4.9/net-dp83640-avoid-null-pointer-dereference.patch @@ -0,0 +1,43 @@ +From db9d8b29d19d2801793e4419f4c6272bf8951c62 Mon Sep 17 00:00:00 2001 +From: Richard Cochran +Date: Fri, 23 Jun 2017 17:51:31 +0200 +Subject: net: dp83640: Avoid NULL pointer dereference. + +From: Richard Cochran + +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c065226a12b --- /dev/null +++ b/queue-4.9/net-phy-micrel-configure-intterupts-after-autoneg-workaround.patch @@ -0,0 +1,38 @@ +From b866203d872d5deeafcecd25ea429d6748b5bd56 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 20 Jun 2017 12:48:11 -0500 +Subject: net/phy: micrel: configure intterupts after autoneg workaround + +From: Zach Brown + +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 +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..aa92e7f4c3e --- /dev/null +++ b/queue-4.9/net-prevent-sign-extension-in-dev_get_stats.patch @@ -0,0 +1,43 @@ +From 6f64ec74515925cced6df4571638b5a099a49aae Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 27 Jun 2017 07:02:20 -0700 +Subject: net: prevent sign extension in dev_get_stats() + +From: Eric Dumazet + +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 +Cc: Jarod Wilson +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..3aa03a8805f --- /dev/null +++ b/queue-4.9/net-sched-fix-one-possible-panic-when-no-destroy-callback.patch @@ -0,0 +1,44 @@ +From c1a4872ebfb83b1af7144f7b29ac8c4b344a12a8 Mon Sep 17 00:00:00 2001 +From: Gao Feng +Date: Wed, 28 Jun 2017 12:53:54 +0800 +Subject: net: sched: Fix one possible panic when no destroy callback + +From: Gao Feng + +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 +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..33e8e497f2f --- /dev/null +++ b/queue-4.9/net_sched-fix-error-recovery-at-qdisc-creation.patch @@ -0,0 +1,199 @@ +From 87b60cfacf9f17cf71933c6e33b66e68160af71d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 10 Feb 2017 10:31:49 -0800 +Subject: net_sched: fix error recovery at qdisc creation + +From: Eric Dumazet + +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: + [] __dump_stack lib/dump_stack.c:15 [inline] + [] dump_stack+0x6c/0x98 lib/dump_stack.c:51 + [] kasan_object_err+0x21/0x70 mm/kasan/report.c:158 + [] print_address_description mm/kasan/report.c:196 [inline] + [] kasan_report_error+0x1b4/0x4b0 mm/kasan/report.c:285 + [] kasan_report mm/kasan/report.c:305 [inline] + [] __asan_report_load8_noabort+0x43/0x50 mm/kasan/report.c:326 + [] mq_destroy+0x242/0x290 net/sched/sch_mq.c:33 + [] qdisc_destroy+0x12d/0x290 net/sched/sch_generic.c:953 + [] qdisc_create_dflt+0xf0/0x120 net/sched/sch_generic.c:848 + [] attach_default_qdiscs net/sched/sch_generic.c:1029 [inline] + [] dev_activate+0x6ad/0x880 net/sched/sch_generic.c:1064 + [] __dev_open+0x221/0x320 net/core/dev.c:1403 + [] __dev_change_flags+0x15e/0x3e0 net/core/dev.c:6858 + [] dev_change_flags+0x8e/0x140 net/core/dev.c:6926 + [] dev_ifsioc+0x446/0x890 net/core/dev_ioctl.c:260 + [] dev_ioctl+0x1ba/0xb80 net/core/dev_ioctl.c:546 + [] sock_do_ioctl+0x99/0xb0 net/socket.c:879 + [] sock_ioctl+0x2a0/0x390 net/socket.c:958 + [] vfs_ioctl fs/ioctl.c:44 [inline] + [] do_vfs_ioctl+0x8a8/0xe50 fs/ioctl.c:611 + [] SYSC_ioctl fs/ioctl.c:626 [inline] + [] SyS_ioctl+0x94/0xc0 fs/ioctl.c:617 + [] entry_SYSCALL_64_fastpath+0x12/0x17 + +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-4.9/series b/queue-4.9/series index 66b41553f86..770727eb557 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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 index 00000000000..9d03e45b4b0 --- /dev/null +++ b/queue-4.9/tcp-reset-sk_rx_dst-in-tcp_disconnect.patch @@ -0,0 +1,40 @@ +From d747a7a51b00984127a88113cdbbc26f91e9d815 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Sat, 24 Jun 2017 23:50:30 -0700 +Subject: tcp: reset sk_rx_dst in tcp_disconnect() + +From: WANG Cong + +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 +Reported-by: Kevin Xu +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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);