Skip to content

Commit

Permalink
rndis_wlan: increase assocbuf size and validate association info offs…
Browse files Browse the repository at this point in the history
…ets 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>
  • Loading branch information
Jussi Kivilinna authored and John W. Linville committed Jun 2, 2010
1 parent d5d1154 commit 3d1ca47
Showing 1 changed file with 29 additions and 7 deletions.
36 changes: 29 additions & 7 deletions drivers/net/wireless/rndis_wlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2495,8 +2495,7 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_assoc_info *info;
u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32];
struct ndis_80211_assoc_info *info = NULL;
u8 bssid[ETH_ALEN];
int resp_ie_len, req_ie_len;
u8 *req_ie, *resp_ie;
Expand All @@ -2515,23 +2514,43 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
resp_ie = NULL;

if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
memset(assoc_buf, 0, sizeof(assoc_buf));
info = (void *)assoc_buf;
info = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
if (!info) {
/* No memory? Try resume work later */
set_bit(WORK_LINK_UP, &priv->work_pending);
queue_work(priv->workqueue, &priv->work);
return;
}

/* Get association info IEs from device and send them back to
* userspace. */
ret = get_association_info(usbdev, info, sizeof(assoc_buf));
/* Get association info IEs from device. */
ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE);
if (!ret) {
req_ie_len = le32_to_cpu(info->req_ie_length);
if (req_ie_len > 0) {
offset = le32_to_cpu(info->offset_req_ies);

if (offset > CONTROL_BUFFER_SIZE)
offset = CONTROL_BUFFER_SIZE;

req_ie = (u8 *)info + offset;

if (offset + req_ie_len > CONTROL_BUFFER_SIZE)
req_ie_len =
CONTROL_BUFFER_SIZE - offset;
}

resp_ie_len = le32_to_cpu(info->resp_ie_length);
if (resp_ie_len > 0) {
offset = le32_to_cpu(info->offset_resp_ies);

if (offset > CONTROL_BUFFER_SIZE)
offset = CONTROL_BUFFER_SIZE;

resp_ie = (u8 *)info + offset;

if (offset + resp_ie_len > CONTROL_BUFFER_SIZE)
resp_ie_len =
CONTROL_BUFFER_SIZE - offset;
}
}
} else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC))
Expand Down Expand Up @@ -2563,6 +2582,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);

if (info != NULL)
kfree(info);

priv->connected = true;
memcpy(priv->bssid, bssid, ETH_ALEN);

Expand Down

0 comments on commit 3d1ca47

Please sign in to comment.