Skip to content

Commit b156e0f

Browse files
sjancnashif
authored andcommitted
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 4225466 commit b156e0f

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
@@ -2396,13 +2396,23 @@ static void l2cap_chan_recv_queue(struct bt_l2cap_le_chan *chan,
23962396
}
23972397
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
23982398

2399-
static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
2399+
static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf,
2400+
bool complete)
24002401
{
24012402
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
24022403
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
24032404

24042405
if (L2CAP_LE_CID_IS_DYN(ch->rx.cid)) {
2405-
l2cap_chan_recv_queue(ch, buf);
2406+
if (complete) {
2407+
l2cap_chan_recv_queue(ch, buf);
2408+
} else {
2409+
/* if packet was not complete this means peer device
2410+
* overflowed our RX and channel shall be disconnected
2411+
*/
2412+
bt_l2cap_chan_disconnect(chan);
2413+
net_buf_unref(buf);
2414+
}
2415+
24062416
return;
24072417
}
24082418
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
@@ -2413,7 +2423,7 @@ static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
24132423
net_buf_unref(buf);
24142424
}
24152425

2416-
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
2426+
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf, bool complete)
24172427
{
24182428
struct bt_l2cap_hdr *hdr;
24192429
struct bt_l2cap_chan *chan;
@@ -2443,7 +2453,7 @@ void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
24432453
return;
24442454
}
24452455

2446-
l2cap_chan_recv(chan, buf);
2456+
l2cap_chan_recv(chan, buf, complete);
24472457
}
24482458

24492459
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)