aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-10-11 14:46:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-11 14:46:52 -0400
commit7623225f905263424c7254dc6a07bff083a498dd (patch)
tree804b483a7aa2c2ad373fbe2e9b30844dea5c886c /net/wireless/core.c
parentd86a4f2dd4ec554cf3346f4cab763925761c4095 (diff)
Revert "wireless: Use first phyX name available when registering phy devices."
This reverts commit 5a254ffe3ffdfa84fe076009bd8e88da412180d2. The commit failed to take into account that allocated wireless devices (wiphys) are not added into the device list upon allocation, but only when they are registered. Therefore, it opened up a race between allocating and registering a name, so that if two processes allocate and register concurrently ("alloc, alloc, register, register" rather than "alloc, register, alloc, register") the code will attempt to use the same name twice. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c54
1 files changed, 24 insertions, 30 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 1684ad91763c..9c21ebf9780e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -178,10 +178,26 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
178 char *newname) 178 char *newname)
179{ 179{
180 struct cfg80211_registered_device *rdev2; 180 struct cfg80211_registered_device *rdev2;
181 int result; 181 int wiphy_idx, taken = -1, result, digits;
182 182
183 assert_cfg80211_lock(); 183 assert_cfg80211_lock();
184 184
185 /* prohibit calling the thing phy%d when %d is not its number */
186 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
187 if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
188 /* count number of places needed to print wiphy_idx */
189 digits = 1;
190 while (wiphy_idx /= 10)
191 digits++;
192 /*
193 * deny the name if it is phy<idx> where <idx> is printed
194 * without leading zeroes. taken == strlen(newname) here
195 */
196 if (taken == strlen(PHY_NAME) + digits)
197 return -EINVAL;
198 }
199
200
185 /* Ignore nop renames */ 201 /* Ignore nop renames */
186 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) 202 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
187 return 0; 203 return 0;
@@ -189,7 +205,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
189 /* Ensure another device does not already have this name. */ 205 /* Ensure another device does not already have this name. */
190 list_for_each_entry(rdev2, &cfg80211_rdev_list, list) 206 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
191 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) 207 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
192 return -EEXIST; 208 return -EINVAL;
193 209
194 result = device_rename(&rdev->wiphy.dev, newname); 210 result = device_rename(&rdev->wiphy.dev, newname);
195 if (result) 211 if (result)
@@ -304,11 +320,9 @@ static void cfg80211_event_work(struct work_struct *work)
304struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) 320struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
305{ 321{
306 static int wiphy_counter; 322 static int wiphy_counter;
307 int i; 323
308 struct cfg80211_registered_device *rdev, *rdev2; 324 struct cfg80211_registered_device *rdev;
309 int alloc_size; 325 int alloc_size;
310 char nname[IFNAMSIZ + 1];
311 bool found = false;
312 326
313 WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); 327 WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
314 WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); 328 WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
@@ -332,37 +346,17 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
332 346
333 if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { 347 if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) {
334 wiphy_counter--; 348 wiphy_counter--;
335 goto too_many_devs;
336 }
337
338 /* 64k wiphy devices is enough for anyone! */
339 for (i = 0; i < 0xFFFF; i++) {
340 found = false;
341 snprintf(nname, sizeof(nname)-1, PHY_NAME "%d", i);
342 nname[sizeof(nname)-1] = 0;
343 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
344 if (strcmp(nname, dev_name(&rdev2->wiphy.dev)) == 0) {
345 found = true;
346 break;
347 }
348
349 if (!found)
350 break;
351 }
352
353 if (unlikely(found)) {
354too_many_devs:
355 mutex_unlock(&cfg80211_mutex); 349 mutex_unlock(&cfg80211_mutex);
356 /* ugh, too many devices already! */ 350 /* ugh, wrapped! */
357 kfree(rdev); 351 kfree(rdev);
358 return NULL; 352 return NULL;
359 } 353 }
360 354
361 /* give it a proper name */
362 dev_set_name(&rdev->wiphy.dev, "%s", nname);
363
364 mutex_unlock(&cfg80211_mutex); 355 mutex_unlock(&cfg80211_mutex);
365 356
357 /* give it a proper name */
358 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
359
366 mutex_init(&rdev->mtx); 360 mutex_init(&rdev->mtx);
367 mutex_init(&rdev->devlist_mtx); 361 mutex_init(&rdev->devlist_mtx);
368 INIT_LIST_HEAD(&rdev->netdev_list); 362 INIT_LIST_HEAD(&rdev->netdev_list);