.. | .. |
---|
5 | 5 | * (for nl80211's connect() and wext) |
---|
6 | 6 | * |
---|
7 | 7 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> |
---|
8 | | - * Copyright (C) 2009 Intel Corporation. All rights reserved. |
---|
| 8 | + * Copyright (C) 2009, 2020 Intel Corporation. All rights reserved. |
---|
9 | 9 | * Copyright 2017 Intel Deutschland GmbH |
---|
10 | 10 | */ |
---|
11 | 11 | |
---|
.. | .. |
---|
24 | 24 | |
---|
25 | 25 | /* |
---|
26 | 26 | * Software SME in cfg80211, using auth/assoc/deauth calls to the |
---|
27 | | - * driver. This is is for implementing nl80211's connect/disconnect |
---|
| 27 | + * driver. This is for implementing nl80211's connect/disconnect |
---|
28 | 28 | * and wireless extensions (if configured.) |
---|
29 | 29 | */ |
---|
30 | 30 | |
---|
.. | .. |
---|
205 | 205 | return err; |
---|
206 | 206 | case CFG80211_CONN_ASSOC_FAILED_TIMEOUT: |
---|
207 | 207 | *treason = NL80211_TIMEOUT_ASSOC; |
---|
208 | | - /* fall through */ |
---|
| 208 | + fallthrough; |
---|
209 | 209 | case CFG80211_CONN_ASSOC_FAILED: |
---|
210 | 210 | cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
---|
211 | 211 | NULL, 0, |
---|
.. | .. |
---|
215 | 215 | cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
---|
216 | 216 | NULL, 0, |
---|
217 | 217 | WLAN_REASON_DEAUTH_LEAVING, false); |
---|
218 | | - /* fall through */ |
---|
| 218 | + fallthrough; |
---|
219 | 219 | case CFG80211_CONN_ABANDON: |
---|
220 | 220 | /* free directly, disconnected event already sent */ |
---|
221 | 221 | cfg80211_sme_free(wdev); |
---|
.. | .. |
---|
269 | 269 | rtnl_unlock(); |
---|
270 | 270 | } |
---|
271 | 271 | |
---|
| 272 | +static void cfg80211_step_auth_next(struct cfg80211_conn *conn, |
---|
| 273 | + struct cfg80211_bss *bss) |
---|
| 274 | +{ |
---|
| 275 | + memcpy(conn->bssid, bss->bssid, ETH_ALEN); |
---|
| 276 | + conn->params.bssid = conn->bssid; |
---|
| 277 | + conn->params.channel = bss->channel; |
---|
| 278 | + conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; |
---|
| 279 | +} |
---|
| 280 | + |
---|
272 | 281 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
---|
273 | 282 | static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) |
---|
274 | 283 | { |
---|
.. | .. |
---|
286 | 295 | if (!bss) |
---|
287 | 296 | return NULL; |
---|
288 | 297 | |
---|
289 | | - memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN); |
---|
290 | | - wdev->conn->params.bssid = wdev->conn->bssid; |
---|
291 | | - wdev->conn->params.channel = bss->channel; |
---|
292 | | - wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; |
---|
| 298 | + cfg80211_step_auth_next(wdev->conn, bss); |
---|
293 | 299 | schedule_work(&rdev->conn_work); |
---|
294 | 300 | |
---|
295 | 301 | return bss; |
---|
.. | .. |
---|
568 | 574 | wdev->conn->params.ssid_len = wdev->ssid_len; |
---|
569 | 575 | |
---|
570 | 576 | /* see if we have the bss already */ |
---|
571 | | - bss = cfg80211_get_conn_bss(wdev); |
---|
| 577 | + bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel, |
---|
| 578 | + wdev->conn->params.bssid, |
---|
| 579 | + wdev->conn->params.ssid, |
---|
| 580 | + wdev->conn->params.ssid_len, |
---|
| 581 | + wdev->conn_bss_type, |
---|
| 582 | + IEEE80211_PRIVACY(wdev->conn->params.privacy)); |
---|
572 | 583 | |
---|
573 | 584 | if (prev_bssid) { |
---|
574 | 585 | memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN); |
---|
.. | .. |
---|
579 | 590 | if (bss) { |
---|
580 | 591 | enum nl80211_timeout_reason treason; |
---|
581 | 592 | |
---|
| 593 | + cfg80211_step_auth_next(wdev->conn, bss); |
---|
582 | 594 | err = cfg80211_conn_do_work(wdev, &treason); |
---|
583 | 595 | cfg80211_put_bss(wdev->wiphy, bss); |
---|
584 | 596 | } else { |
---|
.. | .. |
---|
694 | 706 | return; |
---|
695 | 707 | } |
---|
696 | 708 | |
---|
| 709 | + wdev->unprot_beacon_reported = 0; |
---|
697 | 710 | nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr, |
---|
698 | 711 | GFP_KERNEL); |
---|
699 | 712 | |
---|
.. | .. |
---|
741 | 754 | } |
---|
742 | 755 | |
---|
743 | 756 | if (cr->status != WLAN_STATUS_SUCCESS) { |
---|
744 | | - kzfree(wdev->connect_keys); |
---|
| 757 | + kfree_sensitive(wdev->connect_keys); |
---|
745 | 758 | wdev->connect_keys = NULL; |
---|
746 | 759 | wdev->ssid_len = 0; |
---|
747 | 760 | wdev->conn_owner_nlportid = 0; |
---|
.. | .. |
---|
796 | 809 | u8 *next; |
---|
797 | 810 | |
---|
798 | 811 | if (params->bss) { |
---|
799 | | - /* Make sure the bss entry provided by the driver is valid. */ |
---|
800 | 812 | struct cfg80211_internal_bss *ibss = bss_from_pub(params->bss); |
---|
801 | 813 | |
---|
802 | | - if (WARN_ON(list_empty(&ibss->list))) { |
---|
803 | | - cfg80211_put_bss(wdev->wiphy, params->bss); |
---|
804 | | - return; |
---|
| 814 | + if (list_empty(&ibss->list)) { |
---|
| 815 | + struct cfg80211_bss *found = NULL, *tmp = params->bss; |
---|
| 816 | + |
---|
| 817 | + found = cfg80211_get_bss(wdev->wiphy, NULL, |
---|
| 818 | + params->bss->bssid, |
---|
| 819 | + wdev->ssid, wdev->ssid_len, |
---|
| 820 | + wdev->conn_bss_type, |
---|
| 821 | + IEEE80211_PRIVACY_ANY); |
---|
| 822 | + if (found) { |
---|
| 823 | + /* The same BSS is already updated so use it |
---|
| 824 | + * instead, as it has latest info. |
---|
| 825 | + */ |
---|
| 826 | + params->bss = found; |
---|
| 827 | + } else { |
---|
| 828 | + /* Update with BSS provided by driver, it will |
---|
| 829 | + * be freshly added and ref cnted, we can free |
---|
| 830 | + * the old one. |
---|
| 831 | + * |
---|
| 832 | + * signal_valid can be false, as we are not |
---|
| 833 | + * expecting the BSS to be found. |
---|
| 834 | + * |
---|
| 835 | + * keep the old timestamp to avoid confusion |
---|
| 836 | + */ |
---|
| 837 | + cfg80211_bss_update(rdev, ibss, false, |
---|
| 838 | + ibss->ts); |
---|
| 839 | + } |
---|
| 840 | + |
---|
| 841 | + cfg80211_put_bss(wdev->wiphy, tmp); |
---|
805 | 842 | } |
---|
806 | 843 | } |
---|
807 | 844 | |
---|
.. | .. |
---|
897 | 934 | cfg80211_hold_bss(bss_from_pub(info->bss)); |
---|
898 | 935 | wdev->current_bss = bss_from_pub(info->bss); |
---|
899 | 936 | |
---|
| 937 | + wdev->unprot_beacon_reported = 0; |
---|
900 | 938 | nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy), |
---|
901 | 939 | wdev->netdev, info, GFP_KERNEL); |
---|
902 | 940 | |
---|
.. | .. |
---|
1072 | 1110 | wdev->current_bss = NULL; |
---|
1073 | 1111 | wdev->ssid_len = 0; |
---|
1074 | 1112 | wdev->conn_owner_nlportid = 0; |
---|
1075 | | - kzfree(wdev->connect_keys); |
---|
| 1113 | + kfree_sensitive(wdev->connect_keys); |
---|
1076 | 1114 | wdev->connect_keys = NULL; |
---|
1077 | 1115 | |
---|
1078 | 1116 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); |
---|
.. | .. |
---|
1092 | 1130 | |
---|
1093 | 1131 | if (wiphy_ext_feature_isset( |
---|
1094 | 1132 | wdev->wiphy, |
---|
1095 | | - NL80211_EXT_FEATURE_BEACON_PROTECTION)) |
---|
| 1133 | + NL80211_EXT_FEATURE_BEACON_PROTECTION) || |
---|
| 1134 | + wiphy_ext_feature_isset( |
---|
| 1135 | + wdev->wiphy, |
---|
| 1136 | + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT)) |
---|
1096 | 1137 | max_key_idx = 7; |
---|
1097 | 1138 | for (i = 0; i <= max_key_idx; i++) |
---|
1098 | 1139 | rdev_del_key(rdev, dev, i, false, NULL); |
---|
.. | .. |
---|
1182 | 1223 | |
---|
1183 | 1224 | cfg80211_oper_and_ht_capa(&connect->ht_capa_mask, |
---|
1184 | 1225 | rdev->wiphy.ht_capa_mod_mask); |
---|
| 1226 | + cfg80211_oper_and_vht_capa(&connect->vht_capa_mask, |
---|
| 1227 | + rdev->wiphy.vht_capa_mod_mask); |
---|
1185 | 1228 | |
---|
1186 | 1229 | if (connkeys && connkeys->def >= 0) { |
---|
1187 | 1230 | int idx; |
---|
.. | .. |
---|
1214 | 1257 | } else { |
---|
1215 | 1258 | if (WARN_ON(connkeys)) |
---|
1216 | 1259 | return -EINVAL; |
---|
| 1260 | + |
---|
| 1261 | + /* connect can point to wdev->wext.connect which |
---|
| 1262 | + * can hold key data from a previous connection |
---|
| 1263 | + */ |
---|
| 1264 | + connect->key = NULL; |
---|
| 1265 | + connect->key_len = 0; |
---|
| 1266 | + connect->key_idx = 0; |
---|
1217 | 1267 | } |
---|
1218 | 1268 | |
---|
1219 | 1269 | wdev->connect_keys = connkeys; |
---|
.. | .. |
---|
1250 | 1300 | |
---|
1251 | 1301 | ASSERT_WDEV_LOCK(wdev); |
---|
1252 | 1302 | |
---|
1253 | | - kzfree(wdev->connect_keys); |
---|
| 1303 | + kfree_sensitive(wdev->connect_keys); |
---|
1254 | 1304 | wdev->connect_keys = NULL; |
---|
1255 | 1305 | |
---|
1256 | 1306 | wdev->conn_owner_nlportid = 0; |
---|