From 045cfb71a3901005bf6dcedae98cecb3360a0bfc Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 7 Jan 2010 15:01:42 +0100 Subject: mac80211: fix queue selection for packets injected via monitor interface Commit 'mac80211: fix skb buffering issue' added an ->ndo_select_queue() for monitor interfaces which can end up dereferencing ieee802_1d_to_ac[] beyond the end of the array for injected data packets (as skb->priority isn't guaranteed to be zero or within [0:7]), which then triggers the WARN_ON in net/core/dev.c:dev_cap_txqueue(). Fix this by always setting the priority to zero on injected data frames. Signed-off-by: Lennert Buytenhek Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ff762ed34f1e..44188ef80a63 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -685,6 +685,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, return ieee802_1d_to_ac[skb->priority]; } + skb->priority = 0; return ieee80211_downgrade_queue(local, skb); } -- cgit v1.2.3 From d79074488083ec0d7ecd15352192dc1631f25643 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 7 Jan 2010 20:23:53 +0100 Subject: mac80211: add missing sanity checks for action frames Various missing sanity checks caused rejected action frames to be interpreted as channel switch announcements, which can cause a client mode interface to switch away from its operating channel, thereby losing connectivity. This patch ensures that only spectrum management action frames are processed by the CSA handling function and prevents rejected action frames from getting processed by the MLME code. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 +++- net/mac80211/rx.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3e1eab963b8e..05a18f43e1bf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1963,7 +1963,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - /* XXX: differentiate, can only happen for CSA now! */ + if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) + break; + ieee80211_sta_process_chanswitch(sdata, &mgmt->u.action.u.chan_switch.sw_elem, ifmgd->associated); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 54296999834b..82a30c1bf3ab 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2015,6 +2015,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; default: + /* do not process rejected action frames */ + if (mgmt->u.action.category & 0x80) + return RX_DROP_MONITOR; + return RX_CONTINUE; } -- cgit v1.2.3 From b49bb574e44226b332c28439999d196ddec2f643 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 8 Jan 2010 19:00:00 +0100 Subject: mac80211: fix endian error I forgot to convert the radiotap length to CPU endian, which sparse found thankfully. Signed-off-by: Johannes Berg Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/iface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 44188ef80a63..d62ec0803bec 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -675,10 +675,10 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, return 0; if (skb->len < 4 || - skb->len < rtap->it_len + 2 /* frame control */) + skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) return 0; /* doesn't matter, frame will be dropped */ - hdr = (void *)((u8 *)skb->data + rtap->it_len); + hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); if (!ieee80211_is_data(hdr->frame_control)) { skb->priority = 7; -- cgit v1.2.3 From 193e70ef65a6c33f2935ce1f4adeb08ecb9202cf Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Jan 2010 06:47:00 +0100 Subject: mac80211: fix queue selection for data frames on monitor interfaces When ieee80211_monitor_select_queue encounters data frames, it selects the WMM AC based on skb->priority and assumes that skb->priority contains a valid 802.1d tag. However this assumption is incorrect, since ieee80211_select_queue has not been called at this point. If skb->priority > 7, an array overrun occurs, which could lead to invalid values, resulting in crashes in the tx path. Fix this by setting skb->priority based on the 802.11 header for QoS frames and using the default AC for all non-QoS frames. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/iface.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d62ec0803bec..32abae3ce32a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -670,6 +670,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct ieee80211_local *local = sdata->local; struct ieee80211_hdr *hdr; struct ieee80211_radiotap_header *rtap = (void *)skb->data; + u8 *p; if (local->hw.queues < 4) return 0; @@ -680,12 +681,14 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); - if (!ieee80211_is_data(hdr->frame_control)) { + if (!ieee80211_is_data_qos(hdr->frame_control)) { skb->priority = 7; return ieee802_1d_to_ac[skb->priority]; } - skb->priority = 0; + p = ieee80211_get_qos_ctl(hdr); + skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; + return ieee80211_downgrade_queue(local, skb); } -- cgit v1.2.3 From 8c5d9808e95739c9001b852464fd58fd0f583280 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 11 Jan 2010 16:14:57 +0100 Subject: cfg80211: fix refcount imbalance when wext is disabled When CONFIG_CFG80211_WEXT is not set, there is a refcount imbalance with rdev->opencount, fix that by moving it out of the ifdef. Reported-by: Alan Stern Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/wireless/core.c b/net/wireless/core.c index c2a2c563d21a..92b812442488 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -745,9 +745,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, mutex_unlock(&rdev->devlist_mtx); dev_put(dev); } -#ifdef CONFIG_CFG80211_WEXT cfg80211_lock_rdev(rdev); mutex_lock(&rdev->devlist_mtx); +#ifdef CONFIG_CFG80211_WEXT wdev_lock(wdev); switch (wdev->iftype) { case NL80211_IFTYPE_ADHOC: @@ -760,10 +760,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, break; } wdev_unlock(wdev); +#endif rdev->opencount++; mutex_unlock(&rdev->devlist_mtx); cfg80211_unlock_rdev(rdev); -#endif break; case NETDEV_UNREGISTER: /* -- cgit v1.2.3 From 5f6120335c701ba07d5151206071f4d6ccaa684f Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 13 Jan 2010 13:23:14 -0800 Subject: cfg80211: fix channel setting for wext Patch fixes the bug at http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2139 Currently we cannot set the channel using wext extension if we have already associated and disconnected. As cfg80211_mgd_wext_siwfreq will not switch the channel if ssid is set. This fixes it by clearing the ssid. Following is the sequence which it tries to fix. modprobe iwlagn iwconfig wlan0 essid "" ifconfig wlan0 down iwconfig wlan0 chan X wext is marked as deprecate.If we use nl80211 we can easily play with setting the channel. Signed-off-by: Abhijeet Kolekar Acked-by: Samuel Ortiz cc: stable@kernel.org Signed-off-by: John W. Linville --- net/wireless/sme.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 2333d78187e4..dc0fc4989d54 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -655,6 +655,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wdev->wext.connect.ssid_len = 0; #endif } -- cgit v1.2.3 From e5de30c9bf4a39db9f54c4a373470ce65881ade0 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Fri, 15 Jan 2010 12:21:37 +0100 Subject: mac80211: check that ieee80211_set_power_mgmt only handles STA interfaces. ieee80211_set_power_mgmt is meant for STA interfaces only. Moreover, since sdata->u.mgd.mtx is only initialized for STA interfaces, using this code for any other type of interface (like creating a monitor interface) will result in a oops. Cc: stable@kernel.org Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6dc3579c0ac5..9ae1a4760b58 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1331,6 +1331,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_conf *conf = &local->hw.conf; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) return -EOPNOTSUPP; -- cgit v1.2.3 From e850f68b8f27a76c4377c34f2e216b8e7e10db3d Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 16 Jan 2010 14:36:52 -0500 Subject: mac80211: fix sign error in pid controller While testing the pid rate controller in mac80211_hwsim, I noticed that once the controller reached 54 Mbit rates, it would fail to lower the rate when necessary. The debug log shows: 1945 186786 pf_sample 50 3534 3577 50 My interpretation is that the fixed point scaling of the target error value (pf) is incorrect: the error value of 50 compared to a target of 14 case should result in a scaling value of (14-50) = -36 * 256 or -9216, but instead it is (14 * 256)-50, or 3534. Correct this by doing fixed point scaling after subtraction. Signed-off-by: Bob Copeland Acked-by: Stefano Brivio Acked-by: Mattias Nissler Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_algo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 699d3ed869c4..29bc4c516238 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -190,7 +190,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, rate_control_pid_normalize(pinfo, sband->n_bitrates); /* Compute the proportional, integral and derivative errors. */ - err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; + err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT; err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; -- cgit v1.2.3