aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2010-05-18 04:27:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-02 16:13:20 -0400
commit3d1ca47eba76a31ad134e5c4d841234f5a6a92c3 (patch)
tree562226b42dd5881b1efef9baf6c424d638bbb0ba /drivers/net/wireless/rndis_wlan.c
parentd5d1154ffdc87b618518629fce44d51834df0f2e (diff)
rndis_wlan: increase assocbuf size and validate association info offsets from driver
Buffer size for get_association_info was limited to WEXT event size. Since association info no longer is sent through WEXT, this limit is not needed. Code also did not check if data get truncated, memory outside buffer might be addressed. Fix all these. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 4bd61ee627c0..4102cca54882 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2495,8 +2495,7 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
2495static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) 2495static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2496{ 2496{
2497 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 2497 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
2498 struct ndis_80211_assoc_info *info; 2498 struct ndis_80211_assoc_info *info = NULL;
2499 u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32];
2500 u8 bssid[ETH_ALEN]; 2499 u8 bssid[ETH_ALEN];
2501 int resp_ie_len, req_ie_len; 2500 int resp_ie_len, req_ie_len;
2502 u8 *req_ie, *resp_ie; 2501 u8 *req_ie, *resp_ie;
@@ -2515,23 +2514,43 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2515 resp_ie = NULL; 2514 resp_ie = NULL;
2516 2515
2517 if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { 2516 if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
2518 memset(assoc_buf, 0, sizeof(assoc_buf)); 2517 info = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
2519 info = (void *)assoc_buf; 2518 if (!info) {
2519 /* No memory? Try resume work later */
2520 set_bit(WORK_LINK_UP, &priv->work_pending);
2521 queue_work(priv->workqueue, &priv->work);
2522 return;
2523 }
2520 2524
2521 /* Get association info IEs from device and send them back to 2525 /* Get association info IEs from device. */
2522 * userspace. */ 2526 ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE);
2523 ret = get_association_info(usbdev, info, sizeof(assoc_buf));
2524 if (!ret) { 2527 if (!ret) {
2525 req_ie_len = le32_to_cpu(info->req_ie_length); 2528 req_ie_len = le32_to_cpu(info->req_ie_length);
2526 if (req_ie_len > 0) { 2529 if (req_ie_len > 0) {
2527 offset = le32_to_cpu(info->offset_req_ies); 2530 offset = le32_to_cpu(info->offset_req_ies);
2531
2532 if (offset > CONTROL_BUFFER_SIZE)
2533 offset = CONTROL_BUFFER_SIZE;
2534
2528 req_ie = (u8 *)info + offset; 2535 req_ie = (u8 *)info + offset;
2536
2537 if (offset + req_ie_len > CONTROL_BUFFER_SIZE)
2538 req_ie_len =
2539 CONTROL_BUFFER_SIZE - offset;
2529 } 2540 }
2530 2541
2531 resp_ie_len = le32_to_cpu(info->resp_ie_length); 2542 resp_ie_len = le32_to_cpu(info->resp_ie_length);
2532 if (resp_ie_len > 0) { 2543 if (resp_ie_len > 0) {
2533 offset = le32_to_cpu(info->offset_resp_ies); 2544 offset = le32_to_cpu(info->offset_resp_ies);
2545
2546 if (offset > CONTROL_BUFFER_SIZE)
2547 offset = CONTROL_BUFFER_SIZE;
2548
2534 resp_ie = (u8 *)info + offset; 2549 resp_ie = (u8 *)info + offset;
2550
2551 if (offset + resp_ie_len > CONTROL_BUFFER_SIZE)
2552 resp_ie_len =
2553 CONTROL_BUFFER_SIZE - offset;
2535 } 2554 }
2536 } 2555 }
2537 } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) 2556 } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC))
@@ -2563,6 +2582,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2563 } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) 2582 } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
2564 cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); 2583 cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
2565 2584
2585 if (info != NULL)
2586 kfree(info);
2587
2566 priv->connected = true; 2588 priv->connected = true;
2567 memcpy(priv->bssid, bssid, ETH_ALEN); 2589 memcpy(priv->bssid, bssid, ETH_ALEN);
2568 2590