Skip to content

Commit 5846baa

Browse files
committed
Bluetooth: Disconnect L2CAP channel if peer sent too much data
This was affecting L2CAP/LE/CFC/BV-26-C, L2CAP/LE/CFC/BV-27-C, L2CAP/ECFC/BV-33-C and L2CAP/ECFC/BV-34-C qualification test cases. Signed-off-by: Szymon Janc <[email protected]>
1 parent 9bea59a commit 5846baa

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

subsys/bluetooth/host/conn.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,13 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
263263

264264
if (buf->len > net_buf_tailroom(conn->rx)) {
265265
BT_ERR("Not enough buffer space for L2CAP data");
266-
bt_conn_reset_rx_state(conn);
266+
267+
/* Frame is not complete but we still pass it to L2CAP
268+
* so that it may handle error on protocol level
269+
* eg disconnect channel.
270+
*/
271+
bt_l2cap_recv(conn, conn->rx, false);
272+
conn->rx = NULL;
267273
net_buf_unref(buf);
268274
return;
269275
}
@@ -308,7 +314,7 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
308314
conn->rx = NULL;
309315

310316
BT_DBG("Successfully parsed %u byte L2CAP packet", buf->len);
311-
bt_l2cap_recv(conn, buf);
317+
bt_l2cap_recv(conn, buf, true);
312318
}
313319

314320
void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)

subsys/bluetooth/host/l2cap.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,13 +2364,23 @@ static void l2cap_chan_recv_queue(struct bt_l2cap_le_chan *chan,
23642364
}
23652365
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
23662366

2367-
static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
2367+
static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf,
2368+
bool complete)
23682369
{
23692370
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
23702371
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
23712372

23722373
if (L2CAP_LE_CID_IS_DYN(ch->rx.cid)) {
2373-
l2cap_chan_recv_queue(ch, buf);
2374+
if (complete) {
2375+
l2cap_chan_recv_queue(ch, buf);
2376+
} else {
2377+
/* if packet was not complete this means peer device
2378+
* overflowed our RX and channel shall be disconnected
2379+
*/
2380+
bt_l2cap_chan_disconnect(chan);
2381+
net_buf_unref(buf);
2382+
}
2383+
23742384
return;
23752385
}
23762386
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
@@ -2381,7 +2391,7 @@ static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
23812391
net_buf_unref(buf);
23822392
}
23832393

2384-
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
2394+
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf, bool complete)
23852395
{
23862396
struct bt_l2cap_hdr *hdr;
23872397
struct bt_l2cap_chan *chan;
@@ -2411,7 +2421,7 @@ void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
24112421
return;
24122422
}
24132423

2414-
l2cap_chan_recv(chan, buf);
2424+
l2cap_chan_recv(chan, buf, complete);
24152425
}
24162426

24172427
int bt_l2cap_update_conn_param(struct bt_conn *conn,

subsys/bluetooth/host/l2cap_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ static inline int bt_l2cap_send(struct bt_conn *conn, uint16_t cid,
312312
}
313313

314314
/* Receive a new L2CAP PDU from a connection */
315-
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf);
315+
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf, bool complete);
316316

317317
/* Perform connection parameter update request */
318318
int bt_l2cap_update_conn_param(struct bt_conn *conn,

0 commit comments

Comments
 (0)