nimble/l2cap: Fix locking on incoming LE CoC connect request Just use lock when retrieve or add channel to conn object. Without this patch there is a locking issue when ble_l2cap_recv_read() is called on BLE_L2CAP_EVENT_COC_ACCEPT
Issue found during unit test writing for LE CoC Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/11d2cb59 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/11d2cb59 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/11d2cb59 Branch: refs/heads/master Commit: 11d2cb595e40943463f8b9f349820a3fda28f7a5 Parents: e6d3b0e Author: Åukasz Rymanowski <lukasz.rymanow...@codecoup.pl> Authored: Wed Mar 15 12:29:54 2017 +0100 Committer: Åukasz Rymanowski <lukasz.rymanow...@codecoup.pl> Committed: Thu Apr 6 10:04:03 2017 +0200 ---------------------------------------------------------------------- net/nimble/host/src/ble_l2cap_sig.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/11d2cb59/net/nimble/host/src/ble_l2cap_sig.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c index 09ff8e0..ae99f00 100644 --- a/net/nimble/host/src/ble_l2cap_sig.c +++ b/net/nimble/host/src/ble_l2cap_sig.c @@ -665,12 +665,14 @@ ble_l2cap_sig_coc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, scid = le16toh(req->scid); if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) { rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID); + ble_hs_unlock(); goto failed; } chan = ble_hs_conn_chan_find_by_dcid(conn, scid); if (chan) { rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED); + ble_hs_unlock(); goto failed; } @@ -678,6 +680,7 @@ ble_l2cap_sig_coc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, if (rc != 0) { uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc); rsp->result = htole16(coc_err); + ble_hs_unlock(); goto failed; } @@ -687,6 +690,8 @@ ble_l2cap_sig_coc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, chan->coc_tx.credits = le16toh(req->credits); chan->coc_tx.mtu = le16toh(req->mtu); + ble_hs_unlock(); + rc = ble_l2cap_event_coc_accept(chan, le16toh(req->mtu)); if (rc != 0) { uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc); @@ -713,12 +718,10 @@ ble_l2cap_sig_coc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, /* Notify user about connection status */ ble_l2cap_event_coc_connected(chan, rc); - ble_hs_unlock(); return 0; failed: - ble_hs_unlock(); ble_l2cap_sig_tx(conn_handle, txom); return 0; }