Skip to content

Commit

Permalink
host: l2cap: avoid nested ble_hs_lock when disconnecting due to inval…
Browse files Browse the repository at this point in the history
…id packet

When receiving L2CAP packet which checked to be invalid and a disconnection is required we get into a nested lock (the first is in ble_hs_hci_evt_acl_process which wraps ble_l2cap_rx and the second is inside ble_l2cap_sig_tx which is part of the ble_l2cap_disconnect API). Update the lock sequence to avoid it.

host: l2cap: avoid nested ble_hs_lock when disconnecting due to invalid packet

When receiving L2CAP packet which checked to be invalid and a disconnection is required we get into a nested lock (the first is in ble_hs_hci_evt_acl_process which wraps ble_l2cap_rx and the second is inside ble_l2cap_sig_tx which is part of the ble_l2cap_disconnect API). Update the lock sequence to avoid it.
  • Loading branch information
guy-m committed Jan 17, 2025
1 parent cf947cd commit f429190
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
5 changes: 3 additions & 2 deletions nimble/host/src/ble_hs_hci_evt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,9 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
ble_hs_lock();

conn = ble_hs_conn_find(conn_handle);

ble_hs_unlock();

if (conn == NULL) {
/* Peer not connected; quietly discard packet. */
rc = BLE_HS_ENOTCONN;
Expand All @@ -1141,8 +1144,6 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
om = NULL;
}

ble_hs_unlock();

switch (rc) {
case 0:
/* Final fragment received. */
Expand Down
12 changes: 11 additions & 1 deletion nimble/host/src/ble_l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
uint8_t pb;
int rc;

ble_hs_lock();

*out_reject_cid = -1;

pb = BLE_HCI_DATA_PB(hci_hdr->hdh_handle_pb_bc);
Expand All @@ -362,6 +364,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
/* First fragment. */
rc = ble_l2cap_parse_hdr(om, 0, &l2cap_hdr);
if (rc != 0) {
ble_hs_unlock();
goto err;
}

Expand All @@ -381,6 +384,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
l2cap_hdr.cid);
*out_reject_cid = l2cap_hdr.cid;
}
ble_hs_unlock();
goto err;
}

Expand All @@ -389,8 +393,9 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
/* Data exceeds MPS */
BLE_HS_LOG(ERROR, "error: sdu_len > chan->my_coc_mps (%d>%d)\n",
l2cap_hdr.len, chan->my_coc_mps);
ble_l2cap_disconnect(chan);
rc = BLE_HS_EBADDATA;
ble_hs_unlock();
ble_l2cap_disconnect(chan);
goto err;
}

Expand All @@ -404,6 +409,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
* Disconnect peer with invalid behaviour
*/
rc = BLE_HS_EBADDATA;
ble_hs_unlock();
ble_l2cap_disconnect(chan);
goto err;
}
Expand All @@ -418,21 +424,25 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
if (chan == NULL || chan->rx_buf == NULL) {
/* Middle fragment without the start. Discard new packet. */
rc = BLE_HS_EBADDATA;
ble_hs_unlock();
goto err;
}
break;

default:
rc = BLE_HS_EBADDATA;
ble_hs_unlock();
goto err;
}

rc = ble_l2cap_rx_payload(conn, chan, om, out_rx_cb);
om = NULL;
if (rc != 0) {
ble_hs_unlock();
goto err;
}

ble_hs_unlock();
return 0;

err:
Expand Down

0 comments on commit f429190

Please sign in to comment.