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:
Luiz Augusto von Dentz 2019-08-27 14:52:37 +03:00 committed by Carles Cufí
commit 68bfd1422e

View file

@ -374,7 +374,15 @@ static struct net_buf *l2cap_create_le_sig_pdu(struct net_buf *buf,
{
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->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,
ch->chan.ident, sizeof(*req));
if (!buf) {
return -ENOMEM;
}
req = net_buf_add(buf, sizeof(*req));
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,
sizeof(*rej) + data_len);
if (!buf) {
return;
}
rej = net_buf_add(buf, sizeof(*rej));
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,
sizeof(*rsp));
if (!buf) {
return;
}
accepted = le_param_req(conn, &param);
@ -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,
sizeof(*rsp));
if (!buf) {
return;
}
rsp = net_buf_add(buf, 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,
sizeof(*rsp));
if (!buf) {
return;
}
rsp = net_buf_add(buf, sizeof(*rsp));
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(),
sizeof(*ev));
if (!buf) {
return;
}
ev = net_buf_add(buf, sizeof(*ev));
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,
get_ident(), sizeof(*req));
if (!buf) {
return -ENOMEM;
}
req = net_buf_add(buf, sizeof(*req));
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,
ch->chan.ident, sizeof(*req));
if (!buf) {
return -ENOMEM;
}
req = net_buf_add(buf, sizeof(*req));
req->dcid = sys_cpu_to_le16(ch->rx.cid);