From 2c00dd5fec4c603ffbab62dfd1f2971edf687130 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Fri, 17 Feb 2023 08:55:41 +0100 Subject: [PATCH] Bluetooth: host: check net bufs have enough room in user_data Since we accept buffers from external sources in L2CAP, we need to make sure that we have enough room in user data to store the metadata necessary for fragmentation over the HCI link. Signed-off-by: Jonathan Rico --- subsys/bluetooth/host/Kconfig | 7 +++++++ subsys/bluetooth/host/conn.c | 13 +++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 812bbe23afb..75945510868 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -280,6 +280,13 @@ config BT_LIM_ADV_TIMEOUT Appendix A (NORMATIVE): TIMERS AND CONSTANTS it's required to be no more than 180s. +config BT_CONN_TX_USER_DATA_SIZE + int + default 8 + help + Necessary user_data size for allowing packet fragmentation when + sending over HCI. See `struct tx_meta` in conn.c. + if BT_CONN config BT_CONN_TX_MAX diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 06762972a4d..7fb5e83e2ab 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -53,6 +53,9 @@ struct tx_meta { bool is_cont; }; +BUILD_ASSERT(sizeof(struct tx_meta) == CONFIG_BT_CONN_TX_USER_DATA_SIZE, + "User data size is wrong!"); + #define tx_data(buf) ((struct tx_meta *)net_buf_user_data(buf)) K_FIFO_DEFINE(free_tx); @@ -88,7 +91,7 @@ static void notify_connected(struct bt_conn *conn); static struct bt_conn acl_conns[CONFIG_BT_MAX_CONN]; NET_BUF_POOL_DEFINE(acl_tx_pool, CONFIG_BT_L2CAP_TX_BUF_COUNT, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), - sizeof(struct tx_meta), NULL); + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); #if CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 /* Dedicated pool for fragment buffers in case queued up TX buffers don't @@ -98,7 +101,8 @@ NET_BUF_POOL_DEFINE(acl_tx_pool, CONFIG_BT_L2CAP_TX_BUF_COUNT, * another buffer from the acl_tx_pool would result in a deadlock. */ NET_BUF_POOL_FIXED_DEFINE(frag_pool, CONFIG_BT_L2CAP_TX_FRAG_COUNT, - BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_TX_SIZE), 8, NULL); + BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_TX_SIZE), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); #endif /* CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 */ @@ -411,6 +415,11 @@ int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf, LOG_DBG("conn handle %u buf len %u cb %p user_data %p", conn->handle, buf->len, cb, user_data); + if (buf->user_data_size < CONFIG_BT_CONN_TX_USER_DATA_SIZE) { + LOG_ERR("not enough room in user_data"); + return -EINVAL; + } + if (conn->state != BT_CONN_CONNECTED) { LOG_ERR("not connected!"); return -ENOTCONN;