diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2008-05-08 17:30:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-14 16:29:49 -0400 |
commit | 2940bb69fd84047e78fdb1868a8b894df5584255 (patch) | |
tree | 332a12ee08d6b7e974c545041a9e1aaf7dfba80d /net/wireless | |
parent | 601ae7f25aea58f208a7f640f6174aac0652403a (diff) |
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>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 80afacdae46..f1da0b93bc5 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -143,8 +143,11 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv) | |||
143 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | 143 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, |
144 | char *newname) | 144 | char *newname) |
145 | { | 145 | { |
146 | struct cfg80211_registered_device *drv; | ||
146 | int idx, taken = -1, result, digits; | 147 | int idx, taken = -1, result, digits; |
147 | 148 | ||
149 | mutex_lock(&cfg80211_drv_mutex); | ||
150 | |||
148 | /* prohibit calling the thing phy%d when %d is not its number */ | 151 | /* prohibit calling the thing phy%d when %d is not its number */ |
149 | sscanf(newname, PHY_NAME "%d%n", &idx, &taken); | 152 | sscanf(newname, PHY_NAME "%d%n", &idx, &taken); |
150 | if (taken == strlen(newname) && idx != rdev->idx) { | 153 | if (taken == strlen(newname) && idx != rdev->idx) { |
@@ -156,14 +159,30 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
156 | * deny the name if it is phy<idx> where <idx> is printed | 159 | * deny the name if it is phy<idx> where <idx> is printed |
157 | * without leading zeroes. taken == strlen(newname) here | 160 | * without leading zeroes. taken == strlen(newname) here |
158 | */ | 161 | */ |
162 | result = -EINVAL; | ||
159 | if (taken == strlen(PHY_NAME) + digits) | 163 | if (taken == strlen(PHY_NAME) + digits) |
160 | return -EINVAL; | 164 | goto out_unlock; |
165 | } | ||
166 | |||
167 | |||
168 | /* Ignore nop renames */ | ||
169 | result = 0; | ||
170 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) | ||
171 | goto out_unlock; | ||
172 | |||
173 | /* Ensure another device does not already have this name. */ | ||
174 | list_for_each_entry(drv, &cfg80211_drv_list, list) { | ||
175 | result = -EINVAL; | ||
176 | if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0) | ||
177 | goto out_unlock; | ||
161 | } | 178 | } |
162 | 179 | ||
163 | /* this will check for collisions */ | 180 | /* this will only check for collisions in sysfs |
181 | * which is not even always compiled in. | ||
182 | */ | ||
164 | result = device_rename(&rdev->wiphy.dev, newname); | 183 | result = device_rename(&rdev->wiphy.dev, newname); |
165 | if (result) | 184 | if (result) |
166 | return result; | 185 | goto out_unlock; |
167 | 186 | ||
168 | if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, | 187 | if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, |
169 | rdev->wiphy.debugfsdir, | 188 | rdev->wiphy.debugfsdir, |
@@ -172,9 +191,13 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
172 | printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", | 191 | printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", |
173 | newname); | 192 | newname); |
174 | 193 | ||
175 | nl80211_notify_dev_rename(rdev); | 194 | result = 0; |
195 | out_unlock: | ||
196 | mutex_unlock(&cfg80211_drv_mutex); | ||
197 | if (result == 0) | ||
198 | nl80211_notify_dev_rename(rdev); | ||
176 | 199 | ||
177 | return 0; | 200 | return result; |
178 | } | 201 | } |
179 | 202 | ||
180 | /* exported functions */ | 203 | /* exported functions */ |