These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / bluetooth / l2cap_core.c
index dad4197..66e8b6e 100644 (file)
@@ -239,7 +239,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
        else
                dyn_end = L2CAP_CID_DYN_END;
 
-       for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
+       for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
                if (!__l2cap_get_chan_by_scid(conn, cid))
                        return cid;
        }
@@ -1601,7 +1601,7 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
 
        hci_dev_lock(hdev);
 
-       if (user->list.next || user->list.prev) {
+       if (!list_empty(&user->list)) {
                ret = -EINVAL;
                goto out_unlock;
        }
@@ -1631,12 +1631,10 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
 
        hci_dev_lock(hdev);
 
-       if (!user->list.next || !user->list.prev)
+       if (list_empty(&user->list))
                goto out_unlock;
 
-       list_del(&user->list);
-       user->list.next = NULL;
-       user->list.prev = NULL;
+       list_del_init(&user->list);
        user->remove(conn, user);
 
 out_unlock:
@@ -1650,9 +1648,7 @@ static void l2cap_unregister_all_users(struct l2cap_conn *conn)
 
        while (!list_empty(&conn->users)) {
                user = list_first_entry(&conn->users, struct l2cap_user, list);
-               list_del(&user->list);
-               user->list.next = NULL;
-               user->list.prev = NULL;
+               list_del_init(&user->list);
                user->remove(conn, user);
        }
 }
@@ -5254,7 +5250,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
        credits = __le16_to_cpu(rsp->credits);
        result  = __le16_to_cpu(rsp->result);
 
-       if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
+       if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23 ||
+                                          dcid < L2CAP_CID_DYN_START ||
+                                          dcid > L2CAP_CID_LE_DYN_END))
                return -EPROTO;
 
        BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
@@ -5274,6 +5272,11 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
 
        switch (result) {
        case L2CAP_CR_SUCCESS:
+               if (__l2cap_get_chan_by_dcid(conn, dcid)) {
+                       err = -EBADSLT;
+                       break;
+               }
+
                chan->ident = 0;
                chan->dcid = dcid;
                chan->omtu = mtu;
@@ -5441,9 +5444,16 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
                goto response_unlock;
        }
 
+       /* Check for valid dynamic CID range */
+       if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
+               result = L2CAP_CR_INVALID_SCID;
+               chan = NULL;
+               goto response_unlock;
+       }
+
        /* Check if we already have channel with that dcid */
        if (__l2cap_get_chan_by_dcid(conn, scid)) {
-               result = L2CAP_CR_NO_MEM;
+               result = L2CAP_CR_SCID_IN_USE;
                chan = NULL;
                goto response_unlock;
        }
@@ -7117,8 +7127,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                else
                        role = HCI_ROLE_MASTER;
 
-               hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level,
-                                     HCI_LE_CONN_TIMEOUT, role);
+               hcon = hci_connect_le_scan(hdev, dst, dst_type,
+                                          chan->sec_level,
+                                          HCI_LE_CONN_TIMEOUT,
+                                          role);
        } else {
                u8 auth_type = l2cap_get_auth_type(chan);
                hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
@@ -7442,7 +7454,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
        mutex_unlock(&conn->chan_lock);
 }
 
-int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
        struct l2cap_hdr *hdr;
@@ -7485,7 +7497,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                if (len == skb->len) {
                        /* Complete frame received */
                        l2cap_recv_frame(conn, skb);
-                       return 0;
+                       return;
                }
 
                BT_DBG("Start: total len %d, frag len %d", len, skb->len);
@@ -7544,7 +7556,6 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 
 drop:
        kfree_skb(skb);
-       return 0;
 }
 
 static struct hci_cb l2cap_cb = {