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
1 changed files with 28 additions and 5 deletions
|
@ -143,8 +143,11 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv)
|
|||
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
||||
char *newname)
|
||||
{
|
||||
struct cfg80211_registered_device *drv;
|
||||
int idx, taken = -1, result, digits;
|
||||
|
||||
mutex_lock(&cfg80211_drv_mutex);
|
||||
|
||||
/* prohibit calling the thing phy%d when %d is not its number */
|
||||
sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
|
||||
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
|
||||
* without leading zeroes. taken == strlen(newname) here
|
||||
*/
|
||||
result = -EINVAL;
|
||||
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);
|
||||
if (result)
|
||||
return result;
|
||||
goto out_unlock;
|
||||
|
||||
if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
|
||||
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",
|
||||
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 */
|
||||
|
|
Loading…
Reference in a new issue