From: Greg Kroah-Hartman Date: Thu, 15 Jun 2017 07:40:35 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.9.33~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=af30ffc1f28c08d4f6f4c27b7c51b33f897fff25;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch ibmvnic-fix-endian-errors-in-error-reporting-output.patch ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch net-xilinx_emaclite-fix-receive-buffer-overflow.patch tcp-tcp_probe-use-spin_lock_bh.patch tipc-fix-tipc_sk_reinit-race-conditions.patch --- diff --git a/queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch b/queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch new file mode 100644 index 00000000000..c03c5a0c91a --- /dev/null +++ b/queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch @@ -0,0 +1,73 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Herbert Xu +Date: Tue, 23 May 2017 21:53:36 -0400 +Subject: gfs2: Use rhashtable walk interface in glock_hash_walk + +From: Herbert Xu + + +[ Upstream commit 6a25478077d987edc5e2f880590a2bc5fcab4441 ] + +The function glock_hash_walk walks the rhashtable by hand. This +is broken because if it catches the hash table in the middle of +a rehash, then it will miss entries. + +This patch replaces the manual walk by using the rhashtable walk +interface. + +Fixes: 88ffbf3e037e ("GFS2: Use resizable hash table for glocks") +Signed-off-by: Herbert Xu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/glock.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1425,26 +1425,32 @@ static struct shrinker glock_shrinker = + * @sdp: the filesystem + * @bucket: the bucket + * ++ * Note that the function can be called multiple times on the same ++ * object. So the user must ensure that the function can cope with ++ * that. + */ + + static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) + { + struct gfs2_glock *gl; +- struct rhash_head *pos; +- const struct bucket_table *tbl; +- int i; +- +- rcu_read_lock(); +- tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table); +- for (i = 0; i < tbl->size; i++) { +- rht_for_each_entry_rcu(gl, pos, tbl, i, gl_node) { ++ struct rhashtable_iter iter; ++ ++ rhashtable_walk_enter(&gl_hash_table, &iter); ++ ++ do { ++ gl = ERR_PTR(rhashtable_walk_start(&iter)); ++ if (gl) ++ continue; ++ ++ while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) + if ((gl->gl_name.ln_sbd == sdp) && + lockref_get_not_dead(&gl->gl_lockref)) + examiner(gl); +- } +- } +- rcu_read_unlock(); +- cond_resched(); ++ ++ rhashtable_walk_stop(&iter); ++ } while (cond_resched(), gl == ERR_PTR(-EAGAIN)); ++ ++ rhashtable_walk_exit(&iter); + } + + /** diff --git a/queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch b/queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch new file mode 100644 index 00000000000..a92a503e02c --- /dev/null +++ b/queue-4.9/ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch @@ -0,0 +1,39 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Thomas Falcon +Date: Tue, 23 May 2017 21:53:27 -0400 +Subject: ibmvnic: Fix endian error when requesting device capabilities + +From: Thomas Falcon + + +[ Upstream commit 28f4d16570dcf440e54a4d72666d5be452f27d0e ] + +When a vNIC client driver requests a faulty device setting, the +server returns an acceptable value for the client to request. +This 64 bit value was incorrectly being swapped as a 32 bit value, +resulting in loss of data. This patch corrects that by using +the 64 bit swap function. + +Signed-off-by: Thomas Falcon +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/ibmvnic.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -2400,10 +2400,10 @@ static void handle_request_cap_rsp(union + case PARTIALSUCCESS: + dev_info(dev, "req=%lld, rsp=%ld in %s queue, retrying.\n", + *req_value, +- (long int)be32_to_cpu(crq->request_capability_rsp. ++ (long int)be64_to_cpu(crq->request_capability_rsp. + number), name); + release_sub_crqs_no_irqs(adapter); +- *req_value = be32_to_cpu(crq->request_capability_rsp.number); ++ *req_value = be64_to_cpu(crq->request_capability_rsp.number); + init_sub_crqs(adapter, 1); + return; + default: diff --git a/queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch b/queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch new file mode 100644 index 00000000000..50dd8fd7dc3 --- /dev/null +++ b/queue-4.9/ibmvnic-fix-endian-errors-in-error-reporting-output.patch @@ -0,0 +1,50 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Thomas Falcon +Date: Tue, 23 May 2017 21:53:26 -0400 +Subject: ibmvnic: Fix endian errors in error reporting output + +From: Thomas Falcon + + +[ Upstream commit 75224c93fa985f4a6fb983f53208f5c5aa555fbf ] + +Error reports received from firmware were not being converted from +big endian values, leading to bogus error codes reported on little +endian systems. + +Signed-off-by: Thomas Falcon +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/ibmvnic.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -2197,12 +2197,12 @@ static void handle_error_info_rsp(union + + if (!found) { + dev_err(dev, "Couldn't find error id %x\n", +- crq->request_error_rsp.error_id); ++ be32_to_cpu(crq->request_error_rsp.error_id)); + return; + } + + dev_err(dev, "Detailed info for error id %x:", +- crq->request_error_rsp.error_id); ++ be32_to_cpu(crq->request_error_rsp.error_id)); + + for (i = 0; i < error_buff->len; i++) { + pr_cont("%02x", (int)error_buff->buff[i]); +@@ -2281,8 +2281,8 @@ static void handle_error_indication(unio + dev_err(dev, "Firmware reports %serror id %x, cause %d\n", + crq->error_indication. + flags & IBMVNIC_FATAL_ERROR ? "FATAL " : "", +- crq->error_indication.error_id, +- crq->error_indication.error_cause); ++ be32_to_cpu(crq->error_indication.error_id), ++ be16_to_cpu(crq->error_indication.error_cause)); + + error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC); + if (!error_buff) diff --git a/queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch b/queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch new file mode 100644 index 00000000000..213d3857650 --- /dev/null +++ b/queue-4.9/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch @@ -0,0 +1,100 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: "Jonathan T. Leighton" +Date: Tue, 23 May 2017 21:53:33 -0400 +Subject: ipv6: Handle IPv4-mapped src to in6addr_any dst. + +From: "Jonathan T. Leighton" + + +[ Upstream commit 052d2369d1b479cdbbe020fdd6d057d3c342db74 ] + +This patch adds a check on the type of the source address for the case +where the destination address is in6addr_any. If the source is an +IPv4-mapped IPv6 source address, the destination is changed to +::ffff:127.0.0.1, and otherwise the destination is changed to ::1. This +is done in three locations to handle UDP calls to either connect() or +sendmsg() and TCP calls to connect(). Note that udpv6_sendmsg() delays +handling an in6addr_any destination until very late, so the patch only +needs to handle the case where the source is an IPv4-mapped IPv6 +address. + +Signed-off-by: Jonathan T. Leighton +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/datagram.c | 14 +++++++++----- + net/ipv6/tcp_ipv6.c | 11 ++++++++--- + net/ipv6/udp.c | 4 ++++ + 3 files changed, 21 insertions(+), 8 deletions(-) + +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -166,18 +166,22 @@ int __ip6_datagram_connect(struct sock * + if (np->sndflow) + fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK; + +- addr_type = ipv6_addr_type(&usin->sin6_addr); +- +- if (addr_type == IPV6_ADDR_ANY) { ++ if (ipv6_addr_any(&usin->sin6_addr)) { + /* + * connect to self + */ +- usin->sin6_addr.s6_addr[15] = 0x01; ++ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), ++ &usin->sin6_addr); ++ else ++ usin->sin6_addr = in6addr_loopback; + } + ++ addr_type = ipv6_addr_type(&usin->sin6_addr); ++ + daddr = &usin->sin6_addr; + +- if (addr_type == IPV6_ADDR_MAPPED) { ++ if (addr_type & IPV6_ADDR_MAPPED) { + struct sockaddr_in sin; + + if (__ipv6_only_sock(sk)) { +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -148,8 +148,13 @@ static int tcp_v6_connect(struct sock *s + * connect() to INADDR_ANY means loopback (BSD'ism). + */ + +- if (ipv6_addr_any(&usin->sin6_addr)) +- usin->sin6_addr.s6_addr[15] = 0x1; ++ if (ipv6_addr_any(&usin->sin6_addr)) { ++ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), ++ &usin->sin6_addr); ++ else ++ usin->sin6_addr = in6addr_loopback; ++ } + + addr_type = ipv6_addr_type(&usin->sin6_addr); + +@@ -188,7 +193,7 @@ static int tcp_v6_connect(struct sock *s + * TCP over IPv4 + */ + +- if (addr_type == IPV6_ADDR_MAPPED) { ++ if (addr_type & IPV6_ADDR_MAPPED) { + u32 exthdrlen = icsk->icsk_ext_hdr_len; + struct sockaddr_in sin; + +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1049,6 +1049,10 @@ int udpv6_sendmsg(struct sock *sk, struc + if (addr_len < SIN6_LEN_RFC2133) + return -EINVAL; + daddr = &sin6->sin6_addr; ++ if (ipv6_addr_any(daddr) && ++ ipv6_addr_v4mapped(&np->saddr)) ++ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), ++ daddr); + break; + case AF_INET: + goto do_udp_sendmsg; diff --git a/queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch b/queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch new file mode 100644 index 00000000000..ef5feab51a3 --- /dev/null +++ b/queue-4.9/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch @@ -0,0 +1,35 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: "Jonathan T. Leighton" +Date: Tue, 23 May 2017 21:53:34 -0400 +Subject: ipv6: Inhibit IPv4-mapped src address on the wire. + +From: "Jonathan T. Leighton" + + +[ Upstream commit ec5e3b0a1d41fbda0cc33a45bc9e54e91d9d12c7 ] + +This patch adds a check for the problematic case of an IPv4-mapped IPv6 +source address and a destination address that is neither an IPv4-mapped +IPv6 address nor in6addr_any, and returns an appropriate error. The +check in done before returning from looking up the route. + +Signed-off-by: Jonathan T. Leighton +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_output.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1019,6 +1019,9 @@ static int ip6_dst_lookup_tail(struct ne + } + } + #endif ++ if (ipv6_addr_v4mapped(&fl6->saddr) && ++ !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) ++ return -EAFNOSUPPORT; + + return 0; + diff --git a/queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch b/queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch new file mode 100644 index 00000000000..b4011db79f8 --- /dev/null +++ b/queue-4.9/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch @@ -0,0 +1,331 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Anssi Hannula +Date: Tue, 23 May 2017 21:53:28 -0400 +Subject: net: xilinx_emaclite: fix freezes due to unordered I/O + +From: Anssi Hannula + + +[ Upstream commit acf138f1b00bdd1b7cd9894562ed0c2a1670888e ] + +The xilinx_emaclite uses __raw_writel and __raw_readl for register +accesses. Those functions do not imply any kind of memory barriers and +they may be reordered. + +The driver does not seem to take that into account, though, and the +driver does not satisfy the ordering requirements of the hardware. +For clear examples, see xemaclite_mdio_write() and xemaclite_mdio_read() +which try to set MDIO address before initiating the transaction. + +I'm seeing system freezes with the driver with GCC 5.4 and current +Linux kernels on Zynq-7000 SoC immediately when trying to use the +interface. + +In commit 123c1407af87 ("net: emaclite: Do not use microblaze and ppc +IO functions") the driver was switched from non-generic +in_be32/out_be32 (memory barriers, big endian) to +__raw_readl/__raw_writel (no memory barriers, native endian), so +apparently the device follows system endianness and the driver was +originally written with the assumption of memory barriers. + +Rather than try to hunt for each case of missing barrier, just switch +the driver to use iowrite32/ioread32/iowrite32be/ioread32be depending +on endianness instead. + +Tested on little-endian Zynq-7000 ARM SoC FPGA. + +Signed-off-by: Anssi Hannula +Fixes: 123c1407af87 ("net: emaclite: Do not use microblaze and ppc IO +functions") +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/xilinx/xilinx_emaclite.c | 116 +++++++++++++------------- + 1 file changed, 62 insertions(+), 54 deletions(-) + +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -100,6 +100,14 @@ + /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */ + #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT) + ++#ifdef __BIG_ENDIAN ++#define xemaclite_readl ioread32be ++#define xemaclite_writel iowrite32be ++#else ++#define xemaclite_readl ioread32 ++#define xemaclite_writel iowrite32 ++#endif ++ + /** + * struct net_local - Our private per device data + * @ndev: instance of the network device +@@ -156,15 +164,15 @@ static void xemaclite_enable_interrupts( + u32 reg_data; + + /* Enable the Tx interrupts for the first Buffer */ +- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); +- __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, +- drvdata->base_addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); ++ xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK, ++ drvdata->base_addr + XEL_TSR_OFFSET); + + /* Enable the Rx interrupts for the first buffer */ +- __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); ++ xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); + + /* Enable the Global Interrupt Enable */ +- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); ++ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); + } + + /** +@@ -179,17 +187,17 @@ static void xemaclite_disable_interrupts + u32 reg_data; + + /* Disable the Global Interrupt Enable */ +- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); ++ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); + + /* Disable the Tx interrupts for the first buffer */ +- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); +- __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), +- drvdata->base_addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); ++ xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), ++ drvdata->base_addr + XEL_TSR_OFFSET); + + /* Disable the Rx interrupts for the first buffer */ +- reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET); +- __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), +- drvdata->base_addr + XEL_RSR_OFFSET); ++ reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET); ++ xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), ++ drvdata->base_addr + XEL_RSR_OFFSET); + } + + /** +@@ -321,7 +329,7 @@ static int xemaclite_send_data(struct ne + byte_count = ETH_FRAME_LEN; + + /* Check if the expected buffer is available */ +- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | + XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { + +@@ -334,7 +342,7 @@ static int xemaclite_send_data(struct ne + + addr = (void __iomem __force *)((u32 __force)addr ^ + XEL_BUFFER_OFFSET); +- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + + if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | + XEL_TSR_XMIT_ACTIVE_MASK)) != 0) +@@ -345,16 +353,16 @@ static int xemaclite_send_data(struct ne + /* Write the frame to the buffer */ + xemaclite_aligned_write(data, (u32 __force *) addr, byte_count); + +- __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK), +- addr + XEL_TPLR_OFFSET); ++ xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK), ++ addr + XEL_TPLR_OFFSET); + + /* Update the Tx Status Register to indicate that there is a + * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which + * is used by the interrupt handler to check whether a frame + * has been transmitted */ +- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK); +- __raw_writel(reg_data, addr + XEL_TSR_OFFSET); ++ xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET); + + return 0; + } +@@ -379,7 +387,7 @@ static u16 xemaclite_recv_data(struct ne + addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use); + + /* Verify which buffer has valid data */ +- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + + if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { + if (drvdata->rx_ping_pong != 0) +@@ -396,14 +404,14 @@ static u16 xemaclite_recv_data(struct ne + return 0; /* No data was available */ + + /* Verify that buffer has valid data */ +- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + if ((reg_data & XEL_RSR_RECV_DONE_MASK) != + XEL_RSR_RECV_DONE_MASK) + return 0; /* No data was available */ + } + + /* Get the protocol type of the ethernet frame that arrived */ +- proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET + ++ proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET + + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & + XEL_RPLR_LENGTH_MASK); + +@@ -412,7 +420,7 @@ static u16 xemaclite_recv_data(struct ne + if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { + + if (proto_type == ETH_P_IP) { +- length = ((ntohl(__raw_readl(addr + ++ length = ((ntohl(xemaclite_readl(addr + + XEL_HEADER_IP_LENGTH_OFFSET + + XEL_RXBUFF_OFFSET)) >> + XEL_HEADER_SHIFT) & +@@ -434,9 +442,9 @@ static u16 xemaclite_recv_data(struct ne + data, length); + + /* Acknowledge the frame */ +- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + reg_data &= ~XEL_RSR_RECV_DONE_MASK; +- __raw_writel(reg_data, addr + XEL_RSR_OFFSET); ++ xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET); + + return length; + } +@@ -463,14 +471,14 @@ static void xemaclite_update_address(str + + xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN); + +- __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); ++ xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); + + /* Update the MAC address in the EmacLite */ +- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); +- __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); ++ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); ++ xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); + + /* Wait for EmacLite to finish with the MAC address update */ +- while ((__raw_readl(addr + XEL_TSR_OFFSET) & ++ while ((xemaclite_readl(addr + XEL_TSR_OFFSET) & + XEL_TSR_PROG_MAC_ADDR) != 0) + ; + } +@@ -640,32 +648,32 @@ static irqreturn_t xemaclite_interrupt(i + u32 tx_status; + + /* Check if there is Rx Data available */ +- if ((__raw_readl(base_addr + XEL_RSR_OFFSET) & ++ if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) & + XEL_RSR_RECV_DONE_MASK) || +- (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) ++ (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) + & XEL_RSR_RECV_DONE_MASK)) + + xemaclite_rx_handler(dev); + + /* Check if the Transmission for the first buffer is completed */ +- tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET); ++ tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET); + if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && + (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { + + tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; +- __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET); ++ xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET); + + tx_complete = true; + } + + /* Check if the Transmission for the second buffer is completed */ +- tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); ++ tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); + if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && + (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { + + tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; +- __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + +- XEL_TSR_OFFSET); ++ xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + ++ XEL_TSR_OFFSET); + + tx_complete = true; + } +@@ -698,7 +706,7 @@ static int xemaclite_mdio_wait(struct ne + /* wait for the MDIO interface to not be busy or timeout + after some time. + */ +- while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & ++ while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & + XEL_MDIOCTRL_MDIOSTS_MASK) { + if (time_before_eq(end, jiffies)) { + WARN_ON(1); +@@ -734,17 +742,17 @@ static int xemaclite_mdio_read(struct mi + * MDIO Address register. Set the Status bit in the MDIO Control + * register to start a MDIO read transaction. + */ +- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); +- __raw_writel(XEL_MDIOADDR_OP_MASK | +- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), +- lp->base_addr + XEL_MDIOADDR_OFFSET); +- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, +- lp->base_addr + XEL_MDIOCTRL_OFFSET); ++ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); ++ xemaclite_writel(XEL_MDIOADDR_OP_MASK | ++ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), ++ lp->base_addr + XEL_MDIOADDR_OFFSET); ++ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ++ lp->base_addr + XEL_MDIOCTRL_OFFSET); + + if (xemaclite_mdio_wait(lp)) + return -ETIMEDOUT; + +- rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET); ++ rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET); + + dev_dbg(&lp->ndev->dev, + "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n", +@@ -781,13 +789,13 @@ static int xemaclite_mdio_write(struct m + * Data register. Finally, set the Status bit in the MDIO Control + * register to start a MDIO write transaction. + */ +- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); +- __raw_writel(~XEL_MDIOADDR_OP_MASK & +- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), +- lp->base_addr + XEL_MDIOADDR_OFFSET); +- __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); +- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, +- lp->base_addr + XEL_MDIOCTRL_OFFSET); ++ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); ++ xemaclite_writel(~XEL_MDIOADDR_OP_MASK & ++ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), ++ lp->base_addr + XEL_MDIOADDR_OFFSET); ++ xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); ++ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ++ lp->base_addr + XEL_MDIOCTRL_OFFSET); + + return 0; + } +@@ -834,8 +842,8 @@ static int xemaclite_mdio_setup(struct n + /* Enable the MDIO bus by asserting the enable bit in MDIO Control + * register. + */ +- __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, +- lp->base_addr + XEL_MDIOCTRL_OFFSET); ++ xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK, ++ lp->base_addr + XEL_MDIOCTRL_OFFSET); + + bus = mdiobus_alloc(); + if (!bus) { +@@ -1140,8 +1148,8 @@ static int xemaclite_of_probe(struct pla + } + + /* Clear the Tx CSR's in case this is a restart */ +- __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET); +- __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); ++ xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET); ++ xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); + + /* Set the MAC address in the EmacLite device */ + xemaclite_update_address(lp, ndev->dev_addr); diff --git a/queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch b/queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch new file mode 100644 index 00000000000..ae683aa70bb --- /dev/null +++ b/queue-4.9/net-xilinx_emaclite-fix-receive-buffer-overflow.patch @@ -0,0 +1,76 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Anssi Hannula +Date: Tue, 23 May 2017 21:53:29 -0400 +Subject: net: xilinx_emaclite: fix receive buffer overflow + +From: Anssi Hannula + + +[ Upstream commit cd224553641848dd17800fe559e4ff5d208553e8 ] + +xilinx_emaclite looks at the received data to try to determine the +Ethernet packet length but does not properly clamp it if +proto_type == ETH_P_IP or 1500 < proto_type <= 1518, causing a buffer +overflow and a panic via skb_panic() as the length exceeds the allocated +skb size. + +Fix those cases. + +Also add an additional unconditional check with WARN_ON() at the end. + +Signed-off-by: Anssi Hannula +Fixes: bb81b2ddfa19 ("net: add Xilinx emac lite device driver") +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/xilinx/xilinx_emaclite.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -377,7 +377,7 @@ static int xemaclite_send_data(struct ne + * + * Return: Total number of bytes received + */ +-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) ++static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) + { + void __iomem *addr; + u16 length, proto_type; +@@ -417,7 +417,7 @@ static u16 xemaclite_recv_data(struct ne + + /* Check if received ethernet frame is a raw ethernet frame + * or an IP packet or an ARP packet */ +- if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { ++ if (proto_type > ETH_DATA_LEN) { + + if (proto_type == ETH_P_IP) { + length = ((ntohl(xemaclite_readl(addr + +@@ -425,6 +425,7 @@ static u16 xemaclite_recv_data(struct ne + XEL_RXBUFF_OFFSET)) >> + XEL_HEADER_SHIFT) & + XEL_RPLR_LENGTH_MASK); ++ length = min_t(u16, length, ETH_DATA_LEN); + length += ETH_HLEN + ETH_FCS_LEN; + + } else if (proto_type == ETH_P_ARP) +@@ -437,6 +438,9 @@ static u16 xemaclite_recv_data(struct ne + /* Use the length in the frame, plus the header and trailer */ + length = proto_type + ETH_HLEN + ETH_FCS_LEN; + ++ if (WARN_ON(length > maxlen)) ++ length = maxlen; ++ + /* Read from the EmacLite device */ + xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET), + data, length); +@@ -611,7 +615,7 @@ static void xemaclite_rx_handler(struct + + skb_reserve(skb, 2); + +- len = xemaclite_recv_data(lp, (u8 *) skb->data); ++ len = xemaclite_recv_data(lp, (u8 *) skb->data, len); + + if (!len) { + dev->stats.rx_errors++; diff --git a/queue-4.9/series b/queue-4.9/series index 163d937f115..0fd339af336 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -2,3 +2,12 @@ pci-pm-add-needs_resume-flag-to-avoid-suspend-complete-optimization.patch drm-i915-prevent-the-system-suspend-complete-optimization.patch partitions-msdos-freebsd-ufs2-file-systems-are-not-recognized.patch netfilter-nf_conntrack_sip-fix-wrong-memory-initialisation.patch +ibmvnic-fix-endian-errors-in-error-reporting-output.patch +ibmvnic-fix-endian-error-when-requesting-device-capabilities.patch +net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch +net-xilinx_emaclite-fix-receive-buffer-overflow.patch +tcp-tcp_probe-use-spin_lock_bh.patch +ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch +ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch +tipc-fix-tipc_sk_reinit-race-conditions.patch +gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch diff --git a/queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch b/queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch new file mode 100644 index 00000000000..203f145f53d --- /dev/null +++ b/queue-4.9/tcp-tcp_probe-use-spin_lock_bh.patch @@ -0,0 +1,45 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Eric Dumazet +Date: Tue, 23 May 2017 21:53:32 -0400 +Subject: tcp: tcp_probe: use spin_lock_bh() + +From: Eric Dumazet + + +[ Upstream commit e70ac171658679ecf6bea4bbd9e9325cd6079d2b ] + +tcp_rcv_established() can now run in process context. + +We need to disable BH while acquiring tcp probe spinlock, +or risk a deadlock. + +Fixes: 5413d1babe8f ("net: do not block BH while processing socket backlog") +Signed-off-by: Eric Dumazet +Reported-by: Ricardo Nabinger Sanchez +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_probe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv4/tcp_probe.c ++++ b/net/ipv4/tcp_probe.c +@@ -117,7 +117,7 @@ static void jtcp_rcv_established(struct + (fwmark > 0 && skb->mark == fwmark)) && + (full || tp->snd_cwnd != tcp_probe.lastcwnd)) { + +- spin_lock(&tcp_probe.lock); ++ spin_lock_bh(&tcp_probe.lock); + /* If log fills, just silently drop */ + if (tcp_probe_avail() > 1) { + struct tcp_log *p = tcp_probe.log + tcp_probe.head; +@@ -157,7 +157,7 @@ static void jtcp_rcv_established(struct + tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1); + } + tcp_probe.lastcwnd = tp->snd_cwnd; +- spin_unlock(&tcp_probe.lock); ++ spin_unlock_bh(&tcp_probe.lock); + + wake_up(&tcp_probe.wait); + } diff --git a/queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch b/queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch new file mode 100644 index 00000000000..2d5053120f9 --- /dev/null +++ b/queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch @@ -0,0 +1,106 @@ +From foo@baz Thu Jun 15 09:31:48 CEST 2017 +From: Herbert Xu +Date: Tue, 23 May 2017 21:53:35 -0400 +Subject: tipc: Fix tipc_sk_reinit race conditions + +From: Herbert Xu + + +[ Upstream commit 9dbbfb0ab6680c6a85609041011484e6658e7d3c ] + +There are two problems with the function tipc_sk_reinit. Firstly +it's doing a manual walk over an rhashtable. This is broken as +an rhashtable can be resized and if you manually walk over it +during a resize then you may miss entries. + +Secondly it's missing memory barriers as previously the code used +spinlocks which provide the barriers implicitly. + +This patch fixes both problems. + +Fixes: 07f6c4bc048a ("tipc: convert tipc reference table to...") +Signed-off-by: Herbert Xu +Acked-by: Ying Xue +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/net.c | 4 ++++ + net/tipc/socket.c | 30 +++++++++++++++++++----------- + 2 files changed, 23 insertions(+), 11 deletions(-) + +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -110,6 +110,10 @@ int tipc_net_start(struct net *net, u32 + char addr_string[16]; + + tn->own_addr = addr; ++ ++ /* Ensure that the new address is visible before we reinit. */ ++ smp_mb(); ++ + tipc_named_reinit(net); + tipc_sk_reinit(net); + +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -335,8 +335,6 @@ static int tipc_sk_create(struct net *ne + INIT_LIST_HEAD(&tsk->publications); + msg = &tsk->phdr; + tn = net_generic(sock_net(sk), tipc_net_id); +- tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, +- NAMED_H_SIZE, 0); + + /* Finish initializing socket data structures */ + sock->ops = ops; +@@ -346,6 +344,13 @@ static int tipc_sk_create(struct net *ne + pr_warn("Socket create failed; port number exhausted\n"); + return -EINVAL; + } ++ ++ /* Ensure tsk is visible before we read own_addr. */ ++ smp_mb(); ++ ++ tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, ++ NAMED_H_SIZE, 0); ++ + msg_set_origport(msg, tsk->portid); + setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk); + sk->sk_backlog_rcv = tipc_backlog_rcv; +@@ -2264,24 +2269,27 @@ static int tipc_sk_withdraw(struct tipc_ + void tipc_sk_reinit(struct net *net) + { + struct tipc_net *tn = net_generic(net, tipc_net_id); +- const struct bucket_table *tbl; +- struct rhash_head *pos; ++ struct rhashtable_iter iter; + struct tipc_sock *tsk; + struct tipc_msg *msg; +- int i; + +- rcu_read_lock(); +- tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); +- for (i = 0; i < tbl->size; i++) { +- rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { ++ rhashtable_walk_enter(&tn->sk_rht, &iter); ++ ++ do { ++ tsk = ERR_PTR(rhashtable_walk_start(&iter)); ++ if (tsk) ++ continue; ++ ++ while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) { + spin_lock_bh(&tsk->sk.sk_lock.slock); + msg = &tsk->phdr; + msg_set_prevnode(msg, tn->own_addr); + msg_set_orignode(msg, tn->own_addr); + spin_unlock_bh(&tsk->sk.sk_lock.slock); + } +- } +- rcu_read_unlock(); ++ ++ rhashtable_walk_stop(&iter); ++ } while (tsk == ERR_PTR(-EAGAIN)); + } + + static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid)