diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-01-23 21:44:15 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-01 04:26:45 +0100 |
commit | 09552ccd8277e6382097e93a40f7311a09449367 (patch) | |
tree | c6e9b3f46ab04a0f1a461699d01cd6dbaa71e9bb /drivers/net/wireless/b43/dma.c | |
parent | b43: Fix suspend/resume (diff) | |
download | linux-09552ccd8277e6382097e93a40f7311a09449367.tar.xz linux-09552ccd8277e6382097e93a40f7311a09449367.zip |
b43: Drop packets that we are not able to encrypt
We must not transmit packets we're not able to encrypt.
This fixes a bug where in a tiny timeframe after machine resume
packets can get sent unencrypted and might leak information.
This also fixes three small resource leakages I spotted while fixing
the security problem. Properly deallocate the DMA slots in any DMA
allocation error path.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/b43/dma.c')
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3e73d2a523aa..8a708b77925d 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, { const struct b43_dma_ops *ops = ring->ops; u8 *header; - int slot; + int slot, old_top_slot, old_used_slots; int err; struct b43_dmadesc_generic *desc; struct b43_dmadesc_meta *meta; @@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring, #define SLOTS_PER_PACKET 2 B43_WARN_ON(skb_shinfo(skb)->nr_frags); + old_top_slot = ring->current_slot; + old_used_slots = ring->used_slots; + /* Get a slot for the header. */ slot = request_slot(ring); desc = ops->idx2desc(ring, slot, &meta_hdr); @@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring, header = &(ring->txhdr_cache[slot * hdrsize]); cookie = generate_cookie(ring, slot); - b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, ctl, cookie); + err = b43_generate_txhdr(ring->dev, header, + skb->data, skb->len, ctl, cookie); + if (unlikely(err)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; + return err; + } meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, hdrsize, 1); - if (dma_mapping_error(meta_hdr->dmaaddr)) + if (dma_mapping_error(meta_hdr->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; return -EIO; + } ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, hdrsize, 1, 0, 0); @@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, if (dma_mapping_error(meta->dmaaddr)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -ENOMEM; goto out_unmap_hdr; } @@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (dma_mapping_error(meta->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -EIO; goto out_free_bounce; } @@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev, B43_WARN_ON(ring->stopped); err = dma_tx_fragment(ring, skb, ctl); + if (unlikely(err == -ENOKEY)) { + /* Drop this packet, as we don't have the encryption key + * anymore and must not transmit it unencrypted. */ + dev_kfree_skb_any(skb); + err = 0; + goto out_unlock; + } if (unlikely(err)) { b43err(dev->wl, "DMA tx mapping failure\n"); goto out_unlock; |