Commit 68bfd142 authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz Committed by Carles Cufi
Browse files

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: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 6a71ebf6
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -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);