Skip to contentSkip to conversation

4.12.14-stable review

PATCH In review Greg Kroah-Hartman 4 participants 58 messages Sep 18, 2017 – Sep 20, 2017 Stable branch

lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 4.12.14-stable review

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Wed Sep 20 09:09:47 UTC 2017. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.12.14-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.12.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 4.12.14-rc1

Song Liu <[email protected]>
md/raid5: release/flush io in raid5_do_work()

Shaohua Li <[email protected]>
md/raid1/10: reset bio allocated from mempool

Eric Biggers <[email protected]>
idr: remove WARN_ON_ONCE() when trying to replace negative ID

Miklos Szeredi <[email protected]>
fuse: allow server to run in different pid_ns

Andy Lutomirski <[email protected]>
x86/switch_to/64: Rewrite FS/GS switching yet again to fix AMD CPUs

Andy Lutomirski <[email protected]>
x86/fsgsbase/64: Report FSBASE and GSBASE correctly in core dumps

Andy Lutomirski <[email protected]>
x86/fsgsbase/64: Fully initialize FS and GS state in start_thread_common

Jaegeuk Kim <[email protected]>
f2fs: check hot_data for roll-forward recovery

Jaegeuk Kim <[email protected]>
f2fs: let fill_super handle roll-forward errors

Marcelo Ricardo Leitner <[email protected]>
sctp: fix missing wake ups in some situations

Eric Dumazet <[email protected]>
ipv6: fix typo in fib6_net_exit()

Sabrina Dubroca <[email protected]>
ipv6: fix memory leak with multiple tables during netns destruction

Xin Long <[email protected]>
ip6_gre: update mtu properly in ip6gre_err

Jason Wang <[email protected]>
vhost_net: correctly check tx avail during rx busy polling

Claudiu Manoil <[email protected]>
gianfar: Fix Tx flow control deactivation

Jesper Dangaard Brouer <[email protected]>
Revert "net: fix percpu memory leaks"

Jesper Dangaard Brouer <[email protected]>
Revert "net: use lib/percpu_counter API for fragmentation mem accounting"

Ido Schimmel <[email protected]>
bridge: switchdev: Clear forward mark when transmitting packet

Ido Schimmel <[email protected]>
mlxsw: spectrum: Forbid linking to devices that have uppers

Andrew Lunn <[email protected]>
net: fec: Allow reception of frames bigger than 1522 bytes

Florian Fainelli <[email protected]>
Revert "net: phy: Correctly process PHY_HALTED in phy_stop_machine()"

Tal Gilboa <[email protected]>
net/mlx5e: Fix CQ moderation mode not set properly

Moshe Shemesh <[email protected]>
net/mlx5e: Fix inline header size for small packets

Shahar Klein <[email protected]>
net/mlx5: E-Switch, Unload the representors in the correct order

Paul Blakey <[email protected]>
net/mlx5e: Properly resolve TC offloaded ipv6 vxlan tunnel source address

Inbar Karmy <[email protected]>
net/mlx5e: Don't override user RSS upon set channels

Eran Ben Elisha <[email protected]>
net/mlx5e: Fix dangling page pointer on DMA mapping error

Noa Osherovich <[email protected]>
net/mlx5: Fix arm SRQ command for ISSI version 0

Huy Nguyen <[email protected]>
net/mlx5e: Fix DCB_CAP_ATTR_DCBX capability for DCBNL getcap.

Huy Nguyen <[email protected]>
net/mlx5e: Check for qos capability in dcbnl_initialize

Florian Fainelli <[email protected]>
net: dsa: bcm_sf2: Fix number of CFP entries for BCM7278

Eric Dumazet <[email protected]>
kcm: do not attach PF_KCM sockets to avoid deadlock

Benjamin Poirier <[email protected]>
packet: Don't write vnet header beyond end of buffer

Xin Long <[email protected]>
ipv6: do not set sk_destruct in IPV6_ADDRFORM sockopt

Xin Long <[email protected]>
ipv6: set dst.obsolete when a cached route has expired

Stefano Brivio <[email protected]>
cxgb4: Fix stack out-of-bounds read due to wrong size to t4_record_mbox()

Antoine Tenart <[email protected]>
net: mvpp2: fix the mac address used when using PPv2.2

Paolo Abeni <[email protected]>
udp6: set rx_dst_cookie on rx_dst updates

stephen hemminger <[email protected]>
netvsc: fix deadlock betwen link status and removal

Florian Fainelli <[email protected]>
net: systemport: Free DMA coherent descriptors on errors

Florian Fainelli <[email protected]>
net: bcmgenet: Be drop monitor friendly

Florian Fainelli <[email protected]>
net: systemport: Be drop monitor friendly

Bob Peterson <[email protected]>
tipc: Fix tipc_sk_reinit handling of -EAGAIN

Arnd Bergmann <[email protected]>
qlge: avoid memcpy buffer overflow

Stefano Brivio <[email protected]>
sctp: Avoid out-of-bounds reads from address storage

Florian Fainelli <[email protected]>
fsl/man: Inherit parent device and of_node

Daniel Borkmann <[email protected]>
bpf: fix map value attribute for hash of maps

Eric Dumazet <[email protected]>
udp: on peeking bad csum, drop packets even if not at head

Sabrina Dubroca <[email protected]>
macsec: add genl family module alias

Wei Wang <[email protected]>
ipv6: fix sparse warning on rt6i_node

Wei Wang <[email protected]>
ipv6: add rcu grace period before freeing fib6_node

Stefano Brivio <[email protected]>
ipv6: accept 64k - 1 packet length in ip6_find_1stfragopt()

-------------

Diffstat:

 Makefile                                           |   4 +-
 arch/x86/include/asm/elf.h                         |   5 +-
 arch/x86/kernel/process_64.c                       | 236 ++++++++++++---------
 drivers/md/raid1.c                                 |  19 +-
 drivers/md/raid10.c                                |  35 ++-
 drivers/md/raid5.c                                 |   4 +
 drivers/net/dsa/bcm_sf2.c                          |   4 +
 drivers/net/dsa/bcm_sf2.h                          |   1 +
 drivers/net/dsa/bcm_sf2_cfp.c                      |   8 +-
 drivers/net/ethernet/broadcom/bcmsysport.c         |   4 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet.c     |   4 +-
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |   6 +-
 drivers/net/ethernet/freescale/fec_main.c          |   8 +-
 drivers/net/ethernet/freescale/fman/mac.c          |   2 +
 drivers/net/ethernet/freescale/gianfar.c           |   2 +-
 drivers/net/ethernet/marvell/mvpp2.c               |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en.h       |   1 +
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |  24 ++-
 .../net/ethernet/mellanox/mlx5/core/en_ethtool.c   |   6 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |   1 +
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    |   8 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c    |  17 +-
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/srq.c      |  12 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   6 +
 drivers/net/ethernet/qlogic/qlge/qlge_dbg.c        |   2 +-
 drivers/net/hyperv/netvsc_drv.c                    |   7 +-
 drivers/net/macsec.c                               |   1 +
 drivers/net/phy/phy.c                              |   3 -
 drivers/vhost/net.c                                |   7 +-
 fs/f2fs/recovery.c                                 |   4 +-
 fs/fuse/dev.c                                      |  13 +-
 fs/fuse/file.c                                     |   3 -
 include/linux/netdevice.h                          |   2 +
 include/net/inet_frag.h                            |  35 +--
 include/net/ip6_fib.h                              |  31 ++-
 include/net/udp.h                                  |   2 +-
 kernel/bpf/hashtab.c                               |  30 +--
 lib/idr.c                                          |   2 +-
 net/bridge/br_device.c                             |   3 +
 net/core/datagram.c                                |   2 +-
 net/core/dev.c                                     |   3 +-
 net/ieee802154/6lowpan/reassembly.c                |  11 +-
 net/ipv4/inet_fragment.c                           |   4 +-
 net/ipv4/ip_fragment.c                             |  12 +-
 net/ipv4/udp.c                                     |   3 +-
 net/ipv6/addrconf.c                                |   2 +-
 net/ipv6/ip6_fib.c                                 |  60 ++++--
 net/ipv6/ip6_gre.c                                 |   4 +-
 net/ipv6/ipv6_sockglue.c                           |   1 -
 net/ipv6/netfilter/nf_conntrack_reasm.c            |  12 +-
 net/ipv6/output_core.c                             |   6 +-
 net/ipv6/reassembly.c                              |  12 +-
 net/ipv6/route.c                                   |  20 +-
 net/ipv6/udp.c                                     |  11 +-
 net/kcm/kcmsock.c                                  |   4 +
 net/packet/af_packet.c                             |  12 +-
 net/sctp/sctp_diag.c                               |   7 +-
 net/sctp/socket.c                                  |   3 +-
 net/sctp/ulpqueue.c                                |   3 +-
 net/tipc/socket.c                                  |   6 +-
 62 files changed, 466 insertions(+), 300 deletions(-)
author maintainer
#1 lore raw

PATCH 1/52 ipv6: accept 64k - 1 packet length in ip6_find_1stfragopt()

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefano Brivio <[email protected]>

[ Upstream commit 3de33e1ba0506723ab25734e098cf280ecc34756 ]

A packet length of exactly IPV6_MAXPLEN is allowed, we should refuse parsing options only if the size is 64KiB or more.

While at it, remove one extra variable and one assignment which were also introduced by the commit that introduced the size check. Checking the sum 'offset + len' and only later adding 'len' to 'offset' doesn't provide any advantage over directly summing to 'offset' and checking it.

Fixes 6399f1fae4ec ("ipv6: avoid overflow of offset in ip6_find_1stfragopt")
---
 net/ipv6/output_core.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
