diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2009-08-28 05:59:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-28 14:40:56 -0400 |
commit | 5fd8f2503b0888ed0c8e0017264059a3f9dc51c0 (patch) | |
tree | af5b0d441c535ebd1cc01b38662ddad92a9f2d1b /drivers/net/wireless/rndis_wlan.c | |
parent | db0dd396da45502e02c64c4153c5822ab5a59a5f (diff) |
rndis_wlan: resize bssid list if too small
Buffer used for bssid list might be too small. Change rndis_query_oid()
to return required buffer length to caller and make rndis_check_bssid_list()
resize buffer when needed.
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.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 37796210db55..2309ad2214a0 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -676,7 +676,8 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
676 | 676 | ||
677 | if (ret == 0) { | 677 | if (ret == 0) { |
678 | ret = le32_to_cpu(u.get_c->len); | 678 | ret = le32_to_cpu(u.get_c->len); |
679 | *len = (*len > ret) ? ret : *len; | 679 | if (ret > *len) |
680 | *len = ret; | ||
680 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); | 681 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); |
681 | ret = rndis_error_status(u.get_c->status); | 682 | ret = rndis_error_status(u.get_c->status); |
682 | 683 | ||
@@ -1656,6 +1657,9 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, | |||
1656 | int ie_len, bssid_len; | 1657 | int ie_len, bssid_len; |
1657 | u8 *ie; | 1658 | u8 *ie; |
1658 | 1659 | ||
1660 | devdbg(usbdev, " found bssid: '%.32s' [%pM]", bssid->ssid.essid, | ||
1661 | bssid->mac); | ||
1662 | |||
1659 | /* parse bssid structure */ | 1663 | /* parse bssid structure */ |
1660 | bssid_len = le32_to_cpu(bssid->length); | 1664 | bssid_len = le32_to_cpu(bssid->length); |
1661 | 1665 | ||
@@ -1695,10 +1699,12 @@ static int rndis_check_bssid_list(struct usbnet *usbdev) | |||
1695 | struct ndis_80211_bssid_list_ex *bssid_list; | 1699 | struct ndis_80211_bssid_list_ex *bssid_list; |
1696 | struct ndis_80211_bssid_ex *bssid; | 1700 | struct ndis_80211_bssid_ex *bssid; |
1697 | int ret = -EINVAL, len, count, bssid_len; | 1701 | int ret = -EINVAL, len, count, bssid_len; |
1702 | bool resized = false; | ||
1698 | 1703 | ||
1699 | devdbg(usbdev, "check_bssid_list"); | 1704 | devdbg(usbdev, "check_bssid_list"); |
1700 | 1705 | ||
1701 | len = CONTROL_BUFFER_SIZE; | 1706 | len = CONTROL_BUFFER_SIZE; |
1707 | resize_buf: | ||
1702 | buf = kmalloc(len, GFP_KERNEL); | 1708 | buf = kmalloc(len, GFP_KERNEL); |
1703 | if (!buf) { | 1709 | if (!buf) { |
1704 | ret = -ENOMEM; | 1710 | ret = -ENOMEM; |
@@ -1709,11 +1715,18 @@ static int rndis_check_bssid_list(struct usbnet *usbdev) | |||
1709 | if (ret != 0) | 1715 | if (ret != 0) |
1710 | goto out; | 1716 | goto out; |
1711 | 1717 | ||
1718 | if (!resized && len > CONTROL_BUFFER_SIZE) { | ||
1719 | resized = true; | ||
1720 | kfree(buf); | ||
1721 | goto resize_buf; | ||
1722 | } | ||
1723 | |||
1712 | bssid_list = buf; | 1724 | bssid_list = buf; |
1713 | bssid = bssid_list->bssid; | 1725 | bssid = bssid_list->bssid; |
1714 | bssid_len = le32_to_cpu(bssid->length); | 1726 | bssid_len = le32_to_cpu(bssid->length); |
1715 | count = le32_to_cpu(bssid_list->num_items); | 1727 | count = le32_to_cpu(bssid_list->num_items); |
1716 | devdbg(usbdev, "check_bssid_list: %d BSSIDs found", count); | 1728 | devdbg(usbdev, "check_bssid_list: %d BSSIDs found (buflen: %d)", count, |
1729 | len); | ||
1717 | 1730 | ||
1718 | while (count && ((void *)bssid + bssid_len) <= (buf + len)) { | 1731 | while (count && ((void *)bssid + bssid_len) <= (buf + len)) { |
1719 | rndis_bss_info_update(usbdev, bssid); | 1732 | rndis_bss_info_update(usbdev, bssid); |