From: Greg Kroah-Hartman Date: Thu, 15 Jun 2017 07:39:46 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v4.9.33~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=54d468208b8ee33b3d6c6a7572b0b7d43c4cfd30;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches 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 --- diff --git a/queue-3.18/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch b/queue-3.18/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch new file mode 100644 index 00000000000..15b5df87cd3 --- /dev/null +++ b/queue-3.18/ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch @@ -0,0 +1,100 @@ +From foo@baz Thu Jun 15 09:38:54 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 +@@ -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 +@@ -164,8 +164,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); + +@@ -204,7 +209,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 +@@ -1107,6 +1107,10 @@ int udpv6_sendmsg(struct kiocb *iocb, st + 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-3.18/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch b/queue-3.18/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch new file mode 100644 index 00000000000..e176b38c7ce --- /dev/null +++ b/queue-3.18/ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch @@ -0,0 +1,35 @@ +From foo@baz Thu Jun 15 09:38:54 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 +@@ -960,6 +960,9 @@ static int ip6_dst_lookup_tail(struct so + } + } + #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-3.18/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch b/queue-3.18/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch new file mode 100644 index 00000000000..01b9e71c459 --- /dev/null +++ b/queue-3.18/net-xilinx_emaclite-fix-freezes-due-to-unordered-i-o.patch @@ -0,0 +1,331 @@ +From foo@baz Thu Jun 15 09:38:54 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 +@@ -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; + } +@@ -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) { +@@ -1138,8 +1146,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-3.18/net-xilinx_emaclite-fix-receive-buffer-overflow.patch b/queue-3.18/net-xilinx_emaclite-fix-receive-buffer-overflow.patch new file mode 100644 index 00000000000..c7d9bbe6946 --- /dev/null +++ b/queue-3.18/net-xilinx_emaclite-fix-receive-buffer-overflow.patch @@ -0,0 +1,76 @@ +From foo@baz Thu Jun 15 09:38:54 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 +@@ -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++; diff --git a/queue-3.18/series b/queue-3.18/series index ec4d0d856a8..ce13f581415 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -1,3 +1,7 @@ s390-vmem-fix-identity-mapping.patch partitions-msdos-freebsd-ufs2-file-systems-are-not-recognized.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