aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Brivio <stefano.brivio@polimi.it>2008-02-02 13:16:01 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-05 14:35:46 -0500
commit9eca9a8e81928685b4de00ecef83a7c13c340fc9 (patch)
tree9029574fe8c64a8b75c3f682d6ba2f4fd1ced504
parentada50731c0346bf900dc387edd3a6961297bf2d3 (diff)
b43legacy: drop packets we are not able to encrypt
We must drop any packets we are not able to encrypt. We must not send them unencrypted or with an all-zero-key (which basically is the same as unencrypted, from a security point of view). This might only trigger shortly after resume before mac80211 reassociated and reconfigured the keys. It is safe to drop these packets, as the association they belong to is not guaranteed anymore anyway. This is a security fix in the sense that it prevents information leakage. This patch by Michael Buesch has been ported to b43legacy. Cc: Michael Buesch <mb@bu3sch.de> Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/b43legacy/dma.c11
-rw-r--r--drivers/net/wireless/b43legacy/pio.c18
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c15
-rw-r--r--drivers/net/wireless/b43legacy/xmit.h2
4 files changed, 38 insertions, 8 deletions
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 83161d9af81..0023de8235b 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -1181,9 +1181,11 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
1181 1181
1182 header = &(ring->txhdr_cache[slot * sizeof( 1182 header = &(ring->txhdr_cache[slot * sizeof(
1183 struct b43legacy_txhdr_fw3)]); 1183 struct b43legacy_txhdr_fw3)]);
1184 b43legacy_generate_txhdr(ring->dev, header, 1184 err = b43legacy_generate_txhdr(ring->dev, header,
1185 skb->data, skb->len, ctl, 1185 skb->data, skb->len, ctl,
1186 generate_cookie(ring, slot)); 1186 generate_cookie(ring, slot));
1187 if (unlikely(err))
1188 return err;
1187 1189
1188 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, 1190 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
1189 sizeof(struct b43legacy_txhdr_fw3), 1); 1191 sizeof(struct b43legacy_txhdr_fw3), 1);
@@ -1282,6 +1284,13 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
1282 B43legacy_BUG_ON(ring->stopped); 1284 B43legacy_BUG_ON(ring->stopped);
1283 1285
1284 err = dma_tx_fragment(ring, skb, ctl); 1286 err = dma_tx_fragment(ring, skb, ctl);
1287 if (unlikely(err == -ENOKEY)) {
1288 /* Drop this packet, as we don't have the encryption key
1289 * anymore and must not transmit it unencrypted. */
1290 dev_kfree_skb_any(skb);
1291 err = 0;
1292 goto out_unlock;
1293 }
1285 if (unlikely(err)) { 1294 if (unlikely(err)) {
1286 b43legacyerr(dev->wl, "DMA tx mapping failure\n"); 1295 b43legacyerr(dev->wl, "DMA tx mapping failure\n");
1287 goto out_unlock; 1296 goto out_unlock;
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index 1f48ec7fbe9..bcdd54eb2ed 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -181,7 +181,7 @@ union txhdr_union {
181 struct b43legacy_txhdr_fw3 txhdr_fw3; 181 struct b43legacy_txhdr_fw3 txhdr_fw3;
182}; 182};
183 183
184static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, 184static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
185 struct sk_buff *skb, 185 struct sk_buff *skb,
186 struct b43legacy_pio_txpacket *packet, 186 struct b43legacy_pio_txpacket *packet,
187 size_t txhdr_size) 187 size_t txhdr_size)
@@ -189,14 +189,17 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
189 union txhdr_union txhdr_data; 189 union txhdr_union txhdr_data;
190 u8 *txhdr = NULL; 190 u8 *txhdr = NULL;
191 unsigned int octets; 191 unsigned int octets;
192 int err;
192 193
193 txhdr = (u8 *)(&txhdr_data.txhdr_fw3); 194 txhdr = (u8 *)(&txhdr_data.txhdr_fw3);
194 195
195 B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); 196 B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
196 b43legacy_generate_txhdr(queue->dev, 197 err = b43legacy_generate_txhdr(queue->dev,
197 txhdr, skb->data, skb->len, 198 txhdr, skb->data, skb->len,
198 &packet->txstat.control, 199 &packet->txstat.control,
199 generate_cookie(queue, packet)); 200 generate_cookie(queue, packet));
201 if (err)
202 return err;
200 203
201 tx_start(queue); 204 tx_start(queue);
202 octets = skb->len + txhdr_size; 205 octets = skb->len + txhdr_size;
@@ -204,6 +207,8 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
204 octets--; 207 octets--;
205 tx_data(queue, txhdr, (u8 *)skb->data, octets); 208 tx_data(queue, txhdr, (u8 *)skb->data, octets);
206 tx_complete(queue, skb); 209 tx_complete(queue, skb);
210
211 return 0;
207} 212}
208 213
209static void free_txpacket(struct b43legacy_pio_txpacket *packet, 214static void free_txpacket(struct b43legacy_pio_txpacket *packet,
@@ -226,6 +231,7 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet)
226 struct b43legacy_pioqueue *queue = packet->queue; 231 struct b43legacy_pioqueue *queue = packet->queue;
227 struct sk_buff *skb = packet->skb; 232 struct sk_buff *skb = packet->skb;
228 u16 octets; 233 u16 octets;
234 int err;
229 235
230 octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); 236 octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3);
231 if (queue->tx_devq_size < octets) { 237 if (queue->tx_devq_size < octets) {
@@ -247,8 +253,14 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet)
247 if (queue->tx_devq_used + octets > queue->tx_devq_size) 253 if (queue->tx_devq_used + octets > queue->tx_devq_size)
248 return -EBUSY; 254 return -EBUSY;
249 /* Now poke the device. */ 255 /* Now poke the device. */
250 pio_tx_write_fragment(queue, skb, packet, 256 err = pio_tx_write_fragment(queue, skb, packet,
251 sizeof(struct b43legacy_txhdr_fw3)); 257 sizeof(struct b43legacy_txhdr_fw3));
258 if (unlikely(err == -ENOKEY)) {
259 /* Drop this packet, as we don't have the encryption key
260 * anymore and must not transmit it unencrypted. */
261 free_txpacket(packet, 1);
262 return 0;
263 }
252 264
253 /* Account for the packet size. 265 /* Account for the packet size.
254 * (We must not overflow the device TX queue) 266 * (We must not overflow the device TX queue)
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index e20c552442d..d84408a82db 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -181,7 +181,7 @@ static u8 b43legacy_calc_fallback_rate(u8 bitrate)
181 return 0; 181 return 0;
182} 182}
183 183
184static void generate_txhdr_fw3(struct b43legacy_wldev *dev, 184static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
185 struct b43legacy_txhdr_fw3 *txhdr, 185 struct b43legacy_txhdr_fw3 *txhdr,
186 const unsigned char *fragment_data, 186 const unsigned char *fragment_data,
187 unsigned int fragment_len, 187 unsigned int fragment_len,
@@ -252,6 +252,13 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
252 iv_len = min((size_t)txctl->iv_len, 252 iv_len = min((size_t)txctl->iv_len,
253 ARRAY_SIZE(txhdr->iv)); 253 ARRAY_SIZE(txhdr->iv));
254 memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); 254 memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
255 } else {
256 /* This key is invalid. This might only happen
257 * in a short timeframe after machine resume before
258 * we were able to reconfigure keys.
259 * Drop this packet completely. Do not transmit it
260 * unencrypted to avoid leaking information. */
261 return -ENOKEY;
255 } 262 }
256 } 263 }
257 b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) 264 b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
@@ -345,16 +352,18 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
345 /* Apply the bitfields */ 352 /* Apply the bitfields */
346 txhdr->mac_ctl = cpu_to_le32(mac_ctl); 353 txhdr->mac_ctl = cpu_to_le32(mac_ctl);
347 txhdr->phy_ctl = cpu_to_le16(phy_ctl); 354 txhdr->phy_ctl = cpu_to_le16(phy_ctl);
355
356 return 0;
348} 357}
349 358
350void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, 359int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
351 u8 *txhdr, 360 u8 *txhdr,
352 const unsigned char *fragment_data, 361 const unsigned char *fragment_data,
353 unsigned int fragment_len, 362 unsigned int fragment_len,
354 const struct ieee80211_tx_control *txctl, 363 const struct ieee80211_tx_control *txctl,
355 u16 cookie) 364 u16 cookie)
356{ 365{
357 generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, 366 return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
358 fragment_data, fragment_len, 367 fragment_data, fragment_len,
359 txctl, cookie); 368 txctl, cookie);
360} 369}
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h
index 8a155d0a5d1..bab47928a0c 100644
--- a/drivers/net/wireless/b43legacy/xmit.h
+++ b/drivers/net/wireless/b43legacy/xmit.h
@@ -76,7 +76,7 @@ struct b43legacy_txhdr_fw3 {
76 76
77 77
78 78
79void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, 79int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
80 u8 *txhdr, 80 u8 *txhdr,
81 const unsigned char *fragment_data, 81 const unsigned char *fragment_data,
82 unsigned int fragment_len, 82 unsigned int fragment_len,