From: David Herrmann <dh.herrm...@gmail.com>

3.12-stable review patch.  If anyone has any objections, please let me know.

===============

commit 660f0fc07d21114549c1862e67e78b1cf0c90c29 upstream.

The HIDP specs define an idle-timeout which automatically disconnects a
device. This has always been implemented in the HIDP layer and forced a
synchronous shutdown of the hidp-scheduler. This works just fine, but
lacks a forced disconnect on the underlying l2cap channels. This has been
broken since:

    commit 5205185d461d5902325e457ca80bd421127b7308
    Author: David Herrmann <dh.herrm...@gmail.com>
    Date:   Sat Apr 6 20:28:47 2013 +0200

        Bluetooth: hidp: remove old session-management

The old session-management always forced an l2cap error on the ctrl/intr
channels when shutting down. The new session-management skips this, as we
don't want to enforce channel policy on the caller. In other words, if
user-space removes an HIDP device, the underlying channels (which are
*owned* and *referenced* by user-space) are still left active. User-space
needs to call shutdown(2) or close(2) to release them.

Unfortunately, this does not work with idle-timeouts. There is no way to
signal user-space that the HIDP layer has been stopped. The API simply
does not support any event-passing except for poll(2). Hence, we restore
old behavior and force EUNATCH on the sockets if the HIDP layer is
disconnected due to idle-timeouts (behavior of explicit disconnects
remains unmodified). User-space can still call

    getsockopt(..., SO_ERROR, ...)

..to retrieve the EUNATCH error and clear sk_err. Hence, the channels can
still be re-used (which nobody does so far, though). Therefore, the API
still supports the new behavior, but with this patch it's also compatible
to the old implicit channel shutdown.

Reported-by: Mark Haun <hau...@keteu.org>
Reported-by: Luiz Augusto von Dentz <luiz.de...@gmail.com>
Signed-off-by: David Herrmann <dh.herrm...@gmail.com>
Signed-off-by: Marcel Holtmann <mar...@holtmann.org>
Signed-off-by: Jiri Slaby <jsl...@suse.cz>
---
 net/bluetooth/hidp/core.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index bdc35a7a7fee..49637fb491a9 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -415,6 +415,20 @@ static void hidp_idle_timeout(unsigned long arg)
 {
        struct hidp_session *session = (struct hidp_session *) arg;
 
+       /* The HIDP user-space API only contains calls to add and remove
+        * devices. There is no way to forward events of any kind. Therefore,
+        * we have to forcefully disconnect a device on idle-timeouts. This is
+        * unfortunate and weird API design, but it is spec-compliant and
+        * required for backwards-compatibility. Hence, on idle-timeout, we
+        * signal driver-detach events, so poll() will be woken up with an
+        * error-condition on both sockets.
+        */
+
+       session->intr_sock->sk->sk_err = EUNATCH;
+       session->ctrl_sock->sk->sk_err = EUNATCH;
+       wake_up_interruptible(sk_sleep(session->intr_sock->sk));
+       wake_up_interruptible(sk_sleep(session->ctrl_sock->sk));
+
        hidp_session_terminate(session);
 }
 
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to