From 63044e9f54b6bac50d2380bf4d14f63e9e7de72b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Oct 2008 12:04:29 +0200 Subject: mac80211: fix debugfs lockup When debugfs_create_dir fails, sta_info_debugfs_add_work will not terminate because it will find the same station again and again. This is possible whenever debugfs fails for whatever reason; one reason is a race condition in mac80211, unfortunately we cannot do much about it, so just document it, it just means some station may be missing from debugfs. Signed-off-by: Johannes Berg Cc: Robin Holt Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 11 +++++++++++ net/mac80211/sta_info.c | 7 ++++++- net/mac80211/sta_info.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index b9902e425f09..189d0bafa91a 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -249,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DECLARE_MAC_BUF(mbuf); u8 *mac; + sta->debugfs.add_has_run = true; + if (!stations_dir) return; mac = print_mac(mbuf, sta->sta.addr); + /* + * This might fail due to a race condition: + * When mac80211 unlinks a station, the debugfs entries + * remain, but it is already possible to link a new + * station with the same address which triggers adding + * it to debugfs; therefore, if the old station isn't + * destroyed quickly enough the old station's debugfs + * dir might still be around. + */ sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); if (!sta->debugfs.dir) return; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 9b72d15bc8dc..7fef8ea1f5ec 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -635,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work) spin_lock_irqsave(&local->sta_lock, flags); list_for_each_entry(tmp, &local->sta_list, list) { - if (!tmp->debugfs.dir) { + /* + * debugfs.add_has_run will be set by + * ieee80211_sta_debugfs_add regardless + * of what else it does. + */ + if (!tmp->debugfs.add_has_run) { sta = tmp; __sta_info_pin(sta); break; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a6b51862a89d..168a39a298bd 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -300,6 +300,7 @@ struct sta_info { struct dentry *inactive_ms; struct dentry *last_seq_ctrl; struct dentry *agg_status; + bool add_has_run; } debugfs; #endif -- cgit v1.2.3 From 09914813da37f1ee9d77998a0701629cfbbd98f4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Oct 2008 19:31:17 +0200 Subject: mac80211: fix HT information element parsing There's no checking that the HT IEs are of the right length which can be used by an attacker to cause an out-of-bounds access by sending a too short HT information/capability IE. Fix it by simply pretending those IEs didn't exist when too short. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 6 ++---- net/mac80211/mlme.c | 3 --- net/mac80211/util.c | 8 ++++---- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8025b294588b..156e42a003ae 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -816,8 +816,8 @@ struct ieee802_11_elems { u8 *ext_supp_rates; u8 *wmm_info; u8 *wmm_param; - u8 *ht_cap_elem; - u8 *ht_info_elem; + struct ieee80211_ht_cap *ht_cap_elem; + struct ieee80211_ht_addt_info *ht_info_elem; u8 *mesh_config; u8 *mesh_id; u8 *peer_link; @@ -844,8 +844,6 @@ struct ieee802_11_elems { u8 ext_supp_rates_len; u8 wmm_info_len; u8 wmm_param_len; - u8 ht_cap_elem_len; - u8 ht_info_elem_len; u8 mesh_config_len; u8 mesh_id_len; u8 peer_link_len; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 49f86fa56bff..87665d7bb4f9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1348,10 +1348,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { struct ieee80211_ht_bss_info bss_info; ieee80211_ht_cap_ie_to_ht_info( - (struct ieee80211_ht_cap *) elems.ht_cap_elem, &sta->sta.ht_info); ieee80211_ht_addt_info_ie_to_ht_bss_info( - (struct ieee80211_ht_addt_info *) elems.ht_info_elem, &bss_info); ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); } @@ -1709,7 +1707,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_ht_bss_info bss_info; ieee80211_ht_addt_info_ie_to_ht_bss_info( - (struct ieee80211_ht_addt_info *) elems.ht_info_elem, &bss_info); changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, &bss_info); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f32561ec224c..cee4884b9d06 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -529,12 +529,12 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->ext_supp_rates_len = elen; break; case WLAN_EID_HT_CAPABILITY: - elems->ht_cap_elem = pos; - elems->ht_cap_elem_len = elen; + if (elen >= sizeof(struct ieee80211_ht_cap)) + elems->ht_cap_elem = (void *)pos; break; case WLAN_EID_HT_EXTRA_INFO: - elems->ht_info_elem = pos; - elems->ht_info_elem_len = elen; + if (elen >= sizeof(struct ieee80211_ht_addt_info)) + elems->ht_info_elem = (void *)pos; break; case WLAN_EID_MESH_ID: elems->mesh_id = pos; -- cgit v1.2.3 From c74e90a9e37c4a3923905189a6ebbd7ef61e6e67 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Oct 2008 10:18:36 +0200 Subject: mac80211: fix debugfs netdev rename If, for some reason, a netdev has no debugfs dir, we shouldn't try to rename that dir. Signed-off-by: Johannes Berg Cc: Robin Holt Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 2a4515623776..2ad504fc3414 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -545,8 +545,12 @@ static int netdev_notify(struct notifier_block *nb, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sprintf(buf, "netdev:%s", dev->name); dir = sdata->debugfsdir; + + if (!dir) + return 0; + + sprintf(buf, "netdev:%s", dev->name); if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " "dir to %s\n", buf); -- cgit v1.2.3 From 33c0360bf74d5fded34cb08d3512ada32ad661e4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Oct 2008 10:23:48 +0200 Subject: cfg80211: fix debugfs error handling If something goes wrong creating the debugfs dir or when debugfs is not compiled in, the current code might lead to trouble; make it more robust. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/wireless/core.c b/net/wireless/core.c index 24fdd4cd22cb..5031db7b275b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -184,7 +184,8 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, if (result) goto out_unlock; - if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, + if (rdev->wiphy.debugfsdir && + !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, rdev->wiphy.debugfsdir, rdev->wiphy.debugfsdir->d_parent, newname)) @@ -317,6 +318,8 @@ int wiphy_register(struct wiphy *wiphy) drv->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&drv->wiphy), ieee80211_debugfs_dir); + if (IS_ERR(drv->wiphy.debugfsdir)) + drv->wiphy.debugfsdir = NULL; res = 0; out_unlock: -- cgit v1.2.3 From d048e503a2b01e771ee87921c24d89d7ec3f0c2f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 11 Oct 2008 03:29:55 +0300 Subject: mac80211: Fix scan RX processing oops ieee80211_bss_info_update() can return NULL. Verify that this is not the case before calling ieee802111_rx_bss_put() which would trigger an oops in interrupt context in atomic_dec_and_lock(). Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Acked-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8e6685e7ae85..416bb41099f3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -388,7 +388,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, bss = ieee80211_bss_info_update(sdata->local, rx_status, mgmt, skb->len, &elems, freq, beacon); - ieee80211_rx_bss_put(sdata->local, bss); + if (bss) + ieee80211_rx_bss_put(sdata->local, bss); dev_kfree_skb(skb); return RX_QUEUED; -- cgit v1.2.3 From 4233df6b748193d45f79fb7448991a473061a65d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 13 Oct 2008 13:35:05 +0200 Subject: ath9k/mac80211: disallow fragmentation in ath9k, report to userspace As I've reported, ath9k currently fails utterly when fragmentation is enabled. This makes ath9k "support" hardware fragmentation by not supporting fragmentation at all to avoid the double-free issue. The patch also changes mac80211 to report errors from the driver operation to userspace. That hack in ath9k should be removed once the rate control algorithm it has is fixed, and we can at that time consider removing the hw fragmentation support entirely since it's not used by any driver. Signed-off-by: Johannes Berg Cc: stable@kernel.org Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7e0d53abde24..742f811ca416 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -775,7 +775,7 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, * configure it here */ if (local->ops->set_frag_threshold) - local->ops->set_frag_threshold( + return local->ops->set_frag_threshold( local_to_hw(local), local->fragmentation_threshold); -- cgit v1.2.3