* SIOCGIWSCAN-race
@ 2009-02-21 7:33 Lars Ericsson
2009-02-23 21:11 ` SIOCGIWSCAN-race John W. Linville
0 siblings, 1 reply; 4+ messages in thread
From: Lars Ericsson @ 2009-02-21 7:33 UTC (permalink / raw)
To: 'Johannes Berg'; +Cc: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 960 bytes --]
Hi Johannes,
I have discovered and patched a race in the scanning function since a couple
of releases.
To day I checked the current Linux git and the problem is still there.
The problem is the sequence of events when the scan result is reported back.
The wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
is called before ieee80211_hw_config(local);
ieee80211_hw_config(local) will trig the wpa_supplicant to select an AP.
That may happen before the ieee80211_hw_config() is executed since the
wpa_supplicant
generated actions is executed by an other thread (wpa_supplicant).
The result is that:
- wpa_supplicant setup for an association to an ap using correct channel.
- ieee80211_hw_config() reset the channel to the value before the SCAN
started.
- the association request will be sent out using the wrong channel.
Attached you will find the patch for 2.6.27.
It is not a perfect patch since the code is duplicated but it works :)
Regards
Lars
[-- Attachment #2: lae-mac80211-mlme-SIOCGIWSCAN-race.patch --]
[-- Type: application/octet-stream, Size: 1264 bytes --]
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
old mode 100644
new mode 100755
index b404537..fd9e726
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3788,10 +3788,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
struct ieee80211_sub_if_data *sdata;
union iwreq_data wrqu;
- local->last_scan_completed = jiffies;
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
-
if (local->sta_hw_scanning) {
local->sta_hw_scanning = 0;
if (ieee80211_hw_config(local))
@@ -3803,6 +3799,10 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
ieee80211_restart_sta_timer(sdata);
rcu_read_unlock();
+ local->last_scan_completed = jiffies;
+ memset(&wrqu, 0, sizeof(wrqu));
+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+
goto done;
}
@@ -3811,6 +3811,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
printk(KERN_DEBUG "%s: failed to restore operational "
"channel after scan\n", dev->name);
+ local->last_scan_completed = jiffies;
+ memset(&wrqu, 0, sizeof(wrqu));
+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
netif_tx_lock_bh(local->mdev);
local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: SIOCGIWSCAN-race
2009-02-21 7:33 SIOCGIWSCAN-race Lars Ericsson
@ 2009-02-23 21:11 ` John W. Linville
2009-02-24 1:48 ` SIOCGIWSCAN-race Johannes Berg
0 siblings, 1 reply; 4+ messages in thread
From: John W. Linville @ 2009-02-23 21:11 UTC (permalink / raw)
To: Lars Ericsson; +Cc: 'Johannes Berg', linux-wireless
On Sat, Feb 21, 2009 at 08:33:06AM +0100, Lars Ericsson wrote:
> Hi Johannes,
>
> I have discovered and patched a race in the scanning function since a couple
> of releases.
> To day I checked the current Linux git and the problem is still there.
>
> The problem is the sequence of events when the scan result is reported back.
> The wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
> is called before ieee80211_hw_config(local);
>
> ieee80211_hw_config(local) will trig the wpa_supplicant to select an AP.
> That may happen before the ieee80211_hw_config() is executed since the
> wpa_supplicant
> generated actions is executed by an other thread (wpa_supplicant).
>
> The result is that:
> - wpa_supplicant setup for an association to an ap using correct channel.
> - ieee80211_hw_config() reset the channel to the value before the SCAN
> started.
> - the association request will be sent out using the wrong channel.
>
>
> Attached you will find the patch for 2.6.27.
> It is not a perfect patch since the code is duplicated but it works :)
Looks like the patch would need to be reworked -- the code in 2.6.29
and later is different. Also, any reason we can't just move the
wireless_send_event() down to done:?
Still, this doesn't feel quite right. Shouldn't we be able to queue
the userland-driven channel change until after the scan completes?
John
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f5c7c33..8c13a91 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -437,15 +437,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
local->last_scan_completed = jiffies;
memset(&wrqu, 0, sizeof(wrqu));
- /*
- * local->scan_sdata could have been NULLed by the interface
- * down code in case we were scanning on an interface that is
- * being taken down.
- */
- sdata = local->scan_sdata;
- if (sdata)
- wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
-
if (local->hw_scanning) {
local->hw_scanning = false;
/*
@@ -486,6 +477,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
rcu_read_unlock();
done:
+ /*
+ * local->scan_sdata could have been NULLed by the interface
+ * down code in case we were scanning on an interface that is
+ * being taken down.
+ */
+ sdata = local->scan_sdata;
+ if (sdata)
+ wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
+
ieee80211_mlme_notify_scan_completed(local);
ieee80211_mesh_notify_scan_completed(local);
}
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: SIOCGIWSCAN-race
2009-02-23 21:11 ` SIOCGIWSCAN-race John W. Linville
@ 2009-02-24 1:48 ` Johannes Berg
2009-02-24 5:55 ` SIOCGIWSCAN-race Lars Ericsson
0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2009-02-24 1:48 UTC (permalink / raw)
To: John W. Linville; +Cc: Lars Ericsson, linux-wireless
[-- Attachment #1: Type: text/plain, Size: 3062 bytes --]
On Mon, 2009-02-23 at 16:11 -0500, John W. Linville wrote:
> On Sat, Feb 21, 2009 at 08:33:06AM +0100, Lars Ericsson wrote:
> > Hi Johannes,
> >
> > I have discovered and patched a race in the scanning function since a couple
> > of releases.
> > To day I checked the current Linux git and the problem is still there.
> >
> > The problem is the sequence of events when the scan result is reported back.
> > The wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
> > is called before ieee80211_hw_config(local);
> >
> > ieee80211_hw_config(local) will trig the wpa_supplicant to select an AP.
> > That may happen before the ieee80211_hw_config() is executed since the
> > wpa_supplicant
> > generated actions is executed by an other thread (wpa_supplicant).
> >
> > The result is that:
> > - wpa_supplicant setup for an association to an ap using correct channel.
> > - ieee80211_hw_config() reset the channel to the value before the SCAN
> > started.
> > - the association request will be sent out using the wrong channel.
> >
> >
> > Attached you will find the patch for 2.6.27.
> > It is not a perfect patch since the code is duplicated but it works :)
>
> Looks like the patch would need to be reworked -- the code in 2.6.29
> and later is different.
and the new code with cfg80211 is even more different ;)
> Also, any reason we can't just move the
> wireless_send_event() down to done:?
seems fine
> Still, this doesn't feel quite right. Shouldn't we be able to queue
> the userland-driven channel change until after the scan completes?
?
we do that, well, we set it here:
local->sw_scanning = false;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
but we claim to be on the user requested channel at all times, so that
should be ok
johannes
> John
>
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index f5c7c33..8c13a91 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -437,15 +437,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
> local->last_scan_completed = jiffies;
> memset(&wrqu, 0, sizeof(wrqu));
>
> - /*
> - * local->scan_sdata could have been NULLed by the interface
> - * down code in case we were scanning on an interface that is
> - * being taken down.
> - */
> - sdata = local->scan_sdata;
> - if (sdata)
> - wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
> -
> if (local->hw_scanning) {
> local->hw_scanning = false;
> /*
> @@ -486,6 +477,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
> rcu_read_unlock();
>
> done:
> + /*
> + * local->scan_sdata could have been NULLed by the interface
> + * down code in case we were scanning on an interface that is
> + * being taken down.
> + */
> + sdata = local->scan_sdata;
> + if (sdata)
> + wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
> +
> ieee80211_mlme_notify_scan_completed(local);
> ieee80211_mesh_notify_scan_completed(local);
> }
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: SIOCGIWSCAN-race
2009-02-24 1:48 ` SIOCGIWSCAN-race Johannes Berg
@ 2009-02-24 5:55 ` Lars Ericsson
0 siblings, 0 replies; 4+ messages in thread
From: Lars Ericsson @ 2009-02-24 5:55 UTC (permalink / raw)
To: 'Johannes Berg', 'John W. Linville'; +Cc: linux-wireless
> On Mon, 2009-02-23 at 16:11 -0500, John W. Linville wrote:
> > On Sat, Feb 21, 2009 at 08:33:06AM +0100, Lars Ericsson wrote:
> > > Hi Johannes,
> > >
> > > I have discovered and patched a race in the scanning function since a
couple
> > > of releases.
> > > To day I checked the current Linux git and the problem is still there.
> > >
> > > The problem is the sequence of events when the scan result is reported
back.
> > > The wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
> > > is called before ieee80211_hw_config(local);
> > >
> > > ieee80211_hw_config(local) will trig the wpa_supplicant to select an
AP.
> > > That may happen before the ieee80211_hw_config() is executed since the
> > > wpa_supplicant
> > > generated actions is executed by an other thread (wpa_supplicant).
> > >
> > > The result is that:
> > > - wpa_supplicant setup for an association to an ap using correct
channel.
> > > - ieee80211_hw_config() reset the channel to the value before the SCAN
started.
> > > - the association request will be sent out using the wrong channel.
> > >
> > >
> > > Attached you will find the patch for 2.6.27.
> > > It is not a perfect patch since the code is duplicated but it works :)
> >
> > Looks like the patch would need to be reworked -- the code in 2.6.29
> > and later is different.
>
> and the new code with cfg80211 is even more different ;)
>
OK, I have not moved in to the 'cfg80211' world, yet.
Johannes; do you create the patch for this ?
> > Also, any reason we can't just move the
> > wireless_send_event() down to done:?
>
> seems fine
Perfect, is it to late for 2.6.29 ?
Lars
> > Still, this doesn't feel quite right. Shouldn't we be able to queue
> > the userland-driven channel change until after the scan completes?
>
> ?
> we do that, well, we set it here:
> local->sw_scanning = false;
> ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
>
> but we claim to be on the user requested channel at all times, so that
> should be ok
>
> johannes
>
> > John
> >
> > diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> > index f5c7c33..8c13a91 100644
> > --- a/net/mac80211/scan.c
> > +++ b/net/mac80211/scan.c
> > @@ -437,15 +437,6 @@ void ieee80211_scan_completed(struct
> ieee80211_hw *hw)
> > local->last_scan_completed = jiffies;
> > memset(&wrqu, 0, sizeof(wrqu));
> >
> > - /*
> > - * local->scan_sdata could have been NULLed by the interface
> > - * down code in case we were scanning on an interface that is
> > - * being taken down.
> > - */
> > - sdata = local->scan_sdata;
> > - if (sdata)
> > - wireless_send_event(sdata->dev, SIOCGIWSCAN,
> &wrqu, NULL);
> > -
> > if (local->hw_scanning) {
> > local->hw_scanning = false;
> > /*
> > @@ -486,6 +477,15 @@ void ieee80211_scan_completed(struct
> ieee80211_hw *hw)
> > rcu_read_unlock();
> >
> > done:
> > + /*
> > + * local->scan_sdata could have been NULLed by the interface
> > + * down code in case we were scanning on an interface that is
> > + * being taken down.
> > + */
> > + sdata = local->scan_sdata;
> > + if (sdata)
> > + wireless_send_event(sdata->dev, SIOCGIWSCAN,
> &wrqu, NULL);
> > +
> > ieee80211_mlme_notify_scan_completed(local);
> > ieee80211_mesh_notify_scan_completed(local);
> > }
> >
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-02-24 7:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-21 7:33 SIOCGIWSCAN-race Lars Ericsson
2009-02-23 21:11 ` SIOCGIWSCAN-race John W. Linville
2009-02-24 1:48 ` SIOCGIWSCAN-race Johannes Berg
2009-02-24 5:55 ` SIOCGIWSCAN-race Lars Ericsson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).