net/ipv6/output_core.c +2 -4
@@ -86,7 +86,6 @@ int ip6_find_1stfragopt(struct sk_buff *
 
 	while (offset <= packet_len) {
 		struct ipv6_opt_hdr *exthdr;
-		unsigned int len;
 
 		switch (**nexthdr) {
 
@@ -112,10 +111,9 @@ int ip6_find_1stfragopt(struct sk_buff *
 
 		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
 						 offset);
-		len = ipv6_optlen(exthdr);
-		if (len + offset >= IPV6_MAXPLEN)
+		offset += ipv6_optlen(exthdr);
+		if (offset > IPV6_MAXPLEN)
 			return -EINVAL;
-		offset += len;
 		*nexthdr = &exthdr->nexthdr;
 	}
 
author maintainer
#2 lore raw

PATCH 2/52 ipv6: add rcu grace period before freeing fib6_node

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wei Wang <[email protected]>

[ Upstream commit c5cff8561d2d0006e972bd114afd51f082fee77c ]

We currently keep rt->rt6i_node pointing to the fib6_node for the route. And some functions make use of this pointer to dereference the fib6_node from rt structure, e.g. rt6_check(). However, as there is neither refcount nor rcu taken when dereferencing rt->rt6i_node, it could potentially cause crashes as rt->rt6i_node could be set to NULL by other CPUs when doing a route deletion.
This patch introduces an rcu grace period before freeing fib6_node and makes sure the functions that dereference it takes rcu_read_lock().

Note: there is no "Fixes" tag because this bug was there in a very early stage.

---
 include/net/ip6_fib.h |   29 ++++++++++++++++++++++++++++-
 net/ipv6/ip6_fib.c    |   20 ++++++++++++++++----
 net/ipv6/route.c      |   14 +++++++++++---
 3 files changed, 55 insertions(+), 8 deletions(-)
include/net/ip6_fib.h +28 -1
@@ -70,6 +70,7 @@ struct fib6_node {
 	__u16			fn_flags;
 	int			fn_sernum;
 	struct rt6_info		*rr_ptr;
+	struct rcu_head		rcu;
 };
 
 #ifndef CONFIG_IPV6_SUBTREES
@@ -167,13 +168,39 @@ static inline void rt6_update_expires(st
 	rt0->rt6i_flags |= RTF_EXPIRES;
 }
 
+/* Function to safely get fn->sernum for passed in rt
+ * and store result in passed in cookie.
+ * Return true if we can get cookie safely
+ * Return false if not
+ */
+static inline bool rt6_get_cookie_safe(const struct rt6_info *rt,
+				       u32 *cookie)
+{
+	struct fib6_node *fn;
+	bool status = false;
+
+	rcu_read_lock();
+	fn = rcu_dereference(rt->rt6i_node);
+
+	if (fn) {
+		*cookie = fn->fn_sernum;
+		status = true;
+	}
+
+	rcu_read_unlock();
+	return status;
+}
+
 static inline u32 rt6_get_cookie(const struct rt6_info *rt)
 {
+	u32 cookie = 0;
+
 	if (rt->rt6i_flags & RTF_PCPU ||
 	    (unlikely(rt->dst.flags & DST_NOCACHE) && rt->dst.from))
 		rt = (struct rt6_info *)(rt->dst.from);
+	rt6_get_cookie_safe(rt, &cookie);
 
-	return rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
+	return cookie;
 }
 
 static inline void ip6_rt_put(struct rt6_info *rt)
net/ipv6/ip6_fib.c +16 -4
@@ -148,11 +148,23 @@ static struct fib6_node *node_alloc(void
 	return fn;
 }
 
-static void node_free(struct fib6_node *fn)
+static void node_free_immediate(struct fib6_node *fn)
+{
+	kmem_cache_free(fib6_node_kmem, fn);
+}
+
+static void node_free_rcu(struct rcu_head *head)
 {
+	struct fib6_node *fn = container_of(head, struct fib6_node, rcu);
+
 	kmem_cache_free(fib6_node_kmem, fn);
 }
 
+static void node_free(struct fib6_node *fn)
+{
+	call_rcu(&fn->rcu, node_free_rcu);
+}
+
 static void rt6_rcu_free(struct rt6_info *rt)
 {
 	call_rcu(&rt->dst.rcu_head, dst_rcu_free);
@@ -599,9 +611,9 @@ insert_above:
 
 		if (!in || !ln) {
 			if (in)
-				node_free(in);
+				node_free_immediate(in);
 			if (ln)
-				node_free(ln);
+				node_free_immediate(ln);
 			return ERR_PTR(-ENOMEM);
 		}
 
@@ -1035,7 +1047,7 @@ int fib6_add(struct fib6_node *root, str
 				   root, and then (in failure) stale node
 				   in main tree.
 				 */
-				node_free(sfn);
+				node_free_immediate(sfn);
 				err = PTR_ERR(sn);
 				goto failure;
 			}
net/ipv6/route.c +11 -3
@@ -1289,7 +1289,9 @@ static void rt6_dst_from_metrics_check(s
 
 static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
 {
-	if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
+	u32 rt_cookie;
+
+	if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
 		return NULL;
 
 	if (rt6_check_expired(rt))
@@ -1357,8 +1359,14 @@ static void ip6_link_failure(struct sk_b
 		if (rt->rt6i_flags & RTF_CACHE) {
 			dst_hold(&rt->dst);
 			ip6_del_rt(rt);
-		} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
-			rt->rt6i_node->fn_sernum = -1;
+		} else {
+			struct fib6_node *fn;
+
+			rcu_read_lock();
+			fn = rcu_dereference(rt->rt6i_node);
+			if (fn && (rt->rt6i_flags & RTF_DEFAULT))
+				fn->fn_sernum = -1;
+			rcu_read_unlock();
 		}
 	}
 }
author maintainer
#3 lore raw

PATCH 3/52 ipv6: fix sparse warning on rt6i_node

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wei Wang <[email protected]>

[ Upstream commit 4e587ea71bf924f7dac621f1351653bd41e446cb ]

Commit c5cff8561d2d adds rcu grace period before freeing fib6_node. This generates a new sparse warning on rt->rt6i_node related code:
net/ipv6/route.c:1394:30: error: incompatible types in comparison expression (different address spaces) ./include/net/ip6_fib.h:187:14: error: incompatible types in comparison expression (different address spaces)

This commit adds "__rcu" tag for rt6i_node and makes sure corresponding rcu API is used for it.
After this fix, sparse no longer generates the above warning.

Fixes c5cff8561d2d ("ipv6: add rcu grace period before freeing fib6_node")
---
 include/net/ip6_fib.h |    2 +-
 net/ipv6/addrconf.c   |    2 +-
 net/ipv6/ip6_fib.c    |   11 +++++++----
 net/ipv6/route.c      |    3 ++-
 4 files changed, 11 insertions(+), 7 deletions(-)
include/net/ip6_fib.h +1 -1
@@ -105,7 +105,7 @@ struct rt6_info {
 	 * the same cache line.
 	 */
 	struct fib6_table		*rt6i_table;
-	struct fib6_node		*rt6i_node;
+	struct fib6_node __rcu		*rt6i_node;
 
 	struct in6_addr			rt6i_gateway;
 
net/ipv6/addrconf.c +1 -1
@@ -5541,7 +5541,7 @@ static void __ipv6_ifa_notify(int event,
 		 * our DAD process, so we don't need
 		 * to do it again
 		 */
-		if (!(ifp->rt->rt6i_node))
+		if (!rcu_access_pointer(ifp->rt->rt6i_node))
 			ip6_ins_rt(ifp->rt);
 		if (ifp->idev->cnf.forwarding)
 			addrconf_join_anycast(ifp);
net/ipv6/ip6_fib.c +7 -4
@@ -887,7 +887,7 @@ add:
 
 		rt->dst.rt6_next = iter;
 		*ins = rt;
-		rt->rt6i_node = fn;
+		rcu_assign_pointer(rt->rt6i_node, fn);
 		atomic_inc(&rt->rt6i_ref);
 		if (!info->skip_notify)
 			inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags);
@@ -913,7 +913,7 @@ add:
 			return err;
 
 		*ins = rt;
-		rt->rt6i_node = fn;
+		rcu_assign_pointer(rt->rt6i_node, fn);
 		rt->dst.rt6_next = iter->dst.rt6_next;
 		atomic_inc(&rt->rt6i_ref);
 		if (!info->skip_notify)
@@ -1475,8 +1475,9 @@ static void fib6_del_route(struct fib6_n
 
 int fib6_del(struct rt6_info *rt, struct nl_info *info)
 {
+	struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node,
+				    lockdep_is_held(&rt->rt6i_table->tb6_lock));
 	struct net *net = info->nl_net;
-	struct fib6_node *fn = rt->rt6i_node;
 	struct rt6_info **rtp;
 
 #if RT6_DEBUG >= 2
@@ -1665,7 +1666,9 @@ static int fib6_clean_node(struct fib6_w
 			if (res) {
 #if RT6_DEBUG >= 2
 				pr_debug("%s: del failed: rt=%p@%p err=%d\n",
-					 __func__, rt, rt->rt6i_node, res);
+					 __func__, rt,
+					 rcu_access_pointer(rt->rt6i_node),
+					 res);
 #endif
 				continue;
 			}
net/ipv6/route.c +2 -1
@@ -1383,7 +1383,8 @@ static void rt6_do_update_pmtu(struct rt
 static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
 {
 	return !(rt->rt6i_flags & RTF_CACHE) &&
-		(rt->rt6i_flags & RTF_PCPU || rt->rt6i_node);
+		(rt->rt6i_flags & RTF_PCPU ||
+		 rcu_access_pointer(rt->rt6i_node));
 }
 
 static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
author maintainer
#4 lore raw

PATCH 4/52 macsec: add genl family module alias

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sabrina Dubroca <[email protected]>

[ Upstream commit 78362998f58c7c271e2719dcd0aaced435c801f9 ]

This helps tools such as wpa_supplicant can start even if the macsec module isn't loaded yet.

Fixes c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
---
 drivers/net/macsec.c |    1 +
 1 file changed, 1 insertion(+)
drivers/net/macsec.c +1 -0
@@ -3518,6 +3518,7 @@ module_init(macsec_init);
 module_exit(macsec_exit);
 
 MODULE_ALIAS_RTNL_LINK("macsec");
+MODULE_ALIAS_GENL_FAMILY("macsec");
 
 MODULE_DESCRIPTION("MACsec IEEE 802.1AE");
 MODULE_LICENSE("GPL v2");
author maintainer
#5 lore raw

PATCH 5/52 udp: on peeking bad csum, drop packets even if not at head

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit fd6055a806edc4019be1b9fb7d25262599bca5b1 ]

When peeking, if a bad csum is discovered, the skb is unlinked from the queue with __sk_queue_drop_skb and the peek operation restarted.

__sk_queue_drop_skb only drops packets that match the queue head.

This fails if the skb was found after the head, using SO_PEEK_OFF socket option. This causes an infinite loop.

We MUST drop this problematic skb, and we can simply check if skb was already removed by another thread, by looking at skb->next :

This pointer is set to NULL by the __skb_unlink() operation, that might have happened only under the spinlock protection.

Many thanks to syzkaller team (and particularly Dmitry Vyukov who provided us nice C reproducers exhibiting the lockup) and Willem de Bruijn who provided first version for this patch and a test program.

Fixes 627d2d6b5500 ("udp: enable MSG_PEEK at non-zero offset")
Cc Willem de Bruijn <[email protected]>
---
 net/core/datagram.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/datagram.c +1 -1
@@ -345,7 +345,7 @@ int __sk_queue_drop_skb(struct sock *sk,
 	if (flags & MSG_PEEK) {
 		err = -ENOENT;
 		spin_lock_bh(&sk->sk_receive_queue.lock);
-		if (skb == skb_peek(&sk->sk_receive_queue)) {
+		if (skb->next) {
 			__skb_unlink(skb, &sk->sk_receive_queue);
 			atomic_dec(&skb->users);
 			if (destructor)
author maintainer
#6 lore raw

PATCH 6/52 bpf: fix map value attribute for hash of maps

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel Borkmann <[email protected]>

[ Upstream commit 33ba43ed0afc13a29b1314e3e45a9938d310ba13 ]

Currently, iproute2's BPF ELF loader works fine with array of maps when retrieving the fd from a pinned node and doing a selfcheck against the provided map attributes from the object file, but we fail to do the same for hash of maps and thus refuse to get the map from pinned node.

Reason is that when allocating hash of maps, fd_htab_map_alloc() will set the value size to sizeof(void *), and any user space map creation requests are forced to set 4 bytes as value size. Thus, selfcheck will complain about exposed 8 bytes on 64 bit archs vs. 4 bytes from object file as value size. Contract is that fdinfo or BPF_MAP_GET_FD_BY_ID returns the value size used to create the map.

Fix it by handling it the same way as we do for array of maps, which means that we leave value size at 4 bytes and in the allocation phase round up value size to 8 bytes. alloc_htab_elem() needs an adjustment in order to copy rounded up 8 bytes due to bpf_fd_htab_map_update_elem() calling into htab_map_update_elem() with the pointer of the map pointer as value. Unlike array of maps where we just xchg(), we're using the generic htab_map_update_elem() callback also used from helper calls, which published the key/value already on return, so we need to ensure to memcpy() the right size.

---
 kernel/bpf/hashtab.c |   30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)
kernel/bpf/hashtab.c +17 -13
@@ -652,12 +652,27 @@ static void pcpu_copy_value(struct bpf_h
 	}
 }
 
+static bool fd_htab_map_needs_adjust(const struct bpf_htab *htab)
+{
+	return htab->map.map_type == BPF_MAP_TYPE_HASH_OF_MAPS &&
+	       BITS_PER_LONG == 64;
+}
+
+static u32 htab_size_value(const struct bpf_htab *htab, bool percpu)
+{
+	u32 size = htab->map.value_size;
+
+	if (percpu || fd_htab_map_needs_adjust(htab))
+		size = round_up(size, 8);
+	return size;
+}
+
 static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
 					 void *value, u32 key_size, u32 hash,
 					 bool percpu, bool onallcpus,
 					 struct htab_elem *old_elem)
 {
-	u32 size = htab->map.value_size;
+	u32 size = htab_size_value(htab, percpu);
 	bool prealloc = htab_is_prealloc(htab);
 	struct htab_elem *l_new, **pl_new;
 	void __percpu *pptr;
@@ -696,9 +711,6 @@ static struct htab_elem *alloc_htab_elem
 
 	memcpy(l_new->key, key, key_size);
 	if (percpu) {
-		/* round up value_size to 8 bytes */
-		size = round_up(size, 8);
-
 		if (prealloc) {
 			pptr = htab_elem_get_ptr(l_new, key_size);
 		} else {
@@ -1209,17 +1221,9 @@ const struct bpf_map_ops htab_lru_percpu
 
 static struct bpf_map *fd_htab_map_alloc(union bpf_attr *attr)
 {
-	struct bpf_map *map;
-
 	if (attr->value_size != sizeof(u32))
 		return ERR_PTR(-EINVAL);
-
-	/* pointer is stored internally */
-	attr->value_size = sizeof(void *);
-	map = htab_map_alloc(attr);
-	attr->value_size = sizeof(u32);
-
-	return map;
+	return htab_map_alloc(attr);
 }
 
 static void fd_htab_map_free(struct bpf_map *map)
author maintainer
#7 lore raw

PATCH 7/52 fsl/man: Inherit parent device and of_node

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit a1a50c8e4c241a505b7270e1a3c6e50d94e794b1 ]

Junote Cai reported that he was not able to get a DSA setup involving the Freescale DPAA/FMAN driver to work and narrowed it down to of_find_net_device_by_node(). This function requires the network device's device reference to be correctly set which is the case here, though we have lost any device_node association there.

The problem is that dpaa_eth_add_device() allocates a "dpaa-ethernet" platform device, and later on dpaa_eth_probe() is called but SET_NETDEV_DEV() won't be propagating &pdev->dev.of_node properly. Fix this by inherenting both the parent device and the of_node when dpaa_eth_add_device() creates the platform device.

Fixes 3933961682a3 ("fsl/fman: Add FMan MAC driver")
---
 drivers/net/ethernet/freescale/fman/mac.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/net/ethernet/freescale/fman/mac.c +2 -0
@@ -623,6 +623,8 @@ static struct platform_device *dpaa_eth_
 		goto no_mem;
 	}
 
+	pdev->dev.of_node = node;
+	pdev->dev.parent = priv->dev;
 	set_dma_ops(&pdev->dev, get_dma_ops(priv->dev));
 
 	ret = platform_device_add_data(pdev, &data, sizeof(data));
author maintainer
#8 lore raw

PATCH 8/52 sctp: Avoid out-of-bounds reads from address storage

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefano Brivio <[email protected]>

[ Upstream commit ee6c88bb754e3d363e568da78086adfedb692447 ]

inet_diag_msg_sctp{,l}addr_fill() and sctp_get_sctp_info() copy sizeof(sockaddr_storage) bytes to fill in sockaddr structs used to export diagnostic information to userspace.

However, the memory allocated to store sockaddr information is smaller than that and depends on the address family, so we leak up to 100 uninitialized bytes to userspace. Just use the size of the source structs instead, in all the three cases this is what userspace expects. Zero out the remaining memory.

Unused bytes (i.e. when IPv4 addresses are used) in source structs sctp_sockaddr_entry and sctp_transport are already cleared by sctp_add_bind_addr() and sctp_transport_new(), respectively.

Noticed while testing KASAN-enabled kernel with 'ss':

[ 2326.885243] BUG: KASAN: slab-out-of-bounds in inet_sctp_diag_fill+0x42c/0x6c0 [sctp_diag] at addr ffff881be8779800
[ 2326.896800] Read of size 128 by task ss/9527
[ 2326.901564] CPU: 0 PID: 9527 Comm: ss Not tainted 4.11.0-22.el7a.x86_64 #1
[ 2326.909236] Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.4.3 01/17/2017
[ 2326.917585] Call Trace:
[ 2326.920312]  dump_stack+0x63/0x8d
[ 2326.924014]  kasan_object_err+0x21/0x70
[ 2326.928295]  kasan_report+0x288/0x540
[ 2326.932380]  ? inet_sctp_diag_fill+0x42c/0x6c0 [sctp_diag]
[ 2326.938500]  ? skb_put+0x8b/0xd0
[ 2326.942098]  ? memset+0x31/0x40
[ 2326.945599]  check_memory_region+0x13c/0x1a0
[ 2326.950362]  memcpy+0x23/0x50
[ 2326.953669]  inet_sctp_diag_fill+0x42c/0x6c0 [sctp_diag]
[ 2326.959596]  ? inet_diag_msg_sctpasoc_fill+0x460/0x460 [sctp_diag]
[ 2326.966495]  ? __lock_sock+0x102/0x150
[ 2326.970671]  ? sock_def_wakeup+0x60/0x60
[ 2326.975048]  ? remove_wait_queue+0xc0/0xc0
[ 2326.979619]  sctp_diag_dump+0x44a/0x760 [sctp_diag]
[ 2326.985063]  ? sctp_ep_dump+0x280/0x280 [sctp_diag]
[ 2326.990504]  ? memset+0x31/0x40
[ 2326.994007]  ? mutex_lock+0x12/0x40
[ 2326.997900]  __inet_diag_dump+0x57/0xb0 [inet_diag]
[ 2327.003340]  ? __sys_sendmsg+0x150/0x150
[ 2327.007715]  inet_diag_dump+0x4d/0x80 [inet_diag]
[ 2327.012979]  netlink_dump+0x1e6/0x490
[ 2327.017064]  __netlink_dump_start+0x28e/0x2c0
[ 2327.021924]  inet_diag_handler_cmd+0x189/0x1a0 [inet_diag]
[ 2327.028045]  ? inet_diag_rcv_msg_compat+0x1b0/0x1b0 [inet_diag]
[ 2327.034651]  ? inet_diag_dump_compat+0x190/0x190 [inet_diag]
[ 2327.040965]  ? __netlink_lookup+0x1b9/0x260
[ 2327.045631]  sock_diag_rcv_msg+0x18b/0x1e0
[ 2327.050199]  netlink_rcv_skb+0x14b/0x180
[ 2327.054574]  ? sock_diag_bind+0x60/0x60
[ 2327.058850]  sock_diag_rcv+0x28/0x40
[ 2327.062837]  netlink_unicast+0x2e7/0x3b0
[ 2327.067212]  ? netlink_attachskb+0x330/0x330
[ 2327.071975]  ? kasan_check_write+0x14/0x20
[ 2327.076544]  netlink_sendmsg+0x5be/0x730
[ 2327.080918]  ? netlink_unicast+0x3b0/0x3b0
[ 2327.085486]  ? kasan_check_write+0x14/0x20
[ 2327.090057]  ? selinux_socket_sendmsg+0x24/0x30
[ 2327.095109]  ? netlink_unicast+0x3b0/0x3b0
[ 2327.099678]  sock_sendmsg+0x74/0x80
[ 2327.103567]  ___sys_sendmsg+0x520/0x530
[ 2327.107844]  ? __get_locked_pte+0x178/0x200
[ 2327.112510]  ? copy_msghdr_from_user+0x270/0x270
[ 2327.117660]  ? vm_insert_page+0x360/0x360
[ 2327.122133]  ? vm_insert_pfn_prot+0xb4/0x150
[ 2327.126895]  ? vm_insert_pfn+0x32/0x40
[ 2327.131077]  ? vvar_fault+0x71/0xd0
[ 2327.134968]  ? special_mapping_fault+0x69/0x110
[ 2327.140022]  ? __do_fault+0x42/0x120
[ 2327.144008]  ? __handle_mm_fault+0x1062/0x17a0
[ 2327.148965]  ? __fget_light+0xa7/0xc0
[ 2327.153049]  __sys_sendmsg+0xcb/0x150
[ 2327.157133]  ? __sys_sendmsg+0xcb/0x150
[ 2327.161409]  ? SyS_shutdown+0x140/0x140
[ 2327.165688]  ? exit_to_usermode_loop+0xd0/0xd0
[ 2327.170646]  ? __do_page_fault+0x55d/0x620
[ 2327.175216]  ? __sys_sendmsg+0x150/0x150
[ 2327.179591]  SyS_sendmsg+0x12/0x20
[ 2327.183384]  do_syscall_64+0xe3/0x230
[ 2327.187471]  entry_SYSCALL64_slow_path+0x25/0x25
[ 2327.192622] RIP: 0033:0x7f41d18fa3b0
[ 2327.196608] RSP: 002b:00007ffc3b731218 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
[ 2327.205055] RAX: ffffffffffffffda RBX: 00007ffc3b731380 RCX: 00007f41d18fa3b0
[ 2327.213017] RDX: 0000000000000000 RSI: 00007ffc3b731340 RDI: 0000000000000003
[ 2327.220978] RBP: 0000000000000002 R08: 0000000000000004 R09: 0000000000000040
[ 2327.228939] R10: 00007ffc3b730f30 R11: 0000000000000246 R12: 0000000000000003
[ 2327.236901] R13: 00007ffc3b731340 R14: 00007ffc3b7313d0 R15: 0000000000000084
[ 2327.244865] Object at ffff881be87797e0, in cache kmalloc-64 size: 64
[ 2327.251953] Allocated:
[ 2327.254581] PID = 9484
[ 2327.257215]  save_stack_trace+0x1b/0x20
[ 2327.261485]  save_stack+0x46/0xd0
[ 2327.265179]  kasan_kmalloc+0xad/0xe0
[ 2327.269165]  kmem_cache_alloc_trace+0xe6/0x1d0
[ 2327.274138]  sctp_add_bind_addr+0x58/0x180 [sctp]
[ 2327.279400]  sctp_do_bind+0x208/0x310 [sctp]
[ 2327.284176]  sctp_bind+0x61/0xa0 [sctp]
[ 2327.288455]  inet_bind+0x5f/0x3a0
[ 2327.292151]  SYSC_bind+0x1a4/0x1e0
[ 2327.295944]  SyS_bind+0xe/0x10
[ 2327.299349]  do_syscall_64+0xe3/0x230
[ 2327.303433]  return_from_SYSCALL_64+0x0/0x6a
[ 2327.308194] Freed:
[ 2327.310434] PID = 4131
[ 2327.313065]  save_stack_trace+0x1b/0x20
[ 2327.317344]  save_stack+0x46/0xd0
[ 2327.321040]  kasan_slab_free+0x73/0xc0
[ 2327.325220]  kfree+0x96/0x1a0
[ 2327.328530]  dynamic_kobj_release+0x15/0x40
[ 2327.333195]  kobject_release+0x99/0x1e0
[ 2327.337472]  kobject_put+0x38/0x70
[ 2327.341266]  free_notes_attrs+0x66/0x80
[ 2327.345545]  mod_sysfs_teardown+0x1a5/0x270
[ 2327.350211]  free_module+0x20/0x2a0
[ 2327.354099]  SyS_delete_module+0x2cb/0x2f0
[ 2327.358667]  do_syscall_64+0xe3/0x230
[ 2327.362750]  return_from_SYSCALL_64+0x0/0x6a
[ 2327.367510] Memory state around the buggy address:
[ 2327.372855]  ffff881be8779700: fc fc fc fc 00 00 00 00 00 00 00 00 fc fc fc fc
[ 2327.380914]  ffff881be8779780: fb fb fb fb fb fb fb fb fc fc fc fc 00 00 00 00
[ 2327.388972] >ffff881be8779800: 00 00 00 00 fc fc fc fc fb fb fb fb fb fb fb fb
[ 2327.397031]                                ^
[ 2327.401792]  ffff881be8779880: fc fc fc fc fb fb fb fb fb fb fb fb fc fc fc fc
[ 2327.409850]  ffff881be8779900: 00 00 00 00 00 04 fc fc fc fc fc fc 00 00 00 00
[ 2327.417907] ==================================================================

This fixes CVE-2017-7558.

References: https://bugzilla.redhat.com/show_bug.cgi?id=1480266

Fixes 8f840e47f190 ("sctp: add the sctp_diag.c file")
Cc Xin Long <[email protected]>
Cc Vlad Yasevich <[email protected]>
Cc Neil Horman <[email protected]>
---
 net/sctp/sctp_diag.c |    7 +++++--
 net/sctp/socket.c    |    3 +--
 2 files changed, 6 insertions(+), 4 deletions(-)
net/sctp/sctp_diag.c +5 -2
@@ -70,7 +70,8 @@ static int inet_diag_msg_sctpladdrs_fill
 
 	info = nla_data(attr);
 	list_for_each_entry_rcu(laddr, address_list, list) {
-		memcpy(info, &laddr->a, addrlen);
+		memcpy(info, &laddr->a, sizeof(laddr->a));
+		memset(info + sizeof(laddr->a), 0, addrlen - sizeof(laddr->a));
 		info += addrlen;
 	}
 
@@ -93,7 +94,9 @@ static int inet_diag_msg_sctpaddrs_fill(
 	info = nla_data(attr);
 	list_for_each_entry(from, &asoc->peer.transport_addr_list,
 			    transports) {
-		memcpy(info, &from->ipaddr, addrlen);
+		memcpy(info, &from->ipaddr, sizeof(from->ipaddr));
+		memset(info + sizeof(from->ipaddr), 0,
+		       addrlen - sizeof(from->ipaddr));
 		info += addrlen;
 	}
 
net/sctp/socket.c +1 -2
@@ -4538,8 +4538,7 @@ int sctp_get_sctp_info(struct sock *sk,
 	info->sctpi_ictrlchunks = asoc->stats.ictrlchunks;
 
 	prim = asoc->peer.primary_path;
-	memcpy(&info->sctpi_p_address, &prim->ipaddr,
-	       sizeof(struct sockaddr_storage));
+	memcpy(&info->sctpi_p_address, &prim->ipaddr, sizeof(prim->ipaddr));
 	info->sctpi_p_state = prim->state;
 	info->sctpi_p_cwnd = prim->cwnd;
 	info->sctpi_p_srtt = prim->srtt;
author maintainer
#9 lore raw

PATCH 9/52 qlge: avoid memcpy buffer overflow

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Arnd Bergmann <[email protected]>

[ Upstream commit e58f95831e7468d25eb6e41f234842ecfe6f014f ]

gcc-8.0.0 (snapshot) points out that we copy a variable-length string into a fixed length field using memcpy() with the destination length, and that ends up copying whatever follows the string:

inlined from 'ql_core_dump' at drivers/net/ethernet/qlogic/qlge/qlge_dbg.c:1106:2:
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c:708:2: error: 'memcpy' reading 15 bytes from a region of size 14 [-Werror=stringop-overflow=]
memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1);

Changing it to use strncpy() will instead zero-pad the destination, which seems to be the right thing to do here.

The bug is probably harmless, but it seems like a good idea to address it in stable kernels as well, if only for the purpose of building with gcc-8 without warnings.

Fixes a61f80261306 ("qlge: Add ethtool register dump function.")
---
 drivers/net/ethernet/qlogic/qlge/qlge_dbg.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +1 -1
@@ -724,7 +724,7 @@ static void ql_build_coredump_seg_header
 	seg_hdr->cookie = MPI_COREDUMP_COOKIE;
 	seg_hdr->segNum = seg_number;
 	seg_hdr->segSize = seg_size;
-	memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1);
+	strncpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1);
 }
 
 /*
author maintainer
#10 lore raw

PATCH 10/52 tipc: Fix tipc_sk_reinit handling of -EAGAIN

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bob Peterson <[email protected]>

[ Upstream commit 6c7e983b220f89e03286dc70a41c7ef3a8b409df ]

In 9dbbfb0ab6680c6a85609041011484e6658e7d3c function tipc_sk_reinit had additional logic added to loop in the event that function rhashtable_walk_next() returned -EAGAIN. No worries.

However, if rhashtable_walk_start returns -EAGAIN, it does "continue", and therefore skips the call to rhashtable_walk_stop(). That has the effect of calling rcu_read_lock() without its paired call to rcu_read_unlock(). Since rcu_read_lock() may be nested, the problem may not be apparent for a while, especially since resize events may be rare. But the comments to rhashtable_walk_start() state:

* ...Note that we take the RCU lock in all
* cases including when we return an error. So you must always call
* rhashtable_walk_stop to clean up.

This patch replaces the continue with a goto and label to ensure a matching call to rhashtable_walk_stop().

---
 net/tipc/socket.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
net/tipc/socket.c +3 -3
@@ -2255,8 +2255,8 @@ void tipc_sk_reinit(struct net *net)
 
 	do {
 		tsk = ERR_PTR(rhashtable_walk_start(&iter));
-		if (tsk)
-			continue;
+		if (IS_ERR(tsk))
+			goto walk_stop;
 
 		while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) {
 			spin_lock_bh(&tsk->sk.sk_lock.slock);
@@ -2265,7 +2265,7 @@ void tipc_sk_reinit(struct net *net)
 			msg_set_orignode(msg, tn->own_addr);
 			spin_unlock_bh(&tsk->sk.sk_lock.slock);
 		}
-
+walk_stop:
 		rhashtable_walk_stop(&iter);
 	} while (tsk == ERR_PTR(-EAGAIN));
 }
author maintainer
#11 lore raw

PATCH 11/52 net: systemport: Be drop monitor friendly

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit c45182eb967af11e9482168be5be41aa22e5d321 ]

Utilize dev_consume_skb_any(cb->skb) in bcm_sysport_free_cb() which is used when a TX packet is completed, as well as when the RX ring is cleaned on shutdown. None of these two cases are packet drops, so be drop monitor friendly.

Fixes 80105befdb4b ("net: systemport: add Broadcom SYSTEMPORT Ethernet MAC driver")
---
 drivers/net/ethernet/broadcom/bcmsysport.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bcmsysport.c +1 -1
@@ -593,7 +593,7 @@ static int bcm_sysport_set_coalesce(stru
 
 static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb)
 {
-	dev_kfree_skb_any(cb->skb);
+	dev_consume_skb_any(cb->skb);
 	cb->skb = NULL;
 	dma_unmap_addr_set(cb, dma_addr, 0);
 }
author maintainer
#12 lore raw

PATCH 12/52 net: bcmgenet: Be drop monitor friendly

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit d4fec855905fa8bd5fb1c59f73ad2d74a944876a ]

There are 3 spots where we call dev_kfree_skb() but we are actually just doing a normal SKB consumption: __bcmgenet_tx_reclaim() for normal TX reclamation, bcmgenet_alloc_rx_buffers() during the initial RX ring setup and bcmgenet_free_rx_buffers() during RX ring cleanup.

Fixes d6707bec5986 ("net: bcmgenet: rewrite bcmgenet_rx_refill()")
Fixes f48bed16a756 ("net: bcmgenet: Free skb after last Tx frag")
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +2 -2
@@ -1203,7 +1203,7 @@ static struct enet_cb *bcmgenet_get_txcb
 /* Simple helper to free a control block's resources */
 static void bcmgenet_free_cb(struct enet_cb *cb)
 {
-	dev_kfree_skb_any(cb->skb);
+	dev_consume_skb_any(cb->skb);
 	cb->skb = NULL;
 	dma_unmap_addr_set(cb, dma_addr, 0);
 }
@@ -1868,7 +1868,7 @@ static int bcmgenet_alloc_rx_buffers(str
 		cb = ring->cbs + i;
 		skb = bcmgenet_rx_refill(priv, cb);
 		if (skb)
-			dev_kfree_skb_any(skb);
+			dev_consume_skb_any(skb);
 		if (!cb->skb)
 			return -ENOMEM;
 	}
author maintainer
#13 lore raw

PATCH 13/52 net: systemport: Free DMA coherent descriptors on errors

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit c2062ee3d9615828109ffe8089fbf69bed394d05 ]

In case bcm_sysport_init_tx_ring() is not able to allocate ring->cbs, we would return with an error, and call bcm_sysport_fini_tx_ring() and it would see that ring->cbs is NULL and do nothing. This would leak the coherent DMA descriptor area, so we need to free it on error before returning.

Fixes 80105befdb4b ("net: systemport: add Broadcom SYSTEMPORT Ethernet MAC driver")
---
 drivers/net/ethernet/broadcom/bcmsysport.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/net/ethernet/broadcom/bcmsysport.c +2 -0
@@ -1342,6 +1342,8 @@ static int bcm_sysport_init_tx_ring(stru
 
 	ring->cbs = kcalloc(size, sizeof(struct bcm_sysport_cb), GFP_KERNEL);
 	if (!ring->cbs) {
+		dma_free_coherent(kdev, sizeof(struct dma_desc),
+				  ring->desc_cpu, ring->desc_dma);
 		netif_err(priv, hw, priv->netdev, "CB allocation failed\n");
 		return -ENOMEM;
 	}
author maintainer
#14 lore raw

PATCH 14/52 netvsc: fix deadlock betwen link status and removal

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: stephen hemminger <[email protected]>

[ Upstream commit 9b4e946ce14e20d7addbfb7d9139e604f9fda107 ]

There is a deadlock possible when canceling the link status delayed work queue. The removal process is run with RTNL held, and the link status callback is acquring RTNL.

Resolve the issue by using trylock and rescheduling. If cancel is in process, that block it from happening.

Fixes 122a5f6410f4 ("staging: hv: use delayed_work for netvsc_send_garp()")
---
 drivers/net/hyperv/netvsc_drv.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/hyperv/netvsc_drv.c +6 -1
@@ -1270,7 +1270,12 @@ static void netvsc_link_change(struct wo
 	bool notify = false, reschedule = false;
 	unsigned long flags, next_reconfig, delay;
 
-	rtnl_lock();
+	/* if changes are happening, comeback later */
+	if (!rtnl_trylock()) {
+		schedule_delayed_work(&ndev_ctx->dwork, LINKCHANGE_INT);
+		return;
+	}
+
 	net_device = rtnl_dereference(ndev_ctx->nvdev);
 	if (!net_device)
 		goto out_unlock;
author maintainer
#15 lore raw

PATCH 15/52 udp6: set rx_dst_cookie on rx_dst updates

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Paolo Abeni <[email protected]>

[ Upstream commit 64f0f5d18a47c703c85576375cc010e83dac6a48 ]

Currently, in the udp6 code, the dst cookie is not initialized/updated concurrently with the RX dst used by early demux.

As a result, the dst_check() in the early_demux path always fails, the rx dst cache is always invalidated, and we can't really leverage significant gain from the demux lookup.

Fix it adding udp6 specific variant of sk_rx_dst_set() and use it to set the dst cookie when the dst entry is really changed.

The issue is there since the introduction of early demux for ipv6.

Fixes 5425077d73e0 ("net: ipv6: Add early demux handler for UDP unicast")
---
 include/net/udp.h |    2 +-
 net/ipv4/udp.c    |    3 ++-
 net/ipv6/udp.c    |   11 ++++++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)
include/net/udp.h +1 -1
@@ -265,7 +265,7 @@ static inline struct sk_buff *skb_recv_u
 }
 
 void udp_v4_early_demux(struct sk_buff *skb);
-void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
+bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
 int udp_get_port(struct sock *sk, unsigned short snum,
 		 int (*saddr_cmp)(const struct sock *,
 				  const struct sock *));
net/ipv4/udp.c +2 -1
@@ -1762,13 +1762,14 @@ drop:
 /* For TCP sockets, sk_rx_dst is protected by socket lock
  * For UDP, we use xchg() to guard against concurrent changes.
  */
-void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
+bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
 {
 	struct dst_entry *old;
 
 	dst_hold(dst);
 	old = xchg(&sk->sk_rx_dst, dst);
 	dst_release(old);
+	return old != dst;
 }
 
 /*
net/ipv6/udp.c +10 -1
@@ -752,6 +752,15 @@ start_lookup:
 	return 0;
 }
 
+static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
+{
+	if (udp_sk_rx_dst_set(sk, dst)) {
+		const struct rt6_info *rt = (const struct rt6_info *)dst;
+
+		inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt);
+	}
+}
+
 int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
 		   int proto)
 {
@@ -801,7 +810,7 @@ int __udp6_lib_rcv(struct sk_buff *skb,
 		int ret;
 
 		if (unlikely(sk->sk_rx_dst != dst))
-			udp_sk_rx_dst_set(sk, dst);
+			udp6_sk_rx_dst_set(sk, dst);
 
 		ret = udpv6_queue_rcv_skb(sk, skb);
 		sock_put(sk);
author maintainer
#16 lore raw

PATCH 16/52 net: mvpp2: fix the mac address used when using PPv2.2

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Antoine Tenart <[email protected]>

[ Upstream commit 4c22868264516fe0c42817a87f37efb44254e7a9 ]

The mac address is only retrieved from h/w when using PPv2.1. Otherwise the variable holding it is still checked and used if it contains a valid value. As the variable isn't initialized to an invalid mac address value, we end up with random mac addresses which can be the same for all the ports handled by this PPv2 driver.

Fixes this by initializing the h/w mac address variable to {0}, which is an invalid mac address value. This way the random assignation fallback is called and all ports end up with their own addresses.

Fixes 2697582144dd ("net: mvpp2: handle misc PPv2.1/PPv2.2 differences")
---
 drivers/net/ethernet/marvell/mvpp2.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/mvpp2.c +1 -1
@@ -6465,7 +6465,7 @@ static int mvpp2_port_probe(struct platf
 	struct resource *res;
 	const char *dt_mac_addr;
 	const char *mac_from;
-	char hw_mac_addr[ETH_ALEN];
+	char hw_mac_addr[ETH_ALEN] = {0};
 	u32 id;
 	int features;
 	int phy_mode;
author maintainer
#17 lore raw

PATCH 17/52 cxgb4: Fix stack out-of-bounds read due to wrong size to t4_record_mbox()

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefano Brivio <[email protected]>

[ Upstream commit 0f3086868e8889a823a6e0f3d299102aa895d947 ]

Passing commands for logging to t4_record_mbox() with size MBOX_LEN, when the actual command size is actually smaller, causes out-of-bounds stack accesses in t4_record_mbox() while copying command words here:

	for (i = 0; i < size / 8; i++)
		entry->cmd[i] = be64_to_cpu(cmd[i]);

Up to 48 bytes from the stack are then leaked to debugfs.

This happens whenever we send (and log) commands described by structs fw_sched_cmd (32 bytes leaked), fw_vi_rxmode_cmd (48), fw_hello_cmd (48), fw_bye_cmd (48), fw_initialize_cmd (48), fw_reset_cmd (48), fw_pfvf_cmd (32), fw_eq_eth_cmd (16), fw_eq_ctrl_cmd (32), fw_eq_ofld_cmd (32), fw_acl_mac_cmd(16), fw_rss_glb_config_cmd(32), fw_rss_vi_config_cmd(32), fw_devlog_cmd(32), fw_vi_enable_cmd(48), fw_port_cmd(32), fw_sched_cmd(32), fw_devlog_cmd(32).

The cxgb4vf driver got this right instead.

When we call t4_record_mbox() to log a command reply, a MBOX_LEN size can be used though, as get_mbox_rpl() will fill cmd_rpl up completely.

Fixes 7f080c3f2ff0 ("cxgb4: Add support to enable logging of firmware mailbox commands")
---
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +3 -3
@@ -369,12 +369,12 @@ int t4_wr_mbox_meat_timeout(struct adapt
 		list_del(&entry.list);
 		spin_unlock(&adap->mbox_lock);
 		ret = (v == MBOX_OWNER_FW) ? -EBUSY : -ETIMEDOUT;
-		t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
+		t4_record_mbox(adap, cmd, size, access, ret);
 		return ret;
 	}
 
 	/* Copy in the new mailbox command and send it on its way ... */
-	t4_record_mbox(adap, cmd, MBOX_LEN, access, 0);
+	t4_record_mbox(adap, cmd, size, access, 0);
 	for (i = 0; i < size; i += 8)
 		t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p++));
 
@@ -426,7 +426,7 @@ int t4_wr_mbox_meat_timeout(struct adapt
 	}
 
 	ret = (pcie_fw & PCIE_FW_ERR_F) ? -ENXIO : -ETIMEDOUT;
-	t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
+	t4_record_mbox(adap, cmd, size, access, ret);
 	dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
 		*(const u8 *)cmd, mbox);
 	t4_report_fw_error(adap);
author maintainer
#18 lore raw

PATCH 18/52 ipv6: set dst.obsolete when a cached route has expired

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xin Long <[email protected]>

[ Upstream commit 1e2ea8ad37be25a7cdcc974945935829d534d5d3 ]

Now it doesn't check for the cached route expiration in ipv6's dst_ops->check(), because it trusts dst_gc that would clean the cached route up when it's expired.

The problem is in dst_gc, it would clean the cached route only when it's refcount is 1. If some other module (like xfrm) keeps holding it and the module only release it when dst_ops->check() fails.

But without checking for the cached route expiration, .check() may always return true. Meanwhile, without releasing the cached route, dst_gc couldn't del it. It will cause this cached route never to expire.

This patch is to set dst.obsolete with DST_OBSOLETE_KILL in .gc when it's expired, and check obsolete != DST_OBSOLETE_FORCE_CHK in .check.

Note that this is even needed when ipv6 dst_gc timer is removed one day. It would set dst.obsolete in .redirect and .update_pmtu instead, and check for cached route expiration when getting it, just like what ipv4 route does.

---
 net/ipv6/ip6_fib.c |    4 +++-
 net/ipv6/route.c   |    3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)
