Bluetooth: hidp: verify l2cap sockets
authorDavid Herrmann <dh.herrmann@gmail.com>
Fri, 5 Apr 2013 12:57:34 +0000 (14:57 +0200)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Sat, 6 Apr 2013 02:44:14 +0000 (23:44 -0300)
We need to verify that the given sockets actually are l2cap sockets. If
they aren't, we are not supposed to access bt_sk(sock) and we shouldn't
start the session if the offsets turn out to be valid local BT addresses.

That is, if someone passes a TCP socket to HIDCONNADD, then we access some
random offset in the TCP socket (which isn't even guaranteed to be valid).

Fix this by checking that the socket is an l2cap socket.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/l2cap.h
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_sock.c

index cdd33021f831e8ce2eb7dff17992c2f40685aff6..278830ef92cdbfc37c6178551f3f488415fac449 100644 (file)
@@ -786,6 +786,7 @@ extern bool disable_ertm;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
+bool l2cap_is_socket(struct socket *sock);
 
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 int __l2cap_wait_ack(struct sock *sk);
index 2342327f3335c69ab1bb7de610db392d8731810f..4ab82cb3eac32d6f95ebade82116a7595d65941d 100644 (file)
@@ -973,6 +973,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
        BT_DBG("");
 
+       if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
+               return -EINVAL;
        if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
                        bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
                return -ENOTUNIQ;
index 7f9704993b74044ec1c93e3308c7172393bb062d..141e7b058b7e897e71114a01864942361f31b322 100644 (file)
@@ -43,6 +43,12 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent);
 static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
                                     int proto, gfp_t prio);
 
+bool l2cap_is_socket(struct socket *sock)
+{
+       return sock && sock->ops == &l2cap_sock_ops;
+}
+EXPORT_SYMBOL(l2cap_is_socket);
+
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
        struct sock *sk = sock->sk;