Explorar el Código

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>
Johannes Berg hace 12 años
padre
commit
1345ee6a6d
Se han modificado 1 ficheros con 11 adiciones y 5 borrados
  1. 11 5
      net/wireless/scan.c

+ 11 - 5
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);
 	found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
 
 
 	if (found) {
 	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 */
 		/* Update IEs */
 		if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
 		if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
 			const struct cfg80211_bss_ies *old;
 			const struct cfg80211_bss_ies *old;
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 
 
 			if (found->pub.hidden_beacon_bss &&
 			if (found->pub.hidden_beacon_bss &&
 			    !list_empty(&found->hidden_list)) {
 			    !list_empty(&found->hidden_list)) {
+				const struct cfg80211_bss_ies *f;
+
 				/*
 				/*
 				 * The found BSS struct is one of the probe
 				 * The found BSS struct is one of the probe
 				 * response members of a group, but we're
 				 * 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
 				 * SSID to showing it, which is confusing so
 				 * drop this information.
 				 * drop this information.
 				 */
 				 */
+
+				f = rcu_access_pointer(tmp->pub.beacon_ies);
+				kfree_rcu((struct cfg80211_bss_ies *)f,
+					  rcu_head);
 				goto drop;
 				goto drop;
 			}
 			}
 
 
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 				kfree_rcu((struct cfg80211_bss_ies *)old,
 				kfree_rcu((struct cfg80211_bss_ies *)old,
 					  rcu_head);
 					  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 {
 	} else {
 		struct cfg80211_internal_bss *new;
 		struct cfg80211_internal_bss *new;
 		struct cfg80211_internal_bss *hidden;
 		struct cfg80211_internal_bss *hidden;