net/ipv6/ip6_fib.c +3 -1
@@ -1790,8 +1790,10 @@ static int fib6_age(struct rt6_info *rt,
 		}
 		gc_args->more++;
 	} else if (rt->rt6i_flags & RTF_CACHE) {
+		if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout))
+			rt->dst.obsolete = DST_OBSOLETE_KILL;
 		if (atomic_read(&rt->dst.__refcnt) == 0 &&
-		    time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
+		    rt->dst.obsolete == DST_OBSOLETE_KILL) {
 			RT6_TRACE("aging clone %p\n", rt);
 			return -1;
 		} else if (rt->rt6i_flags & RTF_GATEWAY) {
net/ipv6/route.c +2 -1
@@ -444,7 +444,8 @@ static bool rt6_check_expired(const stru
 		if (time_after(jiffies, rt->dst.expires))
 			return true;
 	} else if (rt->dst.from) {
-		return rt6_check_expired((struct rt6_info *) rt->dst.from);
+		return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
+		       rt6_check_expired((struct rt6_info *)rt->dst.from);
 	}
 	return false;
 }
author maintainer
#19 lore raw

PATCH 19/52 ipv6: do not set sk_destruct in IPV6_ADDRFORM sockopt

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xin Long <[email protected]>

[ Upstream commit e8d411d2980723b8f8ba8e4dd78b694c5fd9ea3e ]

