Bluetooth: Cleanup RFCOMM device registration error handling
authorPeter Hurley <peter@hurleysoftware.com>
Mon, 10 Feb 2014 01:59:20 +0000 (20:59 -0500)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 14 Feb 2014 21:39:32 +0000 (13:39 -0800)
If RFCOMM tty device registration fails, cleanup by releasing
the tty_port reference to trigger rfcomm_dev destruction
(rather than open-coding it).

The dlc reference release is moved into rfcomm_dev_add(),
which ensures cleanup in both error paths -- ie., if
__rfcomm_dev_add() fails or if tty_port_register_device() fails.

Fixes releasing the module reference if device registration fails.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Tested-By: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/rfcomm/tty.c

index 0537a0501595fb856dbfff4406590733005d77b5..375b60dae04dc2f80e078d395ae34d69558faa15 100644 (file)
@@ -93,7 +93,8 @@ static void rfcomm_dev_destruct(struct tty_port *port)
 
        rfcomm_dlc_put(dlc);
 
-       tty_unregister_device(rfcomm_tty_driver, dev->id);
+       if (dev->tty_dev)
+               tty_unregister_device(rfcomm_tty_driver, dev->id);
 
        spin_lock(&rfcomm_dev_lock);
        list_del(&dev->list);
@@ -317,16 +318,15 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
        BT_DBG("id %d channel %d", req->dev_id, req->channel);
 
        dev = __rfcomm_dev_add(req, dlc);
-       if (IS_ERR(dev))
+       if (IS_ERR(dev)) {
+               rfcomm_dlc_put(dlc);
                return PTR_ERR(dev);
+       }
 
        tty = tty_port_register_device(&dev->port, rfcomm_tty_driver,
                        dev->id, NULL);
        if (IS_ERR(tty)) {
-               spin_lock(&rfcomm_dev_lock);
-               list_del(&dev->list);
-               spin_unlock(&rfcomm_dev_lock);
-               kfree(dev);
+               tty_port_put(&dev->port);
                return PTR_ERR(tty);
        }
 
@@ -420,10 +420,8 @@ static int __rfcomm_create_dev(struct sock *sk, void __user *arg)
        }
 
        id = rfcomm_dev_add(&req, dlc);
-       if (id < 0) {
-               rfcomm_dlc_put(dlc);
+       if (id < 0)
                return id;
-       }
 
        if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
                /* DLC is now used by device.