]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jun 2017 07:40:09 +0000 (09:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Jun 2017 07:40:09 +0000 (09:40 +0200)
added patches:
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
tipc-fix-tipc_sk_reinit-race-conditions.patch

queue-4.4/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch [new file with mode: 0644]
queue-4.4/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch [new file with mode: 0644]
queue-4.4/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch [new file with mode: 0644]
queue-4.4/net-xilinx_emaclite-fix-receive-buffer-overflow.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tipc-fix-tipc_sk_reinit-race-conditions.patch [new file with mode: 0644]

diff --git a/queue-4.4/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch b/queue-4.4/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch
new file mode 100644 (file)
index 0000000..1c925cb
--- /dev/null
@@ -0,0 +1,100 @@
+From foo@baz Thu Jun 15 09:36:39 CEST 2017
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+Date: Tue, 23 May 2017 21:53:33 -0400
+Subject: ipv6: Handle IPv4-mapped src to in6addr_any dst.
+
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+
+
+[ 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 <jtleight@udel.edu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -76,18 +76,22 @@ static int __ip6_datagram_connect(struct
+               }
+       }
+-      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
+@@ -149,8 +149,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);
+@@ -189,7 +194,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
+@@ -1136,6 +1136,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.4/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch b/queue-4.4/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch
new file mode 100644 (file)
index 0000000..85d5f8a
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Thu Jun 15 09:36:39 CEST 2017
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+Date: Tue, 23 May 2017 21:53:34 -0400
+Subject: ipv6: Inhibit IPv4-mapped src address on the wire.
+
+From: "Jonathan T. Leighton" <jtleight@udel.edu>
+
+
+[ 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 <jtleight@udel.edu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_output.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1004,6 +1004,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.4/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch b/queue-4.4/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch
new file mode 100644 (file)
index 0000000..f3323c8
--- /dev/null
@@ -0,0 +1,331 @@
+From foo@baz Thu Jun 15 09:36:39 CEST 2017
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 23 May 2017 21:53:28 -0400
+Subject: net: xilinx_emaclite: fix freezes due to unordered I/O
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+
+[ 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 <anssi.hannula@bitwise.fi>
+Fixes: 123c1407af87 ("net: emaclite: Do not use microblaze and ppc IO
+functions")
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -158,15 +166,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);
+ }
+ /**
+@@ -181,17 +189,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);
+ }
+ /**
+@@ -323,7 +331,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) {
+@@ -336,7 +344,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)
+@@ -347,16 +355,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;
+ }
+@@ -381,7 +389,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)
+@@ -398,14 +406,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);
+@@ -414,7 +422,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) &
+@@ -436,9 +444,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;
+ }
+@@ -465,14 +473,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)
+               ;
+ }
+@@ -642,32 +650,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;
+       }
+@@ -700,7 +708,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);
+@@ -736,17 +744,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",
+@@ -783,13 +791,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;
+ }
+@@ -836,8 +844,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) {
+@@ -1141,8 +1149,8 @@ static int xemaclite_of_probe(struct pla
+               dev_warn(dev, "No MAC address found\n");
+       /* 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.4/net-xilinx_emaclite-fix-receive-buffer-overflow.patch b/queue-4.4/net-xilinx_emaclite-fix-receive-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..0e3cb10
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Thu Jun 15 09:36:39 CEST 2017
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 23 May 2017 21:53:29 -0400
+Subject: net: xilinx_emaclite: fix receive buffer overflow
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+
+[ 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 <anssi.hannula@bitwise.fi>
+Fixes: bb81b2ddfa19 ("net: add Xilinx emac lite device driver")
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -379,7 +379,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;
+@@ -419,7 +419,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 +
+@@ -427,6 +427,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)
+@@ -439,6 +440,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);
+@@ -613,7 +617,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++;
index d6aa30c539c8066c3c072d23a8aa817e6fff145f..d86b6f9a8bafb167ee5448b0dc244e80a0044823 100644 (file)
@@ -3,3 +3,8 @@ partitions-msdos-freebsd-ufs2-file-systems-are-not-recognized.patch
 arm-dts-imx6dl-fix-the-vdd_arm_cap-voltage-for-396mhz-operation.patch
 staging-rtl8192e-rtl92e_fill_tx_desc-fix-write-to-mapped-out-memory.patch
 call-echo-service-immediately-after-socket-reconnect.patch
+net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch
+net-xilinx_emaclite-fix-receive-buffer-overflow.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
diff --git a/queue-4.4/tipc-fix-tipc_sk_reinit-race-conditions.patch b/queue-4.4/tipc-fix-tipc_sk_reinit-race-conditions.patch
new file mode 100644 (file)
index 0000000..0a85f5c
--- /dev/null
@@ -0,0 +1,106 @@
+From foo@baz Thu Jun 15 09:36:39 CEST 2017
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Tue, 23 May 2017 21:53:35 -0400
+Subject: tipc: Fix tipc_sk_reinit race conditions
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+
+[ 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 <herbert@gondor.apana.org.au>
+Acked-by: Ying Xue <ying.xue@windriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -114,6 +114,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);
+       tipc_bcast_reinit(net);
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -365,8 +365,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;
+@@ -376,6 +374,13 @@ static int tipc_sk_create(struct net *ne
+               pr_warn("Socket create failed; port numbrer 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;
+@@ -2271,24 +2276,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)