hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/net/bluetooth/l2cap_core.c
....@@ -710,6 +710,17 @@
710710 }
711711 EXPORT_SYMBOL_GPL(l2cap_chan_del);
712712
713
+static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
714
+ l2cap_chan_func_t func, void *data)
715
+{
716
+ struct l2cap_chan *chan, *l;
717
+
718
+ list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
719
+ if (chan->ident == id)
720
+ func(chan, data);
721
+ }
722
+}
723
+
713724 static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
714725 void *data)
715726 {
....@@ -777,23 +788,9 @@
777788
778789 static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
779790 {
780
- struct l2cap_conn *conn = chan->conn;
781
- struct l2cap_ecred_conn_rsp rsp;
782
- u16 result;
783
-
784
- if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
785
- result = L2CAP_CR_LE_AUTHORIZATION;
786
- else
787
- result = L2CAP_CR_LE_BAD_PSM;
788
-
789791 l2cap_state_change(chan, BT_DISCONN);
790792
791
- memset(&rsp, 0, sizeof(rsp));
792
-
793
- rsp.result = cpu_to_le16(result);
794
-
795
- l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
796
- &rsp);
793
+ __l2cap_ecred_conn_rsp_defer(chan);
797794 }
798795
799796 static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
....@@ -848,7 +845,7 @@
848845 break;
849846 case L2CAP_MODE_EXT_FLOWCTL:
850847 l2cap_chan_ecred_connect_reject(chan);
851
- break;
848
+ return;
852849 }
853850 }
854851 }
....@@ -2679,14 +2676,6 @@
26792676 if (IS_ERR(skb))
26802677 return PTR_ERR(skb);
26812678
2682
- /* Channel lock is released before requesting new skb and then
2683
- * reacquired thus we need to recheck channel state.
2684
- */
2685
- if (chan->state != BT_CONNECTED) {
2686
- kfree_skb(skb);
2687
- return -ENOTCONN;
2688
- }
2689
-
26902679 l2cap_do_send(chan, skb);
26912680 return len;
26922681 }
....@@ -2731,14 +2720,6 @@
27312720 if (IS_ERR(skb))
27322721 return PTR_ERR(skb);
27332722
2734
- /* Channel lock is released before requesting new skb and then
2735
- * reacquired thus we need to recheck channel state.
2736
- */
2737
- if (chan->state != BT_CONNECTED) {
2738
- kfree_skb(skb);
2739
- return -ENOTCONN;
2740
- }
2741
-
27422723 l2cap_do_send(chan, skb);
27432724 err = len;
27442725 break;
....@@ -2758,14 +2739,6 @@
27582739 * allocation.
27592740 */
27602741 err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
2761
-
2762
- /* The channel could have been closed while segmenting,
2763
- * check that it is still connected.
2764
- */
2765
- if (chan->state != BT_CONNECTED) {
2766
- __skb_queue_purge(&seg_queue);
2767
- err = -ENOTCONN;
2768
- }
27692742
27702743 if (err)
27712744 break;
....@@ -3958,43 +3931,86 @@
39583931 &rsp);
39593932 }
39603933
3961
-void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
3934
+static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
39623935 {
3963
- struct {
3964
- struct l2cap_ecred_conn_rsp rsp;
3965
- __le16 dcid[5];
3966
- } __packed pdu;
3967
- struct l2cap_conn *conn = chan->conn;
3968
- u16 ident = chan->ident;
3969
- int i = 0;
3936
+ int *result = data;
39703937
3971
- if (!ident)
3938
+ if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
39723939 return;
39733940
3974
- BT_DBG("chan %p ident %d", chan, ident);
3975
-
3976
- pdu.rsp.mtu = cpu_to_le16(chan->imtu);
3977
- pdu.rsp.mps = cpu_to_le16(chan->mps);
3978
- pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
3979
- pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
3980
-
3981
- mutex_lock(&conn->chan_lock);
3982
-
3983
- list_for_each_entry(chan, &conn->chan_l, list) {
3984
- if (chan->ident != ident)
3985
- continue;
3986
-
3987
- /* Reset ident so only one response is sent */
3988
- chan->ident = 0;
3989
-
3990
- /* Include all channels pending with the same ident */
3991
- pdu.dcid[i++] = cpu_to_le16(chan->scid);
3941
+ switch (chan->state) {
3942
+ case BT_CONNECT2:
3943
+ /* If channel still pending accept add to result */
3944
+ (*result)++;
3945
+ return;
3946
+ case BT_CONNECTED:
3947
+ return;
3948
+ default:
3949
+ /* If not connected or pending accept it has been refused */
3950
+ *result = -ECONNREFUSED;
3951
+ return;
39923952 }
3953
+}
39933954
3994
- mutex_unlock(&conn->chan_lock);
3955
+struct l2cap_ecred_rsp_data {
3956
+ struct {
3957
+ struct l2cap_ecred_conn_rsp rsp;
3958
+ __le16 scid[L2CAP_ECRED_MAX_CID];
3959
+ } __packed pdu;
3960
+ int count;
3961
+};
39953962
3996
- l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
3997
- sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
3963
+static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
3964
+{
3965
+ struct l2cap_ecred_rsp_data *rsp = data;
3966
+
3967
+ if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
3968
+ return;
3969
+
3970
+ /* Reset ident so only one response is sent */
3971
+ chan->ident = 0;
3972
+
3973
+ /* Include all channels pending with the same ident */
3974
+ if (!rsp->pdu.rsp.result)
3975
+ rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
3976
+ else
3977
+ l2cap_chan_del(chan, ECONNRESET);
3978
+}
3979
+
3980
+void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
3981
+{
3982
+ struct l2cap_conn *conn = chan->conn;
3983
+ struct l2cap_ecred_rsp_data data;
3984
+ u16 id = chan->ident;
3985
+ int result = 0;
3986
+
3987
+ if (!id)
3988
+ return;
3989
+
3990
+ BT_DBG("chan %p id %d", chan, id);
3991
+
3992
+ memset(&data, 0, sizeof(data));
3993
+
3994
+ data.pdu.rsp.mtu = cpu_to_le16(chan->imtu);
3995
+ data.pdu.rsp.mps = cpu_to_le16(chan->mps);
3996
+ data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
3997
+ data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
3998
+
3999
+ /* Verify that all channels are ready */
4000
+ __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
4001
+
4002
+ if (result > 0)
4003
+ return;
4004
+
4005
+ if (result < 0)
4006
+ data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
4007
+
4008
+ /* Build response */
4009
+ __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
4010
+
4011
+ l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
4012
+ sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
4013
+ &data.pdu);
39984014 }
39994015
40004016 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
....@@ -4287,6 +4303,10 @@
42874303 result = __le16_to_cpu(rsp->result);
42884304 status = __le16_to_cpu(rsp->status);
42894305
4306
+ if (result == L2CAP_CR_SUCCESS && (dcid < L2CAP_CID_DYN_START ||
4307
+ dcid > L2CAP_CID_DYN_END))
4308
+ return -EPROTO;
4309
+
42904310 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
42914311 dcid, scid, result, status);
42924312
....@@ -4318,6 +4338,11 @@
43184338
43194339 switch (result) {
43204340 case L2CAP_CR_SUCCESS:
4341
+ if (__l2cap_get_chan_by_dcid(conn, dcid)) {
4342
+ err = -EBADSLT;
4343
+ break;
4344
+ }
4345
+
43214346 l2cap_state_change(chan, BT_CONFIG);
43224347 chan->ident = 0;
43234348 chan->dcid = dcid;
....@@ -4631,17 +4656,11 @@
46314656
46324657 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
46334658
4634
- mutex_lock(&conn->chan_lock);
4635
-
4636
- chan = __l2cap_get_chan_by_scid(conn, dcid);
4659
+ chan = l2cap_get_chan_by_scid(conn, dcid);
46374660 if (!chan) {
4638
- mutex_unlock(&conn->chan_lock);
46394661 cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
46404662 return 0;
46414663 }
4642
-
4643
- l2cap_chan_hold(chan);
4644
- l2cap_chan_lock(chan);
46454664
46464665 rsp.dcid = cpu_to_le16(chan->scid);
46474666 rsp.scid = cpu_to_le16(chan->dcid);
....@@ -4649,14 +4668,16 @@
46494668
46504669 chan->ops->set_shutdown(chan);
46514670
4671
+ l2cap_chan_unlock(chan);
4672
+ mutex_lock(&conn->chan_lock);
4673
+ l2cap_chan_lock(chan);
46524674 l2cap_chan_del(chan, ECONNRESET);
4675
+ mutex_unlock(&conn->chan_lock);
46534676
46544677 chan->ops->close(chan);
46554678
46564679 l2cap_chan_unlock(chan);
46574680 l2cap_chan_put(chan);
4658
-
4659
- mutex_unlock(&conn->chan_lock);
46604681
46614682 return 0;
46624683 }
....@@ -4677,32 +4698,27 @@
46774698
46784699 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
46794700
4680
- mutex_lock(&conn->chan_lock);
4681
-
4682
- chan = __l2cap_get_chan_by_scid(conn, scid);
4701
+ chan = l2cap_get_chan_by_scid(conn, scid);
46834702 if (!chan) {
4684
- mutex_unlock(&conn->chan_lock);
46854703 return 0;
46864704 }
4687
-
4688
- l2cap_chan_hold(chan);
4689
- l2cap_chan_lock(chan);
46904705
46914706 if (chan->state != BT_DISCONN) {
46924707 l2cap_chan_unlock(chan);
46934708 l2cap_chan_put(chan);
4694
- mutex_unlock(&conn->chan_lock);
46954709 return 0;
46964710 }
46974711
4712
+ l2cap_chan_unlock(chan);
4713
+ mutex_lock(&conn->chan_lock);
4714
+ l2cap_chan_lock(chan);
46984715 l2cap_chan_del(chan, 0);
4716
+ mutex_unlock(&conn->chan_lock);
46994717
47004718 chan->ops->close(chan);
47014719
47024720 l2cap_chan_unlock(chan);
47034721 l2cap_chan_put(chan);
4704
-
4705
- mutex_unlock(&conn->chan_lock);
47064722
47074723 return 0;
47084724 }
....@@ -5976,7 +5992,7 @@
59765992 struct l2cap_ecred_conn_req *req = (void *) data;
59775993 struct {
59785994 struct l2cap_ecred_conn_rsp rsp;
5979
- __le16 dcid[5];
5995
+ __le16 dcid[L2CAP_ECRED_MAX_CID];
59805996 } __packed pdu;
59815997 struct l2cap_chan *chan, *pchan;
59825998 u16 mtu, mps;
....@@ -5989,6 +6005,14 @@
59896005 return -EINVAL;
59906006
59916007 if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
6008
+ result = L2CAP_CR_LE_INVALID_PARAMS;
6009
+ goto response;
6010
+ }
6011
+
6012
+ cmd_len -= sizeof(*req);
6013
+ num_scid = cmd_len / sizeof(u16);
6014
+
6015
+ if (num_scid > ARRAY_SIZE(pdu.dcid)) {
59926016 result = L2CAP_CR_LE_INVALID_PARAMS;
59936017 goto response;
59946018 }
....@@ -6037,8 +6061,6 @@
60376061 }
60386062
60396063 result = L2CAP_CR_LE_SUCCESS;
6040
- cmd_len -= sizeof(*req);
6041
- num_scid = cmd_len / sizeof(u16);
60426064
60436065 for (i = 0; i < num_scid; i++) {
60446066 u16 scid = __le16_to_cpu(req->scid[i]);
....@@ -6091,6 +6113,7 @@
60916113 __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
60926114
60936115 chan->ident = cmd->ident;
6116
+ chan->mode = L2CAP_MODE_EXT_FLOWCTL;
60946117
60956118 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
60966119 l2cap_state_change(chan, BT_CONNECT2);
....@@ -6347,9 +6370,14 @@
63476370 if (!chan)
63486371 goto done;
63496372
6373
+ chan = l2cap_chan_hold_unless_zero(chan);
6374
+ if (!chan)
6375
+ goto done;
6376
+
63506377 l2cap_chan_lock(chan);
63516378 l2cap_chan_del(chan, ECONNREFUSED);
63526379 l2cap_chan_unlock(chan);
6380
+ l2cap_chan_put(chan);
63536381
63546382 done:
63556383 mutex_unlock(&conn->chan_lock);