diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-04-23 05:48:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:29 -0400 |
commit | 0e41f715c04f85a40ae6531d660be2241717be1c (patch) | |
tree | 35e44d6a2d4de54ad6cfd5d7fe2b6348efad2c6a /net/mac80211/ibss.c | |
parent | c7ae011dc8306d982c25fb4f679752e790a08dc4 (diff) |
mac80211: fix various problems in ibss code
There are a few problems in the IBSS code:
a) it tries to activate interfaces that are down after scanning
b) it crashes after scanning on an IBSS iface that isn't active
c) since the ssid_len is used as a flag, need to make it visible
only after all other settings are set, this helps protect
against b)
For b), we get a system crash:
wlan0: Creating new IBSS network, BSSID ce:f9:88:76:1e:4d
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<...>] ieee80211_sta_find_ibss+0x294/0x37d [mac80211]
Call Trace:
[<...>] ieee80211_ibss_notify_scan_completed+0x0/0x88 [mac80211]
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ibss.c')
-rw-r--r-- | net/mac80211/ibss.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6030e003180c..895f4854760c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -786,8 +786,12 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
786 | 786 | ||
787 | mutex_lock(&local->iflist_mtx); | 787 | mutex_lock(&local->iflist_mtx); |
788 | list_for_each_entry(sdata, &local->interfaces, list) { | 788 | list_for_each_entry(sdata, &local->interfaces, list) { |
789 | if (!netif_running(sdata->dev)) | ||
790 | continue; | ||
789 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 791 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
790 | continue; | 792 | continue; |
793 | if (!sdata->u.ibss.ssid_len) | ||
794 | continue; | ||
791 | sdata->u.ibss.last_scan_completed = jiffies; | 795 | sdata->u.ibss.last_scan_completed = jiffies; |
792 | ieee80211_sta_find_ibss(sdata); | 796 | ieee80211_sta_find_ibss(sdata); |
793 | } | 797 | } |
@@ -827,9 +831,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
827 | { | 831 | { |
828 | struct sk_buff *skb; | 832 | struct sk_buff *skb; |
829 | 833 | ||
830 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | ||
831 | sdata->u.ibss.ssid_len = params->ssid_len; | ||
832 | |||
833 | if (params->bssid) { | 834 | if (params->bssid) { |
834 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); | 835 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); |
835 | sdata->u.ibss.fixed_bssid = true; | 836 | sdata->u.ibss.fixed_bssid = true; |
@@ -859,6 +860,17 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
859 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 860 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
860 | sdata->u.ibss.ibss_join_req = jiffies; | 861 | sdata->u.ibss.ibss_join_req = jiffies; |
861 | 862 | ||
863 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | ||
864 | |||
865 | /* | ||
866 | * The ssid_len setting below is used to see whether | ||
867 | * we are active, and we need all other settings | ||
868 | * before that may get visible. | ||
869 | */ | ||
870 | mb(); | ||
871 | |||
872 | sdata->u.ibss.ssid_len = params->ssid_len; | ||
873 | |||
862 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 874 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
863 | queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); | 875 | queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); |
864 | 876 | ||