diff mbox

yellowfin: Fix buffer underrun after dev_alloc_skb() failure

Message ID 4A7C6B08.1040800@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

roel kluin Aug. 7, 2009, 5:57 p.m. UTC
When dev_alloc_skb fails in the first iteration, a buffer underrun occurs.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
Is this the best way to fix this? Untested, please review.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

David Miller Aug. 13, 2009, 4:08 a.m. UTC | #1
From: Roel Kluin <roel.kluin@gmail.com>
Date: Fri, 07 Aug 2009 19:57:28 +0200

> When dev_alloc_skb fails in the first iteration, a buffer underrun occurs.
> 
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
> ---
> Is this the best way to fix this? Untested, please review.

I think this is a case where this code is going to need to
be majorly reworked so that you can pass error status up
to the caller when this allocation failure happens, and
the caller can properly act upon it.

Just silently returning when no RX ring has been allocated,
and the TX ring hasn't been setup at all, is going to be
worse than the array overrun you're supposedly fixing.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index a075801..a82ac32 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -728,7 +728,7 @@  static void yellowfin_tx_timeout(struct net_device *dev)
 static void yellowfin_init_ring(struct net_device *dev)
 {
 	struct yellowfin_private *yp = netdev_priv(dev);
-	int i;
+	int i, j;
 
 	yp->tx_full = 0;
 	yp->cur_rx = yp->cur_tx = 0;
@@ -753,6 +753,11 @@  static void yellowfin_init_ring(struct net_device *dev)
 		yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
 			skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
 	}
+	if (i != RX_RING_SIZE) {
+		for (j = 0; j < i; j++)
+			dev_kfree_skb(yp->rx_skbuff[j]);
+		return;
+	}
 	yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
 	yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);