b43: Drop packets that we are not able to encrypt
PATCH 1/1 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 <[email protected]>
---
This is _not_ only a theoretical problem. I saw a few packets hitting this race condition.
John, please try to push for 2.6.24, as this is a security fix.
Stefano, this might need porting to legacy.
drivers/net/wireless/b43/dma.c +26 -4
@@ -1111,38 +1111,49 @@ struct b43_dmaring *parse_cookie(structstatic int dma_tx_fragment (struct b43_dmaring *ring,struct sk_buff *skb,struct ieee80211_tx_control *ctl) {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;struct b43_dmadesc_meta *meta_hdr;struct sk_buff *bounce_skb;u16 cookie;size_t hdrsize =b43_txhdr_size (ring->dev);#define SLOTS_PER_PACKET 2B43_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);memset (meta_hdr,0 ,sizeof (*meta_hdr)); 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 );/* Get a slot for the payload. */ slot =request_slot (ring); desc = ops->idx2desc (ring, slot, &meta);
@@ -1154,22 +1165,26 @@ static int dma_tx_fragment(struct b43_dm meta->dmaaddr =map_descbuffer (ring, skb->data, skb->len,1 );/* create a bounce buffer in zone_dma on mapping failure. */ 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; }memcpy (skb_put (bounce_skb, skb->len), skb->data, skb->len);dev_kfree_skb_any (skb); skb = bounce_skb; 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; } } ops->fill_descriptor (ring, desc, meta->dmaaddr, skb->len,0 ,1 ,1 );
@@ -1249,12 +1264,19 @@ int b43_dma_tx(struct b43_wldev *dev,/* Check if the queue was stopped in mac80211, * but we got called nevertheless. * That would be a mac80211 bug. */ 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; } ring->nr_tx_packets++; if ((free_slots(ring) < SLOTS_PER_PACKET) ||
drivers/net/wireless/b43/xmit.c +26 -20
84 lines not on this page · raw message
drivers/net/wireless/b43/xmit.h +5 -5
@@ -171,17 +171,17 @@ size_t b43_txhdr_size(struct b43_wldev *if (b43_is_old_txhdr_format (dev))return 100 +sizeof (struct b43_plcp_hdr6 );return 104 +sizeof (struct b43_plcp_hdr6 ); } -void b43_generate_txhdr (struct b43_wldev *dev, -u8 * txhdr, -const unsigned char *fragment_data, -unsigned int fragment_len, -const struct ieee80211_tx_control *txctl,u16 cookie); +int b43_generate_txhdr (struct b43_wldev *dev, +u8 * txhdr, +const unsigned char *fragment_data, +unsigned int fragment_len, +const struct ieee80211_tx_control *txctl,u16 cookie);/* Transmit Status */ struct b43_txstatus {u16 cookie;/* The cookie from the txhdr */ u16 seq;/* Sequence number */ u8 phy_stat;/* PHY TX status */