mwifiex: remove redundant TDLS setup action frame check and avoid leaks
authorBing Zhao <bzhao@marvell.com>
Tue, 15 Jul 2014 03:53:34 +0000 (20:53 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 16 Jul 2014 13:57:58 +0000 (09:57 -0400)
The unwanted frame types are already handled in 'default' case
of the switch/case below.
The str_ptr is allocated but it can be leaked if the length check
fails in the REQUEST/RESP cases. Fix it by allocating sta_ptr
after the length checks.

Reported-by: Paul Stewart <pstew@chromium.org>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Paul Stewart <pstew@chromium.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/tdls.c

index a414161c6064d783ed482c087ff7d7f1a10c013e..4c5fd953893dcb22712f60c618f68499351c1dff 100644 (file)
@@ -781,6 +781,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
        struct mwifiex_sta_node *sta_ptr;
        u8 *peer, *pos, *end;
        u8 i, action, basic;
+       __le16 cap = 0;
        int ie_len = 0;
 
        if (len < (sizeof(struct ethhdr) + 3))
@@ -792,18 +793,9 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
        peer = buf + ETH_ALEN;
        action = *(buf + sizeof(struct ethhdr) + 2);
-
-       /* just handle TDLS setup request/response/confirm */
-       if (action > WLAN_TDLS_SETUP_CONFIRM)
-               return;
-
        dev_dbg(priv->adapter->dev,
                "rx:tdls action: peer=%pM, action=%d\n", peer, action);
 
-       sta_ptr = mwifiex_add_sta_entry(priv, peer);
-       if (!sta_ptr)
-               return;
-
        switch (action) {
        case WLAN_TDLS_SETUP_REQUEST:
                if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
@@ -811,7 +803,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
                pos = buf + sizeof(struct ethhdr) + 4;
                /* payload 1+ category 1 + action 1 + dialog 1 */
-               sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+               cap = cpu_to_le16(*(u16 *)pos);
                ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
                pos += 2;
                break;
@@ -821,7 +813,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
                        return;
                /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
                pos = buf + sizeof(struct ethhdr) + 6;
-               sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+               cap = cpu_to_le16(*(u16 *)pos);
                ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
                pos += 2;
                break;
@@ -833,10 +825,16 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
                ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
                break;
        default:
-               dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
+               dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
                return;
        }
 
+       sta_ptr = mwifiex_add_sta_entry(priv, peer);
+       if (!sta_ptr)
+               return;
+
+       sta_ptr->tdls_cap.capab = cap;
+
        for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
                if (pos + 2 + pos[1] > end)
                        break;