]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
NFC: fix broken device allocation
authorJohan Hovold <johan@kernel.org>
Thu, 30 Mar 2017 10:15:35 +0000 (12:15 +0200)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Fri, 11 Aug 2017 10:37:25 +0000 (12:37 +0200)
BugLink: http://bugs.launchpad.net/bugs/1707233
commit 20777bc57c346b6994f465e0d8261a7fbf213a09 upstream.

Commit 7eda8b8e9677 ("NFC: Use IDR library to assing NFC devices IDs")
moved device-id allocation and struct-device initialisation from
nfc_allocate_device() to nfc_register_device().

This broke just about every nfc-device-registration error path, which
continue to call nfc_free_device() that tries to put the device
reference of the now uninitialised (but zeroed) struct device:

kobject: '(null)' (ce316420): is not initialized, yet kobject_put() is being called.

The late struct-device initialisation also meant that various work
queues whose names are derived from the nfc device name were also
misnamed:

  421 root         0 SW<  [(null)_nci_cmd_]
  422 root         0 SW<  [(null)_nci_rx_w]
  423 root         0 SW<  [(null)_nci_tx_w]

Move the id-allocation and struct-device initialisation back to
nfc_allocate_device() and fix up the single call site which did not use
nfc_free_device() in its error path.

Fixes: 7eda8b8e9677 ("NFC: Use IDR library to assing NFC devices IDs")
Cc: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
net/nfc/core.c
net/nfc/nci/core.c

index 1fe3d3b362c0cdce72d8317488e8b1fc4d58ea1d..c5a2c7e733b3a68ab30ae1e9abd5ce81bdd7c6f0 100644 (file)
@@ -969,6 +969,8 @@ static void nfc_release(struct device *d)
                        kfree(se);
        }
 
+       ida_simple_remove(&nfc_index_ida, dev->idx);
+
        kfree(dev);
 }
 
@@ -1043,6 +1045,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
                                    int tx_headroom, int tx_tailroom)
 {
        struct nfc_dev *dev;
+       int rc;
 
        if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
            !ops->deactivate_target || !ops->im_transceive)
@@ -1055,6 +1058,15 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
        if (!dev)
                return NULL;
 
+       rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
+       if (rc < 0)
+               goto err_free_dev;
+       dev->idx = rc;
+
+       dev->dev.class = &nfc_class;
+       dev_set_name(&dev->dev, "nfc%d", dev->idx);
+       device_initialize(&dev->dev);
+
        dev->ops = ops;
        dev->supported_protocols = supported_protocols;
        dev->tx_headroom = tx_headroom;
@@ -1077,6 +1089,11 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
        }
 
        return dev;
+
+err_free_dev:
+       kfree(dev);
+
+       return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(nfc_allocate_device);
 
@@ -1091,14 +1108,6 @@ int nfc_register_device(struct nfc_dev *dev)
 
        pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
-       dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
-       if (dev->idx < 0)
-               return dev->idx;
-
-       dev->dev.class = &nfc_class;
-       dev_set_name(&dev->dev, "nfc%d", dev->idx);
-       device_initialize(&dev->dev);
-
        mutex_lock(&nfc_devlist_mutex);
        nfc_devlist_generation++;
        rc = device_add(&dev->dev);
@@ -1136,12 +1145,10 @@ EXPORT_SYMBOL(nfc_register_device);
  */
 void nfc_unregister_device(struct nfc_dev *dev)
 {
-       int rc, id;
+       int rc;
 
        pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
-       id = dev->idx;
-
        if (dev->rfkill) {
                rfkill_unregister(dev->rfkill);
                rfkill_destroy(dev->rfkill);
@@ -1166,8 +1173,6 @@ void nfc_unregister_device(struct nfc_dev *dev)
        nfc_devlist_generation++;
        device_del(&dev->dev);
        mutex_unlock(&nfc_devlist_mutex);
-
-       ida_simple_remove(&nfc_index_ida, id);
 }
 EXPORT_SYMBOL(nfc_unregister_device);
 
index 10c99a5784212c92f7fa6ee69a43518ba89dc17c..67583ad7f6102408f3651911cda52492b29fea6b 100644 (file)
@@ -1084,8 +1084,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
        return ndev;
 
 free_nfc:
-       kfree(ndev->nfc_dev);
-
+       nfc_free_device(ndev->nfc_dev);
 free_nci:
        kfree(ndev);
        return NULL;