Skip to content

Commit ba2adb7

Browse files
sjancJohan Hedberg
authored and
Johan Hedberg
committed
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 <[email protected]>
1 parent 2ee61f1 commit ba2adb7

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

subsys/bluetooth/host/l2cap_br.c

+25-18
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
747747
struct bt_l2cap_chan *chan;
748748
struct bt_l2cap_server *server;
749749
struct bt_l2cap_conn_req *req = (void *)buf->data;
750-
uint16_t psm, scid, dcid, result;
750+
uint16_t psm, scid, result;
751751

752752
if (buf->len < sizeof(*req)) {
753753
BT_ERR("Too small L2CAP conn req packet size");
@@ -756,15 +756,14 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
756756

757757
psm = sys_le16_to_cpu(req->psm);
758758
scid = sys_le16_to_cpu(req->scid);
759-
dcid = 0;
760759

761760
BT_DBG("psm 0x%02x scid 0x%04x", psm, scid);
762761

763762
/* Check if there is a server registered */
764763
server = l2cap_br_server_lookup_psm(psm);
765764
if (!server) {
766765
result = BT_L2CAP_BR_ERR_PSM_NOT_SUPP;
767-
goto done;
766+
goto no_chan;
768767
}
769768

770769
/*
@@ -774,18 +773,23 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
774773
if (server->sec_level != BT_SECURITY_NONE &&
775774
BT_FEAT_HOST_SSP(conn->br.features) && !conn->encrypt) {
776775
result = BT_L2CAP_BR_ERR_SEC_BLOCK;
777-
goto done;
776+
goto no_chan;
778777
}
779778

780779
if (!L2CAP_BR_CID_IS_DYN(scid)) {
781780
result = BT_L2CAP_BR_ERR_INVALID_SCID;
782-
goto done;
781+
goto no_chan;
783782
}
784783

785784
chan = bt_l2cap_br_lookup_tx_cid(conn, scid);
786785
if (chan) {
786+
/*
787+
* we have a chan here but this is due to SCID being already in
788+
* use so it is not channel we are suppose to pass to
789+
* l2cap_br_conn_req_reply as wrong DCID would be used
790+
*/
787791
result = BT_L2CAP_BR_ERR_SCID_IN_USE;
788-
goto done;
792+
goto no_chan;
789793
}
790794

791795
/*
@@ -794,16 +798,14 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
794798
* proper result and quit since chan pointer is uninitialized then.
795799
*/
796800
if (server->accept(conn, &chan) < 0) {
797-
l2cap_br_send_conn_rsp(conn, scid, dcid, ident,
798-
BT_L2CAP_BR_ERR_NO_RESOURCES);
799-
return;
801+
result = BT_L2CAP_BR_ERR_NO_RESOURCES;
802+
goto no_chan;
800803
}
801804

802805
chan->required_sec_level = server->sec_level;
803806

804807
l2cap_br_chan_add(conn, chan, l2cap_br_chan_destroy);
805808
BR_CHAN(chan)->tx.cid = scid;
806-
dcid = BR_CHAN(chan)->rx.cid;
807809
chan->ident = ident;
808810
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECT);
809811
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,
824826
result = BT_L2CAP_BR_ERR_SEC_BLOCK;
825827
break;
826828
}
827-
done:
828829
/* Reply on connection request as acceptor */
829830
l2cap_br_conn_req_reply(chan, result);
830831

831-
/* Disconnect link when security rules were violated */
832-
if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
833-
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
832+
if (result != BT_L2CAP_SUCCESS) {
833+
/* Disconnect link when security rules were violated */
834+
if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
835+
bt_conn_disconnect(conn,
836+
BT_HCI_ERR_AUTHENTICATION_FAIL);
837+
}
838+
834839
return;
835840
}
836841

837-
if (result == BT_L2CAP_SUCCESS) {
838-
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
839-
l2cap_br_conf(chan);
840-
}
842+
bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
843+
l2cap_br_conf(chan);
844+
return;
845+
846+
no_chan:
847+
l2cap_br_send_conn_rsp(conn, scid, 0, ident, result);
841848
}
842849

843850
static void l2cap_br_conf_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,

0 commit comments

Comments
 (0)