mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 14:44:42 +02:00
Bluetooth: L2CAP: fix chan mode for LE_CONN_REQ + EXT_FLOWCTL pchan
l2cap_new_connection() sets default value of channel mode to match the
parent channel. l2cap_le_connect_req() left this at the default, and
created L2CAP_MODE_EXT_FLOWCTL channels if listening pchan has that
mode. This causes FLAG_DEFER_SETUP channels to reply to
L2CAP_LE_CONN_REQ with L2CAP_ECRED_CONN_RSP, which is incorrect.
It can also result to stack OOB write (of l2cap_alloc_cid determined
values) in l2cap_ecred_rsp_defer(), as l2cap_le_connect_req() does not
limit maximum number of deferred channels or check for duplicate ident.
Fix by setting chan->mode correctly in l2cap_le_connect_req().
Also check channel mode in l2cap_ecred_rsp_defer(), and do WARN_ON_ONCE
instead of OOB write to make it less brittle.
Fixes: 15f02b9105 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
57938bbdb9
commit
4ef05db5b0
|
|
@ -3894,6 +3894,9 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
|
|||
struct l2cap_ecred_conn_rsp *rsp_flex =
|
||||
container_of(&rsp->pdu.rsp, struct l2cap_ecred_conn_rsp, hdr);
|
||||
|
||||
if (chan->mode != L2CAP_MODE_EXT_FLOWCTL)
|
||||
return;
|
||||
|
||||
/* Check if channel for outgoing connection or if it wasn't deferred
|
||||
* since in those cases it must be skipped.
|
||||
*/
|
||||
|
|
@ -3904,6 +3907,10 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
|
|||
/* Reset ident so only one response is sent */
|
||||
chan->ident = 0;
|
||||
|
||||
/* Unreachable, check in l2cap_ecred_conn_req. If reached, drop rest */
|
||||
if (WARN_ON_ONCE(rsp->count >= ARRAY_SIZE(rsp->pdu.scid)))
|
||||
rsp->pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_NO_MEM);
|
||||
|
||||
/* Include all channels pending with the same ident */
|
||||
if (!rsp->pdu.rsp.result)
|
||||
rsp_flex->dcid[rsp->count++] = cpu_to_le16(chan->scid);
|
||||
|
|
@ -5063,6 +5070,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
|
|||
__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
|
||||
|
||||
chan->ident = cmd->ident;
|
||||
chan->mode = L2CAP_MODE_LE_FLOWCTL;
|
||||
|
||||
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
|
||||
l2cap_state_change(chan, BT_CONNECT2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user