mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
wireless: Add missing locking to cfg80211_dev_rename
device_rename only performs useful and race free validity checking at the optional sysfs level so depending on it for all of the validity checking in cfg80211_dev_rename is racy. Instead implement all of the needed validity checking and locking in cfg80211_dev_rename. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
601ae7f25a
commit
2940bb69fd
@ -143,8 +143,11 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv)
|
|||||||
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
||||||
char *newname)
|
char *newname)
|
||||||
{
|
{
|
||||||
|
struct cfg80211_registered_device *drv;
|
||||||
int idx, taken = -1, result, digits;
|
int idx, taken = -1, result, digits;
|
||||||
|
|
||||||
|
mutex_lock(&cfg80211_drv_mutex);
|
||||||
|
|
||||||
/* prohibit calling the thing phy%d when %d is not its number */
|
/* prohibit calling the thing phy%d when %d is not its number */
|
||||||
sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
|
sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
|
||||||
if (taken == strlen(newname) && idx != rdev->idx) {
|
if (taken == strlen(newname) && idx != rdev->idx) {
|
||||||
@ -156,14 +159,30 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
|||||||
* deny the name if it is phy<idx> where <idx> is printed
|
* deny the name if it is phy<idx> where <idx> is printed
|
||||||
* without leading zeroes. taken == strlen(newname) here
|
* without leading zeroes. taken == strlen(newname) here
|
||||||
*/
|
*/
|
||||||
|
result = -EINVAL;
|
||||||
if (taken == strlen(PHY_NAME) + digits)
|
if (taken == strlen(PHY_NAME) + digits)
|
||||||
return -EINVAL;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this will check for collisions */
|
|
||||||
|
/* Ignore nop renames */
|
||||||
|
result = 0;
|
||||||
|
if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
/* Ensure another device does not already have this name. */
|
||||||
|
list_for_each_entry(drv, &cfg80211_drv_list, list) {
|
||||||
|
result = -EINVAL;
|
||||||
|
if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0)
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this will only check for collisions in sysfs
|
||||||
|
* which is not even always compiled in.
|
||||||
|
*/
|
||||||
result = device_rename(&rdev->wiphy.dev, newname);
|
result = device_rename(&rdev->wiphy.dev, newname);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
|
if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
|
||||||
rdev->wiphy.debugfsdir,
|
rdev->wiphy.debugfsdir,
|
||||||
@ -172,9 +191,13 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
|||||||
printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
|
printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
|
||||||
newname);
|
newname);
|
||||||
|
|
||||||
nl80211_notify_dev_rename(rdev);
|
result = 0;
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&cfg80211_drv_mutex);
|
||||||
|
if (result == 0)
|
||||||
|
nl80211_notify_dev_rename(rdev);
|
||||||
|
|
||||||
return 0;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exported functions */
|
/* exported functions */
|
||||||
|
Loading…
Reference in New Issue
Block a user