Commit c7718ee9 authored by Aleksander Jan Bajkowski's avatar Aleksander Jan Bajkowski Committed by David S. Miller

net: lantiq: fix memory corruption in RX ring

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: fe1a5642 ("net: lantiq: Add Lantiq / Intel VRX200 Ethernet driver ")
Signed-off-by: default avatarAleksander Jan Bajkowski <olek2@wp.pl>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fc516d3a
...@@ -154,6 +154,7 @@ static int xrx200_close(struct net_device *net_dev) ...@@ -154,6 +154,7 @@ static int xrx200_close(struct net_device *net_dev)
static int xrx200_alloc_skb(struct xrx200_chan *ch) static int xrx200_alloc_skb(struct xrx200_chan *ch)
{ {
dma_addr_t mapping;
int ret = 0; int ret = 0;
ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev, ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
...@@ -163,16 +164,17 @@ static int xrx200_alloc_skb(struct xrx200_chan *ch) ...@@ -163,16 +164,17 @@ static int xrx200_alloc_skb(struct xrx200_chan *ch)
goto skip; goto skip;
} }
ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(ch->priv->dev, mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN, XRX200_DMA_DATA_LEN, DMA_FROM_DEVICE);
DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
if (unlikely(dma_mapping_error(ch->priv->dev,
ch->dma.desc_base[ch->dma.desc].addr))) {
dev_kfree_skb_any(ch->skb[ch->dma.desc]); dev_kfree_skb_any(ch->skb[ch->dma.desc]);
ret = -ENOMEM; ret = -ENOMEM;
goto skip; 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: skip:
ch->dma.desc_base[ch->dma.desc].ctl = ch->dma.desc_base[ch->dma.desc].ctl =
LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
...@@ -196,6 +198,8 @@ static int xrx200_hw_receive(struct xrx200_chan *ch) ...@@ -196,6 +198,8 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
ch->dma.desc %= LTQ_DESC_NUM; ch->dma.desc %= LTQ_DESC_NUM;
if (ret) { if (ret) {
ch->skb[ch->dma.desc] = skb;
net_dev->stats.rx_dropped++;
netdev_err(net_dev, "failed to allocate new rx buffer\n"); netdev_err(net_dev, "failed to allocate new rx buffer\n");
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment