Showing error 1553

User: Jiri Slaby
Error type: Leaving function in locked state
Error type description: Some lock is not unlocked on all paths of a function, so it is leaked
File location: net/wireless/core.c
Line in file: 113
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2012-05-21 20:30:05 UTC


Source:

  1/*
  2 * This is the linux wireless configuration interface.
  3 *
  4 * Copyright 2006-2008                Johannes Berg <johannes@sipsolutions.net>
  5 */
  6
  7#include <linux/if.h>
  8#include <linux/module.h>
  9#include <linux/err.h>
 10#include <linux/mutex.h>
 11#include <linux/list.h>
 12#include <linux/nl80211.h>
 13#include <linux/debugfs.h>
 14#include <linux/notifier.h>
 15#include <linux/device.h>
 16#include <net/genetlink.h>
 17#include <net/cfg80211.h>
 18#include <net/wireless.h>
 19#include "nl80211.h"
 20#include "core.h"
 21#include "sysfs.h"
 22#include "reg.h"
 23
 24/* name for sysfs, %d is appended */
 25#define PHY_NAME "phy"
 26
 27MODULE_AUTHOR("Johannes Berg");
 28MODULE_LICENSE("GPL");
 29MODULE_DESCRIPTION("wireless configuration support");
 30
 31/* RCU might be appropriate here since we usually
 32 * only read the list, and that can happen quite
 33 * often because we need to do it for each command */
 34LIST_HEAD(cfg80211_drv_list);
 35DEFINE_MUTEX(cfg80211_drv_mutex);
 36
 37/* for debugfs */
 38static struct dentry *ieee80211_debugfs_dir;
 39
 40/* requires cfg80211_drv_mutex to be held! */
 41static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy)
 42{
 43        struct cfg80211_registered_device *result = NULL, *drv;
 44
 45        list_for_each_entry(drv, &cfg80211_drv_list, list) {
 46                if (drv->idx == wiphy) {
 47                        result = drv;
 48                        break;
 49                }
 50        }
 51
 52        return result;
 53}
 54
 55/* requires cfg80211_drv_mutex to be held! */
 56static struct cfg80211_registered_device *
 57__cfg80211_drv_from_info(struct genl_info *info)
 58{
 59        int ifindex;
 60        struct cfg80211_registered_device *bywiphy = NULL, *byifidx = NULL;
 61        struct net_device *dev;
 62        int err = -EINVAL;
 63
 64        if (info->attrs[NL80211_ATTR_WIPHY]) {
 65                bywiphy = cfg80211_drv_by_wiphy(
 66                                nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
 67                err = -ENODEV;
 68        }
 69
 70        if (info->attrs[NL80211_ATTR_IFINDEX]) {
 71                ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
 72                dev = dev_get_by_index(&init_net, ifindex);
 73                if (dev) {
 74                        if (dev->ieee80211_ptr)
 75                                byifidx =
 76                                        wiphy_to_dev(dev->ieee80211_ptr->wiphy);
 77                        dev_put(dev);
 78                }
 79                err = -ENODEV;
 80        }
 81
 82        if (bywiphy && byifidx) {
 83                if (bywiphy != byifidx)
 84                        return ERR_PTR(-EINVAL);
 85                else
 86                        return bywiphy; /* == byifidx */
 87        }
 88        if (bywiphy)
 89                return bywiphy;
 90
 91        if (byifidx)
 92                return byifidx;
 93
 94        return ERR_PTR(err);
 95}
 96
 97struct cfg80211_registered_device *
 98cfg80211_get_dev_from_info(struct genl_info *info)
 99{
100        struct cfg80211_registered_device *drv;
101
102        mutex_lock(&cfg80211_drv_mutex);
103        drv = __cfg80211_drv_from_info(info);
104
105        /* if it is not an error we grab the lock on
106         * it to assure it won't be going away while
107         * we operate on it */
108        if (!IS_ERR(drv))
109                mutex_lock(&drv->mtx);
110
111        mutex_unlock(&cfg80211_drv_mutex);
112
113        return drv;
114}
115
116struct cfg80211_registered_device *
117cfg80211_get_dev_from_ifindex(int ifindex)
118{
119        struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV);
120        struct net_device *dev;
121
122        mutex_lock(&cfg80211_drv_mutex);
123        dev = dev_get_by_index(&init_net, ifindex);
124        if (!dev)
125                goto out;
126        if (dev->ieee80211_ptr) {
127                drv = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
128                mutex_lock(&drv->mtx);
129        } else
130                drv = ERR_PTR(-ENODEV);
131        dev_put(dev);
132 out:
133        mutex_unlock(&cfg80211_drv_mutex);
134        return drv;
135}
136
137void cfg80211_put_dev(struct cfg80211_registered_device *drv)
138{
139        BUG_ON(IS_ERR(drv));
140        mutex_unlock(&drv->mtx);
141}
142
143int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
144                        char *newname)
145{
146        struct cfg80211_registered_device *drv;
147        int idx, taken = -1, result, digits;
148
149        mutex_lock(&cfg80211_drv_mutex);
150
151        /* prohibit calling the thing phy%d when %d is not its number */
152        sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
153        if (taken == strlen(newname) && idx != rdev->idx) {
154                /* count number of places needed to print idx */
155                digits = 1;
156                while (idx /= 10)
157                        digits++;
158                /*
159                 * deny the name if it is phy<idx> where <idx> is printed
160                 * without leading zeroes. taken == strlen(newname) here
161                 */
162                result = -EINVAL;
163                if (taken == strlen(PHY_NAME) + digits)
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;
178        }
179
180        /* this will only check for collisions in sysfs
181         * which is not even always compiled in.
182         */
183        result = device_rename(&rdev->wiphy.dev, newname);
184        if (result)
185                goto out_unlock;
186
187        if (rdev->wiphy.debugfsdir &&
188            !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
189                            rdev->wiphy.debugfsdir,
190                            rdev->wiphy.debugfsdir->d_parent,
191                            newname))
192                printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
193                       newname);
194
195        result = 0;
196out_unlock:
197        mutex_unlock(&cfg80211_drv_mutex);
198        if (result == 0)
199                nl80211_notify_dev_rename(rdev);
200
201        return result;
202}
203
204/* exported functions */
205
206struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
207{
208        static int wiphy_counter;
209
210        struct cfg80211_registered_device *drv;
211        int alloc_size;
212
213        WARN_ON(!ops->add_key && ops->del_key);
214        WARN_ON(ops->add_key && !ops->del_key);
215
216        alloc_size = sizeof(*drv) + sizeof_priv;
217
218        drv = kzalloc(alloc_size, GFP_KERNEL);
219        if (!drv)
220                return NULL;
221
222        drv->ops = ops;
223
224        mutex_lock(&cfg80211_drv_mutex);
225
226        drv->idx = wiphy_counter++;
227
228        if (unlikely(drv->idx < 0)) {
229                wiphy_counter--;
230                mutex_unlock(&cfg80211_drv_mutex);
231                /* ugh, wrapped! */
232                kfree(drv);
233                return NULL;
234        }
235
236        mutex_unlock(&cfg80211_drv_mutex);
237
238        /* give it a proper name */
239        snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
240                 PHY_NAME "%d", drv->idx);
241
242        mutex_init(&drv->mtx);
243        mutex_init(&drv->devlist_mtx);
244        INIT_LIST_HEAD(&drv->netdev_list);
245
246        device_initialize(&drv->wiphy.dev);
247        drv->wiphy.dev.class = &ieee80211_class;
248        drv->wiphy.dev.platform_data = drv;
249
250        return &drv->wiphy;
251}
252EXPORT_SYMBOL(wiphy_new);
253
254int wiphy_register(struct wiphy *wiphy)
255{
256        struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
257        int res;
258        enum ieee80211_band band;
259        struct ieee80211_supported_band *sband;
260        bool have_band = false;
261        int i;
262        u16 ifmodes = wiphy->interface_modes;
263
264        /* sanity check ifmodes */
265        WARN_ON(!ifmodes);
266        ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
267        if (WARN_ON(ifmodes != wiphy->interface_modes))
268                wiphy->interface_modes = ifmodes;
269
270        /* sanity check supported bands/channels */
271        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
272                sband = wiphy->bands[band];
273                if (!sband)
274                        continue;
275
276                sband->band = band;
277
278                if (!sband->n_channels || !sband->n_bitrates) {
279                        WARN_ON(1);
280                        return -EINVAL;
281                }
282
283                for (i = 0; i < sband->n_channels; i++) {
284                        sband->channels[i].orig_flags =
285                                sband->channels[i].flags;
286                        sband->channels[i].orig_mag =
287                                sband->channels[i].max_antenna_gain;
288                        sband->channels[i].orig_mpwr =
289                                sband->channels[i].max_power;
290                        sband->channels[i].band = band;
291                }
292
293                have_band = true;
294        }
295
296        if (!have_band) {
297                WARN_ON(1);
298                return -EINVAL;
299        }
300
301        /* check and set up bitrates */
302        ieee80211_set_bitrate_flags(wiphy);
303
304        /* set up regulatory info */
305        mutex_lock(&cfg80211_reg_mutex);
306        wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE);
307        mutex_unlock(&cfg80211_reg_mutex);
308
309        mutex_lock(&cfg80211_drv_mutex);
310
311        res = device_add(&drv->wiphy.dev);
312        if (res)
313                goto out_unlock;
314
315        list_add(&drv->list, &cfg80211_drv_list);
316
317        /* add to debugfs */
318        drv->wiphy.debugfsdir =
319                debugfs_create_dir(wiphy_name(&drv->wiphy),
320                                   ieee80211_debugfs_dir);
321        if (IS_ERR(drv->wiphy.debugfsdir))
322                drv->wiphy.debugfsdir = NULL;
323
324        res = 0;
325out_unlock:
326        mutex_unlock(&cfg80211_drv_mutex);
327        return res;
328}
329EXPORT_SYMBOL(wiphy_register);
330
331void wiphy_unregister(struct wiphy *wiphy)
332{
333        struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
334
335        /* protect the device list */
336        mutex_lock(&cfg80211_drv_mutex);
337
338        BUG_ON(!list_empty(&drv->netdev_list));
339
340        /*
341         * Try to grab drv->mtx. If a command is still in progress,
342         * hopefully the driver will refuse it since it's tearing
343         * down the device already. We wait for this command to complete
344         * before unlinking the item from the list.
345         * Note: as codified by the BUG_ON above we cannot get here if
346         * a virtual interface is still associated. Hence, we can only
347         * get to lock contention here if userspace issues a command
348         * that identified the hardware by wiphy index.
349         */
350        mutex_lock(&drv->mtx);
351        /* unlock again before freeing */
352        mutex_unlock(&drv->mtx);
353
354        list_del(&drv->list);
355        device_del(&drv->wiphy.dev);
356        debugfs_remove(drv->wiphy.debugfsdir);
357
358        mutex_unlock(&cfg80211_drv_mutex);
359}
360EXPORT_SYMBOL(wiphy_unregister);
361
362void cfg80211_dev_free(struct cfg80211_registered_device *drv)
363{
364        mutex_destroy(&drv->mtx);
365        mutex_destroy(&drv->devlist_mtx);
366        kfree(drv);
367}
368
369void wiphy_free(struct wiphy *wiphy)
370{
371        put_device(&wiphy->dev);
372}
373EXPORT_SYMBOL(wiphy_free);
374
375static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
376                                         unsigned long state,
377                                         void *ndev)
378{
379        struct net_device *dev = ndev;
380        struct cfg80211_registered_device *rdev;
381
382        if (!dev->ieee80211_ptr)
383                return 0;
384
385        rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
386
387        WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED);
388
389        switch (state) {
390        case NETDEV_REGISTER:
391                mutex_lock(&rdev->devlist_mtx);
392                list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
393                if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
394                                      "phy80211")) {
395                        printk(KERN_ERR "wireless: failed to add phy80211 "
396                                "symlink to netdev!\n");
397                }
398                dev->ieee80211_ptr->netdev = dev;
399                mutex_unlock(&rdev->devlist_mtx);
400                break;
401        case NETDEV_UNREGISTER:
402                mutex_lock(&rdev->devlist_mtx);
403                if (!list_empty(&dev->ieee80211_ptr->list)) {
404                        sysfs_remove_link(&dev->dev.kobj, "phy80211");
405                        list_del_init(&dev->ieee80211_ptr->list);
406                }
407                mutex_unlock(&rdev->devlist_mtx);
408                break;
409        }
410
411        return 0;
412}
413
414static struct notifier_block cfg80211_netdev_notifier = {
415        .notifier_call = cfg80211_netdev_notifier_call,
416};
417
418static int cfg80211_init(void)
419{
420        int err;
421
422        err = wiphy_sysfs_init();
423        if (err)
424                goto out_fail_sysfs;
425
426        err = register_netdevice_notifier(&cfg80211_netdev_notifier);
427        if (err)
428                goto out_fail_notifier;
429
430        err = nl80211_init();
431        if (err)
432                goto out_fail_nl80211;
433
434        ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
435
436        err = regulatory_init();
437        if (err)
438                goto out_fail_reg;
439
440        return 0;
441
442out_fail_reg:
443        debugfs_remove(ieee80211_debugfs_dir);
444out_fail_nl80211:
445        unregister_netdevice_notifier(&cfg80211_netdev_notifier);
446out_fail_notifier:
447        wiphy_sysfs_exit();
448out_fail_sysfs:
449        return err;
450}
451
452subsys_initcall(cfg80211_init);
453
454static void cfg80211_exit(void)
455{
456        debugfs_remove(ieee80211_debugfs_dir);
457        nl80211_exit();
458        unregister_netdevice_notifier(&cfg80211_netdev_notifier);
459        wiphy_sysfs_exit();
460        regulatory_exit();
461}
462module_exit(cfg80211_exit);