ChunYu found a kernel warn_on during syzkaller fuzzing:

[40226.038539] WARNING: CPU: 5 PID: 23720 at net/ipv4/af_inet.c:152 inet_sock_destruct+0x78d/0x9a0
[40226.144849] Call Trace:
[40226.147590]  <IRQ>
[40226.149859]  dump_stack+0xe2/0x186
[40226.176546]  __warn+0x1a4/0x1e0
[40226.180066]  warn_slowpath_null+0x31/0x40
[40226.184555]  inet_sock_destruct+0x78d/0x9a0
[40226.246355]  __sk_destruct+0xfa/0x8c0
[40226.290612]  rcu_process_callbacks+0xaa0/0x18a0
[40226.336816]  __do_softirq+0x241/0x75e
[40226.367758]  irq_exit+0x1f6/0x220
[40226.371458]  smp_apic_timer_interrupt+0x7b/0xa0
[40226.376507]  apic_timer_interrupt+0x93/0xa0

The warn_on happned when sk->sk_rmem_alloc wasn't 0 in inet_sock_destruct. As after commit f970bd9e3a06 ("udp: implement memory accounting helpers"), udp has changed to use udp_destruct_sock as sk_destruct where it would udp_rmem_release all rmem.

But IPV6_ADDRFORM sockopt sets sk_destruct with inet_sock_destruct after changing family to PF_INET. If rmem is not 0 at that time, and there is no place to release rmem before calling inet_sock_destruct, the warn_on will be triggered.

This patch is to fix it by not setting sk_destruct in IPV6_ADDRFORM sockopt any more. As IPV6_ADDRFORM sockopt only works for tcp and udp. TCP sock has already set it's sk_destruct with inet_sock_destruct and UDP has set with udp_destruct_sock since they're created.

Fixes f970bd9e3a06 ("udp: implement memory accounting helpers")
---
 net/ipv6/ipv6_sockglue.c |    1 -
 1 file changed, 1 deletion(-)
net/ipv6/ipv6_sockglue.c +0 -1
@@ -242,7 +242,6 @@ static int do_ipv6_setsockopt(struct soc
 			pktopt = xchg(&np->pktoptions, NULL);
 			kfree_skb(pktopt);
 
-			sk->sk_destruct = inet_sock_destruct;
 			/*
 			 * ... and add it to the refcnt debug socks count
 			 * in the new family. -acme
author maintainer
#20 lore raw

PATCH 20/52 packet: Dont write vnet header beyond end of buffer

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Benjamin Poirier <[email protected]>

[ Upstream commit edbd58be15a957f6a760c4a514cd475217eb97fd ]

... which may happen with certain values of tp_reserve and maclen.

Fixes 58d19b19cd99 ("packet: vnet_hdr support for tpacket_rcv")
Cc Willem de Bruijn <[email protected]>
---
 net/packet/af_packet.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
net/packet/af_packet.c +9 -3
@@ -2192,6 +2192,7 @@ static int tpacket_rcv(struct sk_buff *s
 	struct timespec ts;
 	__u32 ts_status;
 	bool is_drop_n_account = false;
+	bool do_vnet = false;
 
 	/* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT.
 	 * We may add members to them until current aligned size without forcing
@@ -2242,8 +2243,10 @@ static int tpacket_rcv(struct sk_buff *s
 		netoff = TPACKET_ALIGN(po->tp_hdrlen +
 				       (maclen < 16 ? 16 : maclen)) +
 				       po->tp_reserve;
-		if (po->has_vnet_hdr)
+		if (po->has_vnet_hdr) {
 			netoff += sizeof(struct virtio_net_hdr);
+			do_vnet = true;
+		}
 		macoff = netoff - maclen;
 	}
 	if (po->tp_version <= TPACKET_V2) {
@@ -2260,8 +2263,10 @@ static int tpacket_rcv(struct sk_buff *s
 					skb_set_owner_r(copy_skb, sk);
 			}
 			snaplen = po->rx_ring.frame_size - macoff;
-			if ((int)snaplen < 0)
+			if ((int)snaplen < 0) {
 				snaplen = 0;
+				do_vnet = false;
+			}
 		}
 	} else if (unlikely(macoff + snaplen >
 			    GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) {
@@ -2274,6 +2279,7 @@ static int tpacket_rcv(struct sk_buff *s
 		if (unlikely((int)snaplen < 0)) {
 			snaplen = 0;
 			macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len;
+			do_vnet = false;
 		}
 	}
 	spin_lock(&sk->sk_receive_queue.lock);
@@ -2299,7 +2305,7 @@ static int tpacket_rcv(struct sk_buff *s
 	}
 	spin_unlock(&sk->sk_receive_queue.lock);
 
-	if (po->has_vnet_hdr) {
+	if (do_vnet) {
 		if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
 					    sizeof(struct virtio_net_hdr),
 					    vio_le(), true)) {
author maintainer
#21 lore raw

PATCH 21/52 kcm: do not attach PF_KCM sockets to avoid deadlock

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 351050ecd6523374b370341cc29fe61e2201556b ]

syzkaller had no problem to trigger a deadlock, attaching a KCM socket to another one (or itself). (original syzkaller report was a very confusing lockdep splat during a sendmsg())

It seems KCM claims to only support TCP, but no enforcement is done, so we might need to add additional checks.

Fixes ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module")
---
 net/kcm/kcmsock.c |    4 ++++
 1 file changed, 4 insertions(+)
net/kcm/kcmsock.c +4 -0
@@ -1383,6 +1383,10 @@ static int kcm_attach(struct socket *soc
 	if (!csk)
 		return -EINVAL;
 
+	/* We must prevent loops or risk deadlock ! */
+	if (csk->sk_family == PF_KCM)
+		return -EOPNOTSUPP;
+
 	psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL);
 	if (!psock)
 		return -ENOMEM;
author maintainer
#22 lore raw

PATCH 22/52 net: dsa: bcm_sf2: Fix number of CFP entries for BCM7278

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit df191632f814357ee4d646421662d866028b569d ]

BCM7278 has only 128 entries while BCM7445 has the full 256 entries set, fix that.

Fixes 7318166cacad ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
---
 drivers/net/dsa/bcm_sf2.c     |    4 ++++
 drivers/net/dsa/bcm_sf2.h     |    1 +
 drivers/net/dsa/bcm_sf2_cfp.c |    8 ++++----
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/dsa/bcm_sf2.c +4 -0
@@ -1055,6 +1055,7 @@ struct bcm_sf2_of_data {
 	u32 type;
 	const u16 *reg_offsets;
 	unsigned int core_reg_align;
+	unsigned int num_cfp_rules;
 };
 
 /* Register offsets for the SWITCH_REG_* block */
@@ -1078,6 +1079,7 @@ static const struct bcm_sf2_of_data bcm_
 	.type		= BCM7445_DEVICE_ID,
 	.core_reg_align	= 0,
 	.reg_offsets	= bcm_sf2_7445_reg_offsets,
+	.num_cfp_rules	= 256,
 };
 
 static const u16 bcm_sf2_7278_reg_offsets[] = {
@@ -1100,6 +1102,7 @@ static const struct bcm_sf2_of_data bcm_
 	.type		= BCM7278_DEVICE_ID,
 	.core_reg_align	= 1,
 	.reg_offsets	= bcm_sf2_7278_reg_offsets,
+	.num_cfp_rules	= 128,
 };
 
 static const struct of_device_id bcm_sf2_of_match[] = {
@@ -1156,6 +1159,7 @@ static int bcm_sf2_sw_probe(struct platf
 	priv->type = data->type;
 	priv->reg_offsets = data->reg_offsets;
 	priv->core_reg_align = data->core_reg_align;
+	priv->num_cfp_rules = data->num_cfp_rules;
 
 	/* Auto-detection using standard registers will not work, so
 	 * provide an indication of what kind of device we are for
drivers/net/dsa/bcm_sf2.h +1 -0
@@ -72,6 +72,7 @@ struct bcm_sf2_priv {
 	u32 				type;
 	const u16			*reg_offsets;
 	unsigned int			core_reg_align;
+	unsigned int			num_cfp_rules;
 
 	/* spinlock protecting access to the indirect registers */
 	spinlock_t			indir_lock;
drivers/net/dsa/bcm_sf2_cfp.c +4 -4
@@ -98,7 +98,7 @@ static inline void bcm_sf2_cfp_rule_addr
 {
 	u32 reg;
 
-	WARN_ON(addr >= CFP_NUM_RULES);
+	WARN_ON(addr >= priv->num_cfp_rules);
 
 	reg = core_readl(priv, CORE_CFP_ACC);
 	reg &= ~(XCESS_ADDR_MASK << XCESS_ADDR_SHIFT);
@@ -109,7 +109,7 @@ static inline void bcm_sf2_cfp_rule_addr
 static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv)
 {
 	/* Entry #0 is reserved */
-	return CFP_NUM_RULES - 1;
+	return priv->num_cfp_rules - 1;
 }
 
 static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
@@ -523,7 +523,7 @@ static int bcm_sf2_cfp_rule_get_all(stru
 		if (!(reg & OP_STR_DONE))
 			break;
 
-	} while (index < CFP_NUM_RULES);
+	} while (index < priv->num_cfp_rules);
 
 	/* Put the TCAM size here */
 	nfc->data = bcm_sf2_cfp_rule_size(priv);
@@ -544,7 +544,7 @@ int bcm_sf2_get_rxnfc(struct dsa_switch
 	case ETHTOOL_GRXCLSRLCNT:
 		/* Subtract the default, unusable rule */
 		nfc->rule_cnt = bitmap_weight(priv->cfp.used,
-					      CFP_NUM_RULES) - 1;
+					      priv->num_cfp_rules) - 1;
 		/* We support specifying rule locations */
 		nfc->data |= RX_CLS_LOC_SPECIAL;
 		break;
author maintainer
#23 lore raw

PATCH 23/52 net/mlx5e: Check for qos capability in dcbnl_initialize

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Huy Nguyen <[email protected]>

[ Upstream commit 33c52b6718d2a6cb414440c98560818910d896dc ]

qos capability is the master capability bit that determines if the DCBX is supported for the PCI function. If this bit is off, driver cannot run any dcbx code.

Fixes e207b7e99176 ("net/mlx5e: ConnectX-4 firmware support for DCBX")
---
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +3 -0
@@ -754,6 +754,9 @@ void mlx5e_dcbnl_initialize(struct mlx5e
 {
 	struct mlx5e_dcbx *dcbx = &priv->dcbx;
 
+	if (!MLX5_CAP_GEN(priv->mdev, qos))
+		return;
+
 	if (MLX5_CAP_GEN(priv->mdev, dcbx))
 		mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
 
author maintainer
#24 lore raw

PATCH 24/52 net/mlx5e: Fix DCB_CAP_ATTR_DCBX capability for DCBNL getcap.

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Huy Nguyen <[email protected]>

[ Upstream commit 9e10bf1d349787f373484d835efe2dbb5f9c5614 ]

Current code doesn't report DCB_CAP_DCBX_HOST capability when query through getcap. User space lldptool expects capability to have HOST mode set when it wants to configure DCBX CEE mode. In absence of HOST mode capability, lldptool fails to switch to CEE mode.

This fix returns DCB_CAP_DCBX_HOST capability when port's DCBX controlled mode is under software control.

Fixes 3a6a931dfb8e ("net/mlx5e: Support DCBX CEE API")
---
 drivers/net/ethernet/mellanox/mlx5/core/en.h       |    1 +
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |   21 ++++++++++++---------
 2 files changed, 13 insertions(+), 9 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en.h +1 -0
@@ -258,6 +258,7 @@ struct mlx5e_dcbx {
 
 	/* The only setting that cannot be read from FW */
 	u8                         tc_tsa[IEEE_8021QAZ_MAX_TCS];
+	u8                         cap;
 };
 #endif
 
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +12 -9
@@ -288,13 +288,8 @@ static int mlx5e_dcbnl_ieee_setpfc(struc
 static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
-	struct mlx5e_dcbx *dcbx = &priv->dcbx;
-	u8 mode = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_VER_CEE;
-
-	if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
-		mode |= DCB_CAP_DCBX_HOST;
 
-	return mode;
+	return priv->dcbx.cap;
 }
 
 static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
@@ -312,6 +307,7 @@ static u8 mlx5e_dcbnl_setdcbx(struct net
 		/* set dcbx to fw controlled */
 		if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
 			dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+			dcbx->cap &= ~DCB_CAP_DCBX_HOST;
 			return 0;
 		}
 
@@ -324,6 +320,8 @@ static u8 mlx5e_dcbnl_setdcbx(struct net
 	if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
 		return 1;
 
+	dcbx->cap = mode;
+
 	return 0;
 }
 
@@ -628,9 +626,9 @@ static u8 mlx5e_dcbnl_getcap(struct net_
 		*cap = false;
 		break;
 	case DCB_CAP_ATTR_DCBX:
-		*cap = (DCB_CAP_DCBX_LLD_MANAGED |
-			DCB_CAP_DCBX_VER_CEE |
-			DCB_CAP_DCBX_STATIC);
+		*cap = priv->dcbx.cap |
+		       DCB_CAP_DCBX_VER_CEE |
+		       DCB_CAP_DCBX_VER_IEEE;
 		break;
 	default:
 		*cap = 0;
@@ -760,5 +758,10 @@ void mlx5e_dcbnl_initialize(struct mlx5e
 	if (MLX5_CAP_GEN(priv->mdev, dcbx))
 		mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
 
+	priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE |
+			 DCB_CAP_DCBX_VER_IEEE;
+	if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+		priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
+
 	mlx5e_ets_init(priv);
 }
author maintainer
#25 lore raw

PATCH 25/52 net/mlx5: Fix arm SRQ command for ISSI version 0

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Noa Osherovich <[email protected]>

[ Upstream commit 672d0880b7798a917bcc622308f25a0fbb991dab ]

Support for ISSI version 0 was recently broken as the arm_srq_cmd command, which is used only for ISSI version 0, was given the opcode for ISSI version 1 instead of ISSI version 0.

Change arm_srq_cmd to use the correct command opcode for ISSI version 0.

Fixes af1ba291c5e4 ('{net, IB}/mlx5: Refactor internal SRQ API')
---
 drivers/net/ethernet/mellanox/mlx5/core/srq.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/srq.c +6 -6
@@ -201,13 +201,13 @@ static int destroy_srq_cmd(struct mlx5_c
 static int arm_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
 		       u16 lwm, int is_srq)
 {
-	/* arm_srq structs missing using identical xrc ones */
-	u32 srq_in[MLX5_ST_SZ_DW(arm_xrc_srq_in)] = {0};
-	u32 srq_out[MLX5_ST_SZ_DW(arm_xrc_srq_out)] = {0};
+	u32 srq_in[MLX5_ST_SZ_DW(arm_rq_in)] = {0};
+	u32 srq_out[MLX5_ST_SZ_DW(arm_rq_out)] = {0};
 
-	MLX5_SET(arm_xrc_srq_in, srq_in, opcode,   MLX5_CMD_OP_ARM_XRC_SRQ);
-	MLX5_SET(arm_xrc_srq_in, srq_in, xrc_srqn, srq->srqn);
-	MLX5_SET(arm_xrc_srq_in, srq_in, lwm,      lwm);
+	MLX5_SET(arm_rq_in, srq_in, opcode, MLX5_CMD_OP_ARM_RQ);
+	MLX5_SET(arm_rq_in, srq_in, op_mod, MLX5_ARM_RQ_IN_OP_MOD_SRQ);
+	MLX5_SET(arm_rq_in, srq_in, srq_number, srq->srqn);
+	MLX5_SET(arm_rq_in, srq_in, lwm,      lwm);
 
 	return  mlx5_cmd_exec(dev, srq_in, sizeof(srq_in),
 			      srq_out, sizeof(srq_out));
author maintainer
#26 lore raw

PATCH 26/52 net/mlx5e: Fix dangling page pointer on DMA mapping error

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eran Ben Elisha <[email protected]>

[ Upstream commit 0556ce72ab16156af6c94cdc7964e4310acc97c0 ]

Function mlx5e_dealloc_rx_wqe is using page pointer value as an indication to valid DMA mapping. In case that the mapping failed, we released the page but kept the dangling pointer. Store the page pointer only after the DMA mapping passed to avoid invalid page DMA unmap.

Fixes bc77b240b3c5 ("net/mlx5e: Add fragmented memory support for RX multi packet WQE")
---
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +1 -1
@@ -216,13 +216,13 @@ static inline int mlx5e_page_alloc_mappe
 	if (unlikely(!page))
 		return -ENOMEM;
 
-	dma_info->page = page;
 	dma_info->addr = dma_map_page(rq->pdev, page, 0,
 				      RQ_PAGE_SIZE(rq), rq->buff.map_dir);
 	if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) {
 		put_page(page);
 		return -ENOMEM;
 	}
+	dma_info->page = page;
 
 	return 0;
 }
author maintainer
#27 lore raw

PATCH 27/52 net/mlx5e: Dont override user RSS upon set channels

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Inbar Karmy <[email protected]>

[ Upstream commit 5a8e12678c767ccf8bb16d6237569e4a707d655b ]

Currently, increasing the number of combined channels is changing the RSS spread to use the new created channels.
Prevent the RSS spread change in case the user explicitly declare it, to avoid overriding user configuration.

Tested:
when RSS default:

# ethtool -L ens8 combined 4
RSS spread will change and point to 4 channels.
# ethtool -X ens8 equal 4
# ethtool -L ens8 combined 6
RSS will not change after increasing the number of the channels.
Fixes 8bf368620486 ('ethtool: ensure channel counts are within bounds during SCHANNELS')
---
 drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +4 -2
@@ -580,8 +580,10 @@ static int mlx5e_set_channels(struct net
 
 	new_channels.params = priv->channels.params;
 	new_channels.params.num_channels = count;
-	mlx5e_build_default_indir_rqt(priv->mdev, new_channels.params.indirection_rqt,
-				      MLX5E_INDIR_RQT_SIZE, count);
+	if (!netif_is_rxfh_configured(priv->netdev))
+		mlx5e_build_default_indir_rqt(priv->mdev,
+					      new_channels.params.indirection_rqt,
+					      MLX5E_INDIR_RQT_SIZE, count);
 
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
 		priv->channels.params = new_channels.params;
author maintainer
#28 lore raw

PATCH 28/52 net/mlx5e: Properly resolve TC offloaded ipv6 vxlan tunnel source address

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Paul Blakey <[email protected]>

[ Upstream commit 08820528c9d3ff0d0eda047d7ef5ecac2da1ef6c ]

Currently if vxlan tunnel ipv6 src isn't supplied the driver fails to resolve it as part of the route lookup. The resulting encap header is left with a zeroed out ipv6 src address so the packets are sent with this src ip.

Use an appropriate route lookup API that also resolves the source ipv6 address if it's not supplied.

Fixes ce99f6b97fcd ('net/mlx5e: Support SRIOV TC encapsulation offloads for IPv6 tunnels')
---
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +3 -5
@@ -1262,12 +1262,10 @@ static int mlx5e_route_lookup_ipv6(struc
 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 	int ret;
 
-	dst = ip6_route_output(dev_net(mirred_dev), NULL, fl6);
-	ret = dst->error;
-	if (ret) {
-		dst_release(dst);
+	ret = ipv6_stub->ipv6_dst_lookup(dev_net(mirred_dev), NULL, &dst,
+					 fl6);
+	if (ret < 0)
 		return ret;
-	}
 
 	*out_ttl = ip6_dst_hoplimit(dst);
 
author maintainer
#29 lore raw

PATCH 29/52 net/mlx5: E-Switch, Unload the representors in the correct order

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shahar Klein <[email protected]>

[ Upstream commit 191220396db840822fc818edf03c49f0c02eb237 ]

When changing from switchdev to legacy mode, all the representor port devices (uplink nic and reps) are cleaned up. Part of this cleaning process is removing the neigh entries and the hash table containing them. However, a representor neigh entry might be linked to the uplink port hash table and if the uplink nic is cleaned first the cleaning of the representor will end up in null deref.
Fix that by unloading the representors in the opposite order of load.

Fixes cb67b832921c ("net/mlx5e: Introduce SRIOV VF representors")
---
 drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +1 -1
@@ -818,7 +818,7 @@ void esw_offloads_cleanup(struct mlx5_es
 	struct mlx5_eswitch_rep *rep;
 	int vport;
 
-	for (vport = 0; vport < nvports; vport++) {
+	for (vport = nvports - 1; vport >= 0; vport--) {
 		rep = &esw->offloads.vport_reps[vport];
 		if (!rep->valid)
 			continue;
author maintainer
#30 lore raw

PATCH 30/52 net/mlx5e: Fix inline header size for small packets

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Moshe Shemesh <[email protected]>

[ Upstream commit 6aace17e64f4aa1c49802c46bd10688968b3787f ]

Fix inline header size, make sure it is not greater than skb len. This bug effects small packets, for example L2 packets with size < 18.

Fixes ae76715d153e ("net/mlx5e: Check the minimum inline header mode before xmit")
---
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +10 -7
@@ -127,10 +127,10 @@ static inline int mlx5e_skb_l3_header_of
 		return mlx5e_skb_l2_header_offset(skb);
 }
 
-static inline unsigned int mlx5e_calc_min_inline(enum mlx5_inline_modes mode,
-						 struct sk_buff *skb)
+static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode,
+					struct sk_buff *skb)
 {
-	int hlen;
+	u16 hlen;
 
 	switch (mode) {
 	case MLX5_INLINE_MODE_NONE:
@@ -139,19 +139,22 @@ static inline unsigned int mlx5e_calc_mi
 		hlen = eth_get_headlen(skb->data, skb_headlen(skb));
 		if (hlen == ETH_HLEN && !skb_vlan_tag_present(skb))
 			hlen += VLAN_HLEN;
-		return hlen;
+		break;
 	case MLX5_INLINE_MODE_IP:
 		/* When transport header is set to zero, it means no transport
 		 * header. When transport header is set to 0xff's, it means
 		 * transport header wasn't set.
 		 */
-		if (skb_transport_offset(skb))
-			return mlx5e_skb_l3_header_offset(skb);
+		if (skb_transport_offset(skb)) {
+			hlen = mlx5e_skb_l3_header_offset(skb);
+			break;
+		}
 		/* fall through */
 	case MLX5_INLINE_MODE_L2:
 	default:
-		return mlx5e_skb_l2_header_offset(skb);
+		hlen = mlx5e_skb_l2_header_offset(skb);
 	}
+	return min_t(u16, hlen, skb->len);
 }
 
 static inline void mlx5e_tx_skb_pull_inline(unsigned char **skb_data,
author maintainer
#31 lore raw

PATCH 31/52 net/mlx5e: Fix CQ moderation mode not set properly

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tal Gilboa <[email protected]>

[ Upstream commit 1213ad28f9595a08e3877248bbba1a25c40225d6 ]

cq_period_mode assignment was mistakenly removed so it was always set to "0", which is EQE based moderation, regardless of the device CAPs and requested value in ethtool.

Fixes 6a9764efb255 ("net/mlx5e: Isolate open_channels from priv->params")
---
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c |    1 +
 1 file changed, 1 insertion(+)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +1 -0
@@ -1936,6 +1936,7 @@ static void mlx5e_build_rx_cq_param(stru
 	}
 
 	mlx5e_build_common_cq_param(priv, param);
+	param->cq_period_mode = params->rx_cq_period_mode;
 }
 
 static void mlx5e_build_tx_cq_param(struct mlx5e_priv *priv,
author maintainer
#32 lore raw

PATCH 32/52 Revert "net: phy: Correctly process PHY_HALTED in phy_stop_machine()"

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit ebc8254aeae34226d0bc8fda309fd9790d4dccfe ]

This reverts commit 7ad813f208533cebfcc32d3d7474dc1677d1b09a ("net: phy:
Correctly process PHY_HALTED in phy_stop_machine()") because it is creating the possibility for a NULL pointer dereference.

David Daney provide the following call trace and diagram of events:

When ndo_stop() is called we call:

phy_disconnect()

    +---> phy_stop_interrupts() implies: phydev->irq = PHY_POLL;
    +---> phy_stop_machine()
    |      +---> phy_state_machine()
    |              +----> queue_delayed_work(): Work queued.
    +--->phy_detach() implies: phydev->attached_dev = NULL;

Now at a later time the queued work does:

phy_state_machine()

    +---->netif_carrier_off(phydev->attached_dev): Oh no! It is NULL:

CPU 12 Unable to handle kernel paging request at virtual address
0000000000000048, epc == ffffffff80de37ec, ra == ffffffff80c7c Oops[#1]:

CPU: 12 PID: 1502 Comm: kworker/12:1 Not tainted 4.9.43-Cavium-Octeon+ #1
Workqueue: events_power_efficient phy_state_machine
task: 80000004021ed100 task.stack: 8000000409d70000
$ 0   : 0000000000000000 ffffffff84720060 0000000000000048 0000000000000004
$ 4   : 0000000000000000 0000000000000001 0000000000000004 0000000000000000
$ 8   : 0000000000000000 0000000000000000 00000000ffff98f3 0000000000000000
$12   : 8000000409d73fe0 0000000000009c00 ffffffff846547c8 000000000000af3b
$16   : 80000004096bab68 80000004096babd0 0000000000000000 80000004096ba800
$20   : 0000000000000000 0000000000000000 ffffffff81090000 0000000000000008
$24   : 0000000000000061 ffffffff808637b0
$28   : 8000000409d70000 8000000409d73cf0 80000000271bd300 ffffffff80c7804c
Hi    : 000000000000002a
Lo    : 000000000000003f
epc   : ffffffff80de37ec netif_carrier_off+0xc/0x58
ra    : ffffffff80c7804c phy_state_machine+0x48c/0x4f8
Status: 14009ce3        KX SX UX KERNEL EXL IE
Cause : 00800008 (ExcCode 02)
BadVA : 0000000000000048
PrId  : 000d9501 (Cavium Octeon III)
Modules linked in:
Process kworker/12:1 (pid: 1502, threadinfo=8000000409d70000,
task=80000004021ed100, tls=0000000000000000)
Stack : 8000000409a54000 80000004096bab68 80000000271bd300 80000000271c1e00
        0000000000000000 ffffffff808a1708 8000000409a54000 80000000271bd300
        80000000271bd320 8000000409a54030 ffffffff80ff0f00 0000000000000001
        ffffffff81090000 ffffffff808a1ac0 8000000402182080 ffffffff84650000
        8000000402182080 ffffffff84650000 ffffffff80ff0000 8000000409a54000
        ffffffff808a1970 0000000000000000 80000004099e8000 8000000402099240
        0000000000000000 ffffffff808a8598 0000000000000000 8000000408eeeb00
        8000000409a54000 00000000810a1d00 0000000000000000 8000000409d73de8
        8000000409d73de8 0000000000000088 000000000c009c00 8000000409d73e08
        8000000409d73e08 8000000402182080 ffffffff808a84d0 8000000402182080
        ...
Call Trace:
[<ffffffff80de37ec>] netif_carrier_off+0xc/0x58
[<ffffffff80c7804c>] phy_state_machine+0x48c/0x4f8
[<ffffffff808a1708>] process_one_work+0x158/0x368
[<ffffffff808a1ac0>] worker_thread+0x150/0x4c0
[<ffffffff808a8598>] kthread+0xc8/0xe0
[<ffffffff808617f0>] ret_from_kernel_thread+0x14/0x1c

The original motivation for this change originated from Marc Gonzales indicating that his network driver did not have its adjust_link callback executing with phydev->link = 0 while he was expecting it.

PHYLIB has never made any such guarantees ever because phy_stop() merely just tells the workqueue to move into PHY_HALTED state which will happen asynchronously.

Fixes 7ad813f20853 ("net: phy: Correctly process PHY_HALTED in phy_stop_machine()")
---
 drivers/net/phy/phy.c |    3 ---
 1 file changed, 3 deletions(-)
drivers/net/phy/phy.c +0 -3
@@ -749,9 +749,6 @@ void phy_stop_machine(struct phy_device
 	if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
 		phydev->state = PHY_UP;
 	mutex_unlock(&phydev->lock);
-
-	/* Now we can run the state machine synchronously */
-	phy_state_machine(&phydev->state_queue.work);
 }
 
 /**
author maintainer
#33 lore raw

PATCH 33/52 net: fec: Allow reception of frames bigger than 1522 bytes

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andrew Lunn <[email protected]>

[ Upstream commit fbbeefdd21049fcf9437c809da3828b210577f36 ]

The FEC Receive Control Register has a 14 bit field indicating the longest frame that may be received. It is being set to 1522. Frames longer than this are discarded, but counted as being in error.

When using DSA, frames from the switch has an additional header, either 4 or 8 bytes if a Marvell switch is used. Thus a full MTU frame of 1522 bytes received by the switch on a port becomes 1530 bytes when passed to the host via the FEC interface.

Change the maximum receive size to 2048 - 64, where 64 is the maximum rx_alignment applied on the receive buffer for AVB capable FEC cores. Use this value also for the maximum receive buffer size. The driver is already allocating a receive SKB of 2048 bytes, so this change should not have any significant effects.

Tested on imx51, imx6, vf610.

---
 drivers/net/ethernet/freescale/fec_main.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +5 -3
@@ -173,10 +173,12 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
 #endif /* CONFIG_M5272 */
 
 /* The FEC stores dest/src/type/vlan, data, and checksum for receive packets.
+ *
+ * 2048 byte skbufs are allocated. However, alignment requirements
+ * varies between FEC variants. Worst case is 64, so round down by 64.
  */
-#define PKT_MAXBUF_SIZE		1522
+#define PKT_MAXBUF_SIZE		(round_down(2048 - 64, 64))
 #define PKT_MINBUF_SIZE		64
-#define PKT_MAXBLR_SIZE		1536
 
 /* FEC receive acceleration */
 #define FEC_RACC_IPDIS		(1 << 1)
@@ -848,7 +850,7 @@ static void fec_enet_enable_ring(struct
 	for (i = 0; i < fep->num_rx_queues; i++) {
 		rxq = fep->rx_queue[i];
 		writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i));
-		writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i));
+		writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i));
 
 		/* enable DMA1/2 */
 		if (i)
author maintainer
#34 lore raw

PATCH 34/52 mlxsw: spectrum: Forbid linking to devices that have uppers

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ido Schimmel <[email protected]>

[ Upstream commit 25cc72a33835ed8a6f53180a822cadab855852ac ]

The mlxsw driver relies on NETDEV_CHANGEUPPER events to configure the device in case a port is enslaved to a master netdev such as bridge or bond.

Since the driver ignores events unrelated to its ports and their uppers, it's possible to engineer situations in which the device's data path differs from the kernel's.

One example to such a situation is when a port is enslaved to a bond that is already enslaved to a bridge. When the bond was enslaved the driver ignored the event - as the bond wasn't one of its uppers - and therefore a bridge port instance isn't created in the device.

Until such configurations are supported forbid them by checking that the upper device doesn't have uppers of its own.

Fixes 0d65fc13042f ("mlxsw: spectrum: Implement LAG port join/leave")
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |    6 ++++++
 include/linux/netdevice.h                      |    2 ++
 net/core/dev.c                                 |    3 ++-
 3 files changed, 10 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum.c +6 -0
@@ -4110,6 +4110,8 @@ static int mlxsw_sp_netdevice_port_upper
 			return -EINVAL;
 		if (!info->linking)
 			break;
+		if (netdev_has_any_upper_dev(upper_dev))
+			return -EINVAL;
 		/* HW limitation forbids to put ports to multiple bridges. */
 		if (netif_is_bridge_master(upper_dev) &&
 		    !mlxsw_sp_master_bridge_check(mlxsw_sp, upper_dev))
@@ -4274,6 +4276,10 @@ static int mlxsw_sp_netdevice_bridge_eve
 		if (is_vlan_dev(upper_dev) &&
 		    br_dev != mlxsw_sp->master_bridge.dev)
 			return -EINVAL;
+		if (!info->linking)
+			break;
+		if (netdev_has_any_upper_dev(upper_dev))
+			return -EINVAL;
 		break;
 	case NETDEV_CHANGEUPPER:
 		upper_dev = info->upper_dev;
include/linux/netdevice.h +2 -0
@@ -3868,6 +3868,8 @@ int netdev_walk_all_upper_dev_rcu(struct
 bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
 				  struct net_device *upper_dev);
 
+bool netdev_has_any_upper_dev(struct net_device *dev);
+
 void *netdev_lower_get_next_private(struct net_device *dev,
 				    struct list_head **iter);
 void *netdev_lower_get_next_private_rcu(struct net_device *dev,
net/core/dev.c +2 -1
@@ -5590,12 +5590,13 @@ EXPORT_SYMBOL(netdev_has_upper_dev_all_r
  * Find out if a device is linked to an upper device and return true in case
  * it is. The caller must hold the RTNL lock.
  */
-static bool netdev_has_any_upper_dev(struct net_device *dev)
+bool netdev_has_any_upper_dev(struct net_device *dev)
 {
 	ASSERT_RTNL();
 
 	return !list_empty(&dev->adj_list.upper);
 }
+EXPORT_SYMBOL(netdev_has_any_upper_dev);
 
 /**
  * netdev_master_upper_dev_get - Get master upper device
author maintainer
#35 lore raw

PATCH 35/52 bridge: switchdev: Clear forward mark when transmitting packet

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ido Schimmel <[email protected]>

[ Upstream commit 79e99bdd60b484af9afe0147e85a13e66d5c1cdb ]

Commit 6bc506b4fb06 ("bridge: switchdev: Add forward mark support for stacked devices") added the 'offload_fwd_mark' bit to the skb in order to allow drivers to indicate to the bridge driver that they already forwarded the packet in L2.

In case the bit is set, before transmitting the packet from each port, the port's mark is compared with the mark stored in the skb's control block. If both marks are equal, we know the packet arrived from a switch device that already forwarded the packet and it's not re-transmitted.

However, if the packet is transmitted from the bridge device itself (e.g., br0), we should clear the 'offload_fwd_mark' bit as the mark stored in the skb's control block isn't valid.

This scenario can happen in rare cases where a packet was trapped during L3 forwarding and forwarded by the kernel to a bridge device.

Fixes 6bc506b4fb06 ("bridge: switchdev: Add forward mark support for stacked devices")
---
 net/bridge/br_device.c |    3 +++
 1 file changed, 3 insertions(+)
net/bridge/br_device.c +3 -0
@@ -53,6 +53,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *
 	brstats->tx_bytes += skb->len;
 	u64_stats_update_end(&brstats->syncp);
 
+#ifdef CONFIG_NET_SWITCHDEV
+	skb->offload_fwd_mark = 0;
+#endif
 	BR_INPUT_SKB_CB(skb)->brdev = dev;
 
 	skb_reset_mac_header(skb);
author maintainer
#36 lore raw

PATCH 36/52 Revert "net: use lib/percpu_counter API for fragmentation mem accounting"

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jesper Dangaard Brouer <[email protected]>

[ Upstream commit fb452a1aa3fd4034d7999e309c5466ff2d7005aa ]

This reverts commit 6d7b857d541ecd1d9bd997c97242d4ef94b19de2.

There is a bug in fragmentation codes use of the percpu_counter API, that can cause issues on systems with many CPUs.

The frag_mem_limit() just reads the global counter (fbc->count), without considering other CPUs can have upto batch size (130K) that haven't been subtracted yet. Due to the 3MBytes lower thresh limit, this become dangerous at >=24 CPUs (3*1024*1024/130000=24).

The correct API usage would be to use __percpu_counter_compare() which does the right thing, and takes into account the number of (online) CPUs and batch size, to account for this and call __percpu_counter_sum() when needed.

We choose to revert the use of the lib/percpu_counter API for frag memory accounting for several reasons:

1) On systems with CPUs > 24, the heavier fully locked __percpu_counter_sum() is always invoked, which will be more expensive than the atomic_t that is reverted to.

Given systems with more than 24 CPUs are becoming common this doesn't seem like a good option. To mitigate this, the batch size could be decreased and thresh be increased.

2) The add_frag_mem_limit+sub_frag_mem_limit pairs happen on the RX CPU, before SKBs are pushed into sockets on remote CPUs. Given NICs can only hash on L2 part of the IP-header, the NIC-RXq's will likely be limited. Thus, a fair chance that atomic add+dec happen on the same CPU.

Revert note that commit 1d6119baf061 ("net: fix percpu memory leaks") removed init_frag_mem_limit() and instead use inet_frags_init_net(). After this revert, inet_frags_uninit_net() becomes empty.

Fixes 6d7b857d541e ("net: use lib/percpu_counter API for fragmentation mem accounting")
Fixes 1d6119baf061 ("net: fix percpu memory leaks")
---
 include/net/inet_frag.h  |   30 +++++++++---------------------
 net/ipv4/inet_fragment.c |    4 +---
 2 files changed, 10 insertions(+), 24 deletions(-)
include/net/inet_frag.h +9 -21
@@ -1,14 +1,9 @@
 #ifndef __NET_FRAG_H__
 #define __NET_FRAG_H__
 
-#include <linux/percpu_counter.h>
-
 struct netns_frags {
-	/* The percpu_counter "mem" need to be cacheline aligned.
-	 *  mem.count must not share cacheline with other writers
-	 */
-	struct percpu_counter   mem ____cacheline_aligned_in_smp;
-
+	/* Keep atomic mem on separate cachelines in structs that include it */
+	atomic_t		mem ____cacheline_aligned_in_smp;
 	/* sysctls */
 	int			timeout;
 	int			high_thresh;
@@ -110,11 +105,11 @@ void inet_frags_fini(struct inet_frags *
 
 static inline int inet_frags_init_net(struct netns_frags *nf)
 {
-	return percpu_counter_init(&nf->mem, 0, GFP_KERNEL);
+	atomic_set(&nf->mem, 0);
+	return 0;
 }
 static inline void inet_frags_uninit_net(struct netns_frags *nf)
 {
-	percpu_counter_destroy(&nf->mem);
 }
 
 void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
@@ -140,31 +135,24 @@ static inline bool inet_frag_evicting(st
 
 /* Memory Tracking Functions. */
 
-/* The default percpu_counter batch size is not big enough to scale to
- * fragmentation mem acct sizes.
- * The mem size of a 64K fragment is approx:
- *  (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes
- */
-static unsigned int frag_percpu_counter_batch = 130000;
-
 static inline int frag_mem_limit(struct netns_frags *nf)
 {
-	return percpu_counter_read(&nf->mem);
+	return atomic_read(&nf->mem);
 }
 
 static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
 {
-	percpu_counter_add_batch(&nf->mem, -i, frag_percpu_counter_batch);
+	atomic_sub(i, &nf->mem);
 }
 
 static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
 {
-	percpu_counter_add_batch(&nf->mem, i, frag_percpu_counter_batch);
+	atomic_add(i, &nf->mem);
 }
 
-static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf)
+static inline int sum_frag_mem_limit(struct netns_frags *nf)
 {
-	return percpu_counter_sum_positive(&nf->mem);
+	return atomic_read(&nf->mem);
 }
 
 /* RFC 3168 support :
net/ipv4/inet_fragment.c +1 -3
@@ -234,10 +234,8 @@ evict_again:
 	cond_resched();
 
 	if (read_seqretry(&f->rnd_seqlock, seq) ||
-	    percpu_counter_sum(&nf->mem))
+	    sum_frag_mem_limit(nf))
 		goto evict_again;
-
-	percpu_counter_destroy(&nf->mem);
 }
 EXPORT_SYMBOL(inet_frags_exit_net);
 
author maintainer
#37 lore raw

PATCH 37/52 Revert "net: fix percpu memory leaks"

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jesper Dangaard Brouer <[email protected]>

[ Upstream commit 5a63643e583b6a9789d7a225ae076fb4e603991c ]

This reverts commit 1d6119baf0610f813eb9d9580eb4fd16de5b4ceb.

After reverting commit 6d7b857d541e ("net: use lib/percpu_counter API for fragmentation mem accounting") then here is no need for this fix-up patch. As percpu_counter is no longer used, it cannot memory leak it any-longer.

Fixes 6d7b857d541e ("net: use lib/percpu_counter API for fragmentation mem accounting")
Fixes 1d6119baf061 ("net: fix percpu memory leaks")
---
 include/net/inet_frag.h                 |    7 +------
 net/ieee802154/6lowpan/reassembly.c     |   11 +++--------
 net/ipv4/ip_fragment.c                  |   12 +++---------
 net/ipv6/netfilter/nf_conntrack_reasm.c |   12 +++---------
 net/ipv6/reassembly.c                   |   12 +++---------
 5 files changed, 13 insertions(+), 41 deletions(-)
include/net/inet_frag.h +1 -6
@@ -103,15 +103,10 @@ struct inet_frags {
 int inet_frags_init(struct inet_frags *);
 void inet_frags_fini(struct inet_frags *);
 
-static inline int inet_frags_init_net(struct netns_frags *nf)
+static inline void inet_frags_init_net(struct netns_frags *nf)
 {
 	atomic_set(&nf->mem, 0);
-	return 0;
 }
-static inline void inet_frags_uninit_net(struct netns_frags *nf)
-{
-}
-
 void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
 
 void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
net/ieee802154/6lowpan/reassembly.c +3 -8
@@ -580,19 +580,14 @@ static int __net_init lowpan_frags_init_
 {
 	struct netns_ieee802154_lowpan *ieee802154_lowpan =
 		net_ieee802154_lowpan(net);
-	int res;
 
 	ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
 	ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
 	ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
 
-	res = inet_frags_init_net(&ieee802154_lowpan->frags);
-	if (res)
-		return res;
-	res = lowpan_frags_ns_sysctl_register(net);
-	if (res)
-		inet_frags_uninit_net(&ieee802154_lowpan->frags);
-	return res;
+	inet_frags_init_net(&ieee802154_lowpan->frags);
+
+	return lowpan_frags_ns_sysctl_register(net);
 }
 
 static void __net_exit lowpan_frags_exit_net(struct net *net)
net/ipv4/ip_fragment.c +3 -9
@@ -844,8 +844,6 @@ static void __init ip4_frags_ctl_registe
 
 static int __net_init ipv4_frags_init_net(struct net *net)
 {
-	int res;
-
 	/* Fragment cache limits.
 	 *
 	 * The fragment memory accounting code, (tries to) account for
@@ -871,13 +869,9 @@ static int __net_init ipv4_frags_init_ne
 
 	net->ipv4.frags.max_dist = 64;
 
-	res = inet_frags_init_net(&net->ipv4.frags);
-	if (res)
-		return res;
-	res = ip4_frags_ns_ctl_register(net);
-	if (res)
-		inet_frags_uninit_net(&net->ipv4.frags);
-	return res;
+	inet_frags_init_net(&net->ipv4.frags);
+
+	return ip4_frags_ns_ctl_register(net);
 }
 
 static void __net_exit ipv4_frags_exit_net(struct net *net)
net/ipv6/netfilter/nf_conntrack_reasm.c +3 -9
@@ -622,18 +622,12 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_gather);
 
 static int nf_ct_net_init(struct net *net)
 {
-	int res;
-
 	net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
 	net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
 	net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT;
-	res = inet_frags_init_net(&net->nf_frag.frags);
-	if (res)
-		return res;
-	res = nf_ct_frag6_sysctl_register(net);
-	if (res)
-		inet_frags_uninit_net(&net->nf_frag.frags);
-	return res;
+	inet_frags_init_net(&net->nf_frag.frags);
+
+	return nf_ct_frag6_sysctl_register(net);
 }
 
 static void nf_ct_net_exit(struct net *net)
net/ipv6/reassembly.c +3 -9
@@ -714,19 +714,13 @@ static void ip6_frags_sysctl_unregister(
 
 static int __net_init ipv6_frags_init_net(struct net *net)
 {
-	int res;
-
 	net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
 	net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
 	net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT;
 
-	res = inet_frags_init_net(&net->ipv6.frags);
-	if (res)
-		return res;
-	res = ip6_frags_ns_sysctl_register(net);
-	if (res)
-		inet_frags_uninit_net(&net->ipv6.frags);
-	return res;
+	inet_frags_init_net(&net->ipv6.frags);
+
+	return ip6_frags_ns_sysctl_register(net);
 }
 
 static void __net_exit ipv6_frags_exit_net(struct net *net)
author maintainer
#38 lore raw

PATCH 38/52 gianfar: Fix Tx flow control deactivation

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Claudiu Manoil <[email protected]>

[ Upstream commit 5d621672bc1a1e5090c1ac5432a18c79e0e13e03 ]

The wrong register is checked for the Tx flow control bit,
it should have been maccfg1 not maccfg2.
This went unnoticed for so long probably because the impact is hardly visible, not to mention the tangled code from adjust_link(). First, link flow control (i.e. handling of Rx/Tx link level pause frames) is disabled by default (needs to be enabled via 'ethtool -A'). Secondly, maccfg2 always returns 0 for tx_flow_oldval (except for a few old boards), which results in Tx flow control remaining always on once activated.

Fixes 45b679c9a3ccd9e34f28e6ec677b812a860eb8eb ("gianfar: Implement PAUSE frame generation support")
---
 drivers/net/ethernet/freescale/gianfar.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/gianfar.c +1 -1
@@ -3687,7 +3687,7 @@ static noinline void gfar_update_link_st
 		u32 tempval1 = gfar_read(&regs->maccfg1);
 		u32 tempval = gfar_read(&regs->maccfg2);
 		u32 ecntrl = gfar_read(&regs->ecntrl);
-		u32 tx_flow_oldval = (tempval & MACCFG1_TX_FLOW);
+		u32 tx_flow_oldval = (tempval1 & MACCFG1_TX_FLOW);
 
 		if (phydev->duplex != priv->oldduplex) {
 			if (!(phydev->duplex))
author maintainer
#39 lore raw

PATCH 39/52 vhost_net: correctly check tx avail during rx busy polling

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Wang <[email protected]>

[ Upstream commit 8b949bef9172ca69d918e93509a4ecb03d0355e0 ]

We check tx avail through vhost_enable_notify() in the past which is wrong since it only checks whether or not guest has filled more available buffer since last avail idx synchronization which was just done by vhost_vq_avail_empty() before. What we really want is checking pending buffers in the avail ring. Fix this by calling vhost_vq_avail_empty() instead.

This issue could be noticed by doing netperf TCP_RR benchmark as client from guest (but not host). With this fix, TCP_RR from guest to localhost restores from 1375.91 trans per sec to 55235.28 trans per sec on my laptop (Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz).

Fixes 030881372460 ("vhost_net: basic polling support")
---
 drivers/vhost/net.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/vhost/net.c +6 -1
@@ -557,8 +557,13 @@ static int vhost_net_rx_peek_head_len(st
 
 		preempt_enable();
 
-		if (vhost_enable_notify(&net->dev, vq))
+		if (!vhost_vq_avail_empty(&net->dev, vq))
 			vhost_poll_queue(&vq->poll);
+		else if (unlikely(vhost_enable_notify(&net->dev, vq))) {
+			vhost_disable_notify(&net->dev, vq);
+			vhost_poll_queue(&vq->poll);
+		}
+
 		mutex_unlock(&vq->mutex);
 
 		len = peek_head_len(sk);
author maintainer
#40 lore raw

PATCH 40/52 ip6_gre: update mtu properly in ip6gre_err

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xin Long <[email protected]>

[ Upstream commit 5c25f30c93fdc5bf25e62101aeaae7a4f9b421b3 ]

Now when probessing ICMPV6_PKT_TOOBIG, ip6gre_err only subtracts the offset of gre header from mtu info. The expected mtu of gre device should also subtract gre header. Otherwise, the next packets still can't be sent out.

Jianlin found this issue when using the topo:
client(ip6gre)<---->(nic1)route(nic2)<----->(ip6gre)server

and reducing nic2's mtu, then both tcp and sctp's performance with big size data became 0.

This patch is to fix it by also subtracting grehdr (tun->tun_hlen) from mtu info when updating gre device's mtu in ip6gre_err(). It also needs to subtract ETH_HLEN if gre dev'type is ARPHRD_ETHER.

---
 net/ipv6/ip6_gre.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv6/ip6_gre.c +3 -1
@@ -432,7 +432,9 @@ static void ip6gre_err(struct sk_buff *s
 		}
 		break;
 	case ICMPV6_PKT_TOOBIG:
-		mtu = be32_to_cpu(info) - offset;
+		mtu = be32_to_cpu(info) - offset - t->tun_hlen;
+		if (t->dev->type == ARPHRD_ETHER)
+			mtu -= ETH_HLEN;
 		if (mtu < IPV6_MIN_MTU)
 			mtu = IPV6_MIN_MTU;
 		t->dev->mtu = mtu;
author maintainer
#41 lore raw

PATCH 41/52 ipv6: fix memory leak with multiple tables during netns destruction

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sabrina Dubroca <[email protected]>

[ Upstream commit ba1cc08d9488c94cb8d94f545305688b72a2a300 ]

fib6_net_exit only frees the main and local tables. If another table was created with fib6_alloc_table, we leak it when the netns is destroyed.

Fix this in the same way ip_fib_net_exit cleans up tables, by walking through the whole hashtable of fib6_table's. We can get rid of the special cases for local and main, since they're also part of the hashtable.

Reproducer:
ip netns add x
ip -net x -6 rule add from 6003:1::/64 table 100 ip netns del x

Fixes 58f09b78b730 ("[NETNS][IPV6] ip6_fib - make it per network namespace")
---
 net/ipv6/ip6_fib.c |   25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)
net/ipv6/ip6_fib.c +19 -6
@@ -201,6 +201,12 @@ static void rt6_release(struct rt6_info
 	}
 }
 
+static void fib6_free_table(struct fib6_table *table)
+{
+	inetpeer_invalidate_tree(&table->tb6_peers);
+	kfree(table);
+}
+
 static void fib6_link_table(struct net *net, struct fib6_table *tb)
 {
 	unsigned int h;
@@ -1911,15 +1917,22 @@ out_timer:
 
 static void fib6_net_exit(struct net *net)
 {
+	unsigned int i;
+
 	rt6_ifdown(net, NULL);
 	del_timer_sync(&net->ipv6.ip6_fib_timer);
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers);
-	kfree(net->ipv6.fib6_local_tbl);
-#endif
-	inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers);
-	kfree(net->ipv6.fib6_main_tbl);
+	for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
+		struct hlist_head *head = &net->ipv6.fib_table_hash[i];
+		struct hlist_node *tmp;
+		struct fib6_table *tb;
+
+		hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) {
+			hlist_del(&tb->tb6_hlist);
+			fib6_free_table(tb);
+		}
+	}
+
 	kfree(net->ipv6.fib_table_hash);
 	kfree(net->ipv6.rt6_stats);
 }
author maintainer
#42 lore raw

PATCH 42/52 ipv6: fix typo in fib6_net_exit()

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 32a805baf0fb70b6dbedefcd7249ac7f580f9e3b ]

IPv6 FIB should use FIB6_TABLE_HASHSZ, not FIB_TABLE_HASHSZ.

Fixes ba1cc08d9488 ("ipv6: fix memory leak with multiple tables during netns destruction")
---
 net/ipv6/ip6_fib.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/ip6_fib.c +1 -1
@@ -1922,7 +1922,7 @@ static void fib6_net_exit(struct net *ne
 	rt6_ifdown(net, NULL);
 	del_timer_sync(&net->ipv6.ip6_fib_timer);
 
-	for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
+	for (i = 0; i < FIB6_TABLE_HASHSZ; i++) {
 		struct hlist_head *head = &net->ipv6.fib_table_hash[i];
 		struct hlist_node *tmp;
 		struct fib6_table *tb;
author maintainer
#43 lore raw

PATCH 43/52 sctp: fix missing wake ups in some situations

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Marcelo Ricardo Leitner <[email protected]>

[ Upstream commit 7906b00f5cd1cd484fced7fcda892176e3202c8a ]

Commit fb586f25300f ("sctp: delay calls to sk_data_ready() as much as possible") minimized the number of wake ups that are triggered in case the association receives a packet with multiple data chunks on it and/or when io_events are enabled and then commit 0970f5b36659 ("sctp: signal sk_data_ready earlier on data chunks reception") moved the wake up to as soon as possible. It thus relies on the state machine running later to clean the flag that the event was already generated.

The issue is that there are 2 call paths that calls sctp_ulpq_tail_event() outside of the state machine, causing the flag to linger and possibly omitting a needed wake up in the sequence.

One of the call paths is when enabling SCTP_SENDER_DRY_EVENTS via setsockopt(SCTP_EVENTS), as noticed by Harald Welte. The other is when partial reliability triggers removal of chunks from the send queue when the application calls sendmsg().

This commit fixes it by not setting the flag in case the socket is not owned by the user, as it won't be cleaned later. This works for user-initiated calls and also for rx path processing.

Fixes fb586f25300f ("sctp: delay calls to sk_data_ready() as much as possible")
---
 net/sctp/ulpqueue.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/sctp/ulpqueue.c +2 -1
@@ -265,7 +265,8 @@ int sctp_ulpq_tail_event(struct sctp_ulp
 		sctp_ulpq_clear_pd(ulpq);
 
 	if (queue == &sk->sk_receive_queue && !sp->data_ready_signalled) {
-		sp->data_ready_signalled = 1;
+		if (!sock_owned_by_user(sk))
+			sp->data_ready_signalled = 1;
 		sk->sk_data_ready(sk);
 	}
 	return 1;
author maintainer
#44 lore raw

PATCH 44/52 f2fs: let fill_super handle roll-forward errors

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jaegeuk Kim <[email protected]>

commit afd2b4da40b3b567ef8d8e6881479345a2312a03 upstream.

If we set CP_ERROR_FLAG in roll-forward error, f2fs is no longer to proceed any IOs due to f2fs_cp_error(). But, for example, if some stale data is involved on roll-forward process, we're able to get -ENOENT, getting fs stuck. If we get any error, let fill_super set SBI_NEED_FSCK and try to recover back to stable point.

---
 fs/f2fs/recovery.c |    2 --
 1 file changed, 2 deletions(-)
fs/f2fs/recovery.c +0 -2
@@ -599,8 +599,6 @@ out:
 	}
 
 	clear_sbi_flag(sbi, SBI_POR_DOING);
-	if (err)
-		set_ckpt_flags(sbi, CP_ERROR_FLAG);
 	mutex_unlock(&sbi->cp_mutex);
 
 	/* let's drop all the directory inodes for clean checkpoint */
author maintainer
#45 lore raw

PATCH 45/52 f2fs: check hot_data for roll-forward recovery

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jaegeuk Kim <[email protected]>

commit 125c9fb1ccb53eb2ea9380df40f3c743f3fb2fed upstream.

We need to check HOT_DATA to truncate any previous data block when doing roll-forward recovery.

---
 fs/f2fs/recovery.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/f2fs/recovery.c +1 -1
@@ -291,7 +291,7 @@ static int check_index_in_prev_nodes(str
 		return 0;
 
 	/* Get the previous summary */
-	for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
 		struct curseg_info *curseg = CURSEG_I(sbi, i);
 		if (curseg->segno == segno) {
 			sum = curseg->sum_blk->entries[blkoff];
author maintainer
#46 lore raw

PATCH 46/52 x86/fsgsbase/64: Fully initialize FS and GS state in start_thread_common

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <[email protected]>

commit 767d035d838f4fd6b5a5bbd7a3f6d293b7f65a49 upstream.

execve used to leak FSBASE and GSBASE on AMD CPUs. Fix it.

The security impact of this bug is small but not quite zero -- it could weaken ASLR when a privileged task execs a less privileged program, but only if program changed bitness across the exec, or the child binary was highly unusual or actively malicious. A child program that was compromised after the exec would not have access to the leaked base.

Cc Borislav Petkov <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chang Seok <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/process_64.c |    9 +++++++++
 1 file changed, 9 insertions(+)
arch/x86/kernel/process_64.c +9 -0
@@ -229,10 +229,19 @@ start_thread_common(struct pt_regs *regs
 		    unsigned long new_sp,
 		    unsigned int _cs, unsigned int _ss, unsigned int _ds)
 {
+	WARN_ON_ONCE(regs != current_pt_regs());
+
+	if (static_cpu_has(X86_BUG_NULL_SEG)) {
+		/* Loading zero below won't clear the base. */
+		loadsegment(fs, __USER_DS);
+		load_gs_index(__USER_DS);
+	}
+
 	loadsegment(fs, 0);
 	loadsegment(es, _ds);
 	loadsegment(ds, _ds);
 	load_gs_index(0);
+
 	regs->ip		= new_ip;
 	regs->sp		= new_sp;
 	regs->cs		= _cs;
author maintainer
#47 lore raw

PATCH 47/52 x86/fsgsbase/64: Report FSBASE and GSBASE correctly in core dumps

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <[email protected]>

commit 9584d98bed7a7a904d0702ad06bbcc94703cb5b4 upstream.

In ELF_COPY_CORE_REGS, we're copying from the current task, so accessing thread.fsbase and thread.gsbase makes no sense. Just read the values from the CPU registers.

In practice, the old code would have been correct most of the time simply because thread.fsbase and thread.gsbase usually matched the CPU registers.

Cc Borislav Petkov <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chang Seok <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/include/asm/elf.h |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/elf.h +3 -2
@@ -204,6 +204,7 @@ void set_personality_ia32(bool);
 
 #define ELF_CORE_COPY_REGS(pr_reg, regs)			\
 do {								\
+	unsigned long base;					\
 	unsigned v;						\
 	(pr_reg)[0] = (regs)->r15;				\
 	(pr_reg)[1] = (regs)->r14;				\
@@ -226,8 +227,8 @@ do {								\
 	(pr_reg)[18] = (regs)->flags;				\
 	(pr_reg)[19] = (regs)->sp;				\
 	(pr_reg)[20] = (regs)->ss;				\
-	(pr_reg)[21] = current->thread.fsbase;			\
-	(pr_reg)[22] = current->thread.gsbase;			\
+	rdmsrl(MSR_FS_BASE, base); (pr_reg)[21] = base;		\
+	rdmsrl(MSR_KERNEL_GS_BASE, base); (pr_reg)[22] = base;	\
 	asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v;	\
 	asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v;	\
 	asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v;	\
author maintainer
#48 lore raw

PATCH 48/52 x86/switch_to/64: Rewrite FS/GS switching yet again to fix AMD CPUs

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <[email protected]>

commit e137a4d8f4dd2e277e355495b6b2cb241a8693c3 upstream.

Switching FS and GS is a mess, and the current code is still subtly
wrong: it assumes that "Loading a nonzero value into FS sets the index and base", which is false on AMD CPUs if the value being loaded is 1, 2, or 3.

(The current code came from commit 3e2b68d752c9 ("x86/asm, sched/x86: Rewrite the FS and GS context switch code"), which made it better but didn't fully fix it.)

Rewrite it to be much simpler and more obviously correct. This should fix it fully on AMD CPUs and shouldn't adversely affect performance.

Cc Borislav Petkov <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chang Seok <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/process_64.c |  227 +++++++++++++++++++++++--------------------
 1 file changed, 122 insertions(+), 105 deletions(-)
arch/x86/kernel/process_64.c +122 -105
@@ -149,6 +149,123 @@ void release_thread(struct task_struct *
 	}
 }
 
+enum which_selector {
+	FS,
+	GS
+};
+
+/*
+ * Saves the FS or GS base for an outgoing thread if FSGSBASE extensions are
+ * not available.  The goal is to be reasonably fast on non-FSGSBASE systems.
+ * It's forcibly inlined because it'll generate better code and this function
+ * is hot.
+ */
+static __always_inline void save_base_legacy(struct task_struct *prev_p,
+					     unsigned short selector,
+					     enum which_selector which)
+{
+	if (likely(selector == 0)) {
+		/*
+		 * On Intel (without X86_BUG_NULL_SEG), the segment base could
+		 * be the pre-existing saved base or it could be zero.  On AMD
+		 * (with X86_BUG_NULL_SEG), the segment base could be almost
+		 * anything.
+		 *
+		 * This branch is very hot (it's hit twice on almost every
+		 * context switch between 64-bit programs), and avoiding
+		 * the RDMSR helps a lot, so we just assume that whatever
+		 * value is already saved is correct.  This matches historical
+		 * Linux behavior, so it won't break existing applications.
+		 *
+		 * To avoid leaking state, on non-X86_BUG_NULL_SEG CPUs, if we
+		 * report that the base is zero, it needs to actually be zero:
+		 * see the corresponding logic in load_seg_legacy.
+		 */
+	} else {
+		/*
+		 * If the selector is 1, 2, or 3, then the base is zero on
+		 * !X86_BUG_NULL_SEG CPUs and could be anything on
+		 * X86_BUG_NULL_SEG CPUs.  In the latter case, Linux
+		 * has never attempted to preserve the base across context
+		 * switches.
+		 *
+		 * If selector > 3, then it refers to a real segment, and
+		 * saving the base isn't necessary.
+		 */
+		if (which == FS)
+			prev_p->thread.fsbase = 0;
+		else
+			prev_p->thread.gsbase = 0;
+	}
+}
+
+static __always_inline void save_fsgs(struct task_struct *task)
+{
+	savesegment(fs, task->thread.fsindex);
+	savesegment(gs, task->thread.gsindex);
+	save_base_legacy(task, task->thread.fsindex, FS);
+	save_base_legacy(task, task->thread.gsindex, GS);
+}
+
+static __always_inline void loadseg(enum which_selector which,
+				    unsigned short sel)
+{
+	if (which == FS)
+		loadsegment(fs, sel);
+	else
+		load_gs_index(sel);
+}
+
+static __always_inline void load_seg_legacy(unsigned short prev_index,
+					    unsigned long prev_base,
+					    unsigned short next_index,
+					    unsigned long next_base,
+					    enum which_selector which)
+{
+	if (likely(next_index <= 3)) {
+		/*
+		 * The next task is using 64-bit TLS, is not using this
+		 * segment at all, or is having fun with arcane CPU features.
+		 */
+		if (next_base == 0) {
+			/*
+			 * Nasty case: on AMD CPUs, we need to forcibly zero
+			 * the base.
+			 */
+			if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
+				loadseg(which, __USER_DS);
+				loadseg(which, next_index);
+			} else {
+				/*
+				 * We could try to exhaustively detect cases
+				 * under which we can skip the segment load,
+				 * but there's really only one case that matters
+				 * for performance: if both the previous and
+				 * next states are fully zeroed, we can skip
+				 * the load.
+				 *
+				 * (This assumes that prev_base == 0 has no
+				 * false positives.  This is the case on
+				 * Intel-style CPUs.)
+				 */
+				if (likely(prev_index | next_index | prev_base))
+					loadseg(which, next_index);
+			}
+		} else {
+			if (prev_index != next_index)
+				loadseg(which, next_index);
+			wrmsrl(which == FS ? MSR_FS_BASE : MSR_KERNEL_GS_BASE,
+			       next_base);
+		}
+	} else {
+		/*
+		 * The next task is using a real segment.  Loading the selector
+		 * is sufficient.
+		 */
+		loadseg(which, next_index);
+	}
+}
+
 int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
 		unsigned long arg, struct task_struct *p, unsigned long tls)
 {
@@ -286,7 +403,6 @@ __switch_to(struct task_struct *prev_p,
 	struct fpu *next_fpu = &next->fpu;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
-	unsigned prev_fsindex, prev_gsindex;
 
 	switch_fpu_prepare(prev_fpu, cpu);
 
@@ -295,8 +411,7 @@ __switch_to(struct task_struct *prev_p,
 	 *
 	 * (e.g. xen_load_tls())
 	 */
-	savesegment(fs, prev_fsindex);
-	savesegment(gs, prev_gsindex);
+	save_fsgs(prev_p);
 
 	/*
 	 * Load TLS before restoring any segments so that segment loads
@@ -335,108 +450,10 @@ __switch_to(struct task_struct *prev_p,
 	if (unlikely(next->ds | prev->ds))
 		loadsegment(ds, next->ds);
 
-	/*
-	 * Switch FS and GS.
-	 *
-	 * These are even more complicated than DS and ES: they have
-	 * 64-bit bases are that controlled by arch_prctl.  The bases
-	 * don't necessarily match the selectors, as user code can do
-	 * any number of things to cause them to be inconsistent.
-	 *
-	 * We don't promise to preserve the bases if the selectors are
-	 * nonzero.  We also don't promise to preserve the base if the
-	 * selector is zero and the base doesn't match whatever was
-	 * most recently passed to ARCH_SET_FS/GS.  (If/when the
-	 * FSGSBASE instructions are enabled, we'll need to offer
-	 * stronger guarantees.)
-	 *
-	 * As an invariant,
-	 * (fsbase != 0 && fsindex != 0) || (gsbase != 0 && gsindex != 0) is
-	 * impossible.
-	 */
-	if (next->fsindex) {
-		/* Loading a nonzero value into FS sets the index and base. */
-		loadsegment(fs, next->fsindex);
-	} else {
-		if (next->fsbase) {
-			/* Next index is zero but next base is nonzero. */
-			if (prev_fsindex)
-				loadsegment(fs, 0);
-			wrmsrl(MSR_FS_BASE, next->fsbase);
-		} else {
-			/* Next base and index are both zero. */
-			if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
-				/*
-				 * We don't know the previous base and can't
-				 * find out without RDMSR.  Forcibly clear it.
-				 */
-				loadsegment(fs, __USER_DS);
-				loadsegment(fs, 0);
-			} else {
-				/*
-				 * If the previous index is zero and ARCH_SET_FS
-				 * didn't change the base, then the base is
-				 * also zero and we don't need to do anything.
-				 */
-				if (prev->fsbase || prev_fsindex)
-					loadsegment(fs, 0);
-			}
-		}
-	}
-	/*
-	 * Save the old state and preserve the invariant.
-	 * NB: if prev_fsindex == 0, then we can't reliably learn the base
-	 * without RDMSR because Intel user code can zero it without telling
-	 * us and AMD user code can program any 32-bit value without telling
-	 * us.
-	 */
-	if (prev_fsindex)
-		prev->fsbase = 0;
-	prev->fsindex = prev_fsindex;
-
-	if (next->gsindex) {
-		/* Loading a nonzero value into GS sets the index and base. */
-		load_gs_index(next->gsindex);
-	} else {
-		if (next->gsbase) {
-			/* Next index is zero but next base is nonzero. */
-			if (prev_gsindex)
-				load_gs_index(0);
-			wrmsrl(MSR_KERNEL_GS_BASE, next->gsbase);
-		} else {
-			/* Next base and index are both zero. */
-			if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
-				/*
-				 * We don't know the previous base and can't
-				 * find out without RDMSR.  Forcibly clear it.
-				 *
-				 * This contains a pointless SWAPGS pair.
-				 * Fixing it would involve an explicit check
-				 * for Xen or a new pvop.
-				 */
-				load_gs_index(__USER_DS);
-				load_gs_index(0);
-			} else {
-				/*
-				 * If the previous index is zero and ARCH_SET_GS
-				 * didn't change the base, then the base is
-				 * also zero and we don't need to do anything.
-				 */
-				if (prev->gsbase || prev_gsindex)
-					load_gs_index(0);
-			}
-		}
-	}
-	/*
-	 * Save the old state and preserve the invariant.
-	 * NB: if prev_gsindex == 0, then we can't reliably learn the base
-	 * without RDMSR because Intel user code can zero it without telling
-	 * us and AMD user code can program any 32-bit value without telling
-	 * us.
-	 */
-	if (prev_gsindex)
-		prev->gsbase = 0;
-	prev->gsindex = prev_gsindex;
+	load_seg_legacy(prev->fsindex, prev->fsbase,
+			next->fsindex, next->fsbase, FS);
+	load_seg_legacy(prev->gsindex, prev->gsbase,
+			next->gsindex, next->gsbase, GS);
 
 	switch_fpu_finish(next_fpu, cpu);
 
author maintainer
#49 lore raw

PATCH 49/52 fuse: allow server to run in different pid_ns

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miklos Szeredi <[email protected]>

commit 5d6d3a301c4e749e04be6fcdcf4cb1ffa8bae524 upstream.

Commit 0b6e9ea041e6 ("fuse: Add support for pid namespaces") broke Sandstorm.io development tools, which have been sending FUSE file descriptors across PID namespace boundaries since early 2014.

The above patch added a check that prevented I/O on the fuse device file descriptor if the pid namespace of the reader/writer was different from the pid namespace of the mounter. With this change passing the device file descriptor to a different pid namespace simply doesn't work. The check was added because pids are transferred to/from the fuse userspace server in the namespace registered at mount time.

To fix this regression, remove the checks and do the following:

1) the pid in the request header (the pid of the task that initiated the filesystem operation) is translated to the reader's pid namespace. If a mapping doesn't exist for this pid, then a zero pid is used. Note: even if a mapping would exist between the initiator task's pid namespace and the reader's pid namespace the pid will be zero if either mapping from initator's to mounter's namespace or mapping from mounter's to reader's namespace doesn't exist.

2) The lk.pid value in setlk/setlkw requests and getlk reply is left alone. Userspace should not interpret this value anyway. Also allow the setlk/setlkw operations if the pid of the task cannot be represented in the mounter's namespace (pid being zero in that case).

Fixes 0b6e9ea041e6 ("fuse: Add support for pid namespaces")
Cc Eric W. Biederman <[email protected]>
Cc Seth Forshee <[email protected]>
---
 fs/fuse/dev.c  |   13 +++++++------
 fs/fuse/file.c |    3 ---
 2 files changed, 7 insertions(+), 9 deletions(-)
fs/fuse/dev.c +7 -6
@@ -1222,9 +1222,6 @@ static ssize_t fuse_dev_do_read(struct f
 	struct fuse_in *in;
 	unsigned reqsize;
 
-	if (task_active_pid_ns(current) != fc->pid_ns)
-		return -EIO;
-
  restart:
 	spin_lock(&fiq->waitq.lock);
 	err = -EAGAIN;
@@ -1262,6 +1259,13 @@ static ssize_t fuse_dev_do_read(struct f
 
 	in = &req->in;
 	reqsize = in->h.len;
+
+	if (task_active_pid_ns(current) != fc->pid_ns) {
+		rcu_read_lock();
+		in->h.pid = pid_vnr(find_pid_ns(in->h.pid, fc->pid_ns));
+		rcu_read_unlock();
+	}
+
 	/* If request is too large, reply with an error and restart the read */
 	if (nbytes < reqsize) {
 		req->out.h.error = -EIO;
@@ -1823,9 +1827,6 @@ static ssize_t fuse_dev_do_write(struct
 	struct fuse_req *req;
 	struct fuse_out_header oh;
 
-	if (task_active_pid_ns(current) != fc->pid_ns)
-		return -EIO;
-
 	if (nbytes < sizeof(struct fuse_out_header))
 		return -EINVAL;
 
fs/fuse/file.c +0 -3
@@ -2180,9 +2180,6 @@ static int fuse_setlk(struct file *file,
 	if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
 		return 0;
 
-	if (pid && pid_nr == 0)
-		return -EOVERFLOW;
-
 	fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
 	err = fuse_simple_request(fc, &args);
 
author maintainer
#50 lore raw

PATCH 50/52 idr: remove WARN_ON_ONCE() when trying to replace negative ID

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Biggers <[email protected]>

commit a47f68d6a944113bdc8097db6f933c2e17c27bf9 upstream.

IDR only supports non-negative IDs. There used to be a 'WARN_ON_ONCE(id < 0)' in idr_replace(), but it was intentionally removed by commit 2e1c9b286765 ("idr: remove WARN_ON_ONCE() on negative IDs").

Then it was added back by commit 0a835c4f090a ("Reimplement IDR and IDA using the radix tree"). However it seems that adding it back was a mistake, given that some users such as drm_gem_handle_delete() (DRM_IOCTL_GEM_CLOSE) pass in a value from userspace to idr_replace(), allowing the WARN_ON_ONCE to be triggered. drm_gem_handle_delete() actually just wants idr_replace() to return an error code if the ID is not allocated, including in the case where the ID is invalid (negative).

So once again remove the bogus WARN_ON_ONCE().

This bug was found by syzkaller, which encountered the following warning:

    WARNING: CPU: 3 PID: 3008 at lib/idr.c:157 idr_replace+0x1d8/0x240 lib/idr.c:157
    Kernel panic - not syncing: panic_on_warn set ...

    CPU: 3 PID: 3008 Comm: syzkaller218828 Not tainted 4.13.0-rc4-next-20170811 #2
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
    Call Trace:
     fixup_bug+0x40/0x90 arch/x86/kernel/traps.c:190
     do_trap_no_signal arch/x86/kernel/traps.c:224 [inline]
     do_trap+0x260/0x390 arch/x86/kernel/traps.c:273
     do_error_trap+0x120/0x390 arch/x86/kernel/traps.c:310
     do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:323
     invalid_op+0x1e/0x30 arch/x86/entry/entry_64.S:930
    RIP: 0010:idr_replace+0x1d8/0x240 lib/idr.c:157
    RSP: 0018:ffff8800394bf9f8 EFLAGS: 00010297
    RAX: ffff88003c6c60c0 RBX: 1ffff10007297f43 RCX: 0000000000000000
    RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8800394bfa78
    RBP: ffff8800394bfae0 R08: ffffffff82856487 R09: 0000000000000000
    R10: ffff8800394bf9a8 R11: ffff88006c8bae28 R12: ffffffffffffffff
    R13: ffff8800394bfab8 R14: dffffc0000000000 R15: ffff8800394bfbc8
     drm_gem_handle_delete+0x33/0xa0 drivers/gpu/drm/drm_gem.c:297
     drm_gem_close_ioctl+0xa1/0xe0 drivers/gpu/drm/drm_gem.c:671
     drm_ioctl_kernel+0x1e7/0x2e0 drivers/gpu/drm/drm_ioctl.c:729
     drm_ioctl+0x72e/0xa50 drivers/gpu/drm/drm_ioctl.c:825
     vfs_ioctl fs/ioctl.c:45 [inline]
     do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:685
     SYSC_ioctl fs/ioctl.c:700 [inline]
     SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691
     entry_SYSCALL_64_fastpath+0x1f/0xbe

Here is a C reproducer:

    #include <fcntl.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <sys/ioctl.h>
    #include <drm/drm.h>

    int main(void)
    {
            int cardfd = open("/dev/dri/card0", O_RDONLY);

            ioctl(cardfd, DRM_IOCTL_GEM_CLOSE,
                  &(struct drm_gem_close) { .handle = -1 } );
    }
Fixes 0a835c4f090a ("Reimplement IDR and IDA using the radix tree")
Cc Dmitry Vyukov <[email protected]>
Cc Matthew Wilcox <[email protected]>
---
 lib/idr.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/idr.c +1 -1
@@ -154,7 +154,7 @@ void *idr_replace(struct idr *idr, void
 	void __rcu **slot = NULL;
 	void *entry;
 
-	if (WARN_ON_ONCE(id < 0))
+	if (id < 0)
 		return ERR_PTR(-EINVAL);
 	if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr)))
 		return ERR_PTR(-EINVAL);
author maintainer
#51 lore raw

PATCH 51/52 md/raid1/10: reset bio allocated from mempool

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shaohua Li <[email protected]>

commit 208410b546207cfc4c832635fa46419cfa86b4cd upstream.

Data allocated from mempool doesn't always get initialized, this happens when the data is reused instead of fresh allocation. In the raid1/10 case, we must reinitialize the bios.

Fixes f0250618361d(md: raid10: don't use bio's vec table to manage resync pages)
Fixes 98d30c5812c3(md: raid1: don't use bio's vec table to manage resync pages)
Cc Ming Lei <[email protected]>
---
 drivers/md/raid1.c  |   19 ++++++++++++++++++-
 drivers/md/raid10.c |   35 ++++++++++++++++++++++++++++++++---
 2 files changed, 50 insertions(+), 4 deletions(-)
drivers/md/raid1.c +18 -1
@@ -2586,6 +2586,23 @@ static int init_resync(struct r1conf *co
 	return 0;
 }
 
+static struct r1bio *raid1_alloc_init_r1buf(struct r1conf *conf)
+{
+	struct r1bio *r1bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
+	struct resync_pages *rps;
+	struct bio *bio;
+	int i;
+
+	for (i = conf->poolinfo->raid_disks; i--; ) {
+		bio = r1bio->bios[i];
+		rps = bio->bi_private;
+		bio_reset(bio);
+		bio->bi_private = rps;
+	}
+	r1bio->master_bio = NULL;
+	return r1bio;
+}
+
 /*
  * perform a "sync" on one "block"
  *
@@ -2671,7 +2688,7 @@ static sector_t raid1_sync_request(struc
 
 	bitmap_cond_end_sync(mddev->bitmap, sector_nr,
 		mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
-	r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
+	r1_bio = raid1_alloc_init_r1buf(conf);
 
 	raise_barrier(conf, sector_nr);
 
drivers/md/raid10.c +32 -3
@@ -2807,6 +2807,35 @@ static int init_resync(struct r10conf *c
 	return 0;
 }
 
+static struct r10bio *raid10_alloc_init_r10buf(struct r10conf *conf)
+{
+	struct r10bio *r10bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+	struct rsync_pages *rp;
+	struct bio *bio;
+	int nalloc;
+	int i;
+
+	if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery) ||
+	    test_bit(MD_RECOVERY_RESHAPE, &conf->mddev->recovery))
+		nalloc = conf->copies; /* resync */
+	else
+		nalloc = 2; /* recovery */
+
+	for (i = 0; i < nalloc; i++) {
+		bio = r10bio->devs[i].bio;
+		rp = bio->bi_private;
+		bio_reset(bio);
+		bio->bi_private = rp;
+		bio = r10bio->devs[i].repl_bio;
+		if (bio) {
+			rp = bio->bi_private;
+			bio_reset(bio);
+			bio->bi_private = rp;
+		}
+	}
+	return r10bio;
+}
+
 /*
  * perform a "sync" on one "block"
  *
@@ -3036,7 +3065,7 @@ static sector_t raid10_sync_request(stru
 				atomic_inc(&mreplace->nr_pending);
 			rcu_read_unlock();
 
-			r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+			r10_bio = raid10_alloc_init_r10buf(conf);
 			r10_bio->state = 0;
 			raise_barrier(conf, rb2 != NULL);
 			atomic_set(&r10_bio->remaining, 0);
@@ -3245,7 +3274,7 @@ static sector_t raid10_sync_request(stru
 		}
 		if (sync_blocks < max_sync)
 			max_sync = sync_blocks;
-		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+		r10_bio = raid10_alloc_init_r10buf(conf);
 		r10_bio->state = 0;
 
 		r10_bio->mddev = mddev;
@@ -4369,7 +4398,7 @@ static sector_t reshape_request(struct m
 
 read_more:
 	/* Now schedule reads for blocks from sector_nr to last */
-	r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+	r10_bio = raid10_alloc_init_r10buf(conf);
 	r10_bio->state = 0;
 	raise_barrier(conf, sectors_done != 0);
 	atomic_set(&r10_bio->remaining, 0);
author maintainer
#52 lore raw

PATCH 52/52 md/raid5: release/flush io in raid5_do_work()

In reply to Greg Kroah-Hartman

4.12-stable review patch. If anyone has any objections, please let me know.

------------------

From: Song Liu <[email protected]>

commit 9c72a18e46ebe0f09484cce8ebf847abdab58498 upstream.

In raid5, there are scenarios where some ios are deferred to a later time, and some IO need a flush to complete. To make sure we make progress with these IOs, we need to call the following functions:

    flush_deferred_bios(conf);
    r5l_flush_stripe_to_raid(conf->log);

Both of these functions are called in raid5d(), but missing in raid5_do_work(). As a result, these functions are not called when multi-threading (group_thread_cnt > 0) is enabled. This patch adds calls to these function to raid5_do_work().

Note for stable branches:

r5l_flush_stripe_to_raid(conf->log) is need for 4.4+ flush_deferred_bios(conf) is only needed for 4.11+

---
 drivers/md/raid5.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/md/raid5.c +4 -0
@@ -6238,6 +6238,10 @@ static void raid5_do_work(struct work_st
 
 	spin_unlock_irq(&conf->device_lock);
 
+	flush_deferred_bios(conf);
+
+	r5l_flush_stripe_to_raid(conf->log);
+
 	async_tx_issue_pending_all();
 	blk_finish_plug(&plug);
 
#53 lore raw
In reply to Greg Kroah-Hartman

Hi Greg,

Quoted 8 lines · Greg Kroah-Hartman

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Tested on our production hardware. There was no error in dmesg. Booted up fine, all functionality working.

--
Regards
Sudip

author maintainer
#54 lore raw
Quoted 7 lines · Sudip Mukherjee

Hi Greg,

Quoted 4 lines · Greg Kroah-Hartman

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

Quoted 7 lines
Quoted 4 lines

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Tested on our production hardware. There was no error in dmesg. Booted up fine, all functionality working.

What does "production hardware" mean, if I might ask?

Anyway, thanks for testing and letting me know.

greg k-h

#55 lore raw
Quoted 13 lines · Greg Kroah-Hartman
Quoted 12 lines · Sudip Mukherjee

Hi Greg,

Quoted 8 lines · Greg Kroah-Hartman

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Quoted 4 lines
Quoted 2 lines

Tested on our production hardware. There was no error in dmesg. Booted up fine, all functionality working.

What does "production hardware" mean, if I might ask?

Its a Baytrail Valleyview.

--
Regards
Sudip

#56 lore raw
In reply to Greg Kroah-Hartman
Quoted 4 lines · Greg Kroah-Hartman

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

Quoted 8 lines

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Wed Sep 20 09:09:47 UTC 2017. Anything received after that time might be too late.

Build results:

	total: 145 pass: 145 fail: 0
Qemu test results:
	total: 122 pass: 122 fail: 0

Details are available at http://kerneltests.org/builders.

Guenter

#57 lore raw
In reply to Greg Kroah-Hartman
Quoted 13 lines · Greg Kroah-Hartman

NOTE: This is going to be the last 4.12.y kernel, after this one, this branch is end-of-life, please move to the 4.13.y kernel tree at this point in time.

This is the start of the stable review cycle for the 4.12.14 release. There are 52 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Wed Sep 20 09:09:47 UTC 2017. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

Quoted 9 lines
	kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.12.14-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.12.y
and the diffstat can be found below.

thanks,

greg k-h

Compiled and booted my test system. No dmesg regressions.

thanks,
-- Shuah