Bluetooth: L2CAP: Fix invalid access if a buffer cannot be allocated
Since bt_l2cap_create_pdu can return NULL when used under syswq context the code should always check its result, this also changes the timeout to have a specific value (RTX maximum timeout) so signalling PDUs still wait for a buffer to become available. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
6a71ebf6c5
commit
68bfd1422e
1 changed files with 33 additions and 1 deletions
|
@ -374,7 +374,15 @@ static struct net_buf *l2cap_create_le_sig_pdu(struct net_buf *buf,
|
||||||
{
|
{
|
||||||
struct bt_l2cap_sig_hdr *hdr;
|
struct bt_l2cap_sig_hdr *hdr;
|
||||||
|
|
||||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
/* Don't wait more than the minimum RTX timeout of 2 seconds */
|
||||||
|
buf = bt_l2cap_create_pdu_timeout(NULL, 0, K_SECONDS(2));
|
||||||
|
if (!buf) {
|
||||||
|
/* If it was not possible to allocate a buffer within the
|
||||||
|
* timeout return NULL.
|
||||||
|
*/
|
||||||
|
BT_ERR("Unable to allocate buffer for op 0x%02x", code);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||||
hdr->code = code;
|
hdr->code = code;
|
||||||
|
@ -415,6 +423,9 @@ static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_LE_CONN_REQ,
|
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_LE_CONN_REQ,
|
||||||
ch->chan.ident, sizeof(*req));
|
ch->chan.ident, sizeof(*req));
|
||||||
|
if (!buf) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
req = net_buf_add(buf, sizeof(*req));
|
req = net_buf_add(buf, sizeof(*req));
|
||||||
req->psm = sys_cpu_to_le16(ch->chan.psm);
|
req->psm = sys_cpu_to_le16(ch->chan.psm);
|
||||||
|
@ -497,6 +508,9 @@ static void l2cap_send_reject(struct bt_conn *conn, u8_t ident,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CMD_REJECT, ident,
|
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CMD_REJECT, ident,
|
||||||
sizeof(*rej) + data_len);
|
sizeof(*rej) + data_len);
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rej = net_buf_add(buf, sizeof(*rej));
|
rej = net_buf_add(buf, sizeof(*rej));
|
||||||
rej->reason = sys_cpu_to_le16(reason);
|
rej->reason = sys_cpu_to_le16(reason);
|
||||||
|
@ -552,6 +566,9 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_CONN_PARAM_RSP, ident,
|
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_CONN_PARAM_RSP, ident,
|
||||||
sizeof(*rsp));
|
sizeof(*rsp));
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
accepted = le_param_req(conn, ¶m);
|
accepted = le_param_req(conn, ¶m);
|
||||||
|
|
||||||
|
@ -804,6 +821,9 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CONN_RSP, ident,
|
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CONN_RSP, ident,
|
||||||
sizeof(*rsp));
|
sizeof(*rsp));
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||||
(void)memset(rsp, 0, sizeof(*rsp));
|
(void)memset(rsp, 0, sizeof(*rsp));
|
||||||
|
@ -936,6 +956,9 @@ static void le_disconn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_DISCONN_RSP, ident,
|
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_DISCONN_RSP, ident,
|
||||||
sizeof(*rsp));
|
sizeof(*rsp));
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||||
rsp->dcid = sys_cpu_to_le16(chan->rx.cid);
|
rsp->dcid = sys_cpu_to_le16(chan->rx.cid);
|
||||||
|
@ -1426,6 +1449,9 @@ static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CREDITS, get_ident(),
|
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CREDITS, get_ident(),
|
||||||
sizeof(*ev));
|
sizeof(*ev));
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ev = net_buf_add(buf, sizeof(*ev));
|
ev = net_buf_add(buf, sizeof(*ev));
|
||||||
ev->cid = sys_cpu_to_le16(chan->rx.cid);
|
ev->cid = sys_cpu_to_le16(chan->rx.cid);
|
||||||
|
@ -1687,6 +1713,9 @@ int bt_l2cap_update_conn_param(struct bt_conn *conn,
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CONN_PARAM_REQ,
|
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CONN_PARAM_REQ,
|
||||||
get_ident(), sizeof(*req));
|
get_ident(), sizeof(*req));
|
||||||
|
if (!buf) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
req = net_buf_add(buf, sizeof(*req));
|
req = net_buf_add(buf, sizeof(*req));
|
||||||
req->min_interval = sys_cpu_to_le16(param->interval_min);
|
req->min_interval = sys_cpu_to_le16(param->interval_min);
|
||||||
|
@ -1821,6 +1850,9 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
|
||||||
|
|
||||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_DISCONN_REQ,
|
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_DISCONN_REQ,
|
||||||
ch->chan.ident, sizeof(*req));
|
ch->chan.ident, sizeof(*req));
|
||||||
|
if (!buf) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
req = net_buf_add(buf, sizeof(*req));
|
req = net_buf_add(buf, sizeof(*req));
|
||||||
req->dcid = sys_cpu_to_le16(ch->rx.cid);
|
req->dcid = sys_cpu_to_le16(ch->rx.cid);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue