mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 10:57:46 +00:00
b43: Fix DMA mapping leakage
This fixes a DMA mapping leakage in the case where we reject a DMA buffer because of its address. Signed-off-by: Michael Buesch <mb@bu3sch.de> Cc: Christian Casteyde <casteyde.christian@free.fr> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
c83dbf687f
commit
ffa9256aaa
1 changed files with 17 additions and 10 deletions
|
@ -560,7 +560,7 @@ static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base,
|
|||
/* Check if a DMA mapping address is invalid. */
|
||||
static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
||||
dma_addr_t addr,
|
||||
size_t buffersize)
|
||||
size_t buffersize, bool dma_to_device)
|
||||
{
|
||||
if (unlikely(dma_mapping_error(addr)))
|
||||
return 1;
|
||||
|
@ -568,11 +568,11 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
|||
switch (ring->type) {
|
||||
case B43_DMA_30BIT:
|
||||
if ((u64)addr + buffersize > (1ULL << 30))
|
||||
return 1;
|
||||
goto address_error;
|
||||
break;
|
||||
case B43_DMA_32BIT:
|
||||
if ((u64)addr + buffersize > (1ULL << 32))
|
||||
return 1;
|
||||
goto address_error;
|
||||
break;
|
||||
case B43_DMA_64BIT:
|
||||
/* Currently we can't have addresses beyond
|
||||
|
@ -582,6 +582,12 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
|||
|
||||
/* The address is OK. */
|
||||
return 0;
|
||||
|
||||
address_error:
|
||||
/* We can't support this address. Unmap it again. */
|
||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup_rx_descbuffer(struct b43_dmaring *ring,
|
||||
|
@ -599,7 +605,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
|
|||
if (unlikely(!skb))
|
||||
return -ENOMEM;
|
||||
dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
|
||||
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
|
||||
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
|
||||
/* ugh. try to realloc in zone_dma */
|
||||
gfp_flags |= GFP_DMA;
|
||||
|
||||
|
@ -612,7 +618,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
|
|||
ring->rx_buffersize, 0);
|
||||
}
|
||||
|
||||
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
|
||||
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -852,7 +858,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||
b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) {
|
||||
if (b43_dma_mapping_error(ring, dma_test,
|
||||
b43_txhdr_size(dev), 1)) {
|
||||
/* ugh realloc */
|
||||
kfree(ring->txhdr_cache);
|
||||
ring->txhdr_cache = kcalloc(nr_slots,
|
||||
|
@ -867,7 +874,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||
DMA_TO_DEVICE);
|
||||
|
||||
if (b43_dma_mapping_error(ring, dma_test,
|
||||
b43_txhdr_size(dev)))
|
||||
b43_txhdr_size(dev), 1))
|
||||
goto err_kfree_txhdr_cache;
|
||||
}
|
||||
|
||||
|
@ -1189,7 +1196,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
|||
|
||||
meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
|
||||
hdrsize, 1);
|
||||
if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) {
|
||||
if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize, 1)) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
return -EIO;
|
||||
|
@ -1208,7 +1215,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
|||
|
||||
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
|
||||
/* create a bounce buffer in zone_dma on mapping failure. */
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
|
||||
if (!bounce_skb) {
|
||||
ring->current_slot = old_top_slot;
|
||||
|
@ -1222,7 +1229,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
|||
skb = bounce_skb;
|
||||
meta->skb = skb;
|
||||
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
err = -EIO;
|
||||
|
|
Loading…
Reference in a new issue