Bluetooth: drivers: Add length checks before net_buf_add_mem

Add length checks before calls to net_buf_add_mem
for dynamically sized data.

This should give a better error response than hitting
the __ASSERT in net_buf_simple_add.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2021-12-08 18:01:20 +01:00 committed by Christopher Friedt
commit b988c803f6
6 changed files with 107 additions and 5 deletions

View file

@ -281,6 +281,8 @@ static inline void read_payload(void)
int read;
if (!rx.buf) {
size_t buf_tailroom;
rx.buf = get_rx(K_NO_WAIT);
if (!rx.buf) {
if (rx.discardable) {
@ -297,8 +299,10 @@ static inline void read_payload(void)
BT_DBG("Allocated rx.buf %p", rx.buf);
if (rx.remaining > net_buf_tailroom(rx.buf)) {
BT_ERR("Not enough space in buffer");
buf_tailroom = net_buf_tailroom(rx.buf);
if (buf_tailroom < rx.remaining) {
BT_ERR("Not enough space in buffer %u/%zu",
rx.remaining, buf_tailroom);
rx.discard = rx.remaining;
reset_rx();
return;

View file

@ -415,6 +415,7 @@ static void bt_uart_isr(const struct device *unused, void *user_data)
uint8_t byte;
int ret;
static uint8_t hdr[4];
size_t buf_tailroom;
ARG_UNUSED(unused);
ARG_UNUSED(user_data);
@ -535,6 +536,14 @@ static void bt_uart_isr(const struct device *unused, void *user_data)
}
}
buf_tailroom = net_buf_tailroom(h5.rx_buf);
if (buf_tailroom < sizeof(byte)) {
BT_ERR("Not enough space in buffer %zu/%zu",
sizeof(byte), buf_tailroom);
h5_reset_rx();
break;
}
net_buf_add_mem(h5.rx_buf, &byte, sizeof(byte));
remaining--;
if (!remaining) {

View file

@ -57,6 +57,7 @@ static struct net_buf *bt_esp_evt_recv(uint8_t *data, size_t remaining)
bool discardable = false;
struct bt_hci_evt_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for event header");
@ -86,6 +87,15 @@ static struct net_buf *bt_esp_evt_recv(uint8_t *data, size_t remaining)
}
net_buf_add_mem(buf, &hdr, sizeof(hdr));
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
continue;
}
net_buf_add_mem(buf, data, remaining);
return buf;
@ -95,6 +105,7 @@ static struct net_buf *bt_esp_acl_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_acl_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ACL header");
@ -119,6 +130,14 @@ static struct net_buf *bt_esp_acl_recv(uint8_t *data, size_t remaining)
return NULL;
}
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %u", remaining);
net_buf_add_mem(buf, data, remaining);
@ -129,6 +148,7 @@ static struct net_buf *bt_esp_iso_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_iso_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ISO header");
@ -153,6 +173,14 @@ static struct net_buf *bt_esp_iso_recv(uint8_t *data, size_t remaining)
return NULL;
}
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %zu", remaining);
net_buf_add_mem(buf, data, remaining);

View file

@ -160,6 +160,8 @@ static void bt_ipm_rx_thread(void)
struct bt_hci_acl_hdr acl_hdr;
TL_AclDataSerial_t *acl;
struct bt_hci_evt_le_meta_event *mev;
size_t buf_tailroom;
size_t buf_add_len;
hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
@ -195,8 +197,18 @@ static void bt_ipm_rx_thread(void)
}
tryfix_event(&hcievt->evtserial.evt);
buf_tailroom = net_buf_tailroom(buf);
buf_add_len = hcievt->evtserial.evt.plen + 2;
if (buf_tailroom < buf_add_len) {
BT_ERR("Not enough space in buffer %zu/%zu",
buf_add_len, buf_tailroom);
net_buf_unref(buf);
goto end_loop;
}
net_buf_add_mem(buf, &hcievt->evtserial.evt,
hcievt->evtserial.evt.plen + 2);
buf_add_len);
break;
case HCI_ACL:
acl = &(((TL_AclDataPacket_t *)hcievt)->AclDataSerial);
@ -206,8 +218,18 @@ static void bt_ipm_rx_thread(void)
BT_DBG("ACL: handle %x, len %x",
acl_hdr.handle, acl_hdr.len);
net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr));
buf_tailroom = net_buf_tailroom(buf);
buf_add_len = acl_hdr.len;
if (buf_tailroom < buf_add_len) {
BT_ERR("Not enough space in buffer %zu/%zu",
buf_add_len, buf_tailroom);
net_buf_unref(buf);
goto end_loop;
}
net_buf_add_mem(buf, (uint8_t *)&acl->acl_data,
acl_hdr.len);
buf_add_len);
break;
default:
BT_ERR("Unknown BT buf type %d",

View file

@ -57,6 +57,7 @@ static struct net_buf *bt_rpmsg_evt_recv(uint8_t *data, size_t remaining)
bool discardable;
struct bt_hci_evt_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for event header");
@ -86,6 +87,15 @@ static struct net_buf *bt_rpmsg_evt_recv(uint8_t *data, size_t remaining)
}
net_buf_add_mem(buf, &hdr, sizeof(hdr));
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
return NULL;
}
net_buf_add_mem(buf, data, remaining);
return buf;
@ -95,6 +105,7 @@ static struct net_buf *bt_rpmsg_acl_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_acl_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ACL header");
@ -119,6 +130,14 @@ static struct net_buf *bt_rpmsg_acl_recv(uint8_t *data, size_t remaining)
return NULL;
}
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %u", remaining);
net_buf_add_mem(buf, data, remaining);
@ -129,6 +148,7 @@ static struct net_buf *bt_rpmsg_iso_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_iso_hdr hdr;
struct net_buf *buf;
size_t buf_tailroom;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ISO header");
@ -153,6 +173,14 @@ static struct net_buf *bt_rpmsg_iso_recv(uint8_t *data, size_t remaining)
return NULL;
}
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
BT_ERR("Not enough space in buffer %zu/%zu",
remaining, buf_tailroom);
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %zu", remaining);
net_buf_add_mem(buf, data, remaining);

View file

@ -103,6 +103,8 @@ static void rx_thread(void *p1, void *p2, void *p3)
while (1) {
static uint8_t frame[512];
struct net_buf *buf;
size_t buf_tailroom;
size_t buf_add_len;
ssize_t len;
if (!uc_ready()) {
@ -131,7 +133,16 @@ static void rx_thread(void *p1, void *p2, void *p3)
continue;
}
net_buf_add_mem(buf, &frame[1], len - 1);
buf_tailroom = net_buf_tailroom(buf);
buf_add_len = len - 1;
if (buf_tailroom < buf_add_len) {
BT_ERR("Not enough space in buffer %zu/%zu",
buf_add_len, buf_tailroom);
net_buf_unref(buf);
continue;
}
net_buf_add_mem(buf, &frame[1], buf_add_len);
BT_DBG("Calling bt_recv(%p)", buf);