aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
authorPaul Stewart <pstew@chromium.org>2012-02-23 20:59:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-07 13:51:37 -0500
commitfcff4f108dce0692410f390a05565f4b1b84577f (patch)
tree38e7c8cc1b28069b8a1bd518388f7585abc6f916 /net/mac80211/scan.c
parenteb9bc6e9a0ac668d2283b8fea1534f8ba31d1692 (diff)
mac80211: Filter duplicate IE ids
mac80211 is lenient with respect to reception of corrupted beacons. Even if the frame is corrupted as a whole, the available IE elements are still passed back and accepted, sometimes replacing legitimate data. It is unknown to what extent this "feature" is made use of, but it is clear that in some cases, this is detrimental. One such case is reported in http://crosbug.com/26832 where an AP corrupts its beacons but not its probe responses. One approach would be to completely reject frames with invaid data (for example, if the last tag extends beyond the end of the enclosing PDU). The enclosed approach is much more conservative: we simply prevent later IEs from overwriting the state from previous ones. This approach hopes that there might be some salient data in the IE stream before the corruption, and seeks to at least prevent that data from being overwritten. This approach will fix the case above. Further, we flag element structures that contain data we think might be corrupted, so that as we fill the mac80211 BSS structure, we try not to replace data from an un-corrupted probe response with that of a corrupted beacon, for example. Short of any statistics gathering in the various forms of AP breakage, it's not possible to ascertain the side effects of more stringent discarding of data. Signed-off-by: Paul Stewart <pstew@chromium.org> Cc: Sam Leffler <sleffler@chromium.org> Cc: Eliad Peller <eliad@wizery.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c71
1 files changed, 51 insertions, 20 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index a9d7235df7c3..33cd16901378 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -104,16 +104,35 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
104 cbss->free_priv = ieee80211_rx_bss_free; 104 cbss->free_priv = ieee80211_rx_bss_free;
105 bss = (void *)cbss->priv; 105 bss = (void *)cbss->priv;
106 106
107 if (elems->parse_error) {
108 if (beacon)
109 bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
110 else
111 bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
112 } else {
113 if (beacon)
114 bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
115 else
116 bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
117 }
118
107 /* save the ERP value so that it is available at association time */ 119 /* save the ERP value so that it is available at association time */
108 if (elems->erp_info && elems->erp_info_len >= 1) { 120 if (elems->erp_info && elems->erp_info_len >= 1 &&
121 (!elems->parse_error ||
122 !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
109 bss->erp_value = elems->erp_info[0]; 123 bss->erp_value = elems->erp_info[0];
110 bss->has_erp_value = true; 124 bss->has_erp_value = true;
125 if (!elems->parse_error)
126 bss->valid_data |= IEEE80211_BSS_VALID_ERP;
111 } 127 }
112 128
113 if (elems->tim) { 129 if (elems->tim && (!elems->parse_error ||
130 !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
114 struct ieee80211_tim_ie *tim_ie = 131 struct ieee80211_tim_ie *tim_ie =
115 (struct ieee80211_tim_ie *)elems->tim; 132 (struct ieee80211_tim_ie *)elems->tim;
116 bss->dtim_period = tim_ie->dtim_period; 133 bss->dtim_period = tim_ie->dtim_period;
134 if (!elems->parse_error)
135 bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
117 } 136 }
118 137
119 /* If the beacon had no TIM IE, or it was invalid, use 1 */ 138 /* If the beacon had no TIM IE, or it was invalid, use 1 */
@@ -121,26 +140,38 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
121 bss->dtim_period = 1; 140 bss->dtim_period = 1;
122 141
123 /* replace old supported rates if we get new values */ 142 /* replace old supported rates if we get new values */
124 srlen = 0; 143 if (!elems->parse_error ||
125 if (elems->supp_rates) { 144 !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
126 clen = IEEE80211_MAX_SUPP_RATES; 145 srlen = 0;
127 if (clen > elems->supp_rates_len) 146 if (elems->supp_rates) {
128 clen = elems->supp_rates_len; 147 clen = IEEE80211_MAX_SUPP_RATES;
129 memcpy(bss->supp_rates, elems->supp_rates, clen); 148 if (clen > elems->supp_rates_len)
130 srlen += clen; 149 clen = elems->supp_rates_len;
131 } 150 memcpy(bss->supp_rates, elems->supp_rates, clen);
132 if (elems->ext_supp_rates) { 151 srlen += clen;
133 clen = IEEE80211_MAX_SUPP_RATES - srlen; 152 }
134 if (clen > elems->ext_supp_rates_len) 153 if (elems->ext_supp_rates) {
135 clen = elems->ext_supp_rates_len; 154 clen = IEEE80211_MAX_SUPP_RATES - srlen;
136 memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen); 155 if (clen > elems->ext_supp_rates_len)
137 srlen += clen; 156 clen = elems->ext_supp_rates_len;
157 memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
158 clen);
159 srlen += clen;
160 }
161 if (srlen) {
162 bss->supp_rates_len = srlen;
163 if (!elems->parse_error)
164 bss->valid_data |= IEEE80211_BSS_VALID_RATES;
165 }
138 } 166 }
139 if (srlen)
140 bss->supp_rates_len = srlen;
141 167
142 bss->wmm_used = elems->wmm_param || elems->wmm_info; 168 if (!elems->parse_error ||
143 bss->uapsd_supported = is_uapsd_supported(elems); 169 !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
170 bss->wmm_used = elems->wmm_param || elems->wmm_info;
171 bss->uapsd_supported = is_uapsd_supported(elems);
172 if (!elems->parse_error)
173 bss->valid_data |= IEEE80211_BSS_VALID_WMM;
174 }
144 175
145 if (!beacon) 176 if (!beacon)
146 bss->last_probe_resp = jiffies; 177 bss->last_probe_resp = jiffies;