From: Greg Kroah-Hartman Date: Sat, 16 Apr 2016 17:05:25 +0000 (-0700) Subject: 4.4-stable patches X-Git-Tag: v3.14.67~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dff7f6bc9cd9d5a47310ff851e1bbf697d832b3f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ath9k-fix-buffer-overrun-for-ar9287.patch ax25-add-link-layer-header-validation-function.patch bonding-fix-bond_get_stats.patch bpf-avoid-copying-junk-bytes-in-bpf_get_current_comm.patch bridge-allow-set-bridge-ageing-time-when-switchdev-disabled.patch bridge-allow-zero-ageing-time.patch cdc_ncm-toggle-altsetting-to-force-reset-before-setup.patch farsync-fix-off-by-one-bug-in-fst_add_one.patch ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch ipv4-don-t-do-expensive-useless-work-during-inetdev-destroy.patch ipv4-fix-broadcast-packets-reception.patch ipv4-initialize-flowi4_flags-before-calling-fib_lookup.patch ipv4-l2tp-fix-a-potential-issue-in-l2tp_ip_recv.patch ipv4-only-create-late-gso-skb-if-skb-is-already-set-up-with-checksum_partial.patch ipv6-count-in-extension-headers-in-skb-network_header.patch ipv6-l2tp-fix-a-potential-issue-in-l2tp_ip6_recv.patch ipv6-re-enable-fragment-header-matching-in-ipv6_find_hdr.patch ipv6-udp-fix-udp_mib_ignoredmulti-updates.patch macvtap-always-pass-ethernet-header-in-linear.patch mld-igmp-fix-reserved-tailroom-calculation.patch mlx4-add-missing-braces-in-verify_qp_parameters.patch mlxsw-spectrum-check-requested-ageing-time-is-valid.patch mpls-find_outdev-check-for-err-ptr-in-addition-to-null-check.patch net-bcmgenet-fix-dma-api-length-mismatch.patch net-fix-bridge-multicast-packet-checksum-validation.patch net-fix-use-after-free-in-the-recvmmsg-exit-path.patch net-jme-fix-suspend-resume-on-jmc260.patch net-qca_spi-clear-iff_tx_skb_sharing.patch net-qca_spi-don-t-clear-iff_broadcast.patch net-validate-variable-length-ll-headers.patch net-vrf-remove-direct-access-to-skb-data.patch packet-validate-variable-length-ll-headers.patch ppp-ensure-file-private_data-can-t-be-overridden.patch ppp-release-rtnl-mutex-when-interface-creation-fails.patch ppp-take-reference-on-channels-netns.patch qlcnic-fix-mailbox-completion-handling-during-spurious-interrupt.patch qlcnic-remove-unnecessary-usage-of-atomic_t.patch qlge-fix-receive-packets-drop.patch qmi_wwan-add-d-link-dwm-221-b1-device-id.patch qmi_wwan-add-sierra-wireless-em74xx-device-id.patch rocker-set-fdb-cleanup-timer-according-to-lowest-ageing-time.patch rtnl-fix-msg-size-calculation-in-if_nlmsg_size.patch sctp-lack-the-check-for-ports-in-sctp_v6_cmp_addr.patch sh_eth-advance-rxdesc-later-in-sh_eth_ring_format.patch sh_eth-fix-null-pointer-dereference-in-sh_eth_ring_format.patch tcp-convert-cached-rtt-from-usec-to-jiffies-when-feeding-initial-rto.patch tcp-dccp-remove-obsolete-warn_on-in-icmp-handlers.patch tcp-fix-tcpi_segs_in-after-connection-establishment.patch tipc-revert-tipc-use-existing-sk_write_queue-for-outgoing-packet-chain.patch tun-bpf-fix-suspicious-rcu-usage-in-tun_-attach-detach-_filter.patch tunnel-clear-ipcb-skb-opt-before-dst_link_failure-called.patch tuntap-restore-default-qdisc.patch udp6-fix-udp-ipv6-encap-resubmit-path.patch usbnet-cleanup-after-bind-in-probe.patch vxlan-fix-missing-options_len-update-on-rx-with-collect-metadata.patch xfrm-fix-crash-observed-during-device-unregistration-and-decryption.patch --- diff --git a/queue-4.4/ath9k-fix-buffer-overrun-for-ar9287.patch b/queue-4.4/ath9k-fix-buffer-overrun-for-ar9287.patch new file mode 100644 index 00000000000..0dd1707a2c1 --- /dev/null +++ b/queue-4.4/ath9k-fix-buffer-overrun-for-ar9287.patch @@ -0,0 +1,68 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Arnd Bergmann +Date: Mon, 14 Mar 2016 15:18:36 +0100 +Subject: ath9k: fix buffer overrun for ar9287 + +From: Arnd Bergmann + +[ Upstream commit 83d6f1f15f8cce844b0a131cbc63e444620e48b5 ] + +Code that was added back in 2.6.38 has an obvious overflow +when accessing a static array, and at the time it was added +only a code comment was put in front of it as a reminder +to have it reviewed properly. + +This has not happened, but gcc-6 now points to the specific +overflow: + +drivers/net/wireless/ath/ath9k/eeprom.c: In function 'ath9k_hw_get_gain_boundaries_pdadcs': +drivers/net/wireless/ath/ath9k/eeprom.c:483:44: error: array subscript is above array bounds [-Werror=array-bounds] + maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4]; + ~~~~~~~~~~~~~~~~~~~~~~~~~^~~ + +It turns out that the correct array length exists in the local +'intercepts' variable of this function, so we can just use that +instead of hardcoding '4', so this patch changes all three +instances to use that variable. The other two instances were +already correct, but it's more consistent this way. + +Signed-off-by: Arnd Bergmann +Fixes: 940cd2c12ebf ("ath9k_hw: merge the ar9287 version of ath9k_hw_get_gain_boundaries_pdadcs") +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath9k/eeprom.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -403,10 +403,9 @@ void ath9k_hw_get_gain_boundaries_pdadcs + + if (match) { + if (AR_SREV_9287(ah)) { +- /* FIXME: array overrun? */ + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_9287[idxL].pwrPdg[i][0]; +- maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4]; ++ maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_9287[idxL].pwrPdg[i], + data_9287[idxL].vpdPdg[i], +@@ -416,7 +415,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs + } else if (eeprom_4k) { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_4k[idxL].pwrPdg[i][0]; +- maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4]; ++ maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_4k[idxL].pwrPdg[i], + data_4k[idxL].vpdPdg[i], +@@ -426,7 +425,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs + } else { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_def[idxL].pwrPdg[i][0]; +- maxPwrT4[i] = data_def[idxL].pwrPdg[i][4]; ++ maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_def[idxL].pwrPdg[i], + data_def[idxL].vpdPdg[i], diff --git a/queue-4.4/ax25-add-link-layer-header-validation-function.patch b/queue-4.4/ax25-add-link-layer-header-validation-function.patch new file mode 100644 index 00000000000..52c54a747ed --- /dev/null +++ b/queue-4.4/ax25-add-link-layer-header-validation-function.patch @@ -0,0 +1,49 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Willem de Bruijn +Date: Wed, 9 Mar 2016 21:58:33 -0500 +Subject: ax25: add link layer header validation function + +From: Willem de Bruijn + +[ Upstream commit ea47781c26510e5d97f80f9aceafe9065bd5e3aa ] + +As variable length protocol, AX25 fails link layer header validation +tests based on a minimum length. header_ops.validate allows protocols +to validate headers that are shorter than hard_header_len. Implement +this callback for AX25. + +See also http://comments.gmane.org/gmane.linux.network/401064 + +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ax25/ax25_ip.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/net/ax25/ax25_ip.c ++++ b/net/ax25/ax25_ip.c +@@ -228,8 +228,23 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff + } + #endif + ++static bool ax25_validate_header(const char *header, unsigned int len) ++{ ++ ax25_digi digi; ++ ++ if (!len) ++ return false; ++ ++ if (header[0]) ++ return true; ++ ++ return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL, ++ NULL); ++} ++ + const struct header_ops ax25_header_ops = { + .create = ax25_hard_header, ++ .validate = ax25_validate_header, + }; + + EXPORT_SYMBOL(ax25_header_ops); diff --git a/queue-4.4/bonding-fix-bond_get_stats.patch b/queue-4.4/bonding-fix-bond_get_stats.patch new file mode 100644 index 00000000000..b3c3ff4ceef --- /dev/null +++ b/queue-4.4/bonding-fix-bond_get_stats.patch @@ -0,0 +1,141 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Eric Dumazet +Date: Thu, 17 Mar 2016 17:23:36 -0700 +Subject: bonding: fix bond_get_stats() + +From: Eric Dumazet + +[ Upstream commit fe30937b65354c7fec244caebbdaae68e28ca797 ] + +bond_get_stats() can be called from rtnetlink (with RTNL held) +or from /proc/net/dev seq handler (with RCU held) + +The logic added in commit 5f0c5f73e5ef ("bonding: make global bonding +stats more reliable") kind of assumed only one cpu could run there. + +If multiple threads are reading /proc/net/dev, stats can be really +messed up after a while. + +A second problem is that some fields are 32bit, so we need to properly +handle the wrap around problem. + +Given that RTNL is not always held, we need to use +bond_for_each_slave_rcu(). + +Fixes: 5f0c5f73e5ef ("bonding: make global bonding stats more reliable") +Signed-off-by: Eric Dumazet +Cc: Andy Gospodarek +Cc: Jay Vosburgh +Cc: Veaceslav Falico +Reviewed-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/bonding/bond_main.c | 63 +++++++++++++++++++++------------------- + include/net/bonding.h | 1 + 2 files changed, 35 insertions(+), 29 deletions(-) + +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3260,6 +3260,30 @@ static int bond_close(struct net_device + return 0; + } + ++/* fold stats, assuming all rtnl_link_stats64 fields are u64, but ++ * that some drivers can provide 32bit values only. ++ */ ++static void bond_fold_stats(struct rtnl_link_stats64 *_res, ++ const struct rtnl_link_stats64 *_new, ++ const struct rtnl_link_stats64 *_old) ++{ ++ const u64 *new = (const u64 *)_new; ++ const u64 *old = (const u64 *)_old; ++ u64 *res = (u64 *)_res; ++ int i; ++ ++ for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) { ++ u64 nv = new[i]; ++ u64 ov = old[i]; ++ ++ /* detects if this particular field is 32bit only */ ++ if (((nv | ov) >> 32) == 0) ++ res[i] += (u32)nv - (u32)ov; ++ else ++ res[i] += nv - ov; ++ } ++} ++ + static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, + struct rtnl_link_stats64 *stats) + { +@@ -3268,43 +3292,23 @@ static struct rtnl_link_stats64 *bond_ge + struct list_head *iter; + struct slave *slave; + ++ spin_lock(&bond->stats_lock); + memcpy(stats, &bond->bond_stats, sizeof(*stats)); + +- bond_for_each_slave(bond, slave, iter) { +- const struct rtnl_link_stats64 *sstats = ++ rcu_read_lock(); ++ bond_for_each_slave_rcu(bond, slave, iter) { ++ const struct rtnl_link_stats64 *new = + dev_get_stats(slave->dev, &temp); +- struct rtnl_link_stats64 *pstats = &slave->slave_stats; + +- stats->rx_packets += sstats->rx_packets - pstats->rx_packets; +- stats->rx_bytes += sstats->rx_bytes - pstats->rx_bytes; +- stats->rx_errors += sstats->rx_errors - pstats->rx_errors; +- stats->rx_dropped += sstats->rx_dropped - pstats->rx_dropped; +- +- stats->tx_packets += sstats->tx_packets - pstats->tx_packets;; +- stats->tx_bytes += sstats->tx_bytes - pstats->tx_bytes; +- stats->tx_errors += sstats->tx_errors - pstats->tx_errors; +- stats->tx_dropped += sstats->tx_dropped - pstats->tx_dropped; +- +- stats->multicast += sstats->multicast - pstats->multicast; +- stats->collisions += sstats->collisions - pstats->collisions; +- +- stats->rx_length_errors += sstats->rx_length_errors - pstats->rx_length_errors; +- stats->rx_over_errors += sstats->rx_over_errors - pstats->rx_over_errors; +- stats->rx_crc_errors += sstats->rx_crc_errors - pstats->rx_crc_errors; +- stats->rx_frame_errors += sstats->rx_frame_errors - pstats->rx_frame_errors; +- stats->rx_fifo_errors += sstats->rx_fifo_errors - pstats->rx_fifo_errors; +- stats->rx_missed_errors += sstats->rx_missed_errors - pstats->rx_missed_errors; +- +- stats->tx_aborted_errors += sstats->tx_aborted_errors - pstats->tx_aborted_errors; +- stats->tx_carrier_errors += sstats->tx_carrier_errors - pstats->tx_carrier_errors; +- stats->tx_fifo_errors += sstats->tx_fifo_errors - pstats->tx_fifo_errors; +- stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors - pstats->tx_heartbeat_errors; +- stats->tx_window_errors += sstats->tx_window_errors - pstats->tx_window_errors; ++ bond_fold_stats(stats, new, &slave->slave_stats); + + /* save off the slave stats for the next run */ +- memcpy(pstats, sstats, sizeof(*sstats)); ++ memcpy(&slave->slave_stats, new, sizeof(*new)); + } ++ rcu_read_unlock(); ++ + memcpy(&bond->bond_stats, stats, sizeof(*stats)); ++ spin_unlock(&bond->stats_lock); + + return stats; + } +@@ -4118,6 +4122,7 @@ void bond_setup(struct net_device *bond_ + struct bonding *bond = netdev_priv(bond_dev); + + spin_lock_init(&bond->mode_lock); ++ spin_lock_init(&bond->stats_lock); + bond->params = bonding_defaults; + + /* Initialize pointers */ +--- a/include/net/bonding.h ++++ b/include/net/bonding.h +@@ -214,6 +214,7 @@ struct bonding { + * ALB mode (6) - to sync the use and modifications of its hash table + */ + spinlock_t mode_lock; ++ spinlock_t stats_lock; + u8 send_peer_notif; + u8 igmp_retrans; + #ifdef CONFIG_PROC_FS diff --git a/queue-4.4/bpf-avoid-copying-junk-bytes-in-bpf_get_current_comm.patch b/queue-4.4/bpf-avoid-copying-junk-bytes-in-bpf_get_current_comm.patch new file mode 100644 index 00000000000..29ad32038cf --- /dev/null +++ b/queue-4.4/bpf-avoid-copying-junk-bytes-in-bpf_get_current_comm.patch @@ -0,0 +1,39 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Alexei Starovoitov +Date: Wed, 9 Mar 2016 20:02:33 -0800 +Subject: bpf: avoid copying junk bytes in bpf_get_current_comm() + +From: Alexei Starovoitov + +[ Upstream commit cdc4e47da8f4c32eeb6b2061a8a834f4362a12b7 ] + +Lots of places in the kernel use memcpy(buf, comm, TASK_COMM_LEN); but +the result is typically passed to print("%s", buf) and extra bytes +after zero don't cause any harm. +In bpf the result of bpf_get_current_comm() is used as the part of +map key and was causing spurious hash map mismatches. +Use strlcpy() to guarantee zero-terminated string. +bpf verifier checks that output buffer is zero-initialized, +so even for short task names the output buffer don't have junk bytes. +Note it's not a security concern, since kprobe+bpf is root only. + +Fixes: ffeedafbf023 ("bpf: introduce current->pid, tgid, uid, gid, comm accessors") +Reported-by: Tobias Waldekranz +Signed-off-by: Alexei Starovoitov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/helpers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/bpf/helpers.c ++++ b/kernel/bpf/helpers.c +@@ -166,7 +166,7 @@ static u64 bpf_get_current_comm(u64 r1, + if (!task) + return -EINVAL; + +- memcpy(buf, task->comm, min_t(size_t, size, sizeof(task->comm))); ++ strlcpy(buf, task->comm, min_t(size_t, size, sizeof(task->comm))); + return 0; + } + diff --git a/queue-4.4/bridge-allow-set-bridge-ageing-time-when-switchdev-disabled.patch b/queue-4.4/bridge-allow-set-bridge-ageing-time-when-switchdev-disabled.patch new file mode 100644 index 00000000000..4c19e2b6774 --- /dev/null +++ b/queue-4.4/bridge-allow-set-bridge-ageing-time-when-switchdev-disabled.patch @@ -0,0 +1,32 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Haishuang Yan +Date: Tue, 29 Mar 2016 18:48:08 +0800 +Subject: bridge: Allow set bridge ageing time when switchdev disabled + +From: Haishuang Yan + +[ Upstream commit 5e263f712691615fb802f06c98d7638c378f5d11 ] + +When NET_SWITCHDEV=n, switchdev_port_attr_set will return -EOPNOTSUPP, +we should ignore this error code and continue to set the ageing time. + +Fixes: c62987bbd8a1 ("bridge: push bridge setting ageing_time down to switchdev") +Signed-off-by: Haishuang Yan +Acked-by: Ido Schimmel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_stp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/bridge/br_stp.c ++++ b/net/bridge/br_stp.c +@@ -586,7 +586,7 @@ int br_set_ageing_time(struct net_bridge + int err; + + err = switchdev_port_attr_set(br->dev, &attr); +- if (err) ++ if (err && err != -EOPNOTSUPP) + return err; + + br->ageing_time = t; diff --git a/queue-4.4/bridge-allow-zero-ageing-time.patch b/queue-4.4/bridge-allow-zero-ageing-time.patch new file mode 100644 index 00000000000..2002e18020d --- /dev/null +++ b/queue-4.4/bridge-allow-zero-ageing-time.patch @@ -0,0 +1,68 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Stephen Hemminger +Date: Tue, 8 Mar 2016 12:59:35 -0800 +Subject: bridge: allow zero ageing time + +From: Stephen Hemminger + +[ Upstream commit 4c656c13b254d598e83e586b7b4d36a2043dad85 ] + +This fixes a regression in the bridge ageing time caused by: +commit c62987bbd8a1 ("bridge: push bridge setting ageing_time down to switchdev") + +There are users of Linux bridge which use the feature that if ageing time +is set to 0 it causes entries to never expire. See: + https://www.linuxfoundation.org/collaborate/workgroups/networking/bridge + +For a pure software bridge, it is unnecessary for the code to have +arbitrary restrictions on what values are allowable. + +Signed-off-by: Stephen Hemminger +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/if_bridge.h | 4 ---- + net/bridge/br_stp.c | 11 ++++++++--- + 2 files changed, 8 insertions(+), 7 deletions(-) + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -46,10 +46,6 @@ struct br_ip_list { + #define BR_LEARNING_SYNC BIT(9) + #define BR_PROXYARP_WIFI BIT(10) + +-/* values as per ieee8021QBridgeFdbAgingTime */ +-#define BR_MIN_AGEING_TIME (10 * HZ) +-#define BR_MAX_AGEING_TIME (1000000 * HZ) +- + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + + extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); +--- a/net/bridge/br_stp.c ++++ b/net/bridge/br_stp.c +@@ -567,6 +567,14 @@ int br_set_max_age(struct net_bridge *br + + } + ++/* Set time interval that dynamic forwarding entries live ++ * For pure software bridge, allow values outside the 802.1 ++ * standard specification for special cases: ++ * 0 - entry never ages (all permanant) ++ * 1 - entry disappears (no persistance) ++ * ++ * Offloaded switch entries maybe more restrictive ++ */ + int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) + { + struct switchdev_attr attr = { +@@ -577,9 +585,6 @@ int br_set_ageing_time(struct net_bridge + unsigned long t = clock_t_to_jiffies(ageing_time); + int err; + +- if (t < BR_MIN_AGEING_TIME || t > BR_MAX_AGEING_TIME) +- return -ERANGE; +- + err = switchdev_port_attr_set(br->dev, &attr); + if (err) + return err; diff --git a/queue-4.4/cdc_ncm-toggle-altsetting-to-force-reset-before-setup.patch b/queue-4.4/cdc_ncm-toggle-altsetting-to-force-reset-before-setup.patch new file mode 100644 index 00000000000..7053d255e72 --- /dev/null +++ b/queue-4.4/cdc_ncm-toggle-altsetting-to-force-reset-before-setup.patch @@ -0,0 +1,44 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Thu, 3 Mar 2016 22:20:53 +0100 +Subject: cdc_ncm: toggle altsetting to force reset before setup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= + +[ Upstream commit 48906f62c96cc2cd35753e59310cb70eb08cc6a5 ] + +Some devices will silently fail setup unless they are reset first. +This is necessary even if the data interface is already in +altsetting 0, which it will be when the device is probed for the +first time. Briefly toggling the altsetting forces a function +reset regardless of the initial state. + +This fixes a setup problem observed on a number of Huawei devices, +appearing to operate in NTB-32 mode even if we explicitly set them +to NTB-16 mode. + +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/cdc_ncm.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -794,7 +794,11 @@ int cdc_ncm_bind_common(struct usbnet *d + + iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; + +- /* reset data interface */ ++ /* Reset data interface. Some devices will not reset properly ++ * unless they are configured first. Toggle the altsetting to ++ * force a reset ++ */ ++ usb_set_interface(dev->udev, iface_no, data_altsetting); + temp = usb_set_interface(dev->udev, iface_no, 0); + if (temp) { + dev_dbg(&intf->dev, "set interface failed\n"); diff --git a/queue-4.4/farsync-fix-off-by-one-bug-in-fst_add_one.patch b/queue-4.4/farsync-fix-off-by-one-bug-in-fst_add_one.patch new file mode 100644 index 00000000000..7a8679aaa15 --- /dev/null +++ b/queue-4.4/farsync-fix-off-by-one-bug-in-fst_add_one.patch @@ -0,0 +1,54 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Arnd Bergmann +Date: Mon, 14 Mar 2016 15:18:35 +0100 +Subject: farsync: fix off-by-one bug in fst_add_one + +From: Arnd Bergmann + +[ Upstream commit e725a66c0202b5f36c2f9d59d26a65c53bbf21f7 ] + +gcc-6 finds an out of bounds access in the fst_add_one function +when calculating the end of the mmio area: + +drivers/net/wan/farsync.c: In function 'fst_add_one': +drivers/net/wan/farsync.c:418:53: error: index 2 denotes an offset greater than size of 'u8[2][8192] {aka unsigned char[2][8192]}' [-Werror=array-bounds] + #define BUF_OFFSET(X) (BFM_BASE + offsetof(struct buf_window, X)) + ^ +include/linux/compiler-gcc.h:158:21: note: in definition of macro '__compiler_offsetof' + __builtin_offsetof(a, b) + ^ +drivers/net/wan/farsync.c:418:37: note: in expansion of macro 'offsetof' + #define BUF_OFFSET(X) (BFM_BASE + offsetof(struct buf_window, X)) + ^~~~~~~~ +drivers/net/wan/farsync.c:2519:36: note: in expansion of macro 'BUF_OFFSET' + + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]); + ^~~~~~~~~~ + +The warning is correct, but not critical because this appears +to be a write-only variable that is set by each WAN driver but +never accessed afterwards. + +I'm taking the minimal fix here, using the correct pointer by +pointing 'mem_end' to the last byte inside of the register area +as all other WAN drivers do, rather than the first byte outside of +it. An alternative would be to just remove the mem_end member +entirely. + +Signed-off-by: Arnd Bergmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wan/farsync.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wan/farsync.c ++++ b/drivers/net/wan/farsync.c +@@ -2516,7 +2516,7 @@ fst_add_one(struct pci_dev *pdev, const + dev->mem_start = card->phys_mem + + BUF_OFFSET ( txBuffer[i][0][0]); + dev->mem_end = card->phys_mem +- + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]); ++ + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER - 1][LEN_RX_BUFFER - 1]); + dev->base_addr = card->pci_conf; + dev->irq = card->irq; + diff --git a/queue-4.4/ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch b/queue-4.4/ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch new file mode 100644 index 00000000000..fe621ff5d16 --- /dev/null +++ b/queue-4.4/ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch @@ -0,0 +1,40 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Thadeu Lima de Souza Cascardo +Date: Fri, 1 Apr 2016 17:17:50 -0300 +Subject: ip6_tunnel: set rtnl_link_ops before calling register_netdevice + +From: Thadeu Lima de Souza Cascardo + +[ Upstream commit b6ee376cb0b7fb4e7e07d6cd248bd40436fb9ba6 ] + +When creating an ip6tnl tunnel with ip tunnel, rtnl_link_ops is not set +before ip6_tnl_create2 is called. When register_netdevice is called, there +is no linkinfo attribute in the NEWLINK message because of that. + +Setting rtnl_link_ops before calling register_netdevice fixes that. + +Fixes: 0b112457229d ("ip6tnl: add support of link creation via rtnl") +Signed-off-by: Thadeu Lima de Souza Cascardo +Acked-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_tunnel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -343,12 +343,12 @@ static int ip6_tnl_create2(struct net_de + + t = netdev_priv(dev); + ++ dev->rtnl_link_ops = &ip6_link_ops; + err = register_netdevice(dev); + if (err < 0) + goto out; + + strcpy(t->parms.name, dev->name); +- dev->rtnl_link_ops = &ip6_link_ops; + + dev_hold(dev); + ip6_tnl_link(ip6n, t); diff --git a/queue-4.4/ipv4-don-t-do-expensive-useless-work-during-inetdev-destroy.patch b/queue-4.4/ipv4-don-t-do-expensive-useless-work-during-inetdev-destroy.patch new file mode 100644 index 00000000000..89d61d4d94b --- /dev/null +++ b/queue-4.4/ipv4-don-t-do-expensive-useless-work-during-inetdev-destroy.patch @@ -0,0 +1,93 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: "David S. Miller" +Date: Sun, 13 Mar 2016 23:28:00 -0400 +Subject: ipv4: Don't do expensive useless work during inetdev destroy. + +From: "David S. Miller" + +[ Upstream commit fbd40ea0180a2d328c5adc61414dc8bab9335ce2 ] + +When an inetdev is destroyed, every address assigned to the interface +is removed. And in this scenerio we do two pointless things which can +be very expensive if the number of assigned interfaces is large: + +1) Address promotion. We are deleting all addresses, so there is no + point in doing this. + +2) A full nf conntrack table purge for every address. We only need to + do this once, as is already caught by the existing + masq_dev_notifier so masq_inet_event() can skip this. + +Reported-by: Solar Designer +Signed-off-by: David S. Miller +Tested-by: Cyrill Gorcunov +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/devinet.c | 4 ++++ + net/ipv4/fib_frontend.c | 4 ++++ + net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 12 ++++++++++-- + 3 files changed, 18 insertions(+), 2 deletions(-) + +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -334,6 +334,9 @@ static void __inet_del_ifa(struct in_dev + + ASSERT_RTNL(); + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* 1. Deleting primary ifaddr forces deletion all secondaries + * unless alias promotion is set + **/ +@@ -380,6 +383,7 @@ static void __inet_del_ifa(struct in_dev + fib_del_ifaddr(ifa, ifa1); + } + ++no_promotions: + /* 2. Unlink it */ + + *ifap = ifa1->ifa_next; +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -922,6 +922,9 @@ void fib_del_ifaddr(struct in_ifaddr *if + subnet = 1; + } + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* Deletion is more complicated than add. + * We should take care of not to delete too much :-) + * +@@ -997,6 +1000,7 @@ void fib_del_ifaddr(struct in_ifaddr *if + } + } + ++no_promotions: + if (!(ok & BRD_OK)) + fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); + if (subnet && ifa->ifa_prefixlen < 31) { +--- a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c ++++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +@@ -108,10 +108,18 @@ static int masq_inet_event(struct notifi + unsigned long event, + void *ptr) + { +- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; ++ struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev; + struct netdev_notifier_info info; + +- netdev_notifier_info_init(&info, dev); ++ /* The masq_dev_notifier will catch the case of the device going ++ * down. So if the inetdev is dead and being destroyed we have ++ * no work to do. Otherwise this is an individual address removal ++ * and we have to perform the flush. ++ */ ++ if (idev->dead) ++ return NOTIFY_DONE; ++ ++ netdev_notifier_info_init(&info, idev->dev); + return masq_device_event(this, event, &info); + } + diff --git a/queue-4.4/ipv4-fix-broadcast-packets-reception.patch b/queue-4.4/ipv4-fix-broadcast-packets-reception.patch new file mode 100644 index 00000000000..c9904276e7a --- /dev/null +++ b/queue-4.4/ipv4-fix-broadcast-packets-reception.patch @@ -0,0 +1,46 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Paolo Abeni +Date: Tue, 22 Mar 2016 09:19:38 +0100 +Subject: ipv4: fix broadcast packets reception + +From: Paolo Abeni + +[ Upstream commit ad0ea1989cc4d5905941d0a9e62c63ad6d859cef ] + +Currently, ingress ipv4 broadcast datagrams are dropped since, +in udp_v4_early_demux(), ip_check_mc_rcu() is invoked even on +bcast packets. + +This patch addresses the issue, invoking ip_check_mc_rcu() +only for mcast packets. + +Fixes: 6e5403093261 ("ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()") +Signed-off-by: Paolo Abeni +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/udp.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1990,10 +1990,14 @@ void udp_v4_early_demux(struct sk_buff * + if (!in_dev) + return; + +- ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, +- iph->protocol); +- if (!ours) +- return; ++ /* we are supposed to accept bcast packets */ ++ if (skb->pkt_type == PACKET_MULTICAST) { ++ ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, ++ iph->protocol); ++ if (!ours) ++ return; ++ } ++ + sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, + uh->source, iph->saddr, dif); + } else if (skb->pkt_type == PACKET_HOST) { diff --git a/queue-4.4/ipv4-initialize-flowi4_flags-before-calling-fib_lookup.patch b/queue-4.4/ipv4-initialize-flowi4_flags-before-calling-fib_lookup.patch new file mode 100644 index 00000000000..812cb7de75b --- /dev/null +++ b/queue-4.4/ipv4-initialize-flowi4_flags-before-calling-fib_lookup.patch @@ -0,0 +1,62 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Lance Richardson +Date: Tue, 22 Mar 2016 14:56:57 -0400 +Subject: ipv4: initialize flowi4_flags before calling fib_lookup() + +From: Lance Richardson + +[ Upstream commit 4cfc86f3dae6ca38ed49cdd78f458a03d4d87992 ] + +Field fl4.flowi4_flags is not initialized in fib_compute_spec_dst() +before calling fib_lookup(), which means fib_table_lookup() is +using non-deterministic data at this line: + + if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) { + +Fix by initializing the entire fl4 structure, which will prevent +similar issues as fields are added in the future by ensuring that +all fields are initialized to zero unless explicitly initialized +to another value. + +Fixes: 58189ca7b2741 ("net: Fix vti use case with oif in dst lookups") +Suggested-by: David Ahern +Signed-off-by: Lance Richardson +Acked-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/fib_frontend.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -280,7 +280,6 @@ __be32 fib_compute_spec_dst(struct sk_bu + struct in_device *in_dev; + struct fib_result res; + struct rtable *rt; +- struct flowi4 fl4; + struct net *net; + int scope; + +@@ -296,14 +295,13 @@ __be32 fib_compute_spec_dst(struct sk_bu + + scope = RT_SCOPE_UNIVERSE; + if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { +- fl4.flowi4_oif = 0; +- fl4.flowi4_iif = LOOPBACK_IFINDEX; +- fl4.daddr = ip_hdr(skb)->saddr; +- fl4.saddr = 0; +- fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); +- fl4.flowi4_scope = scope; +- fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; +- fl4.flowi4_tun_key.tun_id = 0; ++ struct flowi4 fl4 = { ++ .flowi4_iif = LOOPBACK_IFINDEX, ++ .daddr = ip_hdr(skb)->saddr, ++ .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), ++ .flowi4_scope = scope, ++ .flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0, ++ }; + if (!fib_lookup(net, &fl4, &res, 0)) + return FIB_RES_PREFSRC(net, res); + } else { diff --git a/queue-4.4/ipv4-l2tp-fix-a-potential-issue-in-l2tp_ip_recv.patch b/queue-4.4/ipv4-l2tp-fix-a-potential-issue-in-l2tp_ip_recv.patch new file mode 100644 index 00000000000..01f78192846 --- /dev/null +++ b/queue-4.4/ipv4-l2tp-fix-a-potential-issue-in-l2tp_ip_recv.patch @@ -0,0 +1,46 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Haishuang Yan +Date: Sun, 3 Apr 2016 22:09:23 +0800 +Subject: ipv4: l2tp: fix a potential issue in l2tp_ip_recv + +From: Haishuang Yan + +[ Upstream commit 5745b8232e942abd5e16e85fa9b27cc21324acf0 ] + +pskb_may_pull() can change skb->data, so we have to load ptr/optr at the +right place. + +Signed-off-by: Haishuang Yan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ip.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -123,12 +123,11 @@ static int l2tp_ip_recv(struct sk_buff * + struct l2tp_tunnel *tunnel = NULL; + int length; + +- /* Point to L2TP header */ +- optr = ptr = skb->data; +- + if (!pskb_may_pull(skb, 4)) + goto discard; + ++ /* Point to L2TP header */ ++ optr = ptr = skb->data; + session_id = ntohl(*((__be32 *) ptr)); + ptr += 4; + +@@ -156,6 +155,9 @@ static int l2tp_ip_recv(struct sk_buff * + if (!pskb_may_pull(skb, length)) + goto discard; + ++ /* Point to L2TP header */ ++ optr = ptr = skb->data; ++ ptr += 4; + pr_debug("%s: ip recv\n", tunnel->name); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); + } diff --git a/queue-4.4/ipv4-only-create-late-gso-skb-if-skb-is-already-set-up-with-checksum_partial.patch b/queue-4.4/ipv4-only-create-late-gso-skb-if-skb-is-already-set-up-with-checksum_partial.patch new file mode 100644 index 00000000000..806e2b57391 --- /dev/null +++ b/queue-4.4/ipv4-only-create-late-gso-skb-if-skb-is-already-set-up-with-checksum_partial.patch @@ -0,0 +1,51 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: Hannes Frederic Sowa +Date: Mon, 22 Feb 2016 18:43:25 +0100 +Subject: ipv4: only create late gso-skb if skb is already set up with CHECKSUM_PARTIAL + +From: Hannes Frederic Sowa + +[ Upstream commit a8c4a2522a0808c5c2143612909717d1115c40cf ] + +Otherwise we break the contract with GSO to only pass CHECKSUM_PARTIAL +skbs down. This can easily happen with UDP+IPv4 sockets with the first +MSG_MORE write smaller than the MTU, second write is a sendfile. + +Returning -EOPNOTSUPP lets the callers fall back into normal sendmsg path, +were we calculate the checksum manually during copying. + +Commit d749c9cbffd6 ("ipv4: no CHECKSUM_PARTIAL on MSG_MORE corked +sockets") started to exposes this bug. + +Fixes: d749c9cbffd6 ("ipv4: no CHECKSUM_PARTIAL on MSG_MORE corked sockets") +Reported-by: Jiri Benc +Cc: Jiri Benc +Reported-by: Wakko Warner +Cc: Wakko Warner +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_output.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1237,13 +1237,16 @@ ssize_t ip_append_page(struct sock *sk, + if (!skb) + return -EINVAL; + +- cork->length += size; + if ((size + skb->len > mtu) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO)) { ++ if (skb->ip_summed != CHECKSUM_PARTIAL) ++ return -EOPNOTSUPP; ++ + skb_shinfo(skb)->gso_size = mtu - fragheaderlen; + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + } ++ cork->length += size; + + while (size > 0) { + if (skb_is_gso(skb)) { diff --git a/queue-4.4/ipv6-count-in-extension-headers-in-skb-network_header.patch b/queue-4.4/ipv6-count-in-extension-headers-in-skb-network_header.patch new file mode 100644 index 00000000000..99722ef0619 --- /dev/null +++ b/queue-4.4/ipv6-count-in-extension-headers-in-skb-network_header.patch @@ -0,0 +1,81 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Jakub Sitnicki +Date: Tue, 5 Apr 2016 18:41:08 +0200 +Subject: ipv6: Count in extension headers in skb->network_header + +From: Jakub Sitnicki + +[ Upstream commit 3ba3458fb9c050718b95275a3310b74415e767e2 ] + +When sending a UDPv6 message longer than MTU, account for the length +of fragmentable IPv6 extension headers in skb->network_header offset. +Same as we do in alloc_new_skb path in __ip6_append_data(). + +This ensures that later on __ip6_make_skb() will make space in +headroom for fragmentable extension headers: + + /* move skb->data to ip header from ext header */ + if (skb->data < skb_network_header(skb)) + __skb_pull(skb, skb_network_offset(skb)); + +Prevents a splat due to skb_under_panic: + +skbuff: skb_under_panic: text:ffffffff8143397b len:2126 put:14 \ +head:ffff880005bacf50 data:ffff880005bacf4a tail:0x48 end:0xc0 dev:lo +------------[ cut here ]------------ +kernel BUG at net/core/skbuff.c:104! +invalid opcode: 0000 [#1] KASAN +CPU: 0 PID: 160 Comm: reproducer Not tainted 4.6.0-rc2 #65 +[...] +Call Trace: + [] skb_push+0x79/0x80 + [] eth_header+0x2b/0x100 + [] neigh_resolve_output+0x210/0x310 + [] ip6_finish_output2+0x4a7/0x7c0 + [] ip6_output+0x16a/0x280 + [] ip6_local_out+0xb1/0xf0 + [] ip6_send_skb+0x45/0xd0 + [] udp_v6_send_skb+0x246/0x5d0 + [] udpv6_sendmsg+0xa6e/0x1090 +[...] + +Reported-by: Ji Jianwen +Signed-off-by: Jakub Sitnicki +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_output.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1091,8 +1091,8 @@ static inline int ip6_ufo_append_data(st + int getfrag(void *from, char *to, int offset, int len, + int odd, struct sk_buff *skb), + void *from, int length, int hh_len, int fragheaderlen, +- int transhdrlen, int mtu, unsigned int flags, +- const struct flowi6 *fl6) ++ int exthdrlen, int transhdrlen, int mtu, ++ unsigned int flags, const struct flowi6 *fl6) + + { + struct sk_buff *skb; +@@ -1117,7 +1117,7 @@ static inline int ip6_ufo_append_data(st + skb_put(skb, fragheaderlen + transhdrlen); + + /* initialize network header pointer */ +- skb_reset_network_header(skb); ++ skb_set_network_header(skb, exthdrlen); + + /* initialize protocol header pointer */ + skb->transport_header = skb->network_header + fragheaderlen; +@@ -1359,7 +1359,7 @@ emsgsize: + (rt->dst.dev->features & NETIF_F_UFO) && + (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) { + err = ip6_ufo_append_data(sk, queue, getfrag, from, length, +- hh_len, fragheaderlen, ++ hh_len, fragheaderlen, exthdrlen, + transhdrlen, mtu, flags, fl6); + if (err) + goto error; diff --git a/queue-4.4/ipv6-l2tp-fix-a-potential-issue-in-l2tp_ip6_recv.patch b/queue-4.4/ipv6-l2tp-fix-a-potential-issue-in-l2tp_ip6_recv.patch new file mode 100644 index 00000000000..5bb05846ef8 --- /dev/null +++ b/queue-4.4/ipv6-l2tp-fix-a-potential-issue-in-l2tp_ip6_recv.patch @@ -0,0 +1,46 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Haishuang Yan +Date: Sun, 3 Apr 2016 22:09:24 +0800 +Subject: ipv6: l2tp: fix a potential issue in l2tp_ip6_recv + +From: Haishuang Yan + +[ Upstream commit be447f305494e019dfc37ea4cdf3b0e4200b4eba ] + +pskb_may_pull() can change skb->data, so we have to load ptr/optr at the +right place. + +Signed-off-by: Haishuang Yan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ip6.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -135,12 +135,11 @@ static int l2tp_ip6_recv(struct sk_buff + struct l2tp_tunnel *tunnel = NULL; + int length; + +- /* Point to L2TP header */ +- optr = ptr = skb->data; +- + if (!pskb_may_pull(skb, 4)) + goto discard; + ++ /* Point to L2TP header */ ++ optr = ptr = skb->data; + session_id = ntohl(*((__be32 *) ptr)); + ptr += 4; + +@@ -168,6 +167,9 @@ static int l2tp_ip6_recv(struct sk_buff + if (!pskb_may_pull(skb, length)) + goto discard; + ++ /* Point to L2TP header */ ++ optr = ptr = skb->data; ++ ptr += 4; + pr_debug("%s: ip recv\n", tunnel->name); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); + } diff --git a/queue-4.4/ipv6-re-enable-fragment-header-matching-in-ipv6_find_hdr.patch b/queue-4.4/ipv6-re-enable-fragment-header-matching-in-ipv6_find_hdr.patch new file mode 100644 index 00000000000..13a65bd01fe --- /dev/null +++ b/queue-4.4/ipv6-re-enable-fragment-header-matching-in-ipv6_find_hdr.patch @@ -0,0 +1,47 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Florian Westphal +Date: Tue, 1 Mar 2016 16:15:16 +0100 +Subject: ipv6: re-enable fragment header matching in ipv6_find_hdr + +From: Florian Westphal + +[ Upstream commit 5d150a985520bbe3cb2aa1ceef24a7e32f20c15f ] + +When ipv6_find_hdr is used to find a fragment header +(caller specifies target NEXTHDR_FRAGMENT) we erronously return +-ENOENT for all fragments with nonzero offset. + +Before commit 9195bb8e381d, when target was specified, we did not +enter the exthdr walk loop as nexthdr == target so this used to work. + +Now we do (so we can skip empty route headers). When we then stumble upon +a frag with nonzero frag_off we must return -ENOENT ("header not found") +only if the caller did not specifically request NEXTHDR_FRAGMENT. + +This allows nfables exthdr expression to match ipv6 fragments, e.g. via + +nft add rule ip6 filter input frag frag-off gt 0 + +Fixes: 9195bb8e381d ("ipv6: improve ipv6_find_hdr() to skip empty routing headers") +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/exthdrs_core.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/net/ipv6/exthdrs_core.c ++++ b/net/ipv6/exthdrs_core.c +@@ -257,7 +257,11 @@ int ipv6_find_hdr(const struct sk_buff * + *fragoff = _frag_off; + return hp->nexthdr; + } +- return -ENOENT; ++ if (!found) ++ return -ENOENT; ++ if (fragoff) ++ *fragoff = _frag_off; ++ break; + } + hdrlen = 8; + } else if (nexthdr == NEXTHDR_AUTH) { diff --git a/queue-4.4/ipv6-udp-fix-udp_mib_ignoredmulti-updates.patch b/queue-4.4/ipv6-udp-fix-udp_mib_ignoredmulti-updates.patch new file mode 100644 index 00000000000..5159f174e96 --- /dev/null +++ b/queue-4.4/ipv6-udp-fix-udp_mib_ignoredmulti-updates.patch @@ -0,0 +1,34 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Eric Dumazet +Date: Tue, 29 Mar 2016 08:43:41 -0700 +Subject: ipv6: udp: fix UDP_MIB_IGNOREDMULTI updates + +From: Eric Dumazet + +[ Upstream commit 2d4212261fdf13e29728ddb5ea9d60c342cc92b5 ] + +IPv6 counters updates use a different macro than IPv4. + +Fixes: 36cbb2452cbaf ("udp: Increment UDP_MIB_IGNOREDMULTI for arriving unmatched multicasts") +Signed-off-by: Eric Dumazet +Cc: Rick Jones +Cc: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/udp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -837,8 +837,8 @@ start_lookup: + flush_stack(stack, count, skb, count - 1); + } else { + if (!inner_flushed) +- UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, +- proto == IPPROTO_UDPLITE); ++ UDP6_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, ++ proto == IPPROTO_UDPLITE); + consume_skb(skb); + } + return 0; diff --git a/queue-4.4/macvtap-always-pass-ethernet-header-in-linear.patch b/queue-4.4/macvtap-always-pass-ethernet-header-in-linear.patch new file mode 100644 index 00000000000..1a499cf0573 --- /dev/null +++ b/queue-4.4/macvtap-always-pass-ethernet-header-in-linear.patch @@ -0,0 +1,54 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Willem de Bruijn +Date: Tue, 8 Mar 2016 15:18:54 -0500 +Subject: macvtap: always pass ethernet header in linear + +From: Willem de Bruijn + +[ Upstream commit 8e2ad4113ce4671686740f808ff2795395c39eef ] + +The stack expects link layer headers in the skb linear section. +Macvtap can create skbs with llheader in frags in edge cases: +when (IFF_VNET_HDR is off or vnet_hdr.hdr_len < ETH_HLEN) and +prepad + len > PAGE_SIZE and vnet_hdr.flags has no or bad csum. + +Add checks to ensure linear is always at least ETH_HLEN. +At this point, len is already ensured to be >= ETH_HLEN. + +For backwards compatiblity, rounds up short vnet_hdr.hdr_len. +This differs from tap and packet, which return an error. + +Fixes b9fb9ee07e67 ("macvtap: add GSO/csum offload support") +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/macvtap.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -760,6 +760,8 @@ static ssize_t macvtap_get_user(struct m + macvtap16_to_cpu(q, vnet_hdr.hdr_len) : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; ++ else if (copylen < ETH_HLEN) ++ copylen = ETH_HLEN; + linear = copylen; + i = *from; + iov_iter_advance(&i, copylen); +@@ -769,10 +771,11 @@ static ssize_t macvtap_get_user(struct m + + if (!zerocopy) { + copylen = len; +- if (macvtap16_to_cpu(q, vnet_hdr.hdr_len) > good_linear) ++ linear = macvtap16_to_cpu(q, vnet_hdr.hdr_len); ++ if (linear > good_linear) + linear = good_linear; +- else +- linear = macvtap16_to_cpu(q, vnet_hdr.hdr_len); ++ else if (linear < ETH_HLEN) ++ linear = ETH_HLEN; + } + + skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, diff --git a/queue-4.4/mld-igmp-fix-reserved-tailroom-calculation.patch b/queue-4.4/mld-igmp-fix-reserved-tailroom-calculation.patch new file mode 100644 index 00000000000..ebf98f1d758 --- /dev/null +++ b/queue-4.4/mld-igmp-fix-reserved-tailroom-calculation.patch @@ -0,0 +1,118 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Benjamin Poirier +Date: Mon, 29 Feb 2016 15:03:33 -0800 +Subject: mld, igmp: Fix reserved tailroom calculation + +From: Benjamin Poirier + +[ Upstream commit 1837b2e2bcd23137766555a63867e649c0b637f0 ] + +The current reserved_tailroom calculation fails to take hlen and tlen into +account. + +skb: +[__hlen__|__data____________|__tlen___|__extra__] +^ ^ +head skb_end_offset + +In this representation, hlen + data + tlen is the size passed to alloc_skb. +"extra" is the extra space made available in __alloc_skb because of +rounding up by kmalloc. We can reorder the representation like so: + +[__hlen__|__data____________|__extra__|__tlen___] +^ ^ +head skb_end_offset + +The maximum space available for ip headers and payload without +fragmentation is min(mtu, data + extra). Therefore, +reserved_tailroom += data + extra + tlen - min(mtu, data + extra) += skb_end_offset - hlen - min(mtu, skb_end_offset - hlen - tlen) += skb_tailroom - min(mtu, skb_tailroom - tlen) ; after skb_reserve(hlen) + +Compare the second line to the current expression: +reserved_tailroom = skb_end_offset - min(mtu, skb_end_offset) +and we can see that hlen and tlen are not taken into account. + +The min() in the third line can be expanded into: +if mtu < skb_tailroom - tlen: + reserved_tailroom = skb_tailroom - mtu +else: + reserved_tailroom = tlen + +Depending on hlen, tlen, mtu and the number of multicast address records, +the current code may output skbs that have less tailroom than +dev->needed_tailroom or it may output more skbs than needed because not all +space available is used. + +Fixes: 4c672e4b ("ipv6: mld: fix add_grhead skb_over_panic for devs with large MTUs") +Signed-off-by: Benjamin Poirier +Acked-by: Hannes Frederic Sowa +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 24 ++++++++++++++++++++++++ + net/ipv4/igmp.c | 3 +-- + net/ipv6/mcast.c | 3 +-- + 3 files changed, 26 insertions(+), 4 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1908,6 +1908,30 @@ static inline void skb_reserve(struct sk + skb->tail += len; + } + ++/** ++ * skb_tailroom_reserve - adjust reserved_tailroom ++ * @skb: buffer to alter ++ * @mtu: maximum amount of headlen permitted ++ * @needed_tailroom: minimum amount of reserved_tailroom ++ * ++ * Set reserved_tailroom so that headlen can be as large as possible but ++ * not larger than mtu and tailroom cannot be smaller than ++ * needed_tailroom. ++ * The required headroom should already have been reserved before using ++ * this function. ++ */ ++static inline void skb_tailroom_reserve(struct sk_buff *skb, unsigned int mtu, ++ unsigned int needed_tailroom) ++{ ++ SKB_LINEAR_ASSERT(skb); ++ if (mtu < skb_tailroom(skb) - needed_tailroom) ++ /* use at most mtu */ ++ skb->reserved_tailroom = skb_tailroom(skb) - mtu; ++ else ++ /* use up to all available space */ ++ skb->reserved_tailroom = needed_tailroom; ++} ++ + #define ENCAP_TYPE_ETHER 0 + #define ENCAP_TYPE_IPPROTO 1 + +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -356,9 +356,8 @@ static struct sk_buff *igmpv3_newpack(st + skb_dst_set(skb, &rt->dst); + skb->dev = dev; + +- skb->reserved_tailroom = skb_end_offset(skb) - +- min(mtu, skb_end_offset(skb)); + skb_reserve(skb, hlen); ++ skb_tailroom_reserve(skb, mtu, tlen); + + skb_reset_network_header(skb); + pip = ip_hdr(skb); +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@ -1574,9 +1574,8 @@ static struct sk_buff *mld_newpack(struc + return NULL; + + skb->priority = TC_PRIO_CONTROL; +- skb->reserved_tailroom = skb_end_offset(skb) - +- min(mtu, skb_end_offset(skb)); + skb_reserve(skb, hlen); ++ skb_tailroom_reserve(skb, mtu, tlen); + + if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { + /* : diff --git a/queue-4.4/mlx4-add-missing-braces-in-verify_qp_parameters.patch b/queue-4.4/mlx4-add-missing-braces-in-verify_qp_parameters.patch new file mode 100644 index 00000000000..feeddde34b0 --- /dev/null +++ b/queue-4.4/mlx4-add-missing-braces-in-verify_qp_parameters.patch @@ -0,0 +1,51 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Arnd Bergmann +Date: Mon, 14 Mar 2016 15:18:34 +0100 +Subject: mlx4: add missing braces in verify_qp_parameters + +From: Arnd Bergmann + +[ Upstream commit baefd7015cdb304ce6c94f9679d0486c71954766 ] + +The implementation of QP paravirtualization back in linux-3.7 included +some code that looks very dubious, and gcc-6 has grown smart enough +to warn about it: + +drivers/net/ethernet/mellanox/mlx4/resource_tracker.c: In function 'verify_qp_parameters': +drivers/net/ethernet/mellanox/mlx4/resource_tracker.c:3154:5: error: statement is indented as if it were guarded by... [-Werror=misleading-indentation] + if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) { + ^~ +drivers/net/ethernet/mellanox/mlx4/resource_tracker.c:3144:4: note: ...this 'if' clause, but it is not + if (slave != mlx4_master_func_num(dev)) + +>From looking at the context, I'm reasonably sure that the indentation +is correct but that it should have contained curly braces from the +start, as the update_gid() function in the same patch correctly does. + +Signed-off-by: Arnd Bergmann +Fixes: 54679e148287 ("mlx4: Implement QP paravirtualization and maintain phys_pkey_cache for smp_snoop") +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c ++++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +@@ -3132,7 +3132,7 @@ static int verify_qp_parameters(struct m + case QP_TRANS_RTS2RTS: + case QP_TRANS_SQD2SQD: + case QP_TRANS_SQD2RTS: +- if (slave != mlx4_master_func_num(dev)) ++ if (slave != mlx4_master_func_num(dev)) { + if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) { + port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1; + if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) +@@ -3151,6 +3151,7 @@ static int verify_qp_parameters(struct m + if (qp_ctx->alt_path.mgid_index >= num_gids) + return -EINVAL; + } ++ } + break; + default: + break; diff --git a/queue-4.4/mlxsw-spectrum-check-requested-ageing-time-is-valid.patch b/queue-4.4/mlxsw-spectrum-check-requested-ageing-time-is-valid.patch new file mode 100644 index 00000000000..8ef096bcb72 --- /dev/null +++ b/queue-4.4/mlxsw-spectrum-check-requested-ageing-time-is-valid.patch @@ -0,0 +1,56 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Ido Schimmel +Date: Tue, 8 Mar 2016 12:59:33 -0800 +Subject: mlxsw: spectrum: Check requested ageing time is valid + +From: Ido Schimmel + +[ Upstream commit 869f63a4d28144c03c8f4a4c0d1e8f31f8c11a10 ] + +Commit c62987bbd8a1 ("bridge: push bridge setting ageing_time down to +switchdev") added a check for minimum and maximum ageing time, but this +breaks existing behaviour where one can set ageing time to 0 for a +non-learning bridge. + +Push this check down to the driver and allow the check in the bridge +layer to be removed. Currently ageing time 0 is refused by the driver, +but we can later add support for this functionality. + +Signed-off-by: Ido Schimmel +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 ++ + drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 9 +++++++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +@@ -61,6 +61,8 @@ struct mlxsw_sp { + #define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100 + unsigned int interval; /* ms */ + } fdb_notify; ++#define MLXSW_SP_MIN_AGEING_TIME 10 ++#define MLXSW_SP_MAX_AGEING_TIME 1000000 + #define MLXSW_SP_DEFAULT_AGEING_TIME 300 + u32 ageing_time; + struct { +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +@@ -232,8 +232,13 @@ static int mlxsw_sp_port_attr_br_ageing_ + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t); + u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000; + +- if (switchdev_trans_ph_prepare(trans)) +- return 0; ++ if (switchdev_trans_ph_prepare(trans)) { ++ if (ageing_time < MLXSW_SP_MIN_AGEING_TIME || ++ ageing_time > MLXSW_SP_MAX_AGEING_TIME) ++ return -ERANGE; ++ else ++ return 0; ++ } + + return mlxsw_sp_ageing_set(mlxsw_sp, ageing_time); + } diff --git a/queue-4.4/mpls-find_outdev-check-for-err-ptr-in-addition-to-null-check.patch b/queue-4.4/mpls-find_outdev-check-for-err-ptr-in-addition-to-null-check.patch new file mode 100644 index 00000000000..c1d496cff89 --- /dev/null +++ b/queue-4.4/mpls-find_outdev-check-for-err-ptr-in-addition-to-null-check.patch @@ -0,0 +1,112 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Roopa Prabhu +Date: Thu, 7 Apr 2016 21:28:38 -0700 +Subject: mpls: find_outdev: check for err ptr in addition to NULL check + +From: Roopa Prabhu + +[ Upstream commit 94a57f1f8a9de90ab4b0f8748361ff8be706c80c ] + +find_outdev calls inet{,6}_fib_lookup_dev() or dev_get_by_index() to +find the output device. In case of an error, inet{,6}_fib_lookup_dev() +returns error pointer and dev_get_by_index() returns NULL. But the function +only checks for NULL and thus can end up calling dev_put on an ERR_PTR. +This patch adds an additional check for err ptr after the NULL check. + +Before: Trying to add an mpls route with no oif from user, no available +path to 10.1.1.8 and no default route: +$ip -f mpls route add 100 as 200 via inet 10.1.1.8 +[ 822.337195] BUG: unable to handle kernel NULL pointer dereference at +00000000000003a3 +[ 822.340033] IP: [] mpls_nh_assign_dev+0x10b/0x182 +[ 822.340033] PGD 1db38067 PUD 1de9e067 PMD 0 +[ 822.340033] Oops: 0000 [#1] SMP +[ 822.340033] Modules linked in: +[ 822.340033] CPU: 0 PID: 11148 Comm: ip Not tainted 4.5.0-rc7+ #54 +[ 822.340033] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), +BIOS rel-1.7.5.1-0-g8936dbb-20141113_115728-nilsson.home.kraxel.org +04/01/2014 +[ 822.340033] task: ffff88001db82580 ti: ffff88001dad4000 task.ti: +ffff88001dad4000 +[ 822.340033] RIP: 0010:[] [] +mpls_nh_assign_dev+0x10b/0x182 +[ 822.340033] RSP: 0018:ffff88001dad7a88 EFLAGS: 00010282 +[ 822.340033] RAX: ffffffffffffff9b RBX: ffffffffffffff9b RCX: +0000000000000002 +[ 822.340033] RDX: 00000000ffffff9b RSI: 0000000000000008 RDI: +0000000000000000 +[ 822.340033] RBP: ffff88001ddc9ea0 R08: ffff88001e9f1768 R09: +0000000000000000 +[ 822.340033] R10: ffff88001d9c1100 R11: ffff88001e3c89f0 R12: +ffffffff8187e0c0 +[ 822.340033] R13: ffffffff8187e0c0 R14: ffff88001ddc9e80 R15: +0000000000000004 +[ 822.340033] FS: 00007ff9ed798700(0000) GS:ffff88001fc00000(0000) +knlGS:0000000000000000 +[ 822.340033] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 822.340033] CR2: 00000000000003a3 CR3: 000000001de89000 CR4: +00000000000006f0 +[ 822.340033] Stack: +[ 822.340033] 0000000000000000 0000000100000000 0000000000000000 +0000000000000000 +[ 822.340033] 0000000000000000 0801010a00000000 0000000000000000 +0000000000000000 +[ 822.340033] 0000000000000004 ffffffff8148749b ffffffff8187e0c0 +000000000000001c +[ 822.340033] Call Trace: +[ 822.340033] [] ? mpls_rt_alloc+0x2b/0x3e +[ 822.340033] [] ? mpls_rtm_newroute+0x358/0x3e2 +[ 822.340033] [] ? get_page+0x5/0xa +[ 822.340033] [] ? rtnetlink_rcv_msg+0x17e/0x191 +[ 822.340033] [] ? __kmalloc_track_caller+0x8c/0x9e +[ 822.340033] [] ? +rht_key_hashfn.isra.20.constprop.57+0x14/0x1f +[ 822.340033] [] ? __rtnl_unlock+0xc/0xc +[ 822.340033] [] ? netlink_rcv_skb+0x36/0x82 +[ 822.340033] [] ? rtnetlink_rcv+0x1f/0x28 +[ 822.340033] [] ? netlink_unicast+0x106/0x189 +[ 822.340033] [] ? netlink_sendmsg+0x27f/0x2c8 +[ 822.340033] [] ? sock_sendmsg_nosec+0x10/0x1b +[ 822.340033] [] ? ___sys_sendmsg+0x182/0x1e3 +[ 822.340033] [] ? +__alloc_pages_nodemask+0x11c/0x1e4 +[ 822.340033] [] ? PageAnon+0x5/0xd +[ 822.340033] [] ? __page_set_anon_rmap+0x45/0x52 +[ 822.340033] [] ? get_page+0x5/0xa +[ 822.340033] [] ? __lru_cache_add+0x1a/0x3a +[ 822.340033] [] ? current_kernel_time64+0x9/0x30 +[ 822.340033] [] ? __sys_sendmsg+0x3c/0x5a +[ 822.340033] [] ? +entry_SYSCALL_64_fastpath+0x12/0x6a +[ 822.340033] Code: 83 08 04 00 00 65 ff 00 48 8b 3c 24 e8 40 7c f2 ff +eb 13 48 c7 c3 9f ff ff ff eb 0f 89 ce e8 f1 ae f1 ff 48 89 c3 48 85 db +74 15 <48> 8b 83 08 04 00 00 65 ff 08 48 81 fb 00 f0 ff ff 76 0d eb 07 +[ 822.340033] RIP [] mpls_nh_assign_dev+0x10b/0x182 +[ 822.340033] RSP +[ 822.340033] CR2: 00000000000003a3 +[ 822.435363] ---[ end trace 98cc65e6f6b8bf11 ]--- + +After patch: +$ip -f mpls route add 100 as 200 via inet 10.1.1.8 +RTNETLINK answers: Network is unreachable + +Signed-off-by: Roopa Prabhu +Reported-by: David Miller +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -518,6 +518,9 @@ static struct net_device *find_outdev(st + if (!dev) + return ERR_PTR(-ENODEV); + ++ if (IS_ERR(dev)) ++ return dev; ++ + /* The caller is holding rtnl anyways, so release the dev reference */ + dev_put(dev); + diff --git a/queue-4.4/net-bcmgenet-fix-dma-api-length-mismatch.patch b/queue-4.4/net-bcmgenet-fix-dma-api-length-mismatch.patch new file mode 100644 index 00000000000..9102a6e43bc --- /dev/null +++ b/queue-4.4/net-bcmgenet-fix-dma-api-length-mismatch.patch @@ -0,0 +1,45 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Eric Dumazet +Date: Thu, 17 Mar 2016 11:57:06 -0700 +Subject: net: bcmgenet: fix dma api length mismatch + +From: Eric Dumazet + +[ Upstream commit eee577232203842b4dcadb7ab477a298479633ed ] + +When un-mapping skb->data in __bcmgenet_tx_reclaim(), +we must use the length that was used in original dma_map_single(), +instead of skb->len that might be bigger (includes the frags) + +We simply can store skb_len into tx_cb_ptr->dma_len and use it +at unmap time. + +Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file") +Signed-off-by: Eric Dumazet +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -1197,7 +1197,7 @@ static unsigned int __bcmgenet_tx_reclai + dev->stats.tx_bytes += tx_cb_ptr->skb->len; + dma_unmap_single(&dev->dev, + dma_unmap_addr(tx_cb_ptr, dma_addr), +- tx_cb_ptr->skb->len, ++ dma_unmap_len(tx_cb_ptr, dma_len), + DMA_TO_DEVICE); + bcmgenet_free_cb(tx_cb_ptr); + } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { +@@ -1308,7 +1308,7 @@ static int bcmgenet_xmit_single(struct n + } + + dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping); +- dma_unmap_len_set(tx_cb_ptr, dma_len, skb->len); ++ dma_unmap_len_set(tx_cb_ptr, dma_len, skb_len); + length_status = (skb_len << DMA_BUFLENGTH_SHIFT) | dma_desc_flags | + (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT) | + DMA_TX_APPEND_CRC; diff --git a/queue-4.4/net-fix-bridge-multicast-packet-checksum-validation.patch b/queue-4.4/net-fix-bridge-multicast-packet-checksum-validation.patch new file mode 100644 index 00000000000..35876d0b9ba --- /dev/null +++ b/queue-4.4/net-fix-bridge-multicast-packet-checksum-validation.patch @@ -0,0 +1,107 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: =?UTF-8?q?Linus=20L=C3=BCssing?= +Date: Wed, 24 Feb 2016 04:21:42 +0100 +Subject: net: fix bridge multicast packet checksum validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: =?UTF-8?q?Linus=20L=C3=BCssing?= + +[ Upstream commit 9b368814b336b0a1a479135eb2815edbc00efd3c ] + +We need to update the skb->csum after pulling the skb, otherwise +an unnecessary checksum (re)computation can ocure for IGMP/MLD packets +in the bridge code. Additionally this fixes the following splats for +network devices / bridge ports with support for and enabled RX checksum +offloading: + +[...] +[ 43.986968] eth0: hw csum failure +[ 43.990344] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.4.0 #2 +[ 43.996193] Hardware name: BCM2709 +[ 43.999647] [<800204e0>] (unwind_backtrace) from [<8001cf14>] (show_stack+0x10/0x14) +[ 44.007432] [<8001cf14>] (show_stack) from [<801ab614>] (dump_stack+0x80/0x90) +[ 44.014695] [<801ab614>] (dump_stack) from [<802e4548>] (__skb_checksum_complete+0x6c/0xac) +[ 44.023090] [<802e4548>] (__skb_checksum_complete) from [<803a055c>] (ipv6_mc_validate_checksum+0x104/0x178) +[ 44.032959] [<803a055c>] (ipv6_mc_validate_checksum) from [<802e111c>] (skb_checksum_trimmed+0x130/0x188) +[ 44.042565] [<802e111c>] (skb_checksum_trimmed) from [<803a06e8>] (ipv6_mc_check_mld+0x118/0x338) +[ 44.051501] [<803a06e8>] (ipv6_mc_check_mld) from [<803b2c98>] (br_multicast_rcv+0x5dc/0xd00) +[ 44.060077] [<803b2c98>] (br_multicast_rcv) from [<803aa510>] (br_handle_frame_finish+0xac/0x51c) +[...] + +Fixes: 9afd85c9e455 ("net: Export IGMP/MLD message validation code") +Reported-by: Álvaro Fernández Rojas +Signed-off-by: Linus Lüssing +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 17 +++++++++++++++++ + net/core/skbuff.c | 22 ++++++++++++++++++++-- + 2 files changed, 37 insertions(+), 2 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2724,6 +2724,23 @@ static inline void skb_postpull_rcsum(st + + unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); + ++static inline void skb_postpush_rcsum(struct sk_buff *skb, ++ const void *start, unsigned int len) ++{ ++ /* For performing the reverse operation to skb_postpull_rcsum(), ++ * we can instead of ... ++ * ++ * skb->csum = csum_add(skb->csum, csum_partial(start, len, 0)); ++ * ++ * ... just use this equivalent version here to save a few ++ * instructions. Feeding csum of 0 in csum_partial() and later ++ * on adding skb->csum is equivalent to feed skb->csum in the ++ * first place. ++ */ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->csum = csum_partial(start, len, skb->csum); ++} ++ + /** + * pskb_trim_rcsum - trim received skb and update checksum + * @skb: buffer to trim +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2948,6 +2948,24 @@ int skb_append_pagefrags(struct sk_buff + EXPORT_SYMBOL_GPL(skb_append_pagefrags); + + /** ++ * skb_push_rcsum - push skb and update receive checksum ++ * @skb: buffer to update ++ * @len: length of data pulled ++ * ++ * This function performs an skb_push on the packet and updates ++ * the CHECKSUM_COMPLETE checksum. It should be used on ++ * receive path processing instead of skb_push unless you know ++ * that the checksum difference is zero (e.g., a valid IP header) ++ * or you are setting ip_summed to CHECKSUM_NONE. ++ */ ++static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len) ++{ ++ skb_push(skb, len); ++ skb_postpush_rcsum(skb, skb->data, len); ++ return skb->data; ++} ++ ++/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @len: length of data pulled +@@ -4084,9 +4102,9 @@ struct sk_buff *skb_checksum_trimmed(str + if (!pskb_may_pull(skb_chk, offset)) + goto err; + +- __skb_pull(skb_chk, offset); ++ skb_pull_rcsum(skb_chk, offset); + ret = skb_chkf(skb_chk); +- __skb_push(skb_chk, offset); ++ skb_push_rcsum(skb_chk, offset); + + if (ret) + goto err; diff --git a/queue-4.4/net-fix-use-after-free-in-the-recvmmsg-exit-path.patch b/queue-4.4/net-fix-use-after-free-in-the-recvmmsg-exit-path.patch new file mode 100644 index 00000000000..8e82e603adf --- /dev/null +++ b/queue-4.4/net-fix-use-after-free-in-the-recvmmsg-exit-path.patch @@ -0,0 +1,91 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Arnaldo Carvalho de Melo +Date: Mon, 14 Mar 2016 09:56:35 -0300 +Subject: net: Fix use after free in the recvmmsg exit path + +From: Arnaldo Carvalho de Melo + +[ Upstream commit 34b88a68f26a75e4fded796f1a49c40f82234b7d ] + +The syzkaller fuzzer hit the following use-after-free: + + Call Trace: + [] __asan_report_load8_noabort+0x3e/0x40 mm/kasan/report.c:295 + [] __sys_recvmmsg+0x6fa/0x7f0 net/socket.c:2261 + [< inline >] SYSC_recvmmsg net/socket.c:2281 + [] SyS_recvmmsg+0x16f/0x180 net/socket.c:2270 + [] entry_SYSCALL_64_fastpath+0x16/0x7a + arch/x86/entry/entry_64.S:185 + +And, as Dmitry rightly assessed, that is because we can drop the +reference and then touch it when the underlying recvmsg calls return +some packets and then hit an error, which will make recvmmsg to set +sock->sk->sk_err, oops, fix it. + +Reported-and-Tested-by: Dmitry Vyukov +Cc: Alexander Potapenko +Cc: Eric Dumazet +Cc: Kostya Serebryany +Cc: Sasha Levin +Fixes: a2e2725541fa ("net: Introduce recvmmsg socket syscall") +http://lkml.kernel.org/r/20160122211644.GC2470@redhat.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/socket.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +--- a/net/socket.c ++++ b/net/socket.c +@@ -2238,31 +2238,31 @@ int __sys_recvmmsg(int fd, struct mmsghd + break; + } + +-out_put: +- fput_light(sock->file, fput_needed); +- + if (err == 0) +- return datagrams; ++ goto out_put; ++ ++ if (datagrams == 0) { ++ datagrams = err; ++ goto out_put; ++ } + +- if (datagrams != 0) { ++ /* ++ * We may return less entries than requested (vlen) if the ++ * sock is non block and there aren't enough datagrams... ++ */ ++ if (err != -EAGAIN) { + /* +- * We may return less entries than requested (vlen) if the +- * sock is non block and there aren't enough datagrams... ++ * ... or if recvmsg returns an error after we ++ * received some datagrams, where we record the ++ * error to return on the next call or if the ++ * app asks about it using getsockopt(SO_ERROR). + */ +- if (err != -EAGAIN) { +- /* +- * ... or if recvmsg returns an error after we +- * received some datagrams, where we record the +- * error to return on the next call or if the +- * app asks about it using getsockopt(SO_ERROR). +- */ +- sock->sk->sk_err = -err; +- } +- +- return datagrams; ++ sock->sk->sk_err = -err; + } ++out_put: ++ fput_light(sock->file, fput_needed); + +- return err; ++ return datagrams; + } + + SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, diff --git a/queue-4.4/net-jme-fix-suspend-resume-on-jmc260.patch b/queue-4.4/net-jme-fix-suspend-resume-on-jmc260.patch new file mode 100644 index 00000000000..565a7415f20 --- /dev/null +++ b/queue-4.4/net-jme-fix-suspend-resume-on-jmc260.patch @@ -0,0 +1,43 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: Diego Viola +Date: Tue, 23 Feb 2016 12:04:04 -0300 +Subject: net: jme: fix suspend/resume on JMC260 + +From: Diego Viola + +[ Upstream commit ee50c130c82175eaa0820c96b6d3763928af2241 ] + +The JMC260 network card fails to suspend/resume because the call to +jme_start_irq() was too early, moving the call to jme_start_irq() after +the call to jme_reset_link() makes it work. + +Prior this change suspend/resume would fail unless /sys/power/pm_async=0 +was explicitly specified. + +Relevant bug report: https://bugzilla.kernel.org/show_bug.cgi?id=112351 + +Signed-off-by: Diego Viola +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/jme.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/jme.c ++++ b/drivers/net/ethernet/jme.c +@@ -3312,13 +3312,14 @@ jme_resume(struct device *dev) + jme_reset_phy_processor(jme); + jme_phy_calibration(jme); + jme_phy_setEA(jme); +- jme_start_irq(jme); + netif_device_attach(netdev); + + atomic_inc(&jme->link_changing); + + jme_reset_link(jme); + ++ jme_start_irq(jme); ++ + return 0; + } + diff --git a/queue-4.4/net-qca_spi-clear-iff_tx_skb_sharing.patch b/queue-4.4/net-qca_spi-clear-iff_tx_skb_sharing.patch new file mode 100644 index 00000000000..4a71c811b52 --- /dev/null +++ b/queue-4.4/net-qca_spi-clear-iff_tx_skb_sharing.patch @@ -0,0 +1,30 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Stefan Wahren +Date: Tue, 23 Feb 2016 19:23:24 +0000 +Subject: net: qca_spi: clear IFF_TX_SKB_SHARING + +From: Stefan Wahren + +[ Upstream commit a4690afeb0d2d7ba4d60dfa98a89f3bb1ce60ecd ] + +ether_setup sets IFF_TX_SKB_SHARING but this is not supported by +qca_spi as it modifies the skb on xmit. + +Signed-off-by: Stefan Wahren +Fixes: 291ab06ecf67 (net: qualcomm: new Ethernet over SPI driver for QCA7000) +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/qualcomm/qca_spi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/qualcomm/qca_spi.c ++++ b/drivers/net/ethernet/qualcomm/qca_spi.c +@@ -811,6 +811,7 @@ qcaspi_netdev_setup(struct net_device *d + dev->netdev_ops = &qcaspi_netdev_ops; + qcaspi_set_ethtool_ops(dev); + dev->watchdog_timeo = QCASPI_TX_TIMEOUT; ++ dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->tx_queue_len = 100; + + qca = netdev_priv(dev); diff --git a/queue-4.4/net-qca_spi-don-t-clear-iff_broadcast.patch b/queue-4.4/net-qca_spi-don-t-clear-iff_broadcast.patch new file mode 100644 index 00000000000..439864e3ce2 --- /dev/null +++ b/queue-4.4/net-qca_spi-don-t-clear-iff_broadcast.patch @@ -0,0 +1,31 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: Stefan Wahren +Date: Tue, 23 Feb 2016 19:23:23 +0000 +Subject: net: qca_spi: Don't clear IFF_BROADCAST + +From: Stefan Wahren + +[ Upstream commit 2b70bad23c89b121a3e4a00f8968d14ebb78887d ] + +Currently qcaspi_netdev_setup accidentally clears IFF_BROADCAST. +So fix this by keeping the flags from ether_setup. + +Reported-by: Michael Heimpold +Signed-off-by: Stefan Wahren +Fixes: 291ab06ecf67 (net: qualcomm: new Ethernet over SPI driver for QCA7000) +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/qualcomm/qca_spi.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/ethernet/qualcomm/qca_spi.c ++++ b/drivers/net/ethernet/qualcomm/qca_spi.c +@@ -811,7 +811,6 @@ qcaspi_netdev_setup(struct net_device *d + dev->netdev_ops = &qcaspi_netdev_ops; + qcaspi_set_ethtool_ops(dev); + dev->watchdog_timeo = QCASPI_TX_TIMEOUT; +- dev->flags = IFF_MULTICAST; + dev->tx_queue_len = 100; + + qca = netdev_priv(dev); diff --git a/queue-4.4/net-validate-variable-length-ll-headers.patch b/queue-4.4/net-validate-variable-length-ll-headers.patch new file mode 100644 index 00000000000..a7bd1aca4fc --- /dev/null +++ b/queue-4.4/net-validate-variable-length-ll-headers.patch @@ -0,0 +1,75 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Willem de Bruijn +Date: Wed, 9 Mar 2016 21:58:32 -0500 +Subject: net: validate variable length ll headers + +From: Willem de Bruijn + +[ Upstream commit 2793a23aacbd754dbbb5cb75093deb7e4103bace ] + +Netdevice parameter hard_header_len is variously interpreted both as +an upper and lower bound on link layer header length. The field is +used as upper bound when reserving room at allocation, as lower bound +when validating user input in PF_PACKET. + +Clarify the definition to be maximum header length. For validation +of untrusted headers, add an optional validate member to header_ops. + +Allow bypassing of validation by passing CAP_SYS_RAWIO, for instance +for deliberate testing of corrupt input. In this case, pad trailing +bytes, as some device drivers expect completely initialized headers. + +See also http://comments.gmane.org/gmane.linux.network/401064 + +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/netdevice.h | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -265,6 +265,7 @@ struct header_ops { + void (*cache_update)(struct hh_cache *hh, + const struct net_device *dev, + const unsigned char *haddr); ++ bool (*validate)(const char *ll_header, unsigned int len); + }; + + /* These flag bits are private to the generic network queueing +@@ -1398,8 +1399,7 @@ enum netdev_priv_flags { + * @dma: DMA channel + * @mtu: Interface MTU value + * @type: Interface hardware type +- * @hard_header_len: Hardware header length, which means that this is the +- * minimum size of a packet. ++ * @hard_header_len: Maximum hardware header length. + * + * @needed_headroom: Extra headroom the hardware may need, but not in all + * cases can this be guaranteed +@@ -2493,6 +2493,24 @@ static inline int dev_parse_header(const + return dev->header_ops->parse(skb, haddr); + } + ++/* ll_header must have at least hard_header_len allocated */ ++static inline bool dev_validate_header(const struct net_device *dev, ++ char *ll_header, int len) ++{ ++ if (likely(len >= dev->hard_header_len)) ++ return true; ++ ++ if (capable(CAP_SYS_RAWIO)) { ++ memset(ll_header + len, 0, dev->hard_header_len - len); ++ return true; ++ } ++ ++ if (dev->header_ops && dev->header_ops->validate) ++ return dev->header_ops->validate(ll_header, len); ++ ++ return false; ++} ++ + typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len); + int register_gifconf(unsigned int family, gifconf_func_t *gifconf); + static inline int unregister_gifconf(unsigned int family) diff --git a/queue-4.4/net-vrf-remove-direct-access-to-skb-data.patch b/queue-4.4/net-vrf-remove-direct-access-to-skb-data.patch new file mode 100644 index 00000000000..d16a423cfed --- /dev/null +++ b/queue-4.4/net-vrf-remove-direct-access-to-skb-data.patch @@ -0,0 +1,54 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: David Ahern +Date: Tue, 23 Feb 2016 10:10:26 -0800 +Subject: net: vrf: Remove direct access to skb->data + +From: David Ahern + +[ Upstream commit 65c38aa653c14df49e19faad74bd375f36e61c57 ] + +Nik pointed that the VRF driver should be using skb_header_pointer +instead of accessing skb->data and bits beyond directly which can +be garbage. + +Fixes: 35402e313663 ("net: Add IPv6 support to VRF device") +Cc: Nikolay Aleksandrov +Signed-off-by: David Ahern +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vrf.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -114,20 +114,23 @@ static struct dst_ops vrf_dst_ops = { + #if IS_ENABLED(CONFIG_IPV6) + static bool check_ipv6_frame(const struct sk_buff *skb) + { +- const struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->data; +- size_t hlen = sizeof(*ipv6h); ++ const struct ipv6hdr *ipv6h; ++ struct ipv6hdr _ipv6h; + bool rc = true; + +- if (skb->len < hlen) ++ ipv6h = skb_header_pointer(skb, 0, sizeof(_ipv6h), &_ipv6h); ++ if (!ipv6h) + goto out; + + if (ipv6h->nexthdr == NEXTHDR_ICMP) { + const struct icmp6hdr *icmph; ++ struct icmp6hdr _icmph; + +- if (skb->len < hlen + sizeof(*icmph)) ++ icmph = skb_header_pointer(skb, sizeof(_ipv6h), ++ sizeof(_icmph), &_icmph); ++ if (!icmph) + goto out; + +- icmph = (struct icmp6hdr *)(skb->data + sizeof(*ipv6h)); + switch (icmph->icmp6_type) { + case NDISC_ROUTER_SOLICITATION: + case NDISC_ROUTER_ADVERTISEMENT: diff --git a/queue-4.4/packet-validate-variable-length-ll-headers.patch b/queue-4.4/packet-validate-variable-length-ll-headers.patch new file mode 100644 index 00000000000..fe54c082b68 --- /dev/null +++ b/queue-4.4/packet-validate-variable-length-ll-headers.patch @@ -0,0 +1,108 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Willem de Bruijn +Date: Wed, 9 Mar 2016 21:58:34 -0500 +Subject: packet: validate variable length ll headers + +From: Willem de Bruijn + +[ Upstream commit 9ed988cd591500c040b2a6257bc68543e08ceeef ] + +Replace link layer header validation check ll_header_truncate with +more generic dev_validate_header. + +Validation based on hard_header_len incorrectly drops valid packets +in variable length protocols, such as AX25. dev_validate_header +calls header_ops.validate for such protocols to ensure correctness +below hard_header_len. + +See also http://comments.gmane.org/gmane.linux.network/401064 + +Fixes 9c7077622dd9 ("packet: make packet_snd fail on len smaller than l2 header") +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 37 ++++++++++++++++--------------------- + 1 file changed, 16 insertions(+), 21 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1916,6 +1916,10 @@ retry: + goto retry; + } + ++ if (!dev_validate_header(dev, skb->data, len)) { ++ err = -EINVAL; ++ goto out_unlock; ++ } + if (len > (dev->mtu + dev->hard_header_len + extra_len) && + !packet_extra_vlan_len_allowed(dev, skb)) { + err = -EMSGSIZE; +@@ -2326,18 +2330,6 @@ static void tpacket_destruct_skb(struct + sock_wfree(skb); + } + +-static bool ll_header_truncated(const struct net_device *dev, int len) +-{ +- /* net device doesn't like empty head */ +- if (unlikely(len < dev->hard_header_len)) { +- net_warn_ratelimited("%s: packet size is too short (%d < %d)\n", +- current->comm, len, dev->hard_header_len); +- return true; +- } +- +- return false; +-} +- + static void tpacket_set_protocol(const struct net_device *dev, + struct sk_buff *skb) + { +@@ -2420,19 +2412,19 @@ static int tpacket_fill_skb(struct packe + if (unlikely(err < 0)) + return -EINVAL; + } else if (dev->hard_header_len) { +- if (ll_header_truncated(dev, tp_len)) +- return -EINVAL; ++ int hdrlen = min_t(int, dev->hard_header_len, tp_len); + + skb_push(skb, dev->hard_header_len); +- err = skb_store_bits(skb, 0, data, +- dev->hard_header_len); ++ err = skb_store_bits(skb, 0, data, hdrlen); + if (unlikely(err)) + return err; ++ if (!dev_validate_header(dev, skb->data, hdrlen)) ++ return -EINVAL; + if (!skb->protocol) + tpacket_set_protocol(dev, skb); + +- data += dev->hard_header_len; +- to_write -= dev->hard_header_len; ++ data += hdrlen; ++ to_write -= hdrlen; + } + + offset = offset_in_page(data); +@@ -2763,9 +2755,6 @@ static int packet_snd(struct socket *soc + offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len); + if (unlikely(offset < 0)) + goto out_free; +- } else { +- if (ll_header_truncated(dev, len)) +- goto out_free; + } + + /* Returns -EFAULT on error */ +@@ -2773,6 +2762,12 @@ static int packet_snd(struct socket *soc + if (err) + goto out_free; + ++ if (sock->type == SOCK_RAW && ++ !dev_validate_header(dev, skb->data, len)) { ++ err = -EINVAL; ++ goto out_free; ++ } ++ + sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + + if (!gso_type && (len > dev->mtu + reserve + extra_len) && diff --git a/queue-4.4/ppp-ensure-file-private_data-can-t-be-overridden.patch b/queue-4.4/ppp-ensure-file-private_data-can-t-be-overridden.patch new file mode 100644 index 00000000000..55fdc85af45 --- /dev/null +++ b/queue-4.4/ppp-ensure-file-private_data-can-t-be-overridden.patch @@ -0,0 +1,128 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Guillaume Nault +Date: Mon, 14 Mar 2016 21:17:16 +0100 +Subject: ppp: ensure file->private_data can't be overridden + +From: Guillaume Nault + +[ Upstream commit e8e56ffd9d2973398b60ece1f1bebb8d67b4d032 ] + +Locking ppp_mutex must be done before dereferencing file->private_data, +otherwise it could be modified before ppp_unattached_ioctl() takes the +lock. This could lead ppp_unattached_ioctl() to override ->private_data, +thus leaking reference to the ppp_file previously pointed to. + +v2: lock all ppp_ioctl() instead of just checking private_data in + ppp_unattached_ioctl(), to avoid ambiguous behaviour. + +Fixes: f3ff8a4d80e8 ("ppp: push BKL down into the driver") +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ppp/ppp_generic.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -567,7 +567,7 @@ static int get_filter(void __user *arg, + + static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- struct ppp_file *pf = file->private_data; ++ struct ppp_file *pf; + struct ppp *ppp; + int err = -EFAULT, val, val2, i; + struct ppp_idle idle; +@@ -577,9 +577,14 @@ static long ppp_ioctl(struct file *file, + void __user *argp = (void __user *)arg; + int __user *p = argp; + +- if (!pf) +- return ppp_unattached_ioctl(current->nsproxy->net_ns, +- pf, file, cmd, arg); ++ mutex_lock(&ppp_mutex); ++ ++ pf = file->private_data; ++ if (!pf) { ++ err = ppp_unattached_ioctl(current->nsproxy->net_ns, ++ pf, file, cmd, arg); ++ goto out; ++ } + + if (cmd == PPPIOCDETACH) { + /* +@@ -594,7 +599,6 @@ static long ppp_ioctl(struct file *file, + * this fd and reopening /dev/ppp. + */ + err = -EINVAL; +- mutex_lock(&ppp_mutex); + if (pf->kind == INTERFACE) { + ppp = PF_TO_PPP(pf); + rtnl_lock(); +@@ -608,15 +612,13 @@ static long ppp_ioctl(struct file *file, + } else + pr_warn("PPPIOCDETACH file->f_count=%ld\n", + atomic_long_read(&file->f_count)); +- mutex_unlock(&ppp_mutex); +- return err; ++ goto out; + } + + if (pf->kind == CHANNEL) { + struct channel *pch; + struct ppp_channel *chan; + +- mutex_lock(&ppp_mutex); + pch = PF_TO_CHANNEL(pf); + + switch (cmd) { +@@ -638,17 +640,16 @@ static long ppp_ioctl(struct file *file, + err = chan->ops->ioctl(chan, cmd, arg); + up_read(&pch->chan_sem); + } +- mutex_unlock(&ppp_mutex); +- return err; ++ goto out; + } + + if (pf->kind != INTERFACE) { + /* can't happen */ + pr_err("PPP: not interface or channel??\n"); +- return -EINVAL; ++ err = -EINVAL; ++ goto out; + } + +- mutex_lock(&ppp_mutex); + ppp = PF_TO_PPP(pf); + switch (cmd) { + case PPPIOCSMRU: +@@ -823,7 +824,10 @@ static long ppp_ioctl(struct file *file, + default: + err = -ENOTTY; + } ++ ++out: + mutex_unlock(&ppp_mutex); ++ + return err; + } + +@@ -836,7 +840,6 @@ static int ppp_unattached_ioctl(struct n + struct ppp_net *pn; + int __user *p = (int __user *)arg; + +- mutex_lock(&ppp_mutex); + switch (cmd) { + case PPPIOCNEWUNIT: + /* Create a new ppp unit */ +@@ -886,7 +889,7 @@ static int ppp_unattached_ioctl(struct n + default: + err = -ENOTTY; + } +- mutex_unlock(&ppp_mutex); ++ + return err; + } + diff --git a/queue-4.4/ppp-release-rtnl-mutex-when-interface-creation-fails.patch b/queue-4.4/ppp-release-rtnl-mutex-when-interface-creation-fails.patch new file mode 100644 index 00000000000..8a4f71357b7 --- /dev/null +++ b/queue-4.4/ppp-release-rtnl-mutex-when-interface-creation-fails.patch @@ -0,0 +1,29 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Guillaume Nault +Date: Mon, 7 Mar 2016 19:36:44 +0100 +Subject: ppp: release rtnl mutex when interface creation fails + +From: Guillaume Nault + +[ Upstream commit 6faac63a6986f29ef39827f460edd3a5ba64ad5c ] + +Add missing rtnl_unlock() in the error path of ppp_create_interface(). + +Fixes: 58a89ecaca53 ("ppp: fix lockdep splat in ppp_dev_uninit()") +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ppp/ppp_generic.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2803,6 +2803,7 @@ static struct ppp *ppp_create_interface( + + out2: + mutex_unlock(&pn->all_ppp_mutex); ++ rtnl_unlock(); + free_netdev(dev); + out1: + *retp = ret; diff --git a/queue-4.4/ppp-take-reference-on-channels-netns.patch b/queue-4.4/ppp-take-reference-on-channels-netns.patch new file mode 100644 index 00000000000..d3d3a1e33c2 --- /dev/null +++ b/queue-4.4/ppp-take-reference-on-channels-netns.patch @@ -0,0 +1,149 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Guillaume Nault +Date: Wed, 23 Mar 2016 16:38:55 +0100 +Subject: ppp: take reference on channels netns + +From: Guillaume Nault + +[ Upstream commit 1f461dcdd296eecedaffffc6bae2bfa90bd7eb89 ] + +Let channels hold a reference on their network namespace. +Some channel types, like ppp_async and ppp_synctty, can have their +userspace controller running in a different namespace. Therefore they +can't rely on them to preclude their netns from being removed from +under them. + +================================================================== +BUG: KASAN: use-after-free in ppp_unregister_channel+0x372/0x3a0 at +addr ffff880064e217e0 +Read of size 8 by task syz-executor/11581 +============================================================================= +BUG net_namespace (Not tainted): kasan: bad access detected +----------------------------------------------------------------------------- + +Disabling lock debugging due to kernel taint +INFO: Allocated in copy_net_ns+0x6b/0x1a0 age=92569 cpu=3 pid=6906 +[< none >] ___slab_alloc+0x4c7/0x500 kernel/mm/slub.c:2440 +[< none >] __slab_alloc+0x4c/0x90 kernel/mm/slub.c:2469 +[< inline >] slab_alloc_node kernel/mm/slub.c:2532 +[< inline >] slab_alloc kernel/mm/slub.c:2574 +[< none >] kmem_cache_alloc+0x23a/0x2b0 kernel/mm/slub.c:2579 +[< inline >] kmem_cache_zalloc kernel/include/linux/slab.h:597 +[< inline >] net_alloc kernel/net/core/net_namespace.c:325 +[< none >] copy_net_ns+0x6b/0x1a0 kernel/net/core/net_namespace.c:360 +[< none >] create_new_namespaces+0x2f6/0x610 kernel/kernel/nsproxy.c:95 +[< none >] copy_namespaces+0x297/0x320 kernel/kernel/nsproxy.c:150 +[< none >] copy_process.part.35+0x1bf4/0x5760 kernel/kernel/fork.c:1451 +[< inline >] copy_process kernel/kernel/fork.c:1274 +[< none >] _do_fork+0x1bc/0xcb0 kernel/kernel/fork.c:1723 +[< inline >] SYSC_clone kernel/kernel/fork.c:1832 +[< none >] SyS_clone+0x37/0x50 kernel/kernel/fork.c:1826 +[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a kernel/arch/x86/entry/entry_64.S:185 + +INFO: Freed in net_drop_ns+0x67/0x80 age=575 cpu=2 pid=2631 +[< none >] __slab_free+0x1fc/0x320 kernel/mm/slub.c:2650 +[< inline >] slab_free kernel/mm/slub.c:2805 +[< none >] kmem_cache_free+0x2a0/0x330 kernel/mm/slub.c:2814 +[< inline >] net_free kernel/net/core/net_namespace.c:341 +[< none >] net_drop_ns+0x67/0x80 kernel/net/core/net_namespace.c:348 +[< none >] cleanup_net+0x4e5/0x600 kernel/net/core/net_namespace.c:448 +[< none >] process_one_work+0x794/0x1440 kernel/kernel/workqueue.c:2036 +[< none >] worker_thread+0xdb/0xfc0 kernel/kernel/workqueue.c:2170 +[< none >] kthread+0x23f/0x2d0 kernel/drivers/block/aoe/aoecmd.c:1303 +[< none >] ret_from_fork+0x3f/0x70 kernel/arch/x86/entry/entry_64.S:468 +INFO: Slab 0xffffea0001938800 objects=3 used=0 fp=0xffff880064e20000 +flags=0x5fffc0000004080 +INFO: Object 0xffff880064e20000 @offset=0 fp=0xffff880064e24200 + +CPU: 1 PID: 11581 Comm: syz-executor Tainted: G B 4.4.0+ +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 + 00000000ffffffff ffff8800662c7790 ffffffff8292049d ffff88003e36a300 + ffff880064e20000 ffff880064e20000 ffff8800662c77c0 ffffffff816f2054 + ffff88003e36a300 ffffea0001938800 ffff880064e20000 0000000000000000 +Call Trace: + [< inline >] __dump_stack kernel/lib/dump_stack.c:15 + [] dump_stack+0x6f/0xa2 kernel/lib/dump_stack.c:50 + [] print_trailer+0xf4/0x150 kernel/mm/slub.c:654 + [] object_err+0x2f/0x40 kernel/mm/slub.c:661 + [< inline >] print_address_description kernel/mm/kasan/report.c:138 + [] kasan_report_error+0x215/0x530 kernel/mm/kasan/report.c:236 + [< inline >] kasan_report kernel/mm/kasan/report.c:259 + [] __asan_report_load8_noabort+0x3e/0x40 kernel/mm/kasan/report.c:280 + [< inline >] ? ppp_pernet kernel/include/linux/compiler.h:218 + [] ? ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [< inline >] ppp_pernet kernel/include/linux/compiler.h:218 + [] ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [< inline >] ? ppp_pernet kernel/drivers/net/ppp/ppp_generic.c:293 + [] ? ppp_unregister_channel+0xe6/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [] ppp_asynctty_close+0xa3/0x130 kernel/drivers/net/ppp/ppp_async.c:241 + [] ? async_lcp_peek+0x5b0/0x5b0 kernel/drivers/net/ppp/ppp_async.c:1000 + [] tty_ldisc_close.isra.1+0x99/0xe0 kernel/drivers/tty/tty_ldisc.c:478 + [] tty_ldisc_kill+0x40/0x170 kernel/drivers/tty/tty_ldisc.c:744 + [] tty_ldisc_release+0x1b3/0x260 kernel/drivers/tty/tty_ldisc.c:772 + [] tty_release+0xac1/0x13e0 kernel/drivers/tty/tty_io.c:1901 + [] ? release_tty+0x320/0x320 kernel/drivers/tty/tty_io.c:1688 + [] __fput+0x236/0x780 kernel/fs/file_table.c:208 + [] ____fput+0x15/0x20 kernel/fs/file_table.c:244 + [] task_work_run+0x16b/0x200 kernel/kernel/task_work.c:115 + [< inline >] exit_task_work kernel/include/linux/task_work.h:21 + [] do_exit+0x8b5/0x2c60 kernel/kernel/exit.c:750 + [] ? debug_check_no_locks_freed+0x290/0x290 kernel/kernel/locking/lockdep.c:4123 + [] ? mm_update_next_owner+0x6f0/0x6f0 kernel/kernel/exit.c:357 + [] ? __dequeue_signal+0x136/0x470 kernel/kernel/signal.c:550 + [] ? recalc_sigpending_tsk+0x13b/0x180 kernel/kernel/signal.c:145 + [] do_group_exit+0x108/0x330 kernel/kernel/exit.c:880 + [] get_signal+0x5e4/0x14f0 kernel/kernel/signal.c:2307 + [< inline >] ? kretprobe_table_lock kernel/kernel/kprobes.c:1113 + [] ? kprobe_flush_task+0xb5/0x450 kernel/kernel/kprobes.c:1158 + [] do_signal+0x83/0x1c90 kernel/arch/x86/kernel/signal.c:712 + [] ? recycle_rp_inst+0x310/0x310 kernel/include/linux/list.h:655 + [] ? setup_sigcontext+0x780/0x780 kernel/arch/x86/kernel/signal.c:165 + [] ? finish_task_switch+0x424/0x5f0 kernel/kernel/sched/core.c:2692 + [< inline >] ? finish_lock_switch kernel/kernel/sched/sched.h:1099 + [] ? finish_task_switch+0x120/0x5f0 kernel/kernel/sched/core.c:2678 + [< inline >] ? context_switch kernel/kernel/sched/core.c:2807 + [] ? __schedule+0x919/0x1bd0 kernel/kernel/sched/core.c:3283 + [] exit_to_usermode_loop+0xf1/0x1a0 kernel/arch/x86/entry/common.c:247 + [< inline >] prepare_exit_to_usermode kernel/arch/x86/entry/common.c:282 + [] syscall_return_slowpath+0x19f/0x210 kernel/arch/x86/entry/common.c:344 + [] int_ret_from_sys_call+0x25/0x9f kernel/arch/x86/entry/entry_64.S:281 +Memory state around the buggy address: + ffff880064e21680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff880064e21700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffff880064e21780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff880064e21800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff880064e21880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +================================================================== + +Fixes: 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2") +Reported-by: Baozeng Ding +Signed-off-by: Guillaume Nault +Reviewed-by: Cyrill Gorcunov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ppp/ppp_generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2293,7 +2293,7 @@ int ppp_register_net_channel(struct net + + pch->ppp = NULL; + pch->chan = chan; +- pch->chan_net = net; ++ pch->chan_net = get_net(net); + chan->ppp = pch; + init_ppp_file(&pch->file, CHANNEL); + pch->file.hdrlen = chan->hdrlen; +@@ -2390,6 +2390,8 @@ ppp_unregister_channel(struct ppp_channe + spin_lock_bh(&pn->all_channels_lock); + list_del(&pch->list); + spin_unlock_bh(&pn->all_channels_lock); ++ put_net(pch->chan_net); ++ pch->chan_net = NULL; + + pch->file.dead = 1; + wake_up_interruptible(&pch->file.rwait); diff --git a/queue-4.4/qlcnic-fix-mailbox-completion-handling-during-spurious-interrupt.patch b/queue-4.4/qlcnic-fix-mailbox-completion-handling-during-spurious-interrupt.patch new file mode 100644 index 00000000000..82a1954e7de --- /dev/null +++ b/queue-4.4/qlcnic-fix-mailbox-completion-handling-during-spurious-interrupt.patch @@ -0,0 +1,96 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Rajesh Borundia +Date: Tue, 8 Mar 2016 02:39:58 -0500 +Subject: qlcnic: Fix mailbox completion handling during spurious interrupt + +From: Rajesh Borundia + +[ Upstream commit 819bfe764dceec2f6b4551768453f374b4c60443 ] + +o While the driver is in the middle of a MB completion processing +and it receives a spurious MB interrupt, it is mistaken as a good MB +completion interrupt leading to premature completion of the next MB +request. Fix the driver to guard against this by checking the current +state of MB processing and ignore the spurious interrupt. +Also added a stats counter to record this condition. + +Signed-off-by: Rajesh Borundia +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 + + drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 15 +++++++++++---- + drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 3 ++- + 3 files changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +@@ -566,6 +566,7 @@ struct qlcnic_adapter_stats { + u64 tx_dma_map_error; + u64 spurious_intr; + u64 mac_filter_limit_overrun; ++ u64 mbx_spurious_intr; + }; + + /* +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +@@ -2338,9 +2338,9 @@ static void qlcnic_83xx_handle_link_aen( + + static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) + { ++ u32 mask, resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED; + struct qlcnic_adapter *adapter = data; + struct qlcnic_mailbox *mbx; +- u32 mask, resp, event; + unsigned long flags; + + mbx = adapter->ahw->mailbox; +@@ -2350,10 +2350,14 @@ static irqreturn_t qlcnic_83xx_handle_ae + goto out; + + event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); +- if (event & QLCNIC_MBX_ASYNC_EVENT) ++ if (event & QLCNIC_MBX_ASYNC_EVENT) { + __qlcnic_83xx_process_aen(adapter); +- else +- qlcnic_83xx_notify_mbx_response(mbx); ++ } else { ++ if (mbx->rsp_status != rsp_status) ++ qlcnic_83xx_notify_mbx_response(mbx); ++ else ++ adapter->stats.mbx_spurious_intr++; ++ } + + out: + mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); +@@ -4053,6 +4057,7 @@ static void qlcnic_83xx_mailbox_worker(s + struct list_head *head = &mbx->cmd_q; + struct qlcnic_hardware_context *ahw; + struct qlcnic_cmd_args *cmd = NULL; ++ unsigned long flags; + + ahw = adapter->ahw; + +@@ -4062,7 +4067,9 @@ static void qlcnic_83xx_mailbox_worker(s + return; + } + ++ spin_lock_irqsave(&mbx->aen_lock, flags); + mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT; ++ spin_unlock_irqrestore(&mbx->aen_lock, flags); + + spin_lock(&mbx->queue_lock); + +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +@@ -59,7 +59,8 @@ static const struct qlcnic_stats qlcnic_ + QLC_OFF(stats.mac_filter_limit_overrun)}, + {"spurious intr", QLC_SIZEOF(stats.spurious_intr), + QLC_OFF(stats.spurious_intr)}, +- ++ {"mbx spurious intr", QLC_SIZEOF(stats.mbx_spurious_intr), ++ QLC_OFF(stats.mbx_spurious_intr)}, + }; + + static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { diff --git a/queue-4.4/qlcnic-remove-unnecessary-usage-of-atomic_t.patch b/queue-4.4/qlcnic-remove-unnecessary-usage-of-atomic_t.patch new file mode 100644 index 00000000000..01c5bb68c10 --- /dev/null +++ b/queue-4.4/qlcnic-remove-unnecessary-usage-of-atomic_t.patch @@ -0,0 +1,77 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Rajesh Borundia +Date: Tue, 8 Mar 2016 02:39:57 -0500 +Subject: qlcnic: Remove unnecessary usage of atomic_t + +From: Rajesh Borundia + +[ Upstream commit 5bf93251cee1fb66141d1d2eaff86e04a9397bdf ] + +o atomic_t usage is incorrect as we are not implementing +any atomicity. + +Signed-off-by: Rajesh Borundia +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 2 +- + drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 9 ++++----- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +@@ -1099,7 +1099,7 @@ struct qlcnic_mailbox { + unsigned long status; + spinlock_t queue_lock; /* Mailbox queue lock */ + spinlock_t aen_lock; /* Mailbox response/AEN lock */ +- atomic_t rsp_status; ++ u32 rsp_status; + u32 num_cmds; + }; + +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +@@ -491,7 +491,7 @@ irqreturn_t qlcnic_83xx_clear_legacy_int + + static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx) + { +- atomic_set(&mbx->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED); ++ mbx->rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED; + complete(&mbx->completion); + } + +@@ -510,7 +510,7 @@ static void qlcnic_83xx_poll_process_aen + if (event & QLCNIC_MBX_ASYNC_EVENT) { + __qlcnic_83xx_process_aen(adapter); + } else { +- if (atomic_read(&mbx->rsp_status) != rsp_status) ++ if (mbx->rsp_status != rsp_status) + qlcnic_83xx_notify_mbx_response(mbx); + } + out: +@@ -1023,7 +1023,7 @@ static void qlcnic_83xx_process_aen(stru + if (event & QLCNIC_MBX_ASYNC_EVENT) { + __qlcnic_83xx_process_aen(adapter); + } else { +- if (atomic_read(&mbx->rsp_status) != rsp_status) ++ if (mbx->rsp_status != rsp_status) + qlcnic_83xx_notify_mbx_response(mbx); + } + } +@@ -4050,7 +4050,6 @@ static void qlcnic_83xx_mailbox_worker(s + struct qlcnic_adapter *adapter = mbx->adapter; + const struct qlcnic_mbx_ops *mbx_ops = mbx->ops; + struct device *dev = &adapter->pdev->dev; +- atomic_t *rsp_status = &mbx->rsp_status; + struct list_head *head = &mbx->cmd_q; + struct qlcnic_hardware_context *ahw; + struct qlcnic_cmd_args *cmd = NULL; +@@ -4063,7 +4062,7 @@ static void qlcnic_83xx_mailbox_worker(s + return; + } + +- atomic_set(rsp_status, QLC_83XX_MBX_RESPONSE_WAIT); ++ mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT; + + spin_lock(&mbx->queue_lock); + diff --git a/queue-4.4/qlge-fix-receive-packets-drop.patch b/queue-4.4/qlge-fix-receive-packets-drop.patch new file mode 100644 index 00000000000..ca69192d5b0 --- /dev/null +++ b/queue-4.4/qlge-fix-receive-packets-drop.patch @@ -0,0 +1,43 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Manish Chopra +Date: Tue, 15 Mar 2016 07:13:45 -0400 +Subject: qlge: Fix receive packets drop. + +From: Manish Chopra + +[ Upstream commit 2c9a266afefe137bff06bbe0fc48b4d3b3cb348c ] + +When running small packets [length < 256 bytes] traffic, packets were +being dropped due to invalid data in those packets which were +delivered by the driver upto the stack. Using pci_dma_sync_single_for_cpu +ensures copying latest and updated data into skb from the receive buffer. + +Signed-off-by: Sony Chacko +Signed-off-by: Manish Chopra +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/qlogic/qlge/qlge_main.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c ++++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c +@@ -1648,7 +1648,18 @@ static void ql_process_mac_rx_skb(struct + return; + } + skb_reserve(new_skb, NET_IP_ALIGN); ++ ++ pci_dma_sync_single_for_cpu(qdev->pdev, ++ dma_unmap_addr(sbq_desc, mapaddr), ++ dma_unmap_len(sbq_desc, maplen), ++ PCI_DMA_FROMDEVICE); ++ + memcpy(skb_put(new_skb, length), skb->data, length); ++ ++ pci_dma_sync_single_for_device(qdev->pdev, ++ dma_unmap_addr(sbq_desc, mapaddr), ++ dma_unmap_len(sbq_desc, maplen), ++ PCI_DMA_FROMDEVICE); + skb = new_skb; + + /* Frame error, so drop the packet. */ diff --git a/queue-4.4/qmi_wwan-add-d-link-dwm-221-b1-device-id.patch b/queue-4.4/qmi_wwan-add-d-link-dwm-221-b1-device-id.patch new file mode 100644 index 00000000000..0ca72e1e3a0 --- /dev/null +++ b/queue-4.4/qmi_wwan-add-d-link-dwm-221-b1-device-id.patch @@ -0,0 +1,55 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Mon, 28 Mar 2016 22:38:16 +0200 +Subject: qmi_wwan: add "D-Link DWM-221 B1" device id +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= + +[ Upstream commit e84810c7b85a2d7897797b3ad3e879168a8e032a ] + +Thomas reports: +"Windows: + +00 diagnostics +01 modem +02 at-port +03 nmea +04 nic + +Linux: + +T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 +D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 +P: Vendor=2001 ProdID=7e19 Rev=02.32 +S: Manufacturer=Mobile Connect +S: Product=Mobile Connect +S: SerialNumber=0123456789ABCDEF +C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA +I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option +I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan +I: If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage" + +Reported-by: Thomas Schäfer +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -699,6 +699,7 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ + {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ + {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ ++ {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ + {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ + {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ diff --git a/queue-4.4/qmi_wwan-add-sierra-wireless-em74xx-device-id.patch b/queue-4.4/qmi_wwan-add-sierra-wireless-em74xx-device-id.patch new file mode 100644 index 00000000000..e5530530cf8 --- /dev/null +++ b/queue-4.4/qmi_wwan-add-sierra-wireless-em74xx-device-id.patch @@ -0,0 +1,37 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Tue, 1 Mar 2016 14:31:02 +0100 +Subject: qmi_wwan: add Sierra Wireless EM74xx device ID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= + +[ Upstream commit bf13c94ccb33c3182efc92ce4989506a0f541243 ] + +The MC74xx and EM74xx modules use different IDs by default, according +to the Lenovo EM7455 driver for Windows. + +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/qmi_wwan.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -718,8 +718,10 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ + {QMI_FIXED_INTF(0x1199, 0x9070, 8)}, /* Sierra Wireless MC74xx/EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x9070, 10)}, /* Sierra Wireless MC74xx/EM74xx */ +- {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx/EM74xx */ +- {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx/EM74xx */ ++ {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */ ++ {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ ++ {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ ++ {QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */ + {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ + {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ + {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ diff --git a/queue-4.4/rocker-set-fdb-cleanup-timer-according-to-lowest-ageing-time.patch b/queue-4.4/rocker-set-fdb-cleanup-timer-according-to-lowest-ageing-time.patch new file mode 100644 index 00000000000..a1e519364cd --- /dev/null +++ b/queue-4.4/rocker-set-fdb-cleanup-timer-according-to-lowest-ageing-time.patch @@ -0,0 +1,70 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Ido Schimmel +Date: Tue, 8 Mar 2016 12:59:34 -0800 +Subject: rocker: set FDB cleanup timer according to lowest ageing time + +From: Ido Schimmel + +[ Upstream commit 88de1cd457e5cb664d6d437e2ea4750d089165f5 ] + +In rocker, ageing time is a per-port attribute, so the next time the FDB +cleanup timer fires should be set according to the lowest ageing time. + +This will later allow us to delete the BR_MIN_AGEING_TIME macro, which was +added to guarantee minimum ageing time in the bridge layer, thereby breaking +existing behavior. + +Signed-off-by: Ido Schimmel +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/rocker/rocker.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/rocker/rocker.c ++++ b/drivers/net/ethernet/rocker/rocker.c +@@ -239,6 +239,7 @@ struct rocker { + struct { + u64 id; + } hw; ++ unsigned long ageing_time; + spinlock_t cmd_ring_lock; /* for cmd ring accesses */ + struct rocker_dma_ring_info cmd_ring; + struct rocker_dma_ring_info event_ring; +@@ -3704,7 +3705,7 @@ static void rocker_fdb_cleanup(unsigned + struct rocker_port *rocker_port; + struct rocker_fdb_tbl_entry *entry; + struct hlist_node *tmp; +- unsigned long next_timer = jiffies + BR_MIN_AGEING_TIME; ++ unsigned long next_timer = jiffies + rocker->ageing_time; + unsigned long expires; + unsigned long lock_flags; + int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE | +@@ -4367,8 +4368,12 @@ static int rocker_port_bridge_ageing_tim + struct switchdev_trans *trans, + u32 ageing_time) + { ++ struct rocker *rocker = rocker_port->rocker; ++ + if (!switchdev_trans_ph_prepare(trans)) { + rocker_port->ageing_time = clock_t_to_jiffies(ageing_time); ++ if (rocker_port->ageing_time < rocker->ageing_time) ++ rocker->ageing_time = rocker_port->ageing_time; + mod_timer(&rocker_port->rocker->fdb_cleanup_timer, jiffies); + } + +@@ -5206,10 +5211,13 @@ static int rocker_probe(struct pci_dev * + goto err_init_tbls; + } + ++ rocker->ageing_time = BR_DEFAULT_AGEING_TIME; + setup_timer(&rocker->fdb_cleanup_timer, rocker_fdb_cleanup, + (unsigned long) rocker); + mod_timer(&rocker->fdb_cleanup_timer, jiffies); + ++ rocker->ageing_time = BR_DEFAULT_AGEING_TIME; ++ + err = rocker_probe_ports(rocker); + if (err) { + dev_err(&pdev->dev, "failed to probe ports\n"); diff --git a/queue-4.4/rtnl-fix-msg-size-calculation-in-if_nlmsg_size.patch b/queue-4.4/rtnl-fix-msg-size-calculation-in-if_nlmsg_size.patch new file mode 100644 index 00000000000..3f5d344e011 --- /dev/null +++ b/queue-4.4/rtnl-fix-msg-size-calculation-in-if_nlmsg_size.patch @@ -0,0 +1,31 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Nicolas Dichtel +Date: Thu, 31 Mar 2016 18:10:31 +0200 +Subject: rtnl: fix msg size calculation in if_nlmsg_size() + +From: Nicolas Dichtel + +[ Upstream commit c57c7a95da842807b475b823ed2e5435c42cb3b0 ] + +Size of the attribute IFLA_PHYS_PORT_NAME was missing. + +Fixes: db24a9044ee1 ("net: add support for phys_port_name") +CC: David Ahern +Signed-off-by: Nicolas Dichtel +Acked-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/rtnetlink.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -905,6 +905,7 @@ static noinline size_t if_nlmsg_size(con + + rtnl_link_get_af_size(dev, ext_filter_mask) /* IFLA_AF_SPEC */ + + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */ + + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */ ++ + nla_total_size(IFNAMSIZ) /* IFLA_PHYS_PORT_NAME */ + + nla_total_size(1); /* IFLA_PROTO_DOWN */ + + } diff --git a/queue-4.4/sctp-lack-the-check-for-ports-in-sctp_v6_cmp_addr.patch b/queue-4.4/sctp-lack-the-check-for-ports-in-sctp_v6_cmp_addr.patch new file mode 100644 index 00000000000..798b4897e67 --- /dev/null +++ b/queue-4.4/sctp-lack-the-check-for-ports-in-sctp_v6_cmp_addr.patch @@ -0,0 +1,37 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Xin Long +Date: Sun, 28 Feb 2016 10:03:51 +0800 +Subject: sctp: lack the check for ports in sctp_v6_cmp_addr + +From: Xin Long + +[ Upstream commit 40b4f0fd74e46c017814618d67ec9127ff20f157 ] + +As the member .cmp_addr of sctp_af_inet6, sctp_v6_cmp_addr should also check +the port of addresses, just like sctp_v4_cmp_addr, cause it's invoked by +sctp_cmp_addr_exact(). + +Now sctp_v6_cmp_addr just check the port when two addresses have different +family, and lack the port check for two ipv6 addresses. that will make +sctp_hash_cmp() cannot work well. + +so fix it by adding ports comparison in sctp_v6_cmp_addr(). + +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -526,6 +526,8 @@ static int sctp_v6_cmp_addr(const union + } + return 0; + } ++ if (addr1->v6.sin6_port != addr2->v6.sin6_port) ++ return 0; + if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) + return 0; + /* If this is a linklocal address, compare the scope_id. */ diff --git a/queue-4.4/series b/queue-4.4/series index 79c94cf550b..edc553188c7 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -21,3 +21,59 @@ drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch xen-events-mask-a-moving-irq.patch +tcp-convert-cached-rtt-from-usec-to-jiffies-when-feeding-initial-rto.patch +tunnel-clear-ipcb-skb-opt-before-dst_link_failure-called.patch +ipv4-only-create-late-gso-skb-if-skb-is-already-set-up-with-checksum_partial.patch +net-jme-fix-suspend-resume-on-jmc260.patch +net-vrf-remove-direct-access-to-skb-data.patch +net-qca_spi-don-t-clear-iff_broadcast.patch +net-qca_spi-clear-iff_tx_skb_sharing.patch +net-fix-bridge-multicast-packet-checksum-validation.patch +sctp-lack-the-check-for-ports-in-sctp_v6_cmp_addr.patch +mld-igmp-fix-reserved-tailroom-calculation.patch +tipc-revert-tipc-use-existing-sk_write_queue-for-outgoing-packet-chain.patch +qmi_wwan-add-sierra-wireless-em74xx-device-id.patch +ipv6-re-enable-fragment-header-matching-in-ipv6_find_hdr.patch +vxlan-fix-missing-options_len-update-on-rx-with-collect-metadata.patch +cdc_ncm-toggle-altsetting-to-force-reset-before-setup.patch +usbnet-cleanup-after-bind-in-probe.patch +udp6-fix-udp-ipv6-encap-resubmit-path.patch +tcp-fix-tcpi_segs_in-after-connection-establishment.patch +ppp-release-rtnl-mutex-when-interface-creation-fails.patch +net-validate-variable-length-ll-headers.patch +ax25-add-link-layer-header-validation-function.patch +packet-validate-variable-length-ll-headers.patch +bpf-avoid-copying-junk-bytes-in-bpf_get_current_comm.patch +sh_eth-fix-null-pointer-dereference-in-sh_eth_ring_format.patch +sh_eth-advance-rxdesc-later-in-sh_eth_ring_format.patch +qlcnic-remove-unnecessary-usage-of-atomic_t.patch +qlcnic-fix-mailbox-completion-handling-during-spurious-interrupt.patch +macvtap-always-pass-ethernet-header-in-linear.patch +mlxsw-spectrum-check-requested-ageing-time-is-valid.patch +rocker-set-fdb-cleanup-timer-according-to-lowest-ageing-time.patch +bridge-allow-zero-ageing-time.patch +ipv4-don-t-do-expensive-useless-work-during-inetdev-destroy.patch +net-fix-use-after-free-in-the-recvmmsg-exit-path.patch +mlx4-add-missing-braces-in-verify_qp_parameters.patch +farsync-fix-off-by-one-bug-in-fst_add_one.patch +ath9k-fix-buffer-overrun-for-ar9287.patch +ppp-ensure-file-private_data-can-t-be-overridden.patch +tcp-dccp-remove-obsolete-warn_on-in-icmp-handlers.patch +qlge-fix-receive-packets-drop.patch +net-bcmgenet-fix-dma-api-length-mismatch.patch +bonding-fix-bond_get_stats.patch +ipv4-fix-broadcast-packets-reception.patch +ipv4-initialize-flowi4_flags-before-calling-fib_lookup.patch +ppp-take-reference-on-channels-netns.patch +xfrm-fix-crash-observed-during-device-unregistration-and-decryption.patch +qmi_wwan-add-d-link-dwm-221-b1-device-id.patch +ipv6-udp-fix-udp_mib_ignoredmulti-updates.patch +bridge-allow-set-bridge-ageing-time-when-switchdev-disabled.patch +rtnl-fix-msg-size-calculation-in-if_nlmsg_size.patch +tun-bpf-fix-suspicious-rcu-usage-in-tun_-attach-detach-_filter.patch +tuntap-restore-default-qdisc.patch +ipv4-l2tp-fix-a-potential-issue-in-l2tp_ip_recv.patch +ipv6-l2tp-fix-a-potential-issue-in-l2tp_ip6_recv.patch +ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch +ipv6-count-in-extension-headers-in-skb-network_header.patch +mpls-find_outdev-check-for-err-ptr-in-addition-to-null-check.patch diff --git a/queue-4.4/sh_eth-advance-rxdesc-later-in-sh_eth_ring_format.patch b/queue-4.4/sh_eth-advance-rxdesc-later-in-sh_eth_ring_format.patch new file mode 100644 index 00000000000..0428f811eac --- /dev/null +++ b/queue-4.4/sh_eth-advance-rxdesc-later-in-sh_eth_ring_format.patch @@ -0,0 +1,46 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Sergei Shtylyov +Date: Tue, 8 Mar 2016 01:37:09 +0300 +Subject: sh_eth: advance 'rxdesc' later in sh_eth_ring_format() + +From: Sergei Shtylyov + +[ Upstream commit d0ba913488dc8c55d1880f5ed34f096dc45fb05d ] + +Iff dma_map_single() fails, 'rxdesc' should point to the last filled RX +descriptor, so that it can be marked as the last one, however the driver +would have already advanced it by that time. In order to fix that, only +fill an RX descriptor once all the data for it is ready. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/renesas/sh_eth.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1185,11 +1185,8 @@ static void sh_eth_ring_format(struct ne + break; + sh_eth_set_receive_align(skb); + +- /* RX descriptor */ +- rxdesc = &mdp->rx_ring[i]; + /* The size of the buffer is a multiple of 32 bytes. */ + buf_len = ALIGN(mdp->rx_buf_sz, 32); +- rxdesc->len = cpu_to_edmac(mdp, buf_len << 16); + dma_addr = dma_map_single(&ndev->dev, skb->data, buf_len, + DMA_FROM_DEVICE); + if (dma_mapping_error(&ndev->dev, dma_addr)) { +@@ -1197,6 +1194,10 @@ static void sh_eth_ring_format(struct ne + break; + } + mdp->rx_skbuff[i] = skb; ++ ++ /* RX descriptor */ ++ rxdesc = &mdp->rx_ring[i]; ++ rxdesc->len = cpu_to_edmac(mdp, buf_len << 16); + rxdesc->addr = cpu_to_edmac(mdp, dma_addr); + rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP); + diff --git a/queue-4.4/sh_eth-fix-null-pointer-dereference-in-sh_eth_ring_format.patch b/queue-4.4/sh_eth-fix-null-pointer-dereference-in-sh_eth_ring_format.patch new file mode 100644 index 00000000000..464a6bc0f61 --- /dev/null +++ b/queue-4.4/sh_eth-fix-null-pointer-dereference-in-sh_eth_ring_format.patch @@ -0,0 +1,33 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Sergei Shtylyov +Date: Tue, 8 Mar 2016 01:36:28 +0300 +Subject: sh_eth: fix NULL pointer dereference in sh_eth_ring_format() + +From: Sergei Shtylyov + +[ Upstream commit c1b7fca65070bfadca94dd53a4e6b71cd4f69715 ] + +In a low memory situation, if netdev_alloc_skb() fails on a first RX ring +loop iteration in sh_eth_ring_format(), 'rxdesc' is still NULL. Avoid +kernel oops by adding the 'rxdesc' check after the loop. + +Reported-by: Wolfram Sang +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/renesas/sh_eth.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1212,7 +1212,8 @@ static void sh_eth_ring_format(struct ne + mdp->dirty_rx = (u32) (i - mdp->num_rx_ring); + + /* Mark the last entry as wrapping the ring. */ +- rxdesc->status |= cpu_to_edmac(mdp, RD_RDLE); ++ if (rxdesc) ++ rxdesc->status |= cpu_to_edmac(mdp, RD_RDLE); + + memset(mdp->tx_ring, 0, tx_ringsize); + diff --git a/queue-4.4/tcp-convert-cached-rtt-from-usec-to-jiffies-when-feeding-initial-rto.patch b/queue-4.4/tcp-convert-cached-rtt-from-usec-to-jiffies-when-feeding-initial-rto.patch new file mode 100644 index 00000000000..94b68497603 --- /dev/null +++ b/queue-4.4/tcp-convert-cached-rtt-from-usec-to-jiffies-when-feeding-initial-rto.patch @@ -0,0 +1,30 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: Konstantin Khlebnikov +Date: Sun, 21 Feb 2016 10:12:39 +0300 +Subject: tcp: convert cached rtt from usec to jiffies when feeding initial rto + +From: Konstantin Khlebnikov + +[ Upstream commit 9bdfb3b79e61c60e1a3e2dc05ad164528afa6b8a ] + +Currently it's converted into msecs, thus HZ=1000 intact. + +Signed-off-by: Konstantin Khlebnikov +Fixes: 740b0f1841f6 ("tcp: switch rtt estimations to usec resolution") +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_metrics.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv4/tcp_metrics.c ++++ b/net/ipv4/tcp_metrics.c +@@ -550,7 +550,7 @@ reset: + */ + if (crtt > tp->srtt_us) { + /* Set RTO like tcp_rtt_estimator(), but from cached RTT. */ +- crtt /= 8 * USEC_PER_MSEC; ++ crtt /= 8 * USEC_PER_SEC / HZ; + inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk)); + } else if (tp->srtt_us == 0) { + /* RFC6298: 5.7 We've failed to get a valid RTT sample from diff --git a/queue-4.4/tcp-dccp-remove-obsolete-warn_on-in-icmp-handlers.patch b/queue-4.4/tcp-dccp-remove-obsolete-warn_on-in-icmp-handlers.patch new file mode 100644 index 00000000000..72f821cea82 --- /dev/null +++ b/queue-4.4/tcp-dccp-remove-obsolete-warn_on-in-icmp-handlers.patch @@ -0,0 +1,52 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Eric Dumazet +Date: Wed, 16 Mar 2016 22:52:15 -0700 +Subject: tcp/dccp: remove obsolete WARN_ON() in icmp handlers + +From: Eric Dumazet + +[ Upstream commit e316ea62e3203d524ff0239a40c56d3a39ad1b5c ] + +Now SYN_RECV request sockets are installed in ehash table, an ICMP +handler can find a request socket while another cpu handles an incoming +packet transforming this SYN_RECV request socket into an ESTABLISHED +socket. + +We need to remove the now obsolete WARN_ON(req->sk), since req->sk +is set when a new child is created and added into listener accept queue. + +If this race happens, the ICMP will do nothing special. + +Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table") +Signed-off-by: Eric Dumazet +Reported-by: Ben Lazarus +Reported-by: Neal Cardwell +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/dccp/ipv4.c | 2 -- + net/ipv4/tcp_ipv4.c | 2 -- + 2 files changed, 4 deletions(-) + +--- a/net/dccp/ipv4.c ++++ b/net/dccp/ipv4.c +@@ -204,8 +204,6 @@ void dccp_req_err(struct sock *sk, u64 s + * ICMPs are not backlogged, hence we cannot get an established + * socket here. + */ +- WARN_ON(req->sk); +- + if (!between48(seq, dccp_rsk(req)->dreq_iss, dccp_rsk(req)->dreq_gss)) { + NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + } else { +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -320,8 +320,6 @@ void tcp_req_err(struct sock *sk, u32 se + /* ICMPs are not backlogged, hence we cannot get + * an established socket here. + */ +- WARN_ON(req->sk); +- + if (seq != tcp_rsk(req)->snt_isn) { + NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + } else if (abort) { diff --git a/queue-4.4/tcp-fix-tcpi_segs_in-after-connection-establishment.patch b/queue-4.4/tcp-fix-tcpi_segs_in-after-connection-establishment.patch new file mode 100644 index 00000000000..ab8956f6aeb --- /dev/null +++ b/queue-4.4/tcp-fix-tcpi_segs_in-after-connection-establishment.patch @@ -0,0 +1,60 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Eric Dumazet +Date: Sun, 6 Mar 2016 09:29:21 -0800 +Subject: tcp: fix tcpi_segs_in after connection establishment + +From: Eric Dumazet + +[ Upstream commit a9d99ce28ed359d68cf6f3c1a69038aefedf6d6a ] + +If final packet (ACK) of 3WHS is lost, it appears we do not properly +account the following incoming segment into tcpi_segs_in + +While we are at it, starts segs_in with one, to count the SYN packet. + +We do not yet count number of SYN we received for a request sock, we +might add this someday. + +packetdrill script showing proper behavior after fix : + +// Tests tcpi_segs_in when 3rd packet (ACK) of 3WHS is lost +0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 + +0 bind(3, ..., ...) = 0 + +0 listen(3, 1) = 0 + + +0 < S 0:0(0) win 32792 + +0 > S. 0:0(0) ack 1 ++.020 < P. 1:1001(1000) ack 1 win 32792 + + +0 accept(3, ..., ...) = 4 + ++.000 %{ assert tcpi_segs_in == 2, 'tcpi_segs_in=%d' % tcpi_segs_in }% + +Fixes: 2efd055c53c06 ("tcp: add tcpi_segs_in and tcpi_segs_out to tcp_info") +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_minisocks.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -458,7 +458,7 @@ struct sock *tcp_create_openreq_child(co + + newtp->rcv_wup = newtp->copied_seq = + newtp->rcv_nxt = treq->rcv_isn + 1; +- newtp->segs_in = 0; ++ newtp->segs_in = 1; + + newtp->snd_sml = newtp->snd_una = + newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1; +@@ -818,6 +818,7 @@ int tcp_child_process(struct sock *paren + int ret = 0; + int state = child->sk_state; + ++ tcp_sk(child)->segs_in += max_t(u16, 1, skb_shinfo(skb)->gso_segs); + if (!sock_owned_by_user(child)) { + ret = tcp_rcv_state_process(child, skb); + /* Wakeup parent, send SIGIO */ diff --git a/queue-4.4/tipc-revert-tipc-use-existing-sk_write_queue-for-outgoing-packet-chain.patch b/queue-4.4/tipc-revert-tipc-use-existing-sk_write_queue-for-outgoing-packet-chain.patch new file mode 100644 index 00000000000..970efdce68f --- /dev/null +++ b/queue-4.4/tipc-revert-tipc-use-existing-sk_write_queue-for-outgoing-packet-chain.patch @@ -0,0 +1,206 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Parthasarathy Bhuvaragan +Date: Tue, 1 Mar 2016 11:07:09 +0100 +Subject: tipc: Revert "tipc: use existing sk_write_queue for outgoing packet chain" + +From: Parthasarathy Bhuvaragan + +[ Upstream commit f214fc402967e1bc94ad7f39faa03db5813d6849 ] + +reverts commit 94153e36e709e ("tipc: use existing sk_write_queue for +outgoing packet chain") + +In Commit 94153e36e709e, we assume that we fill & empty the socket's +sk_write_queue within the same lock_sock() session. + +This is not true if the link is congested. During congestion, the +socket lock is released while we wait for the congestion to cease. +This implementation causes a nullptr exception, if the user space +program has several threads accessing the same socket descriptor. + +Consider two threads of the same program performing the following: + Thread1 Thread2 +-------------------- ---------------------- +Enter tipc_sendmsg() Enter tipc_sendmsg() +lock_sock() lock_sock() +Enter tipc_link_xmit(), ret=ELINKCONG spin on socket lock.. +sk_wait_event() : +release_sock() grab socket lock + : Enter tipc_link_xmit(), ret=0 + : release_sock() +Wakeup after congestion +lock_sock() +skb = skb_peek(pktchain); +!! TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong; + +In this case, the second thread transmits the buffers belonging to +both thread1 and thread2 successfully. When the first thread wakeup +after the congestion it assumes that the pktchain is intact and +operates on the skb's in it, which leads to the following exception: + +[2102.439969] BUG: unable to handle kernel NULL pointer dereference at 00000000000000d0 +[2102.440074] IP: [] __tipc_link_xmit+0x2b0/0x4d0 [tipc] +[2102.440074] PGD 3fa3f067 PUD 3fa6b067 PMD 0 +[2102.440074] Oops: 0000 [#1] SMP +[2102.440074] CPU: 2 PID: 244 Comm: sender Not tainted 3.12.28 #1 +[2102.440074] RIP: 0010:[] [] __tipc_link_xmit+0x2b0/0x4d0 [tipc] +[...] +[2102.440074] Call Trace: +[2102.440074] [] ? schedule+0x29/0x70 +[2102.440074] [] ? tipc_node_unlock+0x46/0x170 [tipc] +[2102.440074] [] tipc_link_xmit+0x51/0xf0 [tipc] +[2102.440074] [] tipc_send_stream+0x11e/0x4f0 [tipc] +[2102.440074] [] ? __wake_up_sync+0x20/0x20 +[2102.440074] [] tipc_send_packet+0x1c/0x20 [tipc] +[2102.440074] [] sock_sendmsg+0xa8/0xd0 +[2102.440074] [] ? release_sock+0x145/0x170 +[2102.440074] [] ___sys_sendmsg+0x3d8/0x3e0 +[2102.440074] [] ? _raw_spin_unlock+0xe/0x10 +[2102.440074] [] ? handle_mm_fault+0x6ca/0x9d0 +[2102.440074] [] ? set_next_entity+0x85/0xa0 +[2102.440074] [] ? _raw_spin_unlock_irq+0xe/0x20 +[2102.440074] [] ? finish_task_switch+0x5c/0xc0 +[2102.440074] [] ? __schedule+0x34c/0x950 +[2102.440074] [] __sys_sendmsg+0x42/0x80 +[2102.440074] [] SyS_sendmsg+0x12/0x20 +[2102.440074] [] system_call_fastpath+0x16/0x1b + +In this commit, we maintain the skb list always in the stack. + +Signed-off-by: Parthasarathy Bhuvaragan +Acked-by: Ying Xue +Acked-by: Jon Maloy +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/socket.c | 33 +++++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 14 deletions(-) + +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -673,7 +673,7 @@ static int tipc_sendmcast(struct socket + struct tipc_sock *tsk = tipc_sk(sk); + struct net *net = sock_net(sk); + struct tipc_msg *mhdr = &tsk->phdr; +- struct sk_buff_head *pktchain = &sk->sk_write_queue; ++ struct sk_buff_head pktchain; + struct iov_iter save = msg->msg_iter; + uint mtu; + int rc; +@@ -687,14 +687,16 @@ static int tipc_sendmcast(struct socket + msg_set_nameupper(mhdr, seq->upper); + msg_set_hdr_sz(mhdr, MCAST_H_SIZE); + ++ skb_queue_head_init(&pktchain); ++ + new_mtu: + mtu = tipc_bcast_get_mtu(net); +- rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, pktchain); ++ rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, &pktchain); + if (unlikely(rc < 0)) + return rc; + + do { +- rc = tipc_bcast_xmit(net, pktchain); ++ rc = tipc_bcast_xmit(net, &pktchain); + if (likely(!rc)) + return dsz; + +@@ -704,7 +706,7 @@ new_mtu: + if (!rc) + continue; + } +- __skb_queue_purge(pktchain); ++ __skb_queue_purge(&pktchain); + if (rc == -EMSGSIZE) { + msg->msg_iter = save; + goto new_mtu; +@@ -863,7 +865,7 @@ static int __tipc_sendmsg(struct socket + struct net *net = sock_net(sk); + struct tipc_msg *mhdr = &tsk->phdr; + u32 dnode, dport; +- struct sk_buff_head *pktchain = &sk->sk_write_queue; ++ struct sk_buff_head pktchain; + struct sk_buff *skb; + struct tipc_name_seq *seq; + struct iov_iter save; +@@ -924,17 +926,18 @@ static int __tipc_sendmsg(struct socket + msg_set_hdr_sz(mhdr, BASIC_H_SIZE); + } + ++ skb_queue_head_init(&pktchain); + save = m->msg_iter; + new_mtu: + mtu = tipc_node_get_mtu(net, dnode, tsk->portid); +- rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, pktchain); ++ rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, &pktchain); + if (rc < 0) + return rc; + + do { +- skb = skb_peek(pktchain); ++ skb = skb_peek(&pktchain); + TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong; +- rc = tipc_node_xmit(net, pktchain, dnode, tsk->portid); ++ rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid); + if (likely(!rc)) { + if (sock->state != SS_READY) + sock->state = SS_CONNECTING; +@@ -946,7 +949,7 @@ new_mtu: + if (!rc) + continue; + } +- __skb_queue_purge(pktchain); ++ __skb_queue_purge(&pktchain); + if (rc == -EMSGSIZE) { + m->msg_iter = save; + goto new_mtu; +@@ -1016,7 +1019,7 @@ static int __tipc_send_stream(struct soc + struct net *net = sock_net(sk); + struct tipc_sock *tsk = tipc_sk(sk); + struct tipc_msg *mhdr = &tsk->phdr; +- struct sk_buff_head *pktchain = &sk->sk_write_queue; ++ struct sk_buff_head pktchain; + DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); + u32 portid = tsk->portid; + int rc = -EINVAL; +@@ -1044,17 +1047,19 @@ static int __tipc_send_stream(struct soc + + timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); + dnode = tsk_peer_node(tsk); ++ skb_queue_head_init(&pktchain); + + next: + save = m->msg_iter; + mtu = tsk->max_pkt; + send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE); +- rc = tipc_msg_build(mhdr, m, sent, send, mtu, pktchain); ++ rc = tipc_msg_build(mhdr, m, sent, send, mtu, &pktchain); + if (unlikely(rc < 0)) + return rc; ++ + do { + if (likely(!tsk_conn_cong(tsk))) { +- rc = tipc_node_xmit(net, pktchain, dnode, portid); ++ rc = tipc_node_xmit(net, &pktchain, dnode, portid); + if (likely(!rc)) { + tsk->sent_unacked++; + sent += send; +@@ -1063,7 +1068,7 @@ next: + goto next; + } + if (rc == -EMSGSIZE) { +- __skb_queue_purge(pktchain); ++ __skb_queue_purge(&pktchain); + tsk->max_pkt = tipc_node_get_mtu(net, dnode, + portid); + m->msg_iter = save; +@@ -1077,7 +1082,7 @@ next: + rc = tipc_wait_for_sndpkt(sock, &timeo); + } while (!rc); + +- __skb_queue_purge(pktchain); ++ __skb_queue_purge(&pktchain); + return sent ? sent : rc; + } + diff --git a/queue-4.4/tun-bpf-fix-suspicious-rcu-usage-in-tun_-attach-detach-_filter.patch b/queue-4.4/tun-bpf-fix-suspicious-rcu-usage-in-tun_-attach-detach-_filter.patch new file mode 100644 index 00000000000..df5cbd625fd --- /dev/null +++ b/queue-4.4/tun-bpf-fix-suspicious-rcu-usage-in-tun_-attach-detach-_filter.patch @@ -0,0 +1,207 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Daniel Borkmann +Date: Thu, 31 Mar 2016 02:13:18 +0200 +Subject: tun, bpf: fix suspicious RCU usage in tun_{attach, detach}_filter + +From: Daniel Borkmann + +[ Upstream commit 5a5abb1fa3b05dd6aa821525832644c1e7d2905f ] + +Sasha Levin reported a suspicious rcu_dereference_protected() warning +found while fuzzing with trinity that is similar to this one: + + [ 52.765684] net/core/filter.c:2262 suspicious rcu_dereference_protected() usage! + [ 52.765688] other info that might help us debug this: + [ 52.765695] rcu_scheduler_active = 1, debug_locks = 1 + [ 52.765701] 1 lock held by a.out/1525: + [ 52.765704] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x17/0x20 + [ 52.765721] stack backtrace: + [ 52.765728] CPU: 1 PID: 1525 Comm: a.out Not tainted 4.5.0+ #264 + [...] + [ 52.765768] Call Trace: + [ 52.765775] [] dump_stack+0x85/0xc8 + [ 52.765784] [] lockdep_rcu_suspicious+0xd5/0x110 + [ 52.765792] [] sk_detach_filter+0x82/0x90 + [ 52.765801] [] tun_detach_filter+0x35/0x90 [tun] + [ 52.765810] [] __tun_chr_ioctl+0x354/0x1130 [tun] + [ 52.765818] [] ? selinux_file_ioctl+0x130/0x210 + [ 52.765827] [] tun_chr_ioctl+0x13/0x20 [tun] + [ 52.765834] [] do_vfs_ioctl+0x96/0x690 + [ 52.765843] [] ? security_file_ioctl+0x43/0x60 + [ 52.765850] [] SyS_ioctl+0x79/0x90 + [ 52.765858] [] do_syscall_64+0x62/0x140 + [ 52.765866] [] entry_SYSCALL64_slow_path+0x25/0x25 + +Same can be triggered with PROVE_RCU (+ PROVE_RCU_REPEATEDLY) enabled +from tun_attach_filter() when user space calls ioctl(tun_fd, TUN{ATTACH, +DETACH}FILTER, ...) for adding/removing a BPF filter on tap devices. + +Since the fix in f91ff5b9ff52 ("net: sk_{detach|attach}_filter() rcu +fixes") sk_attach_filter()/sk_detach_filter() now dereferences the +filter with rcu_dereference_protected(), checking whether socket lock +is held in control path. + +Since its introduction in 994051625981 ("tun: socket filter support"), +tap filters are managed under RTNL lock from __tun_chr_ioctl(). Thus the +sock_owned_by_user(sk) doesn't apply in this specific case and therefore +triggers the false positive. + +Extend the BPF API with __sk_attach_filter()/__sk_detach_filter() pair +that is used by tap filters and pass in lockdep_rtnl_is_held() for the +rcu_dereference_protected() checks instead. + +Reported-by: Sasha Levin +Signed-off-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 8 +++++--- + include/linux/filter.h | 4 ++++ + net/core/filter.c | 33 +++++++++++++++++++++------------ + 3 files changed, 30 insertions(+), 15 deletions(-) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -621,7 +621,8 @@ static int tun_attach(struct tun_struct + + /* Re-attach the filter to persist device */ + if (!skip_filter && (tun->filter_attached == true)) { +- err = sk_attach_filter(&tun->fprog, tfile->socket.sk); ++ err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, ++ lockdep_rtnl_is_held()); + if (!err) + goto out; + } +@@ -1804,7 +1805,7 @@ static void tun_detach_filter(struct tun + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); +- sk_detach_filter(tfile->socket.sk); ++ __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); + } + + tun->filter_attached = false; +@@ -1817,7 +1818,8 @@ static int tun_attach_filter(struct tun_ + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); +- ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); ++ ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, ++ lockdep_rtnl_is_held()); + if (ret) { + tun_detach_filter(tun, i); + return ret; +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -446,8 +446,12 @@ int bpf_prog_create_from_user(struct bpf + void bpf_prog_destroy(struct bpf_prog *fp); + + int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); ++int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, ++ bool locked); + int sk_attach_bpf(u32 ufd, struct sock *sk); + int sk_detach_filter(struct sock *sk); ++int __sk_detach_filter(struct sock *sk, bool locked); ++ + int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, + unsigned int len); + +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -1139,7 +1139,8 @@ void bpf_prog_destroy(struct bpf_prog *f + } + EXPORT_SYMBOL_GPL(bpf_prog_destroy); + +-static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk) ++static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk, ++ bool locked) + { + struct sk_filter *fp, *old_fp; + +@@ -1155,10 +1156,8 @@ static int __sk_attach_prog(struct bpf_p + return -ENOMEM; + } + +- old_fp = rcu_dereference_protected(sk->sk_filter, +- sock_owned_by_user(sk)); ++ old_fp = rcu_dereference_protected(sk->sk_filter, locked); + rcu_assign_pointer(sk->sk_filter, fp); +- + if (old_fp) + sk_filter_uncharge(sk, old_fp); + +@@ -1175,7 +1174,8 @@ static int __sk_attach_prog(struct bpf_p + * occurs or there is insufficient memory for the filter a negative + * errno code is returned. On success the return is zero. + */ +-int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) ++int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, ++ bool locked) + { + unsigned int fsize = bpf_classic_proglen(fprog); + unsigned int bpf_fsize = bpf_prog_size(fprog->len); +@@ -1213,7 +1213,7 @@ int sk_attach_filter(struct sock_fprog * + if (IS_ERR(prog)) + return PTR_ERR(prog); + +- err = __sk_attach_prog(prog, sk); ++ err = __sk_attach_prog(prog, sk, locked); + if (err < 0) { + __bpf_prog_release(prog); + return err; +@@ -1221,7 +1221,12 @@ int sk_attach_filter(struct sock_fprog * + + return 0; + } +-EXPORT_SYMBOL_GPL(sk_attach_filter); ++EXPORT_SYMBOL_GPL(__sk_attach_filter); ++ ++int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) ++{ ++ return __sk_attach_filter(fprog, sk, sock_owned_by_user(sk)); ++} + + int sk_attach_bpf(u32 ufd, struct sock *sk) + { +@@ -1240,7 +1245,7 @@ int sk_attach_bpf(u32 ufd, struct sock * + return -EINVAL; + } + +- err = __sk_attach_prog(prog, sk); ++ err = __sk_attach_prog(prog, sk, sock_owned_by_user(sk)); + if (err < 0) { + bpf_prog_put(prog); + return err; +@@ -1913,7 +1918,7 @@ static int __init register_sk_filter_ops + } + late_initcall(register_sk_filter_ops); + +-int sk_detach_filter(struct sock *sk) ++int __sk_detach_filter(struct sock *sk, bool locked) + { + int ret = -ENOENT; + struct sk_filter *filter; +@@ -1921,8 +1926,7 @@ int sk_detach_filter(struct sock *sk) + if (sock_flag(sk, SOCK_FILTER_LOCKED)) + return -EPERM; + +- filter = rcu_dereference_protected(sk->sk_filter, +- sock_owned_by_user(sk)); ++ filter = rcu_dereference_protected(sk->sk_filter, locked); + if (filter) { + RCU_INIT_POINTER(sk->sk_filter, NULL); + sk_filter_uncharge(sk, filter); +@@ -1931,7 +1935,12 @@ int sk_detach_filter(struct sock *sk) + + return ret; + } +-EXPORT_SYMBOL_GPL(sk_detach_filter); ++EXPORT_SYMBOL_GPL(__sk_detach_filter); ++ ++int sk_detach_filter(struct sock *sk) ++{ ++ return __sk_detach_filter(sk, sock_owned_by_user(sk)); ++} + + int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, + unsigned int len) diff --git a/queue-4.4/tunnel-clear-ipcb-skb-opt-before-dst_link_failure-called.patch b/queue-4.4/tunnel-clear-ipcb-skb-opt-before-dst_link_failure-called.patch new file mode 100644 index 00000000000..060a2acb01d --- /dev/null +++ b/queue-4.4/tunnel-clear-ipcb-skb-opt-before-dst_link_failure-called.patch @@ -0,0 +1,89 @@ +From foo@baz Sat Apr 16 10:02:52 PDT 2016 +From: Bernie Harris +Date: Mon, 22 Feb 2016 12:58:05 +1300 +Subject: tunnel: Clear IPCB(skb)->opt before dst_link_failure called + +From: Bernie Harris + +[ Upstream commit 5146d1f151122e868e594c7b45115d64825aee5f ] + +IPCB may contain data from previous layers (in the observed case the +qdisc layer). In the observed scenario, the data was misinterpreted as +ip header options, which later caused the ihl to be set to an invalid +value (<5). This resulted in an infinite loop in the mips implementation +of ip_fast_csum. + +This patch clears IPCB(skb)->opt before dst_link_failure can be called for +various types of tunnels. This change only applies to encapsulated ipv4 +packets. + +The code introduced in 11c21a30 which clears all of IPCB has been removed +to be consistent with these changes, and instead the opt field is cleared +unconditionally in ip_tunnel_xmit. The change in ip_tunnel_xmit applies to +SIT, GRE, and IPIP tunnels. + +The relevant vti, l2tp, and pptp functions already contain similar code for +clearing the IPCB. + +Signed-off-by: Bernie Harris +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_tunnel.c | 3 ++- + net/ipv4/udp_tunnel.c | 2 ++ + net/ipv6/ip6_gre.c | 2 ++ + net/ipv6/ip6_tunnel.c | 2 ++ + 4 files changed, 8 insertions(+), 1 deletion(-) + +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -663,6 +663,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, + inner_iph = (const struct iphdr *)skb_inner_network_header(skb); + connected = (tunnel->parms.iph.daddr != 0); + ++ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ++ + dst = tnl_params->daddr; + if (dst == 0) { + /* NBMA tunnel */ +@@ -760,7 +762,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, + tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { + tunnel->err_count--; + +- memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + dst_link_failure(skb); + } else + tunnel->err_count = 0; +--- a/net/ipv4/udp_tunnel.c ++++ b/net/ipv4/udp_tunnel.c +@@ -89,6 +89,8 @@ int udp_tunnel_xmit_skb(struct rtable *r + uh->source = src_port; + uh->len = htons(skb->len); + ++ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ++ + udp_set_csum(nocheck, skb, src, dst, skb->len); + + return iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -778,6 +778,8 @@ static inline int ip6gre_xmit_ipv4(struc + __u32 mtu; + int err; + ++ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ++ + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + encap_limit = t->parms.encap_limit; + +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1180,6 +1180,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str + u8 tproto; + int err; + ++ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ++ + tproto = ACCESS_ONCE(t->parms.proto); + if (tproto != IPPROTO_IPIP && tproto != 0) + return -1; diff --git a/queue-4.4/tuntap-restore-default-qdisc.patch b/queue-4.4/tuntap-restore-default-qdisc.patch new file mode 100644 index 00000000000..166421f87dc --- /dev/null +++ b/queue-4.4/tuntap-restore-default-qdisc.patch @@ -0,0 +1,52 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Jason Wang +Date: Fri, 8 Apr 2016 13:26:48 +0800 +Subject: tuntap: restore default qdisc + +From: Jason Wang + +[ Upstream commit 016adb7260f481168c03e09f785184d6d5278894 ] + +After commit f84bb1eac027 ("net: fix IFF_NO_QUEUE for drivers using +alloc_netdev"), default qdisc was changed to noqueue because +tuntap does not set tx_queue_len during .setup(). This patch restores +default qdisc by setting tx_queue_len in tun_setup(). + +Fixes: f84bb1eac027 ("net: fix IFF_NO_QUEUE for drivers using alloc_netdev") +Cc: Phil Sutter +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin +Acked-by: Phil Sutter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1001,7 +1001,6 @@ static void tun_net_init(struct net_devi + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; +- dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */ + break; + + case IFF_TAP: +@@ -1013,7 +1012,6 @@ static void tun_net_init(struct net_devi + + eth_hw_addr_random(dev); + +- dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */ + break; + } + } +@@ -1464,6 +1462,8 @@ static void tun_setup(struct net_device + + dev->ethtool_ops = &tun_ethtool_ops; + dev->destructor = tun_free_netdev; ++ /* We prefer our own queue length */ ++ dev->tx_queue_len = TUN_READQ_SIZE; + } + + /* Trivial set of netlink ops to allow deleting tun or tap diff --git a/queue-4.4/udp6-fix-udp-ipv6-encap-resubmit-path.patch b/queue-4.4/udp6-fix-udp-ipv6-encap-resubmit-path.patch new file mode 100644 index 00000000000..2dbee8ea22b --- /dev/null +++ b/queue-4.4/udp6-fix-udp-ipv6-encap-resubmit-path.patch @@ -0,0 +1,43 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Bill Sommerfeld +Date: Fri, 4 Mar 2016 14:47:21 -0800 +Subject: udp6: fix UDP/IPv6 encap resubmit path + +From: Bill Sommerfeld + +[ Upstream commit 59dca1d8a6725a121dae6c452de0b2611d5865dc ] + +IPv4 interprets a negative return value from a protocol handler as a +request to redispatch to a new protocol. In contrast, IPv6 interprets a +negative value as an error, and interprets a positive value as a request +for redispatch. + +UDP for IPv6 was unaware of this difference. Change __udp6_lib_rcv() to +return a positive value for redispatch. Note that the socket's +encap_rcv hook still needs to return a negative value to request +dispatch, and in the case of IPv6 packets, adjust IP6CB(skb)->nhoff to +identify the byte containing the next protocol. + +Signed-off-by: Bill Sommerfeld +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/udp.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -916,11 +916,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, + ret = udpv6_queue_rcv_skb(sk, skb); + sock_put(sk); + +- /* a return value > 0 means to resubmit the input, but +- * it wants the return to be -protocol, or 0 +- */ ++ /* a return value > 0 means to resubmit the input */ + if (ret > 0) +- return -ret; ++ return ret; + + return 0; + } diff --git a/queue-4.4/usbnet-cleanup-after-bind-in-probe.patch b/queue-4.4/usbnet-cleanup-after-bind-in-probe.patch new file mode 100644 index 00000000000..231880c9c32 --- /dev/null +++ b/queue-4.4/usbnet-cleanup-after-bind-in-probe.patch @@ -0,0 +1,39 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Oliver Neukum +Date: Mon, 7 Mar 2016 11:31:10 +0100 +Subject: usbnet: cleanup after bind() in probe() + +From: Oliver Neukum + +[ Upstream commit 1666984c8625b3db19a9abc298931d35ab7bc64b ] + +In case bind() works, but a later error forces bailing +in probe() in error cases work and a timer may be scheduled. +They must be killed. This fixes an error case related to +the double free reported in +http://www.spinics.net/lists/netdev/msg367669.html +and needs to go on top of Linus' fix to cdc-ncm. + +Signed-off-by: Oliver Neukum +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/usbnet.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -1766,6 +1766,13 @@ out3: + if (info->unbind) + info->unbind (dev, udev); + out1: ++ /* subdrivers must undo all they did in bind() if they ++ * fail it, but we may fail later and a deferred kevent ++ * may trigger an error resubmitting itself and, worse, ++ * schedule a timer. So we kill it all just in case. ++ */ ++ cancel_work_sync(&dev->kevent); ++ del_timer_sync(&dev->delay); + free_netdev(net); + out: + return status; diff --git a/queue-4.4/vxlan-fix-missing-options_len-update-on-rx-with-collect-metadata.patch b/queue-4.4/vxlan-fix-missing-options_len-update-on-rx-with-collect-metadata.patch new file mode 100644 index 00000000000..5e1a5be33e5 --- /dev/null +++ b/queue-4.4/vxlan-fix-missing-options_len-update-on-rx-with-collect-metadata.patch @@ -0,0 +1,42 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: Daniel Borkmann +Date: Wed, 2 Mar 2016 02:32:08 +0100 +Subject: vxlan: fix missing options_len update on RX with collect metadata + +From: Daniel Borkmann + +[ Upstream commit 4024fcf70556311521e7b6cf79fa50e16f31013a ] + +When signalling to metadata consumers that the metadata_dst entry +carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT), +the dst's vxlan_metadata information is populated, but options_len +is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for +options_len before extracting the data through ip_tunnel_info_opts_get(). + +Geneve uses ip_tunnel_info_opts_set() helper in receive path, which +sets options_len internally, vxlan however uses ip_tunnel_info_opts(), +so when filling vxlan_metadata, we do need to update options_len. + +Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.") +Signed-off-by: Daniel Borkmann +Acked-by: Thomas Graf +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -1306,8 +1306,10 @@ static int vxlan_udp_encap_recv(struct s + gbp = (struct vxlanhdr_gbp *)vxh; + md->gbp = ntohs(gbp->policy_id); + +- if (tun_dst) ++ if (tun_dst) { + tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT; ++ tun_dst->u.tun_info.options_len = sizeof(*md); ++ } + + if (gbp->dont_learn) + md->gbp |= VXLAN_GBP_DONT_LEARN; diff --git a/queue-4.4/xfrm-fix-crash-observed-during-device-unregistration-and-decryption.patch b/queue-4.4/xfrm-fix-crash-observed-during-device-unregistration-and-decryption.patch new file mode 100644 index 00000000000..92f91a89053 --- /dev/null +++ b/queue-4.4/xfrm-fix-crash-observed-during-device-unregistration-and-decryption.patch @@ -0,0 +1,77 @@ +From foo@baz Sat Apr 16 10:02:53 PDT 2016 +From: "subashab@codeaurora.org" +Date: Wed, 23 Mar 2016 22:39:50 -0600 +Subject: xfrm: Fix crash observed during device unregistration and decryption + +From: "subashab@codeaurora.org" + +[ Upstream commit 071d36bf21bcc837be00cea55bcef8d129e7f609 ] + +A crash is observed when a decrypted packet is processed in receive +path. get_rps_cpus() tries to dereference the skb->dev fields but it +appears that the device is freed from the poison pattern. + +[] get_rps_cpu+0x94/0x2f0 +[] netif_rx_internal+0x140/0x1cc +[] netif_rx+0x74/0x94 +[] xfrm_input+0x754/0x7d0 +[] xfrm_input_resume+0x10/0x1c +[] esp_input_done+0x20/0x30 +[] process_one_work+0x244/0x3fc +[] worker_thread+0x2f8/0x418 +[] kthread+0xe0/0xec + +-013|get_rps_cpu( + | dev = 0xFFFFFFC08B688000, + | skb = 0xFFFFFFC0C76AAC00 -> ( + | dev = 0xFFFFFFC08B688000 -> ( + | name = +"...................................................... + | name_hlist = (next = 0xAAAAAAAAAAAAAAAA, pprev = +0xAAAAAAAAAAA + +Following are the sequence of events observed - + +- Encrypted packet in receive path from netdevice is queued +- Encrypted packet queued for decryption (asynchronous) +- Netdevice brought down and freed +- Packet is decrypted and returned through callback in esp_input_done +- Packet is queued again for process in network stack using netif_rx + +Since the device appears to have been freed, the dereference of +skb->dev in get_rps_cpus() leads to an unhandled page fault +exception. + +Fix this by holding on to device reference when queueing packets +asynchronously and releasing the reference on call back return. + +v2: Make the change generic to xfrm as mentioned by Steffen and +update the title to xfrm + +Suggested-by: Herbert Xu +Signed-off-by: Jerome Stanislaus +Signed-off-by: Subash Abhinov Kasiviswanathan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_input.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@ -292,12 +292,15 @@ int xfrm_input(struct sk_buff *skb, int + XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; + + skb_dst_force(skb); ++ dev_hold(skb->dev); + + nexthdr = x->type->input(x, skb); + + if (nexthdr == -EINPROGRESS) + return 0; + resume: ++ dev_put(skb->dev); ++ + spin_lock(&x->lock); + if (nexthdr <= 0) { + if (nexthdr == -EBADMSG) {