aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-01-23 15:44:15 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:26:45 -0500
commit09552ccd8277e6382097e93a40f7311a09449367 (patch)
treec6e9b3f46ab04a0f1a461699d01cd6dbaa71e9bb /drivers
parent7be1bb6b798d506693d2d8668e801951996b5a4a (diff)
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')
-rw-r--r--drivers/net/wireless/b43/dma.c30
-rw-r--r--drivers/net/wireless/b43/xmit.c48
-rw-r--r--drivers/net/wireless/b43/xmit.h10
3 files changed, 58 insertions, 30 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,
1114{ 1114{
1115 const struct b43_dma_ops *ops = ring->ops; 1115 const struct b43_dma_ops *ops = ring->ops;
1116 u8 *header; 1116 u8 *header;
1117 int slot; 1117 int slot, old_top_slot, old_used_slots;
1118 int err; 1118 int err;
1119 struct b43_dmadesc_generic *desc; 1119 struct b43_dmadesc_generic *desc;
1120 struct b43_dmadesc_meta *meta; 1120 struct b43_dmadesc_meta *meta;
@@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1126#define SLOTS_PER_PACKET 2 1126#define SLOTS_PER_PACKET 2
1127 B43_WARN_ON(skb_shinfo(skb)->nr_frags); 1127 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
1128 1128
1129 old_top_slot = ring->current_slot;
1130 old_used_slots = ring->used_slots;
1131
1129 /* Get a slot for the header. */ 1132 /* Get a slot for the header. */
1130 slot = request_slot(ring); 1133 slot = request_slot(ring);
1131 desc = ops->idx2desc(ring, slot, &meta_hdr); 1134 desc = ops->idx2desc(ring, slot, &meta_hdr);
@@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1133 1136
1134 header = &(ring->txhdr_cache[slot * hdrsize]); 1137 header = &(ring->txhdr_cache[slot * hdrsize]);
1135 cookie = generate_cookie(ring, slot); 1138 cookie = generate_cookie(ring, slot);
1136 b43_generate_txhdr(ring->dev, header, 1139 err = b43_generate_txhdr(ring->dev, header,
1137 skb->data, skb->len, ctl, cookie); 1140 skb->data, skb->len, ctl, cookie);
1141 if (unlikely(err)) {
1142 ring->current_slot = old_top_slot;
1143 ring->used_slots = old_used_slots;
1144 return err;
1145 }
1138 1146
1139 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, 1147 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
1140 hdrsize, 1); 1148 hdrsize, 1);
1141 if (dma_mapping_error(meta_hdr->dmaaddr)) 1149 if (dma_mapping_error(meta_hdr->dmaaddr)) {
1150 ring->current_slot = old_top_slot;
1151 ring->used_slots = old_used_slots;
1142 return -EIO; 1152 return -EIO;
1153 }
1143 ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, 1154 ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
1144 hdrsize, 1, 0, 0); 1155 hdrsize, 1, 0, 0);
1145 1156
@@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1157 if (dma_mapping_error(meta->dmaaddr)) { 1168 if (dma_mapping_error(meta->dmaaddr)) {
1158 bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); 1169 bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
1159 if (!bounce_skb) { 1170 if (!bounce_skb) {
1171 ring->current_slot = old_top_slot;
1172 ring->used_slots = old_used_slots;
1160 err = -ENOMEM; 1173 err = -ENOMEM;
1161 goto out_unmap_hdr; 1174 goto out_unmap_hdr;
1162 } 1175 }
@@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1167 meta->skb = skb; 1180 meta->skb = skb;
1168 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); 1181 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1169 if (dma_mapping_error(meta->dmaaddr)) { 1182 if (dma_mapping_error(meta->dmaaddr)) {
1183 ring->current_slot = old_top_slot;
1184 ring->used_slots = old_used_slots;
1170 err = -EIO; 1185 err = -EIO;
1171 goto out_free_bounce; 1186 goto out_free_bounce;
1172 } 1187 }
@@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev,
1252 B43_WARN_ON(ring->stopped); 1267 B43_WARN_ON(ring->stopped);
1253 1268
1254 err = dma_tx_fragment(ring, skb, ctl); 1269 err = dma_tx_fragment(ring, skb, ctl);
1270 if (unlikely(err == -ENOKEY)) {
1271 /* Drop this packet, as we don't have the encryption key
1272 * anymore and must not transmit it unencrypted. */
1273 dev_kfree_skb_any(skb);
1274 err = 0;
1275 goto out_unlock;
1276 }
1255 if (unlikely(err)) { 1277 if (unlikely(err)) {
1256 b43err(dev->wl, "DMA tx mapping failure\n"); 1278 b43err(dev->wl, "DMA tx mapping failure\n");
1257 goto out_unlock; 1279 goto out_unlock;
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 7de2814d527e..7caa26eb4105 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -178,12 +178,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
178} 178}
179 179
180/* Generate a TX data header. */ 180/* Generate a TX data header. */
181void b43_generate_txhdr(struct b43_wldev *dev, 181int b43_generate_txhdr(struct b43_wldev *dev,
182 u8 *_txhdr, 182 u8 *_txhdr,
183 const unsigned char *fragment_data, 183 const unsigned char *fragment_data,
184 unsigned int fragment_len, 184 unsigned int fragment_len,
185 const struct ieee80211_tx_control *txctl, 185 const struct ieee80211_tx_control *txctl,
186 u16 cookie) 186 u16 cookie)
187{ 187{
188 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; 188 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
189 const struct b43_phy *phy = &dev->phy; 189 const struct b43_phy *phy = &dev->phy;
@@ -238,22 +238,27 @@ void b43_generate_txhdr(struct b43_wldev *dev,
238 B43_WARN_ON(key_idx >= dev->max_nr_keys); 238 B43_WARN_ON(key_idx >= dev->max_nr_keys);
239 key = &(dev->key[key_idx]); 239 key = &(dev->key[key_idx]);
240 240
241 if (likely(key->keyconf)) { 241 if (unlikely(!key->keyconf)) {
242 /* This key is valid. Use it for encryption. */ 242 /* This key is invalid. This might only happen
243 243 * in a short timeframe after machine resume before
244 /* Hardware appends ICV. */ 244 * we were able to reconfigure keys.
245 plcp_fragment_len += txctl->icv_len; 245 * Drop this packet completely. Do not transmit it
246 246 * unencrypted to avoid leaking information. */
247 key_idx = b43_kidx_to_fw(dev, key_idx); 247 return -ENOKEY;
248 mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
249 B43_TXH_MAC_KEYIDX;
250 mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
251 B43_TXH_MAC_KEYALG;
252 wlhdr_len = ieee80211_get_hdrlen(fctl);
253 iv_len = min((size_t) txctl->iv_len,
254 ARRAY_SIZE(txhdr->iv));
255 memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
256 } 248 }
249
250 /* Hardware appends ICV. */
251 plcp_fragment_len += txctl->icv_len;
252
253 key_idx = b43_kidx_to_fw(dev, key_idx);
254 mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
255 B43_TXH_MAC_KEYIDX;
256 mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
257 B43_TXH_MAC_KEYALG;
258 wlhdr_len = ieee80211_get_hdrlen(fctl);
259 iv_len = min((size_t) txctl->iv_len,
260 ARRAY_SIZE(txhdr->iv));
261 memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
257 } 262 }
258 if (b43_is_old_txhdr_format(dev)) { 263 if (b43_is_old_txhdr_format(dev)) {
259 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), 264 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
@@ -411,6 +416,7 @@ void b43_generate_txhdr(struct b43_wldev *dev,
411 txhdr->phy_ctl = cpu_to_le16(phy_ctl); 416 txhdr->phy_ctl = cpu_to_le16(phy_ctl);
412 txhdr->extra_ft = extra_ft; 417 txhdr->extra_ft = extra_ft;
413 418
419 return 0;
414} 420}
415 421
416static s8 b43_rssi_postprocess(struct b43_wldev *dev, 422static s8 b43_rssi_postprocess(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index ca2a2ab8654c..41765039552b 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -174,11 +174,11 @@ size_t b43_txhdr_size(struct b43_wldev *dev)
174} 174}
175 175
176 176
177void b43_generate_txhdr(struct b43_wldev *dev, 177int b43_generate_txhdr(struct b43_wldev *dev,
178 u8 * txhdr, 178 u8 * txhdr,
179 const unsigned char *fragment_data, 179 const unsigned char *fragment_data,
180 unsigned int fragment_len, 180 unsigned int fragment_len,
181 const struct ieee80211_tx_control *txctl, u16 cookie); 181 const struct ieee80211_tx_control *txctl, u16 cookie);
182 182
183/* Transmit Status */ 183/* Transmit Status */
184struct b43_txstatus { 184struct b43_txstatus {