summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2013-03-06 10:31:05 +0100
committerJohannes Berg <johannes.berg@intel.com>2013-03-07 12:55:32 +0100
commit1345ee6a6d90813f972379fad8b75f17026fc8b2 (patch)
tree34aa5009c25c2937362318260bbb6aa5c49df4f9 /net
parentcfg80211: fix inconsistency in trace for rdev_set_mac_acl (diff)
downloadlinux-1345ee6a6d90813f972379fad8b75f17026fc8b2.tar.xz
linux-1345ee6a6d90813f972379fad8b75f17026fc8b2.zip
cfg80211: fix potential BSS memory leak and update
In the odd case that while updating information from a beacon, a BSS was found that is part of a hidden group, we drop the new information. In this case, however, we leak the IE buffer from the update, and erroneously update the entry's timestamp so it will never time out. Fix both these issues. Cc: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/scan.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 674aadca0079..e93bd31d23bb 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
if (found) {
- found->pub.beacon_interval = tmp->pub.beacon_interval;
- found->pub.signal = tmp->pub.signal;
- found->pub.capability = tmp->pub.capability;
- found->ts = tmp->ts;
-
/* Update IEs */
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
const struct cfg80211_bss_ies *old;
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
if (found->pub.hidden_beacon_bss &&
!list_empty(&found->hidden_list)) {
+ const struct cfg80211_bss_ies *f;
+
/*
* The found BSS struct is one of the probe
* response members of a group, but we're
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
* SSID to showing it, which is confusing so
* drop this information.
*/
+
+ f = rcu_access_pointer(tmp->pub.beacon_ies);
+ kfree_rcu((struct cfg80211_bss_ies *)f,
+ rcu_head);
goto drop;
}
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
kfree_rcu((struct cfg80211_bss_ies *)old,
rcu_head);
}
+
+ found->pub.beacon_interval = tmp->pub.beacon_interval;
+ found->pub.signal = tmp->pub.signal;
+ found->pub.capability = tmp->pub.capability;
+ found->ts = tmp->ts;
} else {
struct cfg80211_internal_bss *new;
struct cfg80211_internal_bss *hidden;