Bluetooth: L2CAP: Fix use of uninitializer pointer
l2cap_br_conn_req_reply expects valid bt_l2cap_chan pointer but this is achieved only on accept() callback. Use l2cap_br_send_conn_rsp instead for rejecting cases where no channel was accepted. This also makes success path being 'primary' function path ie erros all always handled inside if() statements. Jira: ZEP-1405 Change-Id: I890b4fcf029afce65eba4f2ebae0b1094feb007f Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
This commit is contained in:
parent
2ee61f1f97
commit
ba2adb70b2
1 changed files with 25 additions and 18 deletions
|
@ -747,7 +747,7 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
struct bt_l2cap_chan *chan;
|
||||
struct bt_l2cap_server *server;
|
||||
struct bt_l2cap_conn_req *req = (void *)buf->data;
|
||||
uint16_t psm, scid, dcid, result;
|
||||
uint16_t psm, scid, result;
|
||||
|
||||
if (buf->len < sizeof(*req)) {
|
||||
BT_ERR("Too small L2CAP conn req packet size");
|
||||
|
@ -756,7 +756,6 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
|
||||
psm = sys_le16_to_cpu(req->psm);
|
||||
scid = sys_le16_to_cpu(req->scid);
|
||||
dcid = 0;
|
||||
|
||||
BT_DBG("psm 0x%02x scid 0x%04x", psm, scid);
|
||||
|
||||
|
@ -764,7 +763,7 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
server = l2cap_br_server_lookup_psm(psm);
|
||||
if (!server) {
|
||||
result = BT_L2CAP_BR_ERR_PSM_NOT_SUPP;
|
||||
goto done;
|
||||
goto no_chan;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -774,18 +773,23 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
if (server->sec_level != BT_SECURITY_NONE &&
|
||||
BT_FEAT_HOST_SSP(conn->br.features) && !conn->encrypt) {
|
||||
result = BT_L2CAP_BR_ERR_SEC_BLOCK;
|
||||
goto done;
|
||||
goto no_chan;
|
||||
}
|
||||
|
||||
if (!L2CAP_BR_CID_IS_DYN(scid)) {
|
||||
result = BT_L2CAP_BR_ERR_INVALID_SCID;
|
||||
goto done;
|
||||
goto no_chan;
|
||||
}
|
||||
|
||||
chan = bt_l2cap_br_lookup_tx_cid(conn, scid);
|
||||
if (chan) {
|
||||
/*
|
||||
* we have a chan here but this is due to SCID being already in
|
||||
* use so it is not channel we are suppose to pass to
|
||||
* l2cap_br_conn_req_reply as wrong DCID would be used
|
||||
*/
|
||||
result = BT_L2CAP_BR_ERR_SCID_IN_USE;
|
||||
goto done;
|
||||
goto no_chan;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -794,16 +798,14 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
* proper result and quit since chan pointer is uninitialized then.
|
||||
*/
|
||||
if (server->accept(conn, &chan) < 0) {
|
||||
l2cap_br_send_conn_rsp(conn, scid, dcid, ident,
|
||||
BT_L2CAP_BR_ERR_NO_RESOURCES);
|
||||
return;
|
||||
result = BT_L2CAP_BR_ERR_NO_RESOURCES;
|
||||
goto no_chan;
|
||||
}
|
||||
|
||||
chan->required_sec_level = server->sec_level;
|
||||
|
||||
l2cap_br_chan_add(conn, chan, l2cap_br_chan_destroy);
|
||||
BR_CHAN(chan)->tx.cid = scid;
|
||||
dcid = BR_CHAN(chan)->rx.cid;
|
||||
chan->ident = ident;
|
||||
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECT);
|
||||
atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_ACCEPTOR);
|
||||
|
@ -824,20 +826,25 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
result = BT_L2CAP_BR_ERR_SEC_BLOCK;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
/* Reply on connection request as acceptor */
|
||||
l2cap_br_conn_req_reply(chan, result);
|
||||
|
||||
/* Disconnect link when security rules were violated */
|
||||
if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
|
||||
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
||||
if (result != BT_L2CAP_SUCCESS) {
|
||||
/* Disconnect link when security rules were violated */
|
||||
if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
|
||||
bt_conn_disconnect(conn,
|
||||
BT_HCI_ERR_AUTHENTICATION_FAIL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == BT_L2CAP_SUCCESS) {
|
||||
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
|
||||
l2cap_br_conf(chan);
|
||||
}
|
||||
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
|
||||
l2cap_br_conf(chan);
|
||||
return;
|
||||
|
||||
no_chan:
|
||||
l2cap_br_send_conn_rsp(conn, scid, 0, ident, result);
|
||||
}
|
||||
|
||||
static void l2cap_br_conf_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue