Skip to content

Commit 10a7629

Browse files
anssihgregkh
authored andcommitted
net: xilinx_emaclite: fix receive buffer overflow
[ 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: bb81b2d ("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>
1 parent 7f71f22 commit 10a7629

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

drivers/net/ethernet/xilinx/xilinx_emaclite.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
379379
*
380380
* Return: Total number of bytes received
381381
*/
382-
static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
382+
static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
383383
{
384384
void __iomem *addr;
385385
u16 length, proto_type;
@@ -419,14 +419,15 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
419419

420420
/* Check if received ethernet frame is a raw ethernet frame
421421
* or an IP packet or an ARP packet */
422-
if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
422+
if (proto_type > ETH_DATA_LEN) {
423423

424424
if (proto_type == ETH_P_IP) {
425425
length = ((ntohl(xemaclite_readl(addr +
426426
XEL_HEADER_IP_LENGTH_OFFSET +
427427
XEL_RXBUFF_OFFSET)) >>
428428
XEL_HEADER_SHIFT) &
429429
XEL_RPLR_LENGTH_MASK);
430+
length = min_t(u16, length, ETH_DATA_LEN);
430431
length += ETH_HLEN + ETH_FCS_LEN;
431432

432433
} else if (proto_type == ETH_P_ARP)
@@ -439,6 +440,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
439440
/* Use the length in the frame, plus the header and trailer */
440441
length = proto_type + ETH_HLEN + ETH_FCS_LEN;
441442

443+
if (WARN_ON(length > maxlen))
444+
length = maxlen;
445+
442446
/* Read from the EmacLite device */
443447
xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
444448
data, length);
@@ -613,7 +617,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
613617

614618
skb_reserve(skb, 2);
615619

616-
len = xemaclite_recv_data(lp, (u8 *) skb->data);
620+
len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
617621

618622
if (!len) {
619623
dev->stats.rx_errors++;

0 commit comments

Comments
 (0)