Skip to content

Commit df1e226

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: Classic: L2CAP: Fix seg_recv cannot work issue
When the L2CAP channel connection is in none basic mode, the `seg_recv` cannot work properly if the configuration `CONFIG_BT_L2CAP_SEG_RECV` is enabled. And the L2CAP channel connection will be broken incorrectly. Check whether the received data len exceeds the SDU length if the `SAR` is `BT_L2CAP_CONTROL_SAR_END` or `BT_L2CAP_CONTROL_SAR_CONTI`. And check whether the SDU length is valid if the `SAR` is `BT_L2CAP_CONTROL_SAR_UNSEG` or `BT_L2CAP_CONTROL_SAR_START`. Signed-off-by: Lyle Zhu <[email protected]>
1 parent bc47bce commit df1e226

File tree

1 file changed

+25
-22
lines changed

1 file changed

+25
-22
lines changed

subsys/bluetooth/host/classic/l2cap_br.c

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5341,52 +5341,55 @@ static void bt_l2cap_br_recv_seg_direct(struct bt_l2cap_br_chan *br_chan, struct
53415341

53425342
switch (sar) {
53435343
case BT_L2CAP_CONTROL_SAR_UNSEG:
5344-
__fallthrough;
53455344
case BT_L2CAP_CONTROL_SAR_START:
53465345
if (sar == BT_L2CAP_CONTROL_SAR_START) {
53475346
br_chan->_sdu_len = net_buf_pull_le16(seg);
53485347
} else {
53495348
br_chan->_sdu_len = seg->len;
53505349
}
5351-
br_chan->_sdu_len_done = 0;
53525350

53535351
if (br_chan->_sdu_len > br_chan->rx.mtu) {
53545352
LOG_WRN("SDU exceeds MTU");
5355-
bt_l2cap_chan_disconnect(&br_chan->chan);
5356-
return;
5353+
goto failed;
53575354
}
5355+
5356+
if (br_chan->_sdu_len < seg->len) {
5357+
LOG_WRN("Short data packet %u < %u", br_chan->_sdu_len, seg->len);
5358+
goto failed;
5359+
}
5360+
5361+
br_chan->_sdu_len_done = seg->len;
53585362
break;
53595363
case BT_L2CAP_CONTROL_SAR_END:
5360-
__fallthrough;
53615364
case BT_L2CAP_CONTROL_SAR_CONTI:
53625365
seg_offset = br_chan->_sdu_len_done;
53635366
sdu_remaining = br_chan->_sdu_len - br_chan->_sdu_len_done;
53645367

53655368
br_chan->_sdu_len_done += seg->len;
53665369

5367-
if (sar == BT_L2CAP_CONTROL_SAR_END) {
5368-
if (br_chan->_sdu_len_done < br_chan->_sdu_len) {
5369-
br_chan->_sdu_len = 0;
5370-
br_chan->_sdu_len_done = 0;
5371-
LOG_WRN("Short data packet %u < %u", br_chan->_sdu_len_done,
5372-
br_chan->_sdu_len);
5373-
bt_l2cap_chan_disconnect(&br_chan->chan);
5374-
return;
5375-
}
5370+
if (sdu_remaining < seg->len) {
5371+
LOG_WRN("L2CAP RX PDU total exceeds SDU");
5372+
goto failed;
53765373
}
5377-
break;
5378-
}
53795374

5380-
if (sdu_remaining < seg->len) {
5381-
br_chan->_sdu_len = 0;
5382-
br_chan->_sdu_len_done = 0;
5383-
LOG_WRN("L2CAP RX PDU total exceeds SDU");
5384-
bt_l2cap_chan_disconnect(&br_chan->chan);
5385-
return;
5375+
if ((sar == BT_L2CAP_CONTROL_SAR_END) &&
5376+
(br_chan->_sdu_len_done < br_chan->_sdu_len)) {
5377+
LOG_WRN("Short data packet %u < %u", br_chan->_sdu_len_done,
5378+
br_chan->_sdu_len);
5379+
goto failed;
5380+
}
5381+
break;
53865382
}
53875383

53885384
/* Tail call. */
53895385
br_chan->chan.ops->seg_recv(&br_chan->chan, br_chan->_sdu_len, seg_offset, &seg->b);
5386+
5387+
return;
5388+
5389+
failed:
5390+
br_chan->_sdu_len = 0;
5391+
br_chan->_sdu_len_done = 0;
5392+
bt_l2cap_chan_disconnect(&br_chan->chan);
53905393
}
53915394
#endif /* CONFIG_BT_L2CAP_SEG_RECV */
53925395

0 commit comments

Comments
 (0)