iwlwifi: fix erroneous use of iwl_rx_packet.len as a length
authorDaniel C Halperin <daniel.c.halperin@intel.com>
Thu, 13 Aug 2009 20:31:01 +0000 (13:31 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Aug 2009 15:33:13 +0000 (11:33 -0400)
The field called 'len' in struct iwl_rx_packet is in fact not just a length
field but also includes some flags from the flow handler.  In several places
throughout the driver, this causes incorrect values to be interpreted as
lengths when the field is improperly masked.

In most situations the improper use is for debugging output, and simply results
in an erroneous message, such as:

[551933.070224] ieee80211 phy0: I iwl_rx_statistics Statistics notification received (480 vs -1367342620).

which should read '(480 vs 484)'.

In at least one case this could case bad things to happen:

void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
                                      struct iwl_rx_mem_buffer *rxb)
{
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
        IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
                        "notification for %s:\n",
                        le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
        iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)
);
}
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);

Given the rampant misuse of this field without proper masking throughout the
driver (every use but one), this patch renames the field from 'len' to
'len_n_flags' to reduce confusion.  It also adds the proper masking when
this field is used as a length value.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-rx.c

index b5a4d2ecdd2d61de6528369d637e3da8441bcd98..e9a685d8e3a1650d9320ab06e6d49010607f5df4 100644 (file)
@@ -349,12 +349,13 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
  *
  *****************************************************************************/
 
-void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+               struct iwl_rx_mem_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
                     (int)sizeof(struct iwl3945_notif_statistics),
-                    le32_to_cpu(pkt->len));
+                    le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 
        memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
 
index 720d234c97363183e91d33ace5d7f0e6fd349298..1d539e3b8db1d77eae65ff56392b39a19afa615e 100644 (file)
@@ -494,7 +494,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
 {
        struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
-       int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
+       int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
        int index;
 
        /* reduce the size of the length field itself */
index 9398ad7e42b12bfb23068453cf63ff718e4f226e..f4303843ff9bba50a6722df1c7e4de730873d5af 100644 (file)
@@ -3482,7 +3482,7 @@ struct iwl_wimax_coex_cmd {
  *****************************************************************************/
 
 struct iwl_rx_packet {
-       __le32 len;
+       __le32 len_n_flags;
        struct iwl_cmd_header hdr;
        union {
                struct iwl3945_rx_frame rx_frame;
index 62aa87b4358a14e6bbb67a12c280f27194c6ed47..f4c2431017e27805b51636ad7e760fa30dbddda2 100644 (file)
@@ -2294,10 +2294,11 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
                                      struct iwl_rx_mem_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+       u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
        IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-                       "notification for %s:\n",
-                       le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-       iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+                       "notification for %s:\n", len,
+                       get_cmd_string(pkt->hdr.cmd));
+       iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
 }
 EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
 
index 092d3276175ac035d2aeabfcc5af0582cb4086f2..353d9a2ddbca9a677a492e6bf8943b6c7833b697 100644 (file)
@@ -539,7 +539,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
        IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-                    (int)sizeof(priv->statistics), pkt->len);
+                    (int)sizeof(priv->statistics),
+                    le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 
        change = ((priv->statistics.general.temperature !=
                   pkt->u.stats.general.temperature) ||