diff options
| author | Dan Carpenter <dan.carpenter@oracle.com> | 2012-03-01 02:02:08 -0500 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2012-03-05 15:23:15 -0500 |
| commit | 41eedf39dfb145fb8fa04cd5b799f7bdc7679696 (patch) | |
| tree | 359897e247fc8112046abae3540759eea33213e2 | |
| parent | 5533513784a88049e19dd2ab380a452b61e5171e (diff) | |
rndis_wlan: integer overflows in rndis_wlan_do_link_up_work()
If "offset" is negative then we can get past this check:
if (offset > CONTROL_BUFFER_SIZE)
Or if we pick a very high "req_ie_len" then we can get around the check:
if (offset + req_ie_len > CONTROL_BUFFER_SIZE)
I made "resp_ie_len" and "req_ie_len" unsigned. I don't know if it was
intentional that they were signed in the original.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a330c69583d6..dde45effef14 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -2755,9 +2755,10 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
| 2755 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2755 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 2756 | struct ndis_80211_assoc_info *info = NULL; | 2756 | struct ndis_80211_assoc_info *info = NULL; |
| 2757 | u8 bssid[ETH_ALEN]; | 2757 | u8 bssid[ETH_ALEN]; |
| 2758 | int resp_ie_len, req_ie_len; | 2758 | unsigned int resp_ie_len, req_ie_len; |
| 2759 | unsigned int offset; | ||
| 2759 | u8 *req_ie, *resp_ie; | 2760 | u8 *req_ie, *resp_ie; |
| 2760 | int ret, offset; | 2761 | int ret; |
| 2761 | bool roamed = false; | 2762 | bool roamed = false; |
| 2762 | bool match_bss; | 2763 | bool match_bss; |
| 2763 | 2764 | ||
| @@ -2785,7 +2786,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
| 2785 | ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); | 2786 | ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); |
| 2786 | if (!ret) { | 2787 | if (!ret) { |
| 2787 | req_ie_len = le32_to_cpu(info->req_ie_length); | 2788 | req_ie_len = le32_to_cpu(info->req_ie_length); |
| 2788 | if (req_ie_len > 0) { | 2789 | if (req_ie_len > CONTROL_BUFFER_SIZE) |
| 2790 | req_ie_len = CONTROL_BUFFER_SIZE; | ||
| 2791 | if (req_ie_len != 0) { | ||
| 2789 | offset = le32_to_cpu(info->offset_req_ies); | 2792 | offset = le32_to_cpu(info->offset_req_ies); |
| 2790 | 2793 | ||
| 2791 | if (offset > CONTROL_BUFFER_SIZE) | 2794 | if (offset > CONTROL_BUFFER_SIZE) |
| @@ -2799,7 +2802,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
| 2799 | } | 2802 | } |
| 2800 | 2803 | ||
| 2801 | resp_ie_len = le32_to_cpu(info->resp_ie_length); | 2804 | resp_ie_len = le32_to_cpu(info->resp_ie_length); |
| 2802 | if (resp_ie_len > 0) { | 2805 | if (resp_ie_len > CONTROL_BUFFER_SIZE) |
| 2806 | resp_ie_len = CONTROL_BUFFER_SIZE; | ||
| 2807 | if (resp_ie_len != 0) { | ||
| 2803 | offset = le32_to_cpu(info->offset_resp_ies); | 2808 | offset = le32_to_cpu(info->offset_resp_ies); |
| 2804 | 2809 | ||
| 2805 | if (offset > CONTROL_BUFFER_SIZE) | 2810 | if (offset > CONTROL_BUFFER_SIZE) |
