Message ID | 200912171414.16846.roger.oksanen@cs.helsinki.fi |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
On Thu, 17 Dec 2009, Roger Oksanen wrote: > e100: Fix broken cbs accounting due to missing memset. > > Alan Stern noticed that e100 caused slab corruption. > commit 98468efddb101f8a29af974101c17ba513b07be1 changed > the allocation of cbs to use dma pools that don't return zeroed memory, > especially the cb->status field used to track which cb to clean, causing > (the visible) double freeing of skbs and a wrong free cbs count. > > Now the cbs are explicitly zeroed at allocation time. > > Reported-by: Alan Stern <stern@rowland.harvard.edu> > Signed-off-by: Roger Oksanen <roger.oksanen@cs.helsinki.fi> > --- > drivers/net/e100.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/net/e100.c b/drivers/net/e100.c > index d269a68..29a8840 100644 > --- a/drivers/net/e100.c > +++ b/drivers/net/e100.c > @@ -1815,6 +1815,7 @@ static int e100_alloc_cbs(struct nic *nic) > > nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, > &nic->cbs_dma_addr); > + memset(nic->cbs, 0, count * sizeof(struct cb)); > if (!nic->cbs) > return -ENOMEM; > > @@ -1825,7 +1826,6 @@ static int e100_alloc_cbs(struct nic *nic) > cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); > cb->link = cpu_to_le32(nic->cbs_dma_addr + > ((i+1) % count) * sizeof(struct cb)); > - cb->skb = NULL; > } > > nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; Clearly the memset() belongs after the "if" test, not before. Apart from that, I confirm that this patch fixes the problem in 2.6.32. Tested-by: Alan Stern <stern@rowland.harvard.edu> Alan Stern -- 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 --git a/drivers/net/e100.c b/drivers/net/e100.c index d269a68..29a8840 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1815,6 +1815,7 @@ static int e100_alloc_cbs(struct nic *nic) nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, &nic->cbs_dma_addr); + memset(nic->cbs, 0, count * sizeof(struct cb)); if (!nic->cbs) return -ENOMEM; @@ -1825,7 +1826,6 @@ static int e100_alloc_cbs(struct nic *nic) cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); cb->link = cpu_to_le32(nic->cbs_dma_addr + ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; } nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;