[Bluetooth] Fix L2CAP and HCI setsockopt() information leaks
[pandora-kernel.git] / net / bluetooth / l2cap.c
index f8c25d5..a59b1fb 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -227,7 +227,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
                bt_accept_enqueue(parent, sk);
 }
 
-/* Delete channel. 
+/* Delete channel.
  * Must be called on the locked socket. */
 static void l2cap_chan_del(struct sock *sk, int err)
 {
@@ -238,7 +238,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
 
        BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
 
-       if (conn) { 
+       if (conn) {
                /* Unlink from channel list */
                l2cap_chan_unlink(&conn->chan_list, sk);
                l2cap_pi(sk)->conn = NULL;
@@ -459,8 +459,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
                        sk->sk_state = BT_DISCONN;
                        l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
 
-                       req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-                       req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
+                       req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+                       req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        l2cap_send_cmd(conn, l2cap_get_ident(conn),
                                        L2CAP_DISCONN_REQ, sizeof(req), &req);
                } else {
@@ -590,7 +590,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
                err = -EACCES;
                goto done;
        }
-               
+
        write_lock_bh(&l2cap_sk_list.lock);
 
        if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
@@ -652,7 +652,7 @@ static int l2cap_do_connect(struct sock *sk)
                if (sk->sk_type == SOCK_SEQPACKET) {
                        struct l2cap_conn_req req;
                        l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-                       req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
+                       req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -868,8 +868,8 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
 
        /* Create L2CAP header */
        lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-       lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-       lh->len = __cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+       lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+       lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
 
        if (sk->sk_type == SOCK_DGRAM)
                put_unaligned(l2cap_pi(sk)->psm, (u16 *) skb_put(skb, 2));
@@ -890,7 +890,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
                *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
                if (!*frag)
                        goto fail;
-               
+
                if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
                        err = -EFAULT;
                        goto fail;
@@ -954,11 +954,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               opts.imtu     = l2cap_pi(sk)->imtu;
+               opts.omtu     = l2cap_pi(sk)->omtu;
+               opts.flush_to = l2cap_pi(sk)->flush_to;
+               opts.mode     = 0x00;
+
                len = min_t(unsigned int, sizeof(opts), optlen);
                if (copy_from_user((char *) &opts, optval, len)) {
                        err = -EFAULT;
                        break;
                }
+
                l2cap_pi(sk)->imtu  = opts.imtu;
                l2cap_pi(sk)->omtu  = opts.omtu;
                break;
@@ -1096,7 +1102,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                } else if (sk->sk_state == BT_CONNECT) {
                        struct l2cap_conn_req req;
                        l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-                       req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
+                       req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_REQ, sizeof(req), &req);
                }
@@ -1192,13 +1198,13 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
                return NULL;
 
        lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-       lh->len = __cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
-       lh->cid = __cpu_to_le16(0x0001);
+       lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
+       lh->cid = cpu_to_le16(0x0001);
 
        cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
        cmd->code  = code;
        cmd->ident = ident;
-       cmd->len   = __cpu_to_le16(dlen);
+       cmd->len   = cpu_to_le16(dlen);
 
        if (dlen) {
                count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
@@ -1267,7 +1273,7 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned
 
 static inline void l2cap_parse_conf_req(struct sock *sk, void *data, int len)
 {
-       int type, hint, olen; 
+       int type, hint, olen;
        unsigned long val;
        void *ptr = data;
 
@@ -1316,11 +1322,11 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
                break;
 
        case 2:
-               *((u16 *) opt->val) = __cpu_to_le16(val);
+               *((u16 *) opt->val) = cpu_to_le16(val);
                break;
 
        case 4:
-               *((u32 *) opt->val) = __cpu_to_le32(val);
+               *((u32 *) opt->val) = cpu_to_le32(val);
                break;
 
        default:
@@ -1346,8 +1352,8 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
        //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
        //   l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
 
-       req->dcid  = __cpu_to_le16(pi->dcid);
-       req->flags = __cpu_to_le16(0);
+       req->dcid  = cpu_to_le16(pi->dcid);
+       req->flags = cpu_to_le16(0);
 
        return ptr - data;
 }
@@ -1383,9 +1389,9 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
        else
                flags = 0x0001;
 
-       rsp->scid   = __cpu_to_le16(l2cap_pi(sk)->dcid);
-       rsp->result = __cpu_to_le16(result ? *result : 0);
-       rsp->flags  = __cpu_to_le16(flags);
+       rsp->scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+       rsp->result = cpu_to_le16(result ? *result : 0);
+       rsp->flags  = cpu_to_le16(flags);
 
        return ptr - data;
 }
@@ -1414,7 +1420,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
-               BT_DBG("backlog full %d", parent->sk_ack_backlog); 
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
                goto response;
        }
 
@@ -1470,10 +1476,10 @@ response:
        bh_unlock_sock(parent);
 
 sendresp:
-       rsp.scid   = __cpu_to_le16(scid);
-       rsp.dcid   = __cpu_to_le16(dcid);
-       rsp.result = __cpu_to_le16(result);
-       rsp.status = __cpu_to_le16(status);
+       rsp.scid   = cpu_to_le16(scid);
+       rsp.dcid   = cpu_to_le16(dcid);
+       rsp.result = cpu_to_le16(result);
+       rsp.status = cpu_to_le16(status);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
        return 0;
 }
@@ -1607,14 +1613,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        goto done;
                }
 
-       default: 
+       default:
                sk->sk_state = BT_DISCONN;
                sk->sk_err   = ECONNRESET;
                l2cap_sock_set_timer(sk, HZ * 5);
                {
                        struct l2cap_disconn_req req;
-                       req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-                       req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
+                       req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+                       req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        l2cap_send_cmd(conn, l2cap_get_ident(conn),
                                        L2CAP_DISCONN_REQ, sizeof(req), &req);
                }
@@ -1652,8 +1658,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
                return 0;
 
-       rsp.dcid = __cpu_to_le16(l2cap_pi(sk)->scid);
-       rsp.scid = __cpu_to_le16(l2cap_pi(sk)->dcid);
+       rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+       rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
 
        sk->sk_shutdown = SHUTDOWN_MASK;
@@ -1696,8 +1702,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
 
        BT_DBG("type 0x%4.4x", type);
 
-       rsp.type   = __cpu_to_le16(type);
-       rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
+       rsp.type   = cpu_to_le16(type);
+       rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp);
 
        return 0;
@@ -1794,7 +1800,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
                        BT_DBG("error %d", err);
 
                        /* FIXME: Map err to a valid reason */
-                       rej.reason = __cpu_to_le16(0);
+                       rej.reason = cpu_to_le16(0);
                        l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
                }
 
@@ -1993,10 +1999,10 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
                        result = L2CAP_CR_SEC_BLOCK;
                }
 
-               rsp.scid   = __cpu_to_le16(l2cap_pi(sk)->dcid);
-               rsp.dcid   = __cpu_to_le16(l2cap_pi(sk)->scid);
-               rsp.result = __cpu_to_le16(result);
-               rsp.status = __cpu_to_le16(0);
+               rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+               rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+               rsp.result = cpu_to_le16(result);
+               rsp.status = cpu_to_le16(0);
                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
@@ -2041,10 +2047,10 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
                        result = L2CAP_CR_SEC_BLOCK;
                }
 
-               rsp.scid   = __cpu_to_le16(l2cap_pi(sk)->dcid);
-               rsp.dcid   = __cpu_to_le16(l2cap_pi(sk)->scid);
-               rsp.result = __cpu_to_le16(result);
-               rsp.status = __cpu_to_le16(0);
+               rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+               rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+               rsp.result = cpu_to_le16(result);
+               rsp.status = cpu_to_le16(0);
                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
@@ -2107,7 +2113,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
                if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC)))
                        goto drop;
 
-               memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len);
+               skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
+                             skb->len);
                conn->rx_len = len - skb->len;
        } else {
                BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
@@ -2128,7 +2135,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
                        goto drop;
                }
 
-               memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len);
+               skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
+                             skb->len);
                conn->rx_len -= skb->len;
 
                if (!conn->rx_len) {