diff options
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 989b0561c01b..5e7f344b000d 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) | |||
2495 | static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | 2495 | static 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 | ||