cfg80211: fix race between sysfs and cfg80211
RFC 1/1 cfg80211: fix race between sysfs and cfg80211
device_add() is called before adding the phy to the cfg80211 device list.
So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
An easy workaround is to hold the cfg80211 mutex until the phy is present both in sysfs and cfg80211 device list.
--- net/wireless/core.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
net/wireless/core.c +8 -4
@@ -472,15 +472,19 @@ int wiphy_register(struct wiphy *wiphy)/* check and set up bitrates */ ieee80211_set_bitrate_flags (wiphy); +mutex_lock (&cfg80211_mutex); + res =device_add (&rdev->wiphy.dev); -if (res) +if (res) { +mutex_unlock (&cfg80211_mutex);return res; + } res =rfkill_register (rdev->rfkill); -if (res) +if (res) { +mutex_unlock (&cfg80211_mutex); goto out_rm_dev; - -mutex_lock (&cfg80211_mutex); + }/* set up regulatory info */ wiphy_update_regulatory (wiphy,NL80211_REGDOM_SET_BY_CORE );
Signature · 6 lines
1.7.1 -- Maxime
Johannes Berg
maintainerQuoted 9 lines · Maxime Bizon
device_add()is called before adding the phy to the cfg80211 device list.So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
An easy workaround is to hold the cfg80211 mutex until the phy is present both in sysfs and cfg80211 device list.
Maybe we should hold the mutex around the debugfs stuff as well? Then tools could even access that race-free, and we can simplify the code by having an "out_unlock" label.
johannes
Quoted 3 lines · Johannes Berg
Maybe we should hold the mutex around the debugfs stuff as well? Then tools could even access that race-free, and we can simplify the code by having an "
out_unlock" label.
device_add() is called before adding the phy to the cfg80211 device list.
So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
An easy workaround is to hold the cfg80211 mutex until the phy is present both in sysfs and cfg80211 device list.
--- net/wireless/core.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
net/wireless/core.c +8 -6
@@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy)/* check and set up bitrates */ ieee80211_set_bitrate_flags (wiphy); +mutex_lock (&cfg80211_mutex); + res =device_add (&rdev->wiphy.dev);if (res) -return res; + goto out_unlock; res =rfkill_register (rdev->rfkill);if (res) goto out_rm_dev; -mutex_lock (&cfg80211_mutex); -/* set up regulatory info */ wiphy_update_regulatory (wiphy,NL80211_REGDOM_SET_BY_CORE );list_add_rcu (&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; -mutex_unlock (&cfg80211_mutex); -/* add to debugfs */ rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy),
@@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy) }cfg80211_debugfs_rdev_add (rdev); +mutex_unlock (&cfg80211_mutex);return 0 ; - out_rm_dev: +out_rm_dev:device_del (&rdev->wiphy.dev); + +out_unlock: +mutex_unlock (&cfg80211_mutex);return res; }EXPORT_SYMBOL (wiphy_register);
Signature · 7 lines
1.7.1 -- Maxime
On Sat, 2010-07-17 at 21:29 +0200, Johannes Berg wrote:
Hi Johannes,
Quoted 3 lines
Maybe we should hold the mutex around the debugfs stuff as well? Then tools could even access that race-free, and we can simplify the code by having an "
out_unlock" label.
Any comment on the last patch I sent ?
Thanks !
Signature · 1 line
Maxime
PATCH 1/1 cfg80211: fix race between sysfs and cfg80211
In reply to Johannes BergFrom: Maxime Bizon <[email protected]>
device_add() is called before adding the phy to the cfg80211 device list.
So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
An easy workaround is to hold the cfg80211 mutex until the phy is present in sysfs/cfg80211/debugfs.
--- net/wireless/core.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
net/wireless/core.c +8 -6
@@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy)/* check and set up bitrates */ ieee80211_set_bitrate_flags (wiphy); +mutex_lock (&cfg80211_mutex); + res =device_add (&rdev->wiphy.dev);if (res) -return res; + goto out_unlock; res =rfkill_register (rdev->rfkill);if (res) goto out_rm_dev; -mutex_lock (&cfg80211_mutex); -/* set up regulatory info */ wiphy_update_regulatory (wiphy,NL80211_REGDOM_SET_BY_CORE );list_add_rcu (&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; -mutex_unlock (&cfg80211_mutex); -/* add to debugfs */ rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy),
@@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy) }cfg80211_debugfs_rdev_add (rdev); +mutex_unlock (&cfg80211_mutex);return 0 ; - out_rm_dev: +out_rm_dev:device_del (&rdev->wiphy.dev); + +out_unlock: +mutex_unlock (&cfg80211_mutex);return res; }EXPORT_SYMBOL (wiphy_register);
Signature · 6 lines
1.7.1 -- Maxime
Quoted 9 lines · Maxime Bizon
From: Maxime Bizon <[email protected]>
device_add()is called before adding the phy to the cfg80211 device list.So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
Quoted 5 lines
An easy workaround is to hold the cfg80211 mutex until the phy is present in sysfs/cfg80211/debugfs.
Signed-off-by Maxime Bizon <[email protected]>---
You should resubmit as a new e-mail with a subject of [PATCH v2].
Luis
PATCH v2 1/1 cfg80211: fix race between sysfs and cfg80211
In reply to Johannes BergFrom: Maxime Bizon <[email protected]>
device_add() is called before adding the phy to the cfg80211 device list.
So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs.
An easy workaround is to hold the cfg80211 mutex until the phy is present in sysfs/cfg80211/debugfs.
--- net/wireless/core.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
net/wireless/core.c +8 -6
@@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy)/* check and set up bitrates */ ieee80211_set_bitrate_flags (wiphy); +mutex_lock (&cfg80211_mutex); + res =device_add (&rdev->wiphy.dev);if (res) -return res; + goto out_unlock; res =rfkill_register (rdev->rfkill);if (res) goto out_rm_dev; -mutex_lock (&cfg80211_mutex); -/* set up regulatory info */ wiphy_update_regulatory (wiphy,NL80211_REGDOM_SET_BY_CORE );list_add_rcu (&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; -mutex_unlock (&cfg80211_mutex); -/* add to debugfs */ rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy),
@@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy) }cfg80211_debugfs_rdev_add (rdev); +mutex_unlock (&cfg80211_mutex);return 0 ; - out_rm_dev: +out_rm_dev:device_del (&rdev->wiphy.dev); + +out_unlock: +mutex_unlock (&cfg80211_mutex);return res; }EXPORT_SYMBOL (wiphy_register);
Signature · 6 lines
1.7.1 -- Maxime
On Fri, 2010-07-23 at 04:29 +0200, Maxime Bizon wrote:
Hi,
Quoted 1 line
From: Maxime Bizon <[email protected]>
Any comment/ACK/NACK on this ?
Thanks,
Signature · 1 line
Maxime
Johannes Berg
maintainerQuoted 7 lines · Maxime Bizon
On Fri, 2010-07-23 at 04:29 +0200, Maxime Bizon wrote:
Hi,
Quoted 1 line
From: Maxime Bizon <[email protected]>
Any comment/ACK/NACK on this ?
Err, it was merged a long time ago
johannes
Quoted 1 line · Johannes Berg
Err, it was merged a long time ago
I'm hitting another race now, it appeared after I disabled CONFIG_CRYPTO_MANAGER_TESTS (new option in 2.6.35.2).
I have a userspace daemon that listen for new phy event, and create and configure an AP interface just after it gets the event.
The driver is still inside ieee80211_register_hw(), but the userspace is able to create the AP interface before the call is over. Once wiphy_register() is done, no lock seems to prevent this from happening.
ieee80211_init_rate_ctrl_alg() then fails with EBUSY, and ieee80211_register_hw() starts unregistering the phy.
Is that expected ?
I was able to get past it by taking rtnl lock before wiphy_register()
Signature · 1 line
Maxime
Johannes Berg
maintainerQuoted 8 lines · Maxime Bizon
The driver is still inside
ieee80211_register_hw(), but the userspace is able to create the AP interface before the call is over. Oncewiphy_register()is done, no lock seems to prevent this from happening.
ieee80211_init_rate_ctrl_alg()then fails with EBUSY, andieee80211_register_hw()starts unregistering the phy.Is that expected ?
Oops. No, not really, but I think the problem is that we do wiphy_register far too early. I think we should see if we can reorder the code in register_hw(). It won't be perfect wrt. debugfs, but I don't think that is a problem.
johannes