Skip to content

Commit

Permalink
net: xilinx_emaclite: fix receive buffer overflow
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anssi Hannula authored and David S. Miller committed Feb 15, 2017
1 parent 5463b3d commit cd22455
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions drivers/net/ethernet/xilinx/xilinx_emaclite.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
*
* 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;
Expand Down Expand Up @@ -409,14 +409,15 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)

/* 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(__raw_readl(addr +
XEL_HEADER_IP_LENGTH_OFFSET +
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)
Expand All @@ -429,6 +430,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
/* 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);
Expand Down Expand Up @@ -603,7 +607,7 @@ static void xemaclite_rx_handler(struct net_device *dev)

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++;
Expand Down

0 comments on commit cd22455

Please sign in to comment.