From d6335d840aab0be8b3cdf92a09f038a0c5622b9b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 16 Nov 2015 08:42:19 -0500 Subject: [PATCH] Add queued 4.3 net stable fixes --- kernel.spec | 5 + net_43.mbox | 1330 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1335 insertions(+) create mode 100644 net_43.mbox diff --git a/kernel.spec b/kernel.spec index 7b0f0f797..63f579ffc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -611,6 +611,8 @@ Patch553: ideapad-laptop-Add-Lenovo-Yoga-900-to-no_hw_rfkill-d.patch #CVE-2015-5327 Patch554: X.509-Fix-the-time-validation-ver-3.patch +Patch555: net_43.mbox + # END OF PATCH DEFINITIONS %endif @@ -2054,6 +2056,9 @@ fi # # %changelog +* Mon Nov 16 2015 Josh Boyer +- Add queued 4.3 net stable fixes + * Thu Nov 12 2015 Josh Boyer - CVE-2015-5327 x509 time validation diff --git a/net_43.mbox b/net_43.mbox new file mode 100644 index 000000000..7e4c7a253 --- /dev/null +++ b/net_43.mbox @@ -0,0 +1,1330 @@ +From 212f263930ebc1020ad12dd0fa52a058592709e8 Mon Sep 17 00:00:00 2001 +From: Jon Paul Maloy +Date: Wed, 28 Oct 2015 13:09:53 -0400 +Subject: [PATCH 01/17] tipc: linearize arriving NAME_DISTR and LINK_PROTO + buffers + +[ Upstream commit 5cbb28a4bf65c7e4daa6c25b651fed8eb888c620 ] + +Testing of the new UDP bearer has revealed that reception of +NAME_DISTRIBUTOR, LINK_PROTOCOL/RESET and LINK_PROTOCOL/ACTIVATE +message buffers is not prepared for the case that those may be +non-linear. + +We now linearize all such buffers before they are delivered up to the +generic reception layer. + +In order for the commit to apply cleanly to 'net' and 'stable', we do +the change in the function tipc_udp_recv() for now. Later, we will post +a commit to 'net-next' moving the linearization to generic code, in +tipc_named_rcv() and tipc_link_proto_rcv(). + +Fixes: commit d0f91938bede ("tipc: add ip/udp media type") +Signed-off-by: Jon Maloy +Signed-off-by: David S. Miller +--- + net/tipc/udp_media.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index 6e648d9..cd7c5f1 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -48,6 +48,7 @@ + #include + #include "core.h" + #include "bearer.h" ++#include "msg.h" + + /* IANA assigned UDP port */ + #define UDP_PORT_DEFAULT 6118 +@@ -222,6 +223,10 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) + { + struct udp_bearer *ub; + struct tipc_bearer *b; ++ int usr = msg_user(buf_msg(skb)); ++ ++ if ((usr == LINK_PROTOCOL) || (usr == NAME_DISTRIBUTOR)) ++ skb_linearize(skb); + + ub = rcu_dereference_sk_user_data(sk); + if (!ub) { +-- +2.4.1 + + +From a04db8659b41413b9ef6751b1487c96f4fe5c8c1 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Thu, 29 Oct 2015 18:11:35 -0700 +Subject: [PATCH 02/17] net: bcmgenet: Software reset EPHY after power on + +[ Upstream commit 5dbebbb44a6ad94aab2cd1a46f7676f255403f64 ] + +The EPHY on GENET v1->v3 is extremely finicky, and will show occasional +failures based on the timing and reset sequence, ranging from duplicate +packets, to extremely high latencies. + +Perform an additional software reset, and re-configuration to make sure it is +in a consistent and working state. + +Fixes: 6ac3ce8295e6 ("net: bcmgenet: Remove excessive PHY reset") +Signed-off-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +++- + drivers/net/ethernet/broadcom/genet/bcmgenet.h | 1 + + drivers/net/ethernet/broadcom/genet/bcmmii.c | 18 ++++++++++++++++++ + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +index 1805541..5e3cd76 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -907,8 +907,10 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv, + } + + bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); +- if (mode == GENET_POWER_PASSIVE) ++ if (mode == GENET_POWER_PASSIVE) { + bcmgenet_phy_power_set(priv->dev, true); ++ bcmgenet_mii_reset(priv->dev); ++ } + } + + /* ioctl handle special commands that are not present in ethtool. */ +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h +index 7299d10..c739f7e 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h +@@ -674,6 +674,7 @@ int bcmgenet_mii_init(struct net_device *dev); + int bcmgenet_mii_config(struct net_device *dev); + int bcmgenet_mii_probe(struct net_device *dev); + void bcmgenet_mii_exit(struct net_device *dev); ++void bcmgenet_mii_reset(struct net_device *dev); + void bcmgenet_phy_power_set(struct net_device *dev, bool enable); + void bcmgenet_mii_setup(struct net_device *dev); + +diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c +index c8affad..8bdfe53 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c +@@ -163,6 +163,7 @@ void bcmgenet_mii_setup(struct net_device *dev) + phy_print_status(phydev); + } + ++ + static int bcmgenet_fixed_phy_link_update(struct net_device *dev, + struct fixed_phy_status *status) + { +@@ -172,6 +173,22 @@ static int bcmgenet_fixed_phy_link_update(struct net_device *dev, + return 0; + } + ++/* Perform a voluntary PHY software reset, since the EPHY is very finicky about ++ * not doing it and will start corrupting packets ++ */ ++void bcmgenet_mii_reset(struct net_device *dev) ++{ ++ struct bcmgenet_priv *priv = netdev_priv(dev); ++ ++ if (GENET_IS_V4(priv)) ++ return; ++ ++ if (priv->phydev) { ++ phy_init_hw(priv->phydev); ++ phy_start_aneg(priv->phydev); ++ } ++} ++ + void bcmgenet_phy_power_set(struct net_device *dev, bool enable) + { + struct bcmgenet_priv *priv = netdev_priv(dev); +@@ -214,6 +231,7 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev) + reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); + reg |= EXT_PWR_DN_EN_LD; + bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); ++ bcmgenet_mii_reset(dev); + } + + static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) +-- +2.4.1 + + +From 667672b33d13d71b92244bbd410f0a4122afa428 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Fri, 30 Oct 2015 10:23:33 +0200 +Subject: [PATCH 03/17] ipv4: fix to not remove local route on link down + +[ Upstream commit 4f823defdd5b106a5e89745ee8b163c71855de1e ] + +When fib_netdev_event calls fib_disable_ip on NETDEV_DOWN event +we should not delete the local routes if the local address +is still present. The confusion comes from the fact that both +fib_netdev_event and fib_inetaddr_event use the NETDEV_DOWN +constant. Fix it by returning back the variable 'force'. + +Steps to reproduce: +modprobe dummy +ifconfig dummy0 192.168.168.1 up +ifconfig dummy0 down +ip route list table local | grep dummy | grep host +local 192.168.168.1 dev dummy0 proto kernel scope host src 192.168.168.1 + +Fixes: 8a3d03166f19 ("net: track link-status of ipv4 nexthops") +Signed-off-by: Julian Anastasov +Signed-off-by: David S. Miller +--- + include/net/ip_fib.h | 2 +- + net/ipv4/fib_frontend.c | 13 +++++++------ + net/ipv4/fib_semantics.c | 11 ++++++++--- + 3 files changed, 16 insertions(+), 10 deletions(-) + +diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h +index 727d6e9..965fa5b 100644 +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -317,7 +317,7 @@ void fib_flush_external(struct net *net); + + /* Exported by fib_semantics.c */ + int ip_fib_check_default(__be32 gw, struct net_device *dev); +-int fib_sync_down_dev(struct net_device *dev, unsigned long event); ++int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force); + int fib_sync_down_addr(struct net *net, __be32 local); + int fib_sync_up(struct net_device *dev, unsigned int nh_flags); + void fib_select_multipath(struct fib_result *res); +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 690bcbc..457b2cd 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -1110,9 +1110,10 @@ static void nl_fib_lookup_exit(struct net *net) + net->ipv4.fibnl = NULL; + } + +-static void fib_disable_ip(struct net_device *dev, unsigned long event) ++static void fib_disable_ip(struct net_device *dev, unsigned long event, ++ bool force) + { +- if (fib_sync_down_dev(dev, event)) ++ if (fib_sync_down_dev(dev, event, force)) + fib_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev)); + arp_ifdown(dev); +@@ -1140,7 +1141,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, + /* Last address was deleted from this interface. + * Disable IP. + */ +- fib_disable_ip(dev, event); ++ fib_disable_ip(dev, event, true); + } else { + rt_cache_flush(dev_net(dev)); + } +@@ -1157,7 +1158,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo + unsigned int flags; + + if (event == NETDEV_UNREGISTER) { +- fib_disable_ip(dev, event); ++ fib_disable_ip(dev, event, true); + rt_flush_dev(dev); + return NOTIFY_DONE; + } +@@ -1178,14 +1179,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo + rt_cache_flush(net); + break; + case NETDEV_DOWN: +- fib_disable_ip(dev, event); ++ fib_disable_ip(dev, event, false); + break; + case NETDEV_CHANGE: + flags = dev_get_flags(dev); + if (flags & (IFF_RUNNING | IFF_LOWER_UP)) + fib_sync_up(dev, RTNH_F_LINKDOWN); + else +- fib_sync_down_dev(dev, event); ++ fib_sync_down_dev(dev, event, false); + /* fall through */ + case NETDEV_CHANGEMTU: + rt_cache_flush(net); +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 064bd3c..2aa5b5e 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -1281,7 +1281,13 @@ int fib_sync_down_addr(struct net *net, __be32 local) + return ret; + } + +-int fib_sync_down_dev(struct net_device *dev, unsigned long event) ++/* Event force Flags Description ++ * NETDEV_CHANGE 0 LINKDOWN Carrier OFF, not for scope host ++ * NETDEV_DOWN 0 LINKDOWN|DEAD Link down, not for scope host ++ * NETDEV_DOWN 1 LINKDOWN|DEAD Last address removed ++ * NETDEV_UNREGISTER 1 LINKDOWN|DEAD Device removed ++ */ ++int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force) + { + int ret = 0; + int scope = RT_SCOPE_NOWHERE; +@@ -1290,8 +1296,7 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event) + struct hlist_head *head = &fib_info_devhash[hash]; + struct fib_nh *nh; + +- if (event == NETDEV_UNREGISTER || +- event == NETDEV_DOWN) ++ if (force) + scope = -1; + + hlist_for_each_entry(nh, head, nh_hash) { +-- +2.4.1 + + +From 79c1b779621a34487aaf8a7fa1e499c04fff5c79 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Fri, 30 Oct 2015 10:23:34 +0200 +Subject: [PATCH 04/17] ipv4: update RTNH_F_LINKDOWN flag on UP event + +[ Upstream commit c9b3292eeb52c6834e972eb5b8fe38914771ed12 ] + +When nexthop is part of multipath route we should clear the +LINKDOWN flag when link goes UP or when first address is added. +This is needed because we always set LINKDOWN flag when DEAD flag +was set but now on UP the nexthop is not dead anymore. Examples when +LINKDOWN bit can be forgotten when no NETDEV_CHANGE is delivered: + +- link goes down (LINKDOWN is set), then link goes UP and device +shows carrier OK but LINKDOWN remains set + +- last address is deleted (LINKDOWN is set), then address is +added and device shows carrier OK but LINKDOWN remains set + +Steps to reproduce: +modprobe dummy +ifconfig dummy0 192.168.168.1 up + +here add a multipath route where one nexthop is for dummy0: + +ip route add 1.2.3.4 nexthop dummy0 nexthop SOME_OTHER_DEVICE +ifconfig dummy0 down +ifconfig dummy0 up + +now ip route shows nexthop that is not dead. Now set the sysctl var: + +echo 1 > /proc/sys/net/ipv4/conf/dummy0/ignore_routes_with_linkdown + +now ip route will show a dead nexthop because the forgotten +RTNH_F_LINKDOWN is propagated as RTNH_F_DEAD. + +Fixes: 8a3d03166f19 ("net: track link-status of ipv4 nexthops") +Signed-off-by: Julian Anastasov +Signed-off-by: David S. Miller +--- + net/ipv4/fib_semantics.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 2aa5b5e..e966f85 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -1445,6 +1445,13 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags) + if (!(dev->flags & IFF_UP)) + return 0; + ++ if (nh_flags & RTNH_F_DEAD) { ++ unsigned int flags = dev_get_flags(dev); ++ ++ if (flags & (IFF_RUNNING | IFF_LOWER_UP)) ++ nh_flags |= RTNH_F_LINKDOWN; ++ } ++ + prev_fi = NULL; + hash = fib_devindex_hashfn(dev->ifindex); + head = &fib_info_devhash[hash]; +-- +2.4.1 + + +From 22c6a0b8732f4b426f64f18ca9097288cd996a64 Mon Sep 17 00:00:00 2001 +From: Phil Reid +Date: Fri, 30 Oct 2015 16:43:55 +0800 +Subject: [PATCH 05/17] stmmac: Correctly report PTP capabilities. + +[ Upstream commit e6dbe1eb2db0d7a14991c06278dd3030c45fb825 ] + +priv->hwts_*_en indicate if timestamping is enabled/disabled at run +time. But priv->dma_cap.time_stamp and priv->dma_cap.atime_stamp +indicates HW is support for PTPv1/PTPv2. + +Signed-off-by: Phil Reid +Acked-by: Richard Cochran +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +index 771cda2..2e51b81 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +@@ -721,10 +721,13 @@ static int stmmac_get_ts_info(struct net_device *dev, + { + struct stmmac_priv *priv = netdev_priv(dev); + +- if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) { ++ if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) { + +- info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | ++ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | ++ SOF_TIMESTAMPING_TX_HARDWARE | ++ SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | ++ SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (priv->ptp_clock) +-- +2.4.1 + + +From 27cc4a97a3cdcb3b3daa126667d4e86c9b014909 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 30 Oct 2015 16:54:31 -0700 +Subject: [PATCH 06/17] ipmr: fix possible race resulting from improper usage + of IP_INC_STATS_BH() in preemptible context. + +[ Upstream commit 44f49dd8b5a606870a1f21101522a0f9c4414784 ] + +Fixes the following kernel BUG : + +BUG: using __this_cpu_add() in preemptible [00000000] code: bash/2758 +caller is __this_cpu_preempt_check+0x13/0x15 +CPU: 0 PID: 2758 Comm: bash Tainted: P O 3.18.19 #2 + ffffffff8170eaca ffff880110d1b788 ffffffff81482b2a 0000000000000000 + 0000000000000000 ffff880110d1b7b8 ffffffff812010ae ffff880007cab800 + ffff88001a060800 ffff88013a899108 ffff880108b84240 ffff880110d1b7c8 +Call Trace: +[] dump_stack+0x52/0x80 +[] check_preemption_disabled+0xce/0xe1 +[] __this_cpu_preempt_check+0x13/0x15 +[] ipmr_queue_xmit+0x647/0x70c +[] ip_mr_forward+0x32f/0x34e +[] ip_mroute_setsockopt+0xe03/0x108c +[] ? get_parent_ip+0x11/0x42 +[] ? pollwake+0x4d/0x51 +[] ? default_wake_function+0x0/0xf +[] ? get_parent_ip+0x11/0x42 +[] ? __wake_up_common+0x45/0x77 +[] ? _raw_spin_unlock_irqrestore+0x1d/0x32 +[] ? __wake_up_sync_key+0x4a/0x53 +[] ? sock_def_readable+0x71/0x75 +[] do_ip_setsockopt+0x9d/0xb55 +[] ? unix_seqpacket_sendmsg+0x3f/0x41 +[] ? sock_sendmsg+0x6d/0x86 +[] ? sockfd_lookup_light+0x12/0x5d +[] ? SyS_sendto+0xf3/0x11b +[] ? new_sync_read+0x82/0xaa +[] compat_ip_setsockopt+0x3b/0x99 +[] compat_raw_setsockopt+0x11/0x32 +[] compat_sock_common_setsockopt+0x18/0x1f +[] compat_SyS_setsockopt+0x1a9/0x1cf +[] compat_SyS_socketcall+0x180/0x1e3 +[] cstar_dispatch+0x7/0x1e + +Signed-off-by: Ani Sinha +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/ipmr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 866ee89..8e8203d 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -1682,8 +1682,8 @@ static inline int ipmr_forward_finish(struct sock *sk, struct sk_buff *skb) + { + struct ip_options *opt = &(IPCB(skb)->opt); + +- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); +- IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); ++ IP_INC_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); ++ IP_ADD_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); + + if (unlikely(opt->optlen)) + ip_forward_options(skb); +@@ -1745,7 +1745,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, + * to blackhole. + */ + +- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS); ++ IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); + ip_rt_put(rt); + goto out_free; + } +-- +2.4.1 + + +From 217a7af11532c12fc19168231216160cbf92adc8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Sun, 1 Nov 2015 01:34:50 +0100 +Subject: [PATCH 07/17] qmi_wwan: fix entry for HP lt4112 LTE/HSPA+ Gobi 4G + Module +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 70910791731b5956171e1bfcad707766b8e18fee ] + +The lt4112 is a HP branded Huawei me906e modem. Like other Huawei +modems, it does not have a fixed interface to function mapping. +Instead it uses a Huawei specific scheme: functions are mapped by +subclass and protocol. + +However, the HP vendor ID is used for modems from many different +manufacturers using different schemes, so we cannot apply a generic +vendor rule like we do for the Huawei vendor ID. + +Replace the previous lt4112 entry pointing to an arbitrary interface +number with a device specific subclass + protocol match. + +Reported-and-tested-by: Muri Nicanor +Tested-by: Martin Hauke +Fixes: bb2bdeb83fb1 ("qmi_wwan: Add support for HP lt4112 LTE/HSPA+ Gobi 4G Modem") +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 2a7c1be..1ba1fdc 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -539,6 +539,10 @@ static const struct usb_device_id products[] = { + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, ++ { /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), ++ .driver_info = (unsigned long)&qmi_wwan_info, ++ }, + + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ +@@ -791,7 +795,6 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ +- {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ + + /* 4. Gobi 1000 devices */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +-- +2.4.1 + + +From 8d81dd753b8725645da63cf78c8d280c27e414a3 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 2 Nov 2015 17:08:19 -0800 +Subject: [PATCH 08/17] sit: fix sit0 percpu double allocations + +[ Upstream commit 4ece9009774596ee3df0acba65a324b7ea79387c ] + +sit0 device allocates its percpu storage twice : +- One time in ipip6_tunnel_init() +- One time in ipip6_fb_tunnel_init() + +Thus we leak 48 bytes per possible cpu per network namespace dismantle. + +ipip6_fb_tunnel_init() can be much simpler and does not +return an error, and should be called after register_netdev() + +Note that ipip6_tunnel_clone_6rd() also needs to be called +after register_netdev() (calling ipip6_tunnel_init()) + +Fixes: ebe084aafb7e ("sit: Use ipip6_tunnel_init as the ndo_init function.") +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Cc: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv6/sit.c | 26 ++++---------------------- + 1 file changed, 4 insertions(+), 22 deletions(-) + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 94428fd..dcccae8 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -1394,34 +1394,20 @@ static int ipip6_tunnel_init(struct net_device *dev) + return 0; + } + +-static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) ++static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) + { + struct ip_tunnel *tunnel = netdev_priv(dev); + struct iphdr *iph = &tunnel->parms.iph; + struct net *net = dev_net(dev); + struct sit_net *sitn = net_generic(net, sit_net_id); + +- tunnel->dev = dev; +- tunnel->net = dev_net(dev); +- + iph->version = 4; + iph->protocol = IPPROTO_IPV6; + iph->ihl = 5; + iph->ttl = 64; + +- dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +- if (!dev->tstats) +- return -ENOMEM; +- +- tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); +- if (!tunnel->dst_cache) { +- free_percpu(dev->tstats); +- return -ENOMEM; +- } +- + dev_hold(dev); + rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); +- return 0; + } + + static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) +@@ -1831,23 +1817,19 @@ static int __net_init sit_init_net(struct net *net) + */ + sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + +- err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); +- if (err) +- goto err_dev_free; +- +- ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); + err = register_netdev(sitn->fb_tunnel_dev); + if (err) + goto err_reg_dev; + ++ ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); ++ ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); ++ + t = netdev_priv(sitn->fb_tunnel_dev); + + strcpy(t->parms.name, sitn->fb_tunnel_dev->name); + return 0; + + err_reg_dev: +- dev_put(sitn->fb_tunnel_dev); +-err_dev_free: + ipip6_dev_free(sitn->fb_tunnel_dev); + err_alloc_dev: + return err; +-- +2.4.1 + + +From 03ebc93ed50c5d98c9f86b5831f537a408935d83 Mon Sep 17 00:00:00 2001 +From: Martin Habets +Date: Mon, 2 Nov 2015 12:51:31 +0000 +Subject: [PATCH 09/17] sfc: push partner queue for skb->xmit_more + +[ Upstream commit b2663a4f30e85ec606b806f5135413e6d5c78d1e ] + +When the IP stack passes SKBs the sfc driver puts them in 2 different TX +queues (called partners), one for checksummed and one for not checksummed. +If the SKB has xmit_more set the driver will delay pushing the work to the +NIC. + +When later it does decide to push the buffers this patch ensures it also +pushes the partner queue, if that also has any delayed work. Before this +fix the work in the partner queue would be left for a long time and cause +a netdev watchdog. + +Fixes: 70b33fb ("sfc: add support for skb->xmit_more") +Reported-by: Jianlin Shi +Signed-off-by: Martin Habets +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/sfc/ef10.c | 4 +++- + drivers/net/ethernet/sfc/farch.c | 4 +++- + drivers/net/ethernet/sfc/net_driver.h | 2 ++ + drivers/net/ethernet/sfc/tx.c | 30 ++++++++++++++++++++++++++++-- + 4 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c +index ff649eb..286cc6b 100644 +--- a/drivers/net/ethernet/sfc/ef10.c ++++ b/drivers/net/ethernet/sfc/ef10.c +@@ -1849,7 +1849,9 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue) + unsigned int write_ptr; + efx_qword_t *txd; + +- BUG_ON(tx_queue->write_count == tx_queue->insert_count); ++ tx_queue->xmit_more_available = false; ++ if (unlikely(tx_queue->write_count == tx_queue->insert_count)) ++ return; + + do { + write_ptr = tx_queue->write_count & tx_queue->ptr_mask; +diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c +index f08266f..5a1c5a8 100644 +--- a/drivers/net/ethernet/sfc/farch.c ++++ b/drivers/net/ethernet/sfc/farch.c +@@ -321,7 +321,9 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue) + unsigned write_ptr; + unsigned old_write_count = tx_queue->write_count; + +- BUG_ON(tx_queue->write_count == tx_queue->insert_count); ++ tx_queue->xmit_more_available = false; ++ if (unlikely(tx_queue->write_count == tx_queue->insert_count)) ++ return; + + do { + write_ptr = tx_queue->write_count & tx_queue->ptr_mask; +diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h +index c530e1c..24038ef 100644 +--- a/drivers/net/ethernet/sfc/net_driver.h ++++ b/drivers/net/ethernet/sfc/net_driver.h +@@ -219,6 +219,7 @@ struct efx_tx_buffer { + * @tso_packets: Number of packets via the TSO xmit path + * @pushes: Number of times the TX push feature has been used + * @pio_packets: Number of times the TX PIO feature has been used ++ * @xmit_more_available: Are any packets waiting to be pushed to the NIC + * @empty_read_count: If the completion path has seen the queue as empty + * and the transmission path has not yet checked this, the value of + * @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0. +@@ -253,6 +254,7 @@ struct efx_tx_queue { + unsigned int tso_packets; + unsigned int pushes; + unsigned int pio_packets; ++ bool xmit_more_available; + /* Statistics to supplement MAC stats */ + unsigned long tx_packets; + +diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c +index 1833a01..67f6afa 100644 +--- a/drivers/net/ethernet/sfc/tx.c ++++ b/drivers/net/ethernet/sfc/tx.c +@@ -431,8 +431,20 @@ finish_packet: + efx_tx_maybe_stop_queue(tx_queue); + + /* Pass off to hardware */ +- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) ++ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) { ++ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue); ++ ++ /* There could be packets left on the partner queue if those ++ * SKBs had skb->xmit_more set. If we do not push those they ++ * could be left for a long time and cause a netdev watchdog. ++ */ ++ if (txq2->xmit_more_available) ++ efx_nic_push_buffers(txq2); ++ + efx_nic_push_buffers(tx_queue); ++ } else { ++ tx_queue->xmit_more_available = skb->xmit_more; ++ } + + tx_queue->tx_packets++; + +@@ -722,6 +734,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue) + tx_queue->read_count = 0; + tx_queue->old_read_count = 0; + tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID; ++ tx_queue->xmit_more_available = false; + + /* Set up TX descriptor ring */ + efx_nic_init_tx(tx_queue); +@@ -747,6 +760,7 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue) + + ++tx_queue->read_count; + } ++ tx_queue->xmit_more_available = false; + netdev_tx_reset_queue(tx_queue->core_txq); + } + +@@ -1302,8 +1316,20 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, + efx_tx_maybe_stop_queue(tx_queue); + + /* Pass off to hardware */ +- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) ++ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) { ++ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue); ++ ++ /* There could be packets left on the partner queue if those ++ * SKBs had skb->xmit_more set. If we do not push those they ++ * could be left for a long time and cause a netdev watchdog. ++ */ ++ if (txq2->xmit_more_available) ++ efx_nic_push_buffers(txq2); ++ + efx_nic_push_buffers(tx_queue); ++ } else { ++ tx_queue->xmit_more_available = skb->xmit_more; ++ } + + tx_queue->tso_bursts++; + return NETDEV_TX_OK; +-- +2.4.1 + + +From 80a7f5cf508c8054c3196e1110efecf5e842f698 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 2 Nov 2015 07:50:07 -0800 +Subject: [PATCH 10/17] net: avoid NULL deref in inet_ctl_sock_destroy() + +[ Upstream commit 8fa677d2706d325d71dab91bf6e6512c05214e37 ] + +Under low memory conditions, tcp_sk_init() and icmp_sk_init() +can both iterate on all possible cpus and call inet_ctl_sock_destroy(), +with eventual NULL pointer. + +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Signed-off-by: David S. Miller +--- + include/net/inet_common.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/inet_common.h b/include/net/inet_common.h +index 279f835..109e3ee 100644 +--- a/include/net/inet_common.h ++++ b/include/net/inet_common.h +@@ -41,7 +41,8 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, + + static inline void inet_ctl_sock_destroy(struct sock *sk) + { +- sock_release(sk->sk_socket); ++ if (sk) ++ sock_release(sk->sk_socket); + } + + #endif +-- +2.4.1 + + +From 4cc1b5dbe087a8b3ab518164fa90c9ab4d63e923 Mon Sep 17 00:00:00 2001 +From: Sabrina Dubroca +Date: Wed, 4 Nov 2015 14:47:53 +0100 +Subject: [PATCH 11/17] ipv6: clean up dev_snmp6 proc entry when we fail to + initialize inet6_dev + +[ Upstream commit 2a189f9e57650e9f310ddf4aad75d66c1233a064 ] + +In ipv6_add_dev, when addrconf_sysctl_register fails, we do not clean up +the dev_snmp6 entry that we have already registered for this device. +Call snmp6_unregister_dev in this case. + +Fixes: a317a2f19da7d ("ipv6: fail early when creating netdev named all or default") +Reported-by: Dmitry Vyukov +Signed-off-by: Sabrina Dubroca +Signed-off-by: David S. Miller +--- + net/ipv6/addrconf.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 36b85bd..dd00828 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -417,6 +417,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) + if (err) { + ipv6_mc_destroy_dev(ndev); + del_timer(&ndev->regen_timer); ++ snmp6_unregister_dev(ndev); + goto err_release; + } + /* protected by rtnl_lock */ +-- +2.4.1 + + +From 31aa0cfdfddba6e487aec78ff1f8fffb8bc3015d Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Tue, 3 Nov 2015 14:32:57 -0800 +Subject: [PATCH 12/17] ipv4: disable BH when changing ip local port range + +[ Upstream commit 4ee3bd4a8c7463cdef0b82ebc33fc94a9170a7e0 ] + +This fixes the following lockdep warning: + + [ INFO: inconsistent lock state ] + 4.3.0-rc7+ #1197 Not tainted + --------------------------------- + inconsistent {IN-SOFTIRQ-R} -> {SOFTIRQ-ON-W} usage. + sysctl/1019 [HC0[0]:SC0[0]:HE1:SE1] takes: + (&(&net->ipv4.ip_local_ports.lock)->seqcount){+.+-..}, at: [] ipv4_local_port_range+0xb4/0x12a + {IN-SOFTIRQ-R} state was registered at: + [] __lock_acquire+0x2f6/0xdf0 + [] lock_acquire+0x11c/0x1a4 + [] inet_get_local_port_range+0x4e/0xae + [] udp_flow_src_port.constprop.40+0x23/0x116 + [] vxlan_xmit_one+0x219/0xa6a + [] vxlan_xmit+0xa6b/0xaa5 + [] dev_hard_start_xmit+0x2ae/0x465 + [] __dev_queue_xmit+0x531/0x633 + [] dev_queue_xmit_sk+0x13/0x15 + [] neigh_resolve_output+0x12f/0x14d + [] ip6_finish_output2+0x344/0x39f + [] ip6_finish_output+0x88/0x8e + [] ip6_output+0x91/0xe5 + [] dst_output_sk+0x47/0x4c + [] NF_HOOK_THRESH.constprop.30+0x38/0x82 + [] mld_sendpack+0x189/0x266 + [] mld_ifc_timer_expire+0x1ef/0x223 + [] call_timer_fn+0xfb/0x28c + [] run_timer_softirq+0x1c7/0x1f1 + +Fixes: b8f1a55639e6 ("udp: Add function to make source port for UDP tunnels") +Cc: Tom Herbert +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +--- + net/ipv4/sysctl_net_ipv4.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 894da3a..ade7737 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -48,14 +48,14 @@ static void set_local_port_range(struct net *net, int range[2]) + { + bool same_parity = !((range[0] ^ range[1]) & 1); + +- write_seqlock(&net->ipv4.ip_local_ports.lock); ++ write_seqlock_bh(&net->ipv4.ip_local_ports.lock); + if (same_parity && !net->ipv4.ip_local_ports.warned) { + net->ipv4.ip_local_ports.warned = true; + pr_err_ratelimited("ip_local_port_range: prefer different parity for start/end values.\n"); + } + net->ipv4.ip_local_ports.range[0] = range[0]; + net->ipv4.ip_local_ports.range[1] = range[1]; +- write_sequnlock(&net->ipv4.ip_local_ports.lock); ++ write_sequnlock_bh(&net->ipv4.ip_local_ports.lock); + } + + /* Validate changes from /proc interface. */ +-- +2.4.1 + + +From d04ea27f9dfc17ef6f031fd001b818b1ac70141d Mon Sep 17 00:00:00 2001 +From: David Ahern +Date: Tue, 3 Nov 2015 15:59:28 -0800 +Subject: [PATCH 13/17] net: Fix prefsrc lookups + +[ Upstream commit e1b8d903c6c3862160d2d5036806a94786c8fc4e ] + +A bug report (https://bugzilla.kernel.org/show_bug.cgi?id=107071) noted +that the follwoing ip command is failing with v4.3: + + $ ip route add 10.248.5.0/24 dev bond0.250 table vlan_250 src 10.248.5.154 + RTNETLINK answers: Invalid argument + +021dd3b8a142d changed the lookup of the given preferred source address to +use the table id passed in, but this assumes the local entries are in the +given table which is not necessarily true for non-VRF use cases. When +validating the preferred source fallback to the local table on failure. + +Fixes: 021dd3b8a142d ("net: Add routes to the table associated with the device") +Signed-off-by: David Ahern +Signed-off-by: David S. Miller +--- + net/ipv4/fib_semantics.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index e966f85..ef5892f 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -864,14 +864,21 @@ static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc) + if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || + fib_prefsrc != cfg->fc_dst) { + u32 tb_id = cfg->fc_table; ++ int rc; + + if (tb_id == RT_TABLE_MAIN) + tb_id = RT_TABLE_LOCAL; + +- if (inet_addr_type_table(cfg->fc_nlinfo.nl_net, +- fib_prefsrc, tb_id) != RTN_LOCAL) { +- return false; ++ rc = inet_addr_type_table(cfg->fc_nlinfo.nl_net, ++ fib_prefsrc, tb_id); ++ ++ if (rc != RTN_LOCAL && tb_id != RT_TABLE_LOCAL) { ++ rc = inet_addr_type_table(cfg->fc_nlinfo.nl_net, ++ fib_prefsrc, RT_TABLE_LOCAL); + } ++ ++ if (rc != RTN_LOCAL) ++ return false; + } + return true; + } +-- +2.4.1 + + +From 79f11d5fe0fd0547c8b1d03166e70f2f6ffae8a8 Mon Sep 17 00:00:00 2001 +From: Tobias Klauser +Date: Wed, 4 Nov 2015 13:49:49 +0100 +Subject: [PATCH 14/17] tun_dst: Fix potential NULL dereference + +[ Upstream commit f63ce5b6fa5e9a0faf7a0e1ef2993a502878c78a ] + +In tun_dst_unclone() the return value of skb_metadata_dst() is checked +for being NULL after it is dereferenced. Fix this by moving the +dereference after the NULL check. + +Found by the Coverity scanner (CID 1338068). + +Fixes: fc4099f17240 ("openvswitch: Fix egress tunnel info.") +Cc: Pravin B Shelar +Signed-off-by: Tobias Klauser +Signed-off-by: David S. Miller +--- + include/net/dst_metadata.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h +index ce00971..6816f0f 100644 +--- a/include/net/dst_metadata.h ++++ b/include/net/dst_metadata.h +@@ -63,12 +63,13 @@ static inline struct metadata_dst *tun_rx_dst(int md_size) + static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb) + { + struct metadata_dst *md_dst = skb_metadata_dst(skb); +- int md_size = md_dst->u.tun_info.options_len; ++ int md_size; + struct metadata_dst *new_md; + + if (!md_dst) + return ERR_PTR(-EINVAL); + ++ md_size = md_dst->u.tun_info.options_len; + new_md = metadata_dst_alloc(md_size, GFP_ATOMIC); + if (!new_md) + return ERR_PTR(-ENOMEM); +-- +2.4.1 + + +From 4a75ef6f762c85d73a76a9466672cf66965d82e2 Mon Sep 17 00:00:00 2001 +From: Francesco Ruggeri +Date: Thu, 5 Nov 2015 08:16:14 -0800 +Subject: [PATCH 15/17] packet: race condition in packet_bind + +[ Upstream commit 30f7ea1c2b5f5fb7462c5ae44fe2e40cb2d6a474 ] + +There is a race conditions between packet_notifier and packet_bind{_spkt}. + +It happens if packet_notifier(NETDEV_UNREGISTER) executes between the +time packet_bind{_spkt} takes a reference on the new netdevice and the +time packet_do_bind sets po->ifindex. +In this case the notification can be missed. +If this happens during a dev_change_net_namespace this can result in the +netdevice to be moved to the new namespace while the packet_sock in the +old namespace still holds a reference on it. When the netdevice is later +deleted in the new namespace the deletion hangs since the packet_sock +is not found in the new namespace' &net->packet.sklist. +It can be reproduced with the script below. + +This patch makes packet_do_bind check again for the presence of the +netdevice in the packet_sock's namespace after the synchronize_net +in unregister_prot_hook. +More in general it also uses the rcu lock for the duration of the bind +to stop dev_change_net_namespace/rollback_registered_many from +going past the synchronize_net following unlist_netdevice, so that +no NETDEV_UNREGISTER notifications can happen on the new netdevice +while the bind is executing. In order to do this some code from +packet_bind{_spkt} is consolidated into packet_do_dev. + +import socket, os, time, sys +proto=7 +realDev='em1' +vlanId=400 +if len(sys.argv) > 1: + vlanId=int(sys.argv[1]) +dev='vlan%d' % vlanId + +os.system('taskset -p 0x10 %d' % os.getpid()) + +s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, proto) +os.system('ip link add link %s name %s type vlan id %d' % + (realDev, dev, vlanId)) +os.system('ip netns add dummy') + +pid=os.fork() + +if pid == 0: + # dev should be moved while packet_do_bind is in synchronize net + os.system('taskset -p 0x20000 %d' % os.getpid()) + os.system('ip link set %s netns dummy' % dev) + os.system('ip netns exec dummy ip link del %s' % dev) + s.close() + sys.exit(0) + +time.sleep(.004) +try: + s.bind(('%s' % dev, proto+1)) +except: + print 'Could not bind socket' + s.close() + os.system('ip netns del dummy') + sys.exit(0) + +os.waitpid(pid, 0) +s.close() +os.system('ip netns del dummy') +sys.exit(0) + +Signed-off-by: Francesco Ruggeri +Signed-off-by: David S. Miller +--- + net/packet/af_packet.c | 80 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 49 insertions(+), 31 deletions(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index aa4b15c..27b2898 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2903,22 +2903,40 @@ static int packet_release(struct socket *sock) + * Attach a packet hook. + */ + +-static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) ++static int packet_do_bind(struct sock *sk, const char *name, int ifindex, ++ __be16 proto) + { + struct packet_sock *po = pkt_sk(sk); + struct net_device *dev_curr; + __be16 proto_curr; + bool need_rehook; ++ struct net_device *dev = NULL; ++ int ret = 0; ++ bool unlisted = false; + +- if (po->fanout) { +- if (dev) +- dev_put(dev); +- ++ if (po->fanout) + return -EINVAL; +- } + + lock_sock(sk); + spin_lock(&po->bind_lock); ++ rcu_read_lock(); ++ ++ if (name) { ++ dev = dev_get_by_name_rcu(sock_net(sk), name); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ } else if (ifindex) { ++ dev = dev_get_by_index_rcu(sock_net(sk), ifindex); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ } ++ ++ if (dev) ++ dev_hold(dev); + + proto_curr = po->prot_hook.type; + dev_curr = po->prot_hook.dev; +@@ -2926,14 +2944,29 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + need_rehook = proto_curr != proto || dev_curr != dev; + + if (need_rehook) { +- unregister_prot_hook(sk, true); ++ if (po->running) { ++ rcu_read_unlock(); ++ __unregister_prot_hook(sk, true); ++ rcu_read_lock(); ++ dev_curr = po->prot_hook.dev; ++ if (dev) ++ unlisted = !dev_get_by_index_rcu(sock_net(sk), ++ dev->ifindex); ++ } + + po->num = proto; + po->prot_hook.type = proto; +- po->prot_hook.dev = dev; + +- po->ifindex = dev ? dev->ifindex : 0; +- packet_cached_dev_assign(po, dev); ++ if (unlikely(unlisted)) { ++ dev_put(dev); ++ po->prot_hook.dev = NULL; ++ po->ifindex = -1; ++ packet_cached_dev_reset(po); ++ } else { ++ po->prot_hook.dev = dev; ++ po->ifindex = dev ? dev->ifindex : 0; ++ packet_cached_dev_assign(po, dev); ++ } + } + if (dev_curr) + dev_put(dev_curr); +@@ -2941,7 +2974,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + if (proto == 0 || !need_rehook) + goto out_unlock; + +- if (!dev || (dev->flags & IFF_UP)) { ++ if (!unlisted && (!dev || (dev->flags & IFF_UP))) { + register_prot_hook(sk); + } else { + sk->sk_err = ENETDOWN; +@@ -2950,9 +2983,10 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + } + + out_unlock: ++ rcu_read_unlock(); + spin_unlock(&po->bind_lock); + release_sock(sk); +- return 0; ++ return ret; + } + + /* +@@ -2964,8 +2998,6 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, + { + struct sock *sk = sock->sk; + char name[15]; +- struct net_device *dev; +- int err = -ENODEV; + + /* + * Check legality +@@ -2975,19 +3007,13 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, + return -EINVAL; + strlcpy(name, uaddr->sa_data, sizeof(name)); + +- dev = dev_get_by_name(sock_net(sk), name); +- if (dev) +- err = packet_do_bind(sk, dev, pkt_sk(sk)->num); +- return err; ++ return packet_do_bind(sk, name, 0, pkt_sk(sk)->num); + } + + static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + { + struct sockaddr_ll *sll = (struct sockaddr_ll *)uaddr; + struct sock *sk = sock->sk; +- struct net_device *dev = NULL; +- int err; +- + + /* + * Check legality +@@ -2998,16 +3024,8 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len + if (sll->sll_family != AF_PACKET) + return -EINVAL; + +- if (sll->sll_ifindex) { +- err = -ENODEV; +- dev = dev_get_by_index(sock_net(sk), sll->sll_ifindex); +- if (dev == NULL) +- goto out; +- } +- err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num); +- +-out: +- return err; ++ return packet_do_bind(sk, NULL, sll->sll_ifindex, ++ sll->sll_protocol ? : pkt_sk(sk)->num); + } + + static struct proto packet_proto = { +-- +2.4.1 + + +From b84e1a71f9b380b8fe8843e5af4c72cad640a1dc Mon Sep 17 00:00:00 2001 +From: Jay Vosburgh +Date: Fri, 6 Nov 2015 17:23:23 -0800 +Subject: [PATCH 16/17] bonding: fix panic on non-ARPHRD_ETHER enslave failure + +[ Upstream commit 40baec225765c54eefa870530dd613bad9829bb7 ] + +Since commit 7d5cd2ce529b, when bond_enslave fails on devices that +are not ARPHRD_ETHER, if needed, it resets the bonding device back to +ARPHRD_ETHER by calling ether_setup. + + Unfortunately, ether_setup clobbers dev->flags, clearing IFF_UP +if the bond device is up, leaving it in a quasi-down state without +having actually gone through dev_close. For bonding, if any periodic +work queue items are active (miimon, arp_interval, etc), those will +remain running, as they are stopped by bond_close. At this point, if +the bonding module is unloaded or the bond is deleted, the system will +panic when the work function is called. + + This panic is resolved by calling dev_close on the bond itself +prior to calling ether_setup. + +Cc: Nikolay Aleksandrov +Signed-off-by: Jay Vosburgh +Fixes: 7d5cd2ce5292 ("bonding: correctly handle bonding type change on enslave failure") +Acked-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +--- + drivers/net/bonding/bond_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 771a449..bcd7bdd 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1749,6 +1749,7 @@ err_undo_flags: + slave_dev->dev_addr)) + eth_hw_addr_random(bond_dev); + if (bond_dev->type != ARPHRD_ETHER) { ++ dev_close(bond_dev); + ether_setup(bond_dev); + bond_dev->flags |= IFF_MASTER; + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; +-- +2.4.1 + + +From b019533c6926b5dd5a7b1d6f8cb8616b51e39297 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 9 Nov 2015 17:51:23 -0800 +Subject: [PATCH 17/17] net: fix a race in dst_release() + +[ Upstream commit d69bbf88c8d0b367cf3e3a052f6daadf630ee566 ] + +Only cpu seeing dst refcount going to 0 can safely +dereference dst->flags. + +Otherwise an other cpu might already have freed the dst. + +Fixes: 27b75c95f10d ("net: avoid RCU for NOCACHE dst") +Reported-by: Greg Thelen +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/core/dst.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/dst.c b/net/core/dst.c +index 0771c8c..d6a5a0b 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -306,7 +306,7 @@ void dst_release(struct dst_entry *dst) + if (unlikely(newrefcnt < 0)) + net_warn_ratelimited("%s: dst:%p refcnt:%d\n", + __func__, dst, newrefcnt); +- if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) ++ if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) + call_rcu(&dst->rcu_head, dst_destroy_rcu); + } + } +-- +2.4.1 +