summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-05-18 05:40:44 -0400
committerJohannes Berg <johannes.berg@intel.com>2018-05-18 05:40:44 -0400
commit0fdf1493b41eb64fc7e8c8e1b8830a4bd8c4bbca (patch)
treedfa33dd2675c2cb313fd9a9d22baf6478efe9367
parent39c1134c66b4552f665da576cb625f184a44a8a3 (diff)
mac80211: allocate and fill tidstats only when needed
This fixes memory leaks in the case where we just have the station info on the stack for internal usage without sending it to cfg80211. Fixes: 8689c051a201 ("cfg80211: dynamically allocate per-tid stats for station info") Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/ethtool.c4
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/sta_info.h3
4 files changed, 10 insertions, 8 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5ce9d121af2b..bdf6fa78d0d2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -695,7 +695,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
695 if (sta) { 695 if (sta) {
696 ret = 0; 696 ret = 0;
697 memcpy(mac, sta->sta.addr, ETH_ALEN); 697 memcpy(mac, sta->sta.addr, ETH_ALEN);
698 sta_set_sinfo(sta, sinfo); 698 sta_set_sinfo(sta, sinfo, true);
699 } 699 }
700 700
701 mutex_unlock(&local->sta_mtx); 701 mutex_unlock(&local->sta_mtx);
@@ -724,7 +724,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
724 sta = sta_info_get_bss(sdata, mac); 724 sta = sta_info_get_bss(sdata, mac);
725 if (sta) { 725 if (sta) {
726 ret = 0; 726 ret = 0;
727 sta_set_sinfo(sta, sinfo); 727 sta_set_sinfo(sta, sinfo, true);
728 } 728 }
729 729
730 mutex_unlock(&local->sta_mtx); 730 mutex_unlock(&local->sta_mtx);
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
index 2ba5686cbcab..690c142a7a44 100644
--- a/net/mac80211/ethtool.c
+++ b/net/mac80211/ethtool.c
@@ -108,7 +108,7 @@ static void ieee80211_get_stats(struct net_device *dev,
108 goto do_survey; 108 goto do_survey;
109 109
110 memset(&sinfo, 0, sizeof(sinfo)); 110 memset(&sinfo, 0, sizeof(sinfo));
111 sta_set_sinfo(sta, &sinfo); 111 sta_set_sinfo(sta, &sinfo, false);
112 112
113 i = 0; 113 i = 0;
114 ADD_STA_STATS(sta); 114 ADD_STA_STATS(sta);
@@ -135,7 +135,7 @@ static void ieee80211_get_stats(struct net_device *dev,
135 continue; 135 continue;
136 136
137 memset(&sinfo, 0, sizeof(sinfo)); 137 memset(&sinfo, 0, sizeof(sinfo));
138 sta_set_sinfo(sta, &sinfo); 138 sta_set_sinfo(sta, &sinfo, false);
139 i = 0; 139 i = 0;
140 ADD_STA_STATS(sta); 140 ADD_STA_STATS(sta);
141 } 141 }
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 04d47689b557..6428f1ac37b6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1008,7 +1008,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
1008 1008
1009 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); 1009 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
1010 if (sinfo) 1010 if (sinfo)
1011 sta_set_sinfo(sta, sinfo); 1011 sta_set_sinfo(sta, sinfo, true);
1012 cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); 1012 cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
1013 kfree(sinfo); 1013 kfree(sinfo);
1014 1014
@@ -2079,7 +2079,8 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
2079 return value; 2079 return value;
2080} 2080}
2081 2081
2082void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) 2082void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
2083 bool tidstats)
2083{ 2084{
2084 struct ieee80211_sub_if_data *sdata = sta->sdata; 2085 struct ieee80211_sub_if_data *sdata = sta->sdata;
2085 struct ieee80211_local *local = sdata->local; 2086 struct ieee80211_local *local = sdata->local;
@@ -2233,7 +2234,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2233 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); 2234 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
2234 } 2235 }
2235 2236
2236 if (!cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) { 2237 if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
2237 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 2238 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
2238 struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i]; 2239 struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
2239 2240
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index d79bd6eeb549..81b35f623792 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -744,7 +744,8 @@ static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
744void sta_set_rate_info_tx(struct sta_info *sta, 744void sta_set_rate_info_tx(struct sta_info *sta,
745 const struct ieee80211_tx_rate *rate, 745 const struct ieee80211_tx_rate *rate,
746 struct rate_info *rinfo); 746 struct rate_info *rinfo);
747void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo); 747void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
748 bool tidstats);
748 749
749u32 sta_get_expected_throughput(struct sta_info *sta); 750u32 sta_get_expected_throughput(struct sta_info *sta);
750 751