Skip to content

Commit

Permalink
net: lantiq: fix memory corruption in RX ring
Browse files Browse the repository at this point in the history
In a situation where memory allocation or dma mapping fails, an
invalid address is programmed into the descriptor. This can lead
to memory corruption. If the memory allocation fails, DMA should
reuse the previous skb and mapping and drop the packet. This patch
also increments rx drop counter.

Fixes: fe1a564 ("net: lantiq: Add Lantiq / Intel VRX200 Ethernet driver ")
Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
abajk authored and davem330 committed May 21, 2021
1 parent fc516d3 commit c7718ee
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions drivers/net/ethernet/lantiq_xrx200.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ static int xrx200_close(struct net_device *net_dev)

static int xrx200_alloc_skb(struct xrx200_chan *ch)
{
dma_addr_t mapping;
int ret = 0;

ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
Expand All @@ -163,16 +164,17 @@ static int xrx200_alloc_skb(struct xrx200_chan *ch)
goto skip;
}

ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(ch->priv->dev,
ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(ch->priv->dev,
ch->dma.desc_base[ch->dma.desc].addr))) {
mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
XRX200_DMA_DATA_LEN, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
dev_kfree_skb_any(ch->skb[ch->dma.desc]);
ret = -ENOMEM;
goto skip;
}

ch->dma.desc_base[ch->dma.desc].addr = mapping;
/* Make sure the address is written before we give it to HW */
wmb();
skip:
ch->dma.desc_base[ch->dma.desc].ctl =
LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
Expand All @@ -196,6 +198,8 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
ch->dma.desc %= LTQ_DESC_NUM;

if (ret) {
ch->skb[ch->dma.desc] = skb;
net_dev->stats.rx_dropped++;
netdev_err(net_dev, "failed to allocate new rx buffer\n");
return ret;
}
Expand Down

0 comments on commit c7718ee

Please sign in to comment.