diff options
author | Bing Zhao <bzhao@marvell.com> | 2013-04-12 13:34:17 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-22 15:38:35 -0400 |
commit | d837a2ae40fd37bcbb5a42126e3d89c68c90fccc (patch) | |
tree | d952e47adcbfbb9c7797b5593149df161de3f4e6 | |
parent | 8bc77a4d2c8ca3c07d74465a3738bf60a4e5de41 (diff) |
mwifiex: fix use-after-free in beacon_ie processing
beacon_ie buffer is allocated in mwifiex_fill_new_bss_desc()
and the buffer pointer is saved in bss_desc->beacon_buf.
beacon_ie is freed before the function returns. However,
bss_desc->beacon_buf is still being accessed afterwards.
Fix it by freeing beacon_ie (bss_desc->beacon_buf) in
caller's scope.
Reviewed-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 14 |
2 files changed, 17 insertions, 5 deletions
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index e7f6deaf715e..37b24e830844 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1533,10 +1533,18 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv, | |||
1533 | /* Make a copy of current BSSID descriptor */ | 1533 | /* Make a copy of current BSSID descriptor */ |
1534 | memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, | 1534 | memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, |
1535 | sizeof(priv->curr_bss_params.bss_descriptor)); | 1535 | sizeof(priv->curr_bss_params.bss_descriptor)); |
1536 | |||
1537 | /* The contents of beacon_ie will be copied to its own buffer | ||
1538 | * in mwifiex_save_curr_bcn() | ||
1539 | */ | ||
1536 | mwifiex_save_curr_bcn(priv); | 1540 | mwifiex_save_curr_bcn(priv); |
1537 | spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); | 1541 | spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); |
1538 | 1542 | ||
1539 | done: | 1543 | done: |
1544 | /* beacon_ie buffer was allocated in function | ||
1545 | * mwifiex_fill_new_bss_desc(). Free it now. | ||
1546 | */ | ||
1547 | kfree(bss_desc->beacon_buf); | ||
1540 | kfree(bss_desc); | 1548 | kfree(bss_desc); |
1541 | return 0; | 1549 | return 0; |
1542 | } | 1550 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index e6c9b2ae22ed..27729cfef151 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -140,12 +140,13 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
140 | /* | 140 | /* |
141 | * This function fills bss descriptor structure using provided | 141 | * This function fills bss descriptor structure using provided |
142 | * information. | 142 | * information. |
143 | * beacon_ie buffer is allocated in this function. It is caller's | ||
144 | * responsibility to free the memory. | ||
143 | */ | 145 | */ |
144 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | 146 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, |
145 | struct cfg80211_bss *bss, | 147 | struct cfg80211_bss *bss, |
146 | struct mwifiex_bssdescriptor *bss_desc) | 148 | struct mwifiex_bssdescriptor *bss_desc) |
147 | { | 149 | { |
148 | int ret; | ||
149 | u8 *beacon_ie; | 150 | u8 *beacon_ie; |
150 | size_t beacon_ie_len; | 151 | size_t beacon_ie_len; |
151 | struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; | 152 | struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; |
@@ -165,6 +166,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
165 | 166 | ||
166 | memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); | 167 | memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); |
167 | bss_desc->rssi = bss->signal; | 168 | bss_desc->rssi = bss->signal; |
169 | /* The caller of this function will free beacon_ie */ | ||
168 | bss_desc->beacon_buf = beacon_ie; | 170 | bss_desc->beacon_buf = beacon_ie; |
169 | bss_desc->beacon_buf_size = beacon_ie_len; | 171 | bss_desc->beacon_buf_size = beacon_ie_len; |
170 | bss_desc->beacon_period = bss->beacon_interval; | 172 | bss_desc->beacon_period = bss->beacon_interval; |
@@ -182,10 +184,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
182 | else | 184 | else |
183 | bss_desc->bss_mode = NL80211_IFTYPE_STATION; | 185 | bss_desc->bss_mode = NL80211_IFTYPE_STATION; |
184 | 186 | ||
185 | ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); | 187 | return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); |
186 | |||
187 | kfree(beacon_ie); | ||
188 | return ret; | ||
189 | } | 188 | } |
190 | 189 | ||
191 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, | 190 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, |
@@ -349,6 +348,11 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
349 | } | 348 | } |
350 | 349 | ||
351 | done: | 350 | done: |
351 | /* beacon_ie buffer was allocated in function | ||
352 | * mwifiex_fill_new_bss_desc(). Free it now. | ||
353 | */ | ||
354 | if (bss_desc) | ||
355 | kfree(bss_desc->beacon_buf); | ||
352 | kfree(bss_desc); | 356 | kfree(bss_desc); |
353 | return ret; | 357 | return ret; |
354 | } | 358 | } |