From a67e899cf38ae542d1a028ccd021f9189f76fb74 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 May 2009 18:24:06 -0700 Subject: Bluetooth: Fix issue with sysfs handling for connections Due to a semantic changes in flush_workqueue() the current approach of synchronizing the sysfs handling for connections doesn't work anymore. The whole approach is actually fully broken and based on assumptions that are no longer valid. With the introduction of Simple Pairing support, the creation of low-level ACL links got changed. This change invalidates the reason why in the past two independent work queues have been used for adding/removing sysfs devices. The adding of the actual sysfs device is now postponed until the host controller successfully assigns an unique handle to that link. So the real synchronization happens inside the controller and not the host. The only left-over problem is that some internals of the sysfs device handling are not initialized ahead of time. This leaves potential access to invalid data and can cause various NULL pointer dereferences. To fix this a new function makes sure that all sysfs details are initialized when an connection attempt is made. The actual sysfs device is only registered when the connection has been successfully established. To avoid a race condition with the registration, the check if a device is registered has been moved into the removal work. As an extra protection two flush_work() calls are left in place to make sure a previous add/del work has been completed first. Based on a report by Marc Pignat Signed-off-by: Marcel Holtmann Tested-by: Justin P. Mattock Tested-by: Roger Quadros Tested-by: Marc Pignat --- net/bluetooth/hci_conn.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 375f4b4f7f79..61309b26f271 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -248,6 +248,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); + hci_conn_init_sysfs(conn); + tasklet_enable(&hdev->tx_task); return conn; -- cgit v1.2.3 From 384943ec1bb462e410390ad8f108ff1474cd882d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 8 May 2009 18:20:43 -0700 Subject: Bluetooth: Fix wrong module refcount when connection setup fails The module refcount is increased by hci_dev_hold() call in hci_conn_add() and decreased by hci_dev_put() call in del_conn(). In case the connection setup fails, hci_dev_put() is never called. Procedure to reproduce the issue: # hciconfig hci0 up # lsmod | grep btusb -> "used by" refcount = 1 # hcitool cc -> will get timeout # lsmod | grep btusb -> "used by" refcount = 2 # hciconfig hci0 down # lsmod | grep btusb -> "used by" refcount = 1 # rmmod btusb -> ERROR: Module btusb is in use The hci_dev_put() call got moved into del_conn() with the 2.6.25 kernel to fix an issue with hci_dev going away before hci_conn. However that change was wrong and introduced this problem. When calling hci_conn_del() it has to call hci_dev_put() after freeing the connection details. This handling should be fully symmetric. The execution of del_conn() is done in a work queue and needs it own calls to hci_dev_hold() and hci_dev_put() to ensure that the hci_dev stays until the connection cleanup has been finished. Based on a report by Bing Zhao Signed-off-by: Marcel Holtmann Tested-by: Bing Zhao --- net/bluetooth/hci_conn.c | 2 ++ net/bluetooth/hci_sysfs.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 61309b26f271..85a1c6be2db9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -292,6 +292,8 @@ int hci_conn_del(struct hci_conn *conn) hci_conn_del_sysfs(conn); + hci_dev_put(hdev); + return 0; } diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index a05d45eb3ba1..4cc3624bd22d 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -99,6 +99,8 @@ static void add_conn(struct work_struct *work) BT_ERR("Failed to register connection device"); return; } + + hci_dev_hold(hdev); } /* @@ -134,6 +136,7 @@ static void del_conn(struct work_struct *work) device_del(&conn->dev); put_device(&conn->dev); + hci_dev_put(hdev); } -- cgit v1.2.3 From 1b0336bb36f88976f1210a65b62f6a3e9578ee7b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 9 May 2009 12:04:08 -0700 Subject: Bluetooth: Don't use hci_acl_connect_cancel() for incoming connections The connection setup phase takes around 2 seconds or longer and in that time it is possible that the need for an ACL connection is no longer present. If that happens then, the connection attempt will be canceled. This only applies to outgoing connections, but currently it can also be triggered by incoming connection. Don't call hci_acl_connect_cancel() on incoming connection since these have to be either accepted or rejected in this state. Once they are successfully connected they need to be fully disconnected anyway. Also remove the wrong hci_acl_disconn() call for SCO and eSCO links since at this stage they can't be disconnected either, because the connection handle is still unknown. Based on a report by Johan Hedberg Signed-off-by: Marcel Holtmann Tested-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 85a1c6be2db9..fa47d5d84f5c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -171,10 +171,8 @@ static void hci_conn_timeout(unsigned long arg) switch (conn->state) { case BT_CONNECT: case BT_CONNECT2: - if (conn->type == ACL_LINK) + if (conn->type == ACL_LINK && conn->out) hci_acl_connect_cancel(conn); - else - hci_acl_disconn(conn, 0x13); break; case BT_CONFIG: case BT_CONNECTED: -- cgit v1.2.3