aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-07 11:54:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:44 -0400
commit5ba63533bbf653631faab60f6988506160ec6ba4 (patch)
tree8d9ef2670cd3b2f50fe3581820fba5aca365634d
parentad5351db89681515681c5d5659ddf4c69e3cc6f5 (diff)
cfg80211: fix alignment problem in scan request
The memory layout for scan requests was rather wrong, we put the scan SSIDs before the channels which could lead to the channel pointers being unaligned in memory. It turns out that using a pointer to the channel array isn't necessary anyway since we can embed a zero-length array into the struct. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/main.c16
-rw-r--r--net/mac80211/scan.c10
-rw-r--r--net/wireless/nl80211.c3
-rw-r--r--net/wireless/scan.c4
-rw-r--r--net/wireless/sme.c3
7 files changed, 21 insertions, 21 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index de7d116acc3d..d5756c9fe3d3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -559,7 +559,6 @@ struct cfg80211_ssid {
559struct cfg80211_scan_request { 559struct cfg80211_scan_request {
560 struct cfg80211_ssid *ssids; 560 struct cfg80211_ssid *ssids;
561 int n_ssids; 561 int n_ssids;
562 struct ieee80211_channel **channels;
563 u32 n_channels; 562 u32 n_channels;
564 const u8 *ie; 563 const u8 *ie;
565 size_t ie_len; 564 size_t ie_len;
@@ -568,6 +567,9 @@ struct cfg80211_scan_request {
568 struct wiphy *wiphy; 567 struct wiphy *wiphy;
569 struct net_device *dev; 568 struct net_device *dev;
570 bool aborted; 569 bool aborted;
570
571 /* keep last */
572 struct ieee80211_channel *channels[0];
571}; 573};
572 574
573/** 575/**
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 99433222bc5c..d6bd7dd77960 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -715,7 +715,7 @@ struct ieee80211_local {
715 struct mutex scan_mtx; 715 struct mutex scan_mtx;
716 unsigned long scanning; 716 unsigned long scanning;
717 struct cfg80211_ssid scan_ssid; 717 struct cfg80211_ssid scan_ssid;
718 struct cfg80211_scan_request int_scan_req; 718 struct cfg80211_scan_request *int_scan_req;
719 struct cfg80211_scan_request *scan_req; 719 struct cfg80211_scan_request *scan_req;
720 struct ieee80211_channel *scan_channel; 720 struct ieee80211_channel *scan_channel;
721 const u8 *orig_ies; 721 const u8 *orig_ies;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0c4f8e122ed6..b03fd84777fa 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -765,9 +765,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
765 supp_ht = supp_ht || sband->ht_cap.ht_supported; 765 supp_ht = supp_ht || sband->ht_cap.ht_supported;
766 } 766 }
767 767
768 local->int_scan_req.n_channels = channels; 768 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
769 local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL); 769 sizeof(void *) * channels, GFP_KERNEL);
770 if (!local->int_scan_req.channels) 770 if (!local->int_scan_req)
771 return -ENOMEM; 771 return -ENOMEM;
772 772
773 /* if low-level driver supports AP, we also support VLAN */ 773 /* if low-level driver supports AP, we also support VLAN */
@@ -882,13 +882,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
882 882
883 /* alloc internal scan request */ 883 /* alloc internal scan request */
884 i = 0; 884 i = 0;
885 local->int_scan_req.ssids = &local->scan_ssid; 885 local->int_scan_req->ssids = &local->scan_ssid;
886 local->int_scan_req.n_ssids = 1; 886 local->int_scan_req->n_ssids = 1;
887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
888 if (!hw->wiphy->bands[band]) 888 if (!hw->wiphy->bands[band])
889 continue; 889 continue;
890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { 890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
891 local->int_scan_req.channels[i] = 891 local->int_scan_req->channels[i] =
892 &hw->wiphy->bands[band]->channels[j]; 892 &hw->wiphy->bands[band]->channels[j];
893 i++; 893 i++;
894 } 894 }
@@ -920,7 +920,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
920 fail_workqueue: 920 fail_workqueue:
921 wiphy_unregister(local->hw.wiphy); 921 wiphy_unregister(local->hw.wiphy);
922 fail_wiphy_register: 922 fail_wiphy_register:
923 kfree(local->int_scan_req.channels); 923 kfree(local->int_scan_req->channels);
924 return result; 924 return result;
925} 925}
926EXPORT_SYMBOL(ieee80211_register_hw); 926EXPORT_SYMBOL(ieee80211_register_hw);
@@ -962,7 +962,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
962 wiphy_unregister(local->hw.wiphy); 962 wiphy_unregister(local->hw.wiphy);
963 ieee80211_wep_free(local); 963 ieee80211_wep_free(local);
964 ieee80211_led_exit(local); 964 ieee80211_led_exit(local);
965 kfree(local->int_scan_req.channels); 965 kfree(local->int_scan_req);
966} 966}
967EXPORT_SYMBOL(ieee80211_unregister_hw); 967EXPORT_SYMBOL(ieee80211_unregister_hw);
968 968
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 244f53f3c8b4..e091cbc3434f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -277,7 +277,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
277 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) 277 if (test_bit(SCAN_HW_SCANNING, &local->scanning))
278 ieee80211_restore_scan_ies(local); 278 ieee80211_restore_scan_ies(local);
279 279
280 if (local->scan_req != &local->int_scan_req) 280 if (local->scan_req != local->int_scan_req)
281 cfg80211_scan_done(local->scan_req, aborted); 281 cfg80211_scan_done(local->scan_req, aborted);
282 local->scan_req = NULL; 282 local->scan_req = NULL;
283 283
@@ -423,7 +423,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
423 local->scan_req = req; 423 local->scan_req = req;
424 local->scan_sdata = sdata; 424 local->scan_sdata = sdata;
425 425
426 if (req != &local->int_scan_req && 426 if (req != local->int_scan_req &&
427 sdata->vif.type == NL80211_IFTYPE_STATION && 427 sdata->vif.type == NL80211_IFTYPE_STATION &&
428 !list_empty(&ifmgd->work_list)) { 428 !list_empty(&ifmgd->work_list)) {
429 /* actually wait for the work it's doing to finish/time out */ 429 /* actually wait for the work it's doing to finish/time out */
@@ -743,10 +743,10 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
743 if (local->scan_req) 743 if (local->scan_req)
744 goto unlock; 744 goto unlock;
745 745
746 memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); 746 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
747 local->int_scan_req.ssids[0].ssid_len = ssid_len; 747 local->int_scan_req->ssids[0].ssid_len = ssid_len;
748 748
749 ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); 749 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
750 unlock: 750 unlock:
751 mutex_unlock(&local->scan_mtx); 751 mutex_unlock(&local->scan_mtx);
752 return ret; 752 return ret;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b3d5c1df08dd..667a87d307da 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3002,10 +3002,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3002 goto out; 3002 goto out;
3003 } 3003 }
3004 3004
3005 request->channels = (void *)((char *)request + sizeof(*request));
3006 request->n_channels = n_channels; 3005 request->n_channels = n_channels;
3007 if (n_ssids) 3006 if (n_ssids)
3008 request->ssids = (void *)(request->channels + n_channels); 3007 request->ssids = (void *)&request->channels[n_channels];
3009 request->n_ssids = n_ssids; 3008 request->n_ssids = n_ssids;
3010 if (ie_len) { 3009 if (ie_len) {
3011 if (request->ssids) 3010 if (request->ssids)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1bcb1312bd94..e6c1f11595da 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -612,8 +612,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
612 612
613 creq->wiphy = wiphy; 613 creq->wiphy = wiphy;
614 creq->dev = dev; 614 creq->dev = dev;
615 creq->ssids = (void *)(creq + 1); 615 /* SSIDs come after channels */
616 creq->channels = (void *)(creq->ssids + 1); 616 creq->ssids = (void *)&creq->channels[n_channels];
617 creq->n_channels = n_channels; 617 creq->n_channels = n_channels;
618 creq->n_ssids = 1; 618 creq->n_ssids = 1;
619 619
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 104b33e34d22..8e2ef54ea714 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -65,7 +65,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
65 if (!request) 65 if (!request)
66 return -ENOMEM; 66 return -ENOMEM;
67 67
68 request->channels = (void *)((char *)request + sizeof(*request));
69 if (wdev->conn->params.channel) 68 if (wdev->conn->params.channel)
70 request->channels[0] = wdev->conn->params.channel; 69 request->channels[0] = wdev->conn->params.channel;
71 else { 70 else {
@@ -82,7 +81,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
82 } 81 }
83 } 82 }
84 request->n_channels = n_channels; 83 request->n_channels = n_channels;
85 request->ssids = (void *)(request->channels + n_channels); 84 request->ssids = (void *)&request->channels[n_channels];
86 request->n_ssids = 1; 85 request->n_ssids = 1;
87 86
88 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid, 87 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,