]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
b43legacy: drop packets we are not able to encrypt
authorStefano Brivio <stefano.brivio@polimi.it>
Fri, 25 Jan 2008 13:29:50 +0000 (14:29 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 8 Feb 2008 19:46:28 +0000 (11:46 -0800)
patch 9eca9a8e81928685b4de00ecef83a7c13c340fc9 in mainline.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/wireless/b43legacy/dma.c
drivers/net/wireless/b43legacy/pio.c
drivers/net/wireless/b43legacy/xmit.c
drivers/net/wireless/b43legacy/xmit.h

index 83161d9af813a06a73a7733ea1180217be531094..0023de8235bfad34022ccead4d4eaaf419c31184 100644 (file)
@@ -1181,9 +1181,11 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
 
        header = &(ring->txhdr_cache[slot * sizeof(
                               struct b43legacy_txhdr_fw3)]);
-       b43legacy_generate_txhdr(ring->dev, header,
+       err = b43legacy_generate_txhdr(ring->dev, header,
                                 skb->data, skb->len, ctl,
                                 generate_cookie(ring, slot));
+       if (unlikely(err))
+               return err;
 
        meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
                                       sizeof(struct b43legacy_txhdr_fw3), 1);
@@ -1282,6 +1284,13 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
        B43legacy_BUG_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)) {
                b43legacyerr(dev->wl, "DMA tx mapping failure\n");
                goto out_unlock;
index a1bba44db749999ea6b418bc8918b50fd2039cd6..303450326b21b78364954b03f3459636980a74d1 100644 (file)
@@ -181,7 +181,7 @@ union txhdr_union {
        struct b43legacy_txhdr_fw3 txhdr_fw3;
 };
 
-static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
+static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
                                  struct sk_buff *skb,
                                  struct b43legacy_pio_txpacket *packet,
                                  size_t txhdr_size)
@@ -189,14 +189,17 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
        union txhdr_union txhdr_data;
        u8 *txhdr = NULL;
        unsigned int octets;
+       int err;
 
        txhdr = (u8 *)(&txhdr_data.txhdr_fw3);
 
        B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
-       b43legacy_generate_txhdr(queue->dev,
+       err = b43legacy_generate_txhdr(queue->dev,
                                 txhdr, skb->data, skb->len,
                                 &packet->txstat.control,
                                 generate_cookie(queue, packet));
+       if (err)
+               return err;
 
        tx_start(queue);
        octets = skb->len + txhdr_size;
@@ -204,6 +207,8 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
                octets--;
        tx_data(queue, txhdr, (u8 *)skb->data, octets);
        tx_complete(queue, skb);
+
+       return 0;
 }
 
 static void free_txpacket(struct b43legacy_pio_txpacket *packet,
@@ -226,6 +231,7 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet)
        struct b43legacy_pioqueue *queue = packet->queue;
        struct sk_buff *skb = packet->skb;
        u16 octets;
+       int err;
 
        octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3);
        if (queue->tx_devq_size < octets) {
@@ -247,8 +253,14 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet)
        if (queue->tx_devq_used + octets > queue->tx_devq_size)
                return -EBUSY;
        /* Now poke the device. */
-       pio_tx_write_fragment(queue, skb, packet,
+       err = pio_tx_write_fragment(queue, skb, packet,
                              sizeof(struct b43legacy_txhdr_fw3));
+       if (unlikely(err == -ENOKEY)) {
+               /* Drop this packet, as we don't have the encryption key
+                * anymore and must not transmit it unencrypted. */
+               free_txpacket(packet, 1);
+               return 0;
+       }
 
        /* Account for the packet size.
         * (We must not overflow the device TX queue)
index fa1e65687a63c65f541452dcff9a848e12ba89b1..f10d637b5f814faa29b64c737df5d3dddae23c96 100644 (file)
@@ -181,7 +181,7 @@ static u8 b43legacy_calc_fallback_rate(u8 bitrate)
        return 0;
 }
 
-static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
+static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
                               struct b43legacy_txhdr_fw3 *txhdr,
                               const unsigned char *fragment_data,
                               unsigned int fragment_len,
@@ -252,6 +252,13 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
                        iv_len = min((size_t)txctl->iv_len,
                                     ARRAY_SIZE(txhdr->iv));
                        memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
+               } else {
+                       /* This key is invalid. This might only happen
+                        * in a short timeframe after machine resume before
+                        * we were able to reconfigure keys.
+                        * Drop this packet completely. Do not transmit it
+                        * unencrypted to avoid leaking information. */
+                       return -ENOKEY;
                }
        }
        b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
@@ -344,16 +351,18 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
        /* Apply the bitfields */
        txhdr->mac_ctl = cpu_to_le32(mac_ctl);
        txhdr->phy_ctl = cpu_to_le16(phy_ctl);
+
+       return 0;
 }
 
-void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
                              u8 *txhdr,
                              const unsigned char *fragment_data,
                              unsigned int fragment_len,
                              const struct ieee80211_tx_control *txctl,
                              u16 cookie)
 {
-       generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
+       return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
                           fragment_data, fragment_len,
                           txctl, cookie);
 }
index 8a155d0a5d1fbb2c4b7d4528ce7ae900d8a261be..bab47928a0c9b776e5febd7b546e6da3d635827a 100644 (file)
@@ -76,7 +76,7 @@ struct b43legacy_txhdr_fw3 {
 
 
 
-void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
                              u8 *txhdr,
                              const unsigned char *fragment_data,
                              unsigned int fragment